+++ /dev/null
-
-/*
- * CINELERRA
- * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include "asset.h"
-#include "byteorder.h"
-#include "file.h"
-#include "filebase.h"
-
-
-int64_t FileBase::samples_to_raw(char *out_buffer,
- float **in_buffer,
- int64_t input_len,
- int bits,
- int channels,
- int byte_order,
- int signed_)
-{
- int output_advance; // number of bytes in a sample
- float *buffer_channel; // channel in input buffer
- float *buffer_channel_end;
- int channel;
- int64_t int_sample, int_sample2;
- float float_sample;
- int64_t dither_value, dither_scale = 255;
- int64_t bytes = input_len * channels * (file->bytes_per_sample(bits));
- int machine_byte_order = get_byte_order();
-
- switch(bits)
- {
- case BITSLINEAR8:
- {
- char *output_ptr, *output_end;
- output_advance = channels;
- for(channel = 0; channel < channels; channel++)
- {
- output_ptr = out_buffer + channel;
- buffer_channel = in_buffer[channel];
- buffer_channel_end = buffer_channel + input_len;
-
- if(dither)
- {
- for( ; buffer_channel < buffer_channel_end; buffer_channel++)
- {
- float_sample = *buffer_channel * 0x7fff;
- int_sample = (int64_t)float_sample;
- if(int_sample > -0x7f00) { dither_value = rand() % dither_scale; int_sample -= dither_value; }
- int_sample /= 0x100; // rotating bits screws up the signs
- *output_ptr = int_sample;
- output_ptr += output_advance;
- }
- }
- else
- {
- for( ; buffer_channel < buffer_channel_end; buffer_channel++)
- {
- float_sample = *buffer_channel * 0x7f;
- *output_ptr = (char)float_sample;
- output_ptr += output_advance;
- }
- }
- }
-
-// fix signed
- if(!signed_)
- {
- output_ptr = out_buffer;
- output_end = out_buffer + bytes;
-
- for( ; output_ptr < output_end; output_ptr++)
- *output_ptr ^= 0x80;
- }
- }
- break;
-
- case BITSLINEAR16:
- {
- int16_t *output_ptr;
- output_advance = channels;
- for(channel = 0; channel < channels; channel++)
- {
- output_ptr = (int16_t*)out_buffer + channel;
- buffer_channel = in_buffer[channel];
- buffer_channel_end = buffer_channel + input_len;
-
- if(dither)
- {
- for( ; buffer_channel < buffer_channel_end; buffer_channel++)
- {
- float_sample = *buffer_channel * 0x7fffff;
- int_sample = (int64_t)float_sample;
- if(int_sample > -0x7fff00) { dither_value = rand() % dither_scale; int_sample -= dither_value; }
- int_sample /= 0x100;
- *output_ptr = int_sample;
- output_ptr += output_advance;
- }
- }
- else
- {
- for( ; buffer_channel < buffer_channel_end; buffer_channel++)
- {
- float_sample = *buffer_channel * 0x7fff;
- *output_ptr = (int16_t)float_sample;
- output_ptr += output_advance;
- }
- }
- }
- }
- break;
-
- case BITSLINEAR24:
- {
- char *output_ptr;
- output_advance = asset->channels * 3 - 2;
- for(channel = 0; channel < channels; channel++)
- {
- output_ptr = out_buffer + channel * 3;
- buffer_channel = in_buffer[channel];
- buffer_channel_end = buffer_channel + input_len;
-
-// don't bother dithering 24 bits
- for( ; buffer_channel < buffer_channel_end; buffer_channel++)
- {
- float_sample = *buffer_channel * 0x7fffff;
- int_sample = (int64_t)float_sample;
- int_sample2 = int_sample & 0xff0000;
- *output_ptr++ = (int_sample & 0xff);
- int_sample &= 0xff00;
- *output_ptr++ = (int_sample >> 8);
- *output_ptr = (int_sample2 >> 16);
- output_ptr += output_advance;
- }
- }
- }
- break;
-
- case BITSULAW:
- {
- char *output_ptr;
- output_advance = asset->channels;
-//printf("FileBase::samples_to_raw 1\n");
- generate_ulaw_tables();
-//printf("FileBase::samples_to_raw 2\n");
-
- for(channel = 0; channel < channels; channel++)
- {
- output_ptr = out_buffer + channel;
- buffer_channel = in_buffer[channel];
- buffer_channel_end = buffer_channel + input_len;
- for( ; buffer_channel < buffer_channel_end; buffer_channel++)
- {
- *output_ptr = floattoulaw(*buffer_channel);
- output_ptr += output_advance;
- }
- }
-//printf("FileBase::samples_to_raw 3\n");
- }
- break;
- }
-
-// swap bytes
- if((bits == BITSLINEAR16 && byte_order != machine_byte_order) ||
- (bits == BITSLINEAR24 && !byte_order))
- {
- swap_bytes(file->bytes_per_sample(bits), (unsigned char*)out_buffer, bytes);
- }
-
- return bytes;
-}
-
-
-#define READ_8_MACRO \
- sample = *inbuffer_8; \
- sample /= 0x7f; \
- inbuffer_8 += input_frame;
-
-#define READ_16_MACRO \
- sample = *inbuffer_16; \
- sample /= 0x7fff; \
- inbuffer_16 += input_frame;
-
-#define READ_24_MACRO \
- sample = (unsigned char)*inbuffer_24++; \
- sample_24 = (unsigned char)*inbuffer_24++; \
- sample_24 <<= 8; \
- sample += sample_24; \
- sample_24 = *inbuffer_24; \
- sample_24 <<= 16; \
- sample += sample_24; \
- sample /= 0x7fffff; \
- inbuffer_24 += input_frame; \
-
-#define READ_ULAW_MACRO \
- sample = ulawtofloat(*inbuffer_8); \
- inbuffer_8 += input_frame;
-
-#define LFEATHER_MACRO1 \
- for(feather_current = 0; feather_current < lfeather_len; \
- output_current++, feather_current++) \
- {
-
-#define LFEATHER_MACRO2 \
- current_gain = lfeather_gain + lfeather_slope * feather_current; \
- out_buffer[output_current] = out_buffer[output_current] * (1 - current_gain) + sample * current_gain; \
- }
-
-#define CENTER_MACRO1 \
- for(; output_current < samples; \
- output_current++) \
- {
-
-#define CENTER_MACRO2 \
- out_buffer[output_current] += sample; \
- }
-
-int FileBase::raw_to_samples(float *out_buffer, char *in_buffer,
- int64_t samples, int bits, int channels, int channel, int feather,
- float lfeather_len, float lfeather_gain, float lfeather_slope)
-{
- int64_t output_current = 0; // position in output buffer
- int64_t input_len = samples; // length of input buffer
-// The following are floats because they are multiplied by the slope to get the gain.
- float feather_current; // input position for feather
-
- float sample;
- char *inbuffer_8 = 0; // point to actual byte being read
- int16_t *inbuffer_16 = 0;
- char *inbuffer_24 = 0;
- int sample_24;
- float current_gain;
- int input_frame = 0; // amount to advance the input buffer pointer
-
-// set up the parameters
- switch(bits)
- {
- case BITSLINEAR8:
- inbuffer_8 = in_buffer + channel;
- input_frame = channels;
- break;
-
- case BITSLINEAR16:
- inbuffer_16 = (int16_t *)in_buffer + channel;
- input_frame = channels;
- break;
-
- case BITSLINEAR24:
- inbuffer_24 = in_buffer + channel * 3;
- input_frame = channels * file->bytes_per_sample(bits) - 2;
- break;
-
- case BITSULAW:
- generate_ulaw_tables();
- inbuffer_8 = in_buffer + channel;
- input_frame = channels;
- break;
- }
-
-// read the data
-// ================== calculate feathering and add to buffer ================
- if(feather)
- {
-// left feather
- switch(bits)
- {
- case BITSLINEAR8:
- LFEATHER_MACRO1;
- READ_8_MACRO;
- LFEATHER_MACRO2;
- break;
-
- case BITSLINEAR16:
- LFEATHER_MACRO1;
- READ_16_MACRO;
- LFEATHER_MACRO2;
- break;
-
- case BITSLINEAR24:
- LFEATHER_MACRO1;
- READ_24_MACRO;
- LFEATHER_MACRO2;
- break;
-
- case BITSULAW:
- LFEATHER_MACRO1;
- READ_ULAW_MACRO;
- LFEATHER_MACRO2;
- break;
- }
-
-
-// central region
- switch(bits)
- {
- case BITSLINEAR8:
- CENTER_MACRO1;
- READ_8_MACRO;
- CENTER_MACRO2;
- break;
-
- case BITSLINEAR16:
- CENTER_MACRO1;
- READ_16_MACRO;
- CENTER_MACRO2;
- break;
-
- case BITSLINEAR24:
- CENTER_MACRO1;
- READ_24_MACRO;
- CENTER_MACRO2;
- break;
-
- case BITSULAW:
- CENTER_MACRO1;
- READ_ULAW_MACRO;
- CENTER_MACRO2;
- break;
- }
- }
- else
-// ====================== don't feather and overwrite buffer =================
- {
- switch(bits)
- {
- case BITSLINEAR8:
- for(; output_current < input_len;
- output_current++)
- { READ_8_MACRO; out_buffer[output_current] = sample; }
- break;
-
- case BITSLINEAR16:
- for(; output_current < input_len;
- output_current++)
- { READ_16_MACRO; out_buffer[output_current] = sample; }
- break;
-
- case BITSLINEAR24:
- for(; output_current < input_len;
- output_current++)
- { READ_24_MACRO; out_buffer[output_current] = sample; }
- break;
-
- case BITSULAW:
- for(; output_current < input_len;
- output_current++)
- { READ_ULAW_MACRO; out_buffer[output_current] = sample; }
- break;
- }
- }
-
- return 0;
-}
-
-int FileBase::overlay_float_buffer(float *out_buffer, float *in_buffer,
- int64_t samples,
- float lfeather_len, float lfeather_gain, float lfeather_slope)
-{
- int64_t output_current = 0;
- float sample, current_gain;
- float feather_current; // input position for feather
-
- LFEATHER_MACRO1
- sample = in_buffer[output_current];
- LFEATHER_MACRO2
-
- CENTER_MACRO1
- sample = in_buffer[output_current];
- CENTER_MACRO2
-
- return 0;
-}
-
-
-int FileBase::get_audio_buffer(char **buffer, int64_t len, int64_t bits, int64_t channels)
-{
- int64_t bytes = len * channels * (file->bytes_per_sample(bits));
- if(*buffer && bytes > prev_bytes)
- {
- delete [] *buffer;
- *buffer = 0;
- }
- prev_bytes = bytes;
-
- if(!*buffer) *buffer = new char[bytes];
- return 0;
-}
-
-int FileBase::get_float_buffer(float **buffer, int64_t len)
-{
- if(*buffer && len > prev_len)
- {
- delete [] *buffer;
- *buffer = 0;
- }
- prev_len = len;
-
- if(!*buffer) *buffer = new float[len];
- return 0;
-}