From b04de17f6e2ec3281de37cd7b8076492d0691f81 Mon Sep 17 00:00:00 2001 From: Josh Coalson Date: Tue, 27 Feb 2001 00:01:55 +0000 Subject: [PATCH] add support for 24-bit input --- src/flac/decode.c | 89 +++++++++++++++++++++++++++++++++++++++++++++++---- src/flac/encode.c | 44 ++++++++++++++++++++++--- src/flac/main.c | 4 +-- src/libFLAC/encoder.c | 2 ++ 4 files changed, 125 insertions(+), 14 deletions(-) diff --git a/src/flac/decode.c b/src/flac/decode.c index 13cce80..e448a82 100644 --- a/src/flac/decode.c +++ b/src/flac/decode.c @@ -304,12 +304,14 @@ FLAC__StreamDecoderWriteStatus write_callback(const FLAC__FileDecoder *decoder, FILE *fout = stream_info->fout; unsigned bps = stream_info->bps, channels = stream_info->channels; bool is_big_endian = (stream_info->is_wave_out? false : stream_info->is_big_endian); - bool is_unsigned_samples = (stream_info->is_wave_out? bps==8 : stream_info->is_unsigned_samples); + bool is_unsigned_samples = (stream_info->is_wave_out? bps<=8 : stream_info->is_unsigned_samples); unsigned wide_samples = frame->header.blocksize, wide_sample, sample, channel, byte; static signed char scbuffer[FLAC__MAX_BLOCK_SIZE * FLAC__MAX_CHANNELS * ((FLAC__MAX_BITS_PER_SAMPLE+7)>>3)]; /* WATCHOUT: can be up to 2 megs */ unsigned char *ucbuffer = (unsigned char *)scbuffer; signed short *ssbuffer = (signed short *)scbuffer; unsigned short *usbuffer = (unsigned short *)scbuffer; + signed *slbuffer = (signed *)scbuffer; + unsigned *ulbuffer = (unsigned *)scbuffer; (void)decoder; @@ -353,7 +355,7 @@ FLAC__StreamDecoderWriteStatus write_callback(const FLAC__FileDecoder *decoder, if(is_unsigned_samples) { for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) for(channel = 0; channel < channels; channel++, sample++) - ucbuffer[sample] = buffer[channel][wide_sample] + 128; + ucbuffer[sample] = buffer[channel][wide_sample] + 0x80; } else { for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) @@ -363,11 +365,11 @@ FLAC__StreamDecoderWriteStatus write_callback(const FLAC__FileDecoder *decoder, if(fwrite(ucbuffer, 1, sample, fout) != sample) return FLAC__STREAM_DECODER_WRITE_ABORT; } - else { /* bps == 16 */ + else if(bps == 16) { if(is_unsigned_samples) { for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) for(channel = 0; channel < channels; channel++, sample++) - usbuffer[sample] = buffer[channel][wide_sample] + 32768; + usbuffer[sample] = buffer[channel][wide_sample] + 0x8000; } else { for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) @@ -376,7 +378,8 @@ FLAC__StreamDecoderWriteStatus write_callback(const FLAC__FileDecoder *decoder, } if(is_big_endian != is_big_endian_host) { unsigned char tmp; - for(byte = 0; byte < sample<<1; byte += 2) { + const unsigned bytes = sample * 2; + for(byte = 0; byte < bytes; byte += 2) { tmp = ucbuffer[byte]; ucbuffer[byte] = ucbuffer[byte+1]; ucbuffer[byte+1] = tmp; @@ -385,6 +388,78 @@ FLAC__StreamDecoderWriteStatus write_callback(const FLAC__FileDecoder *decoder, if(fwrite(usbuffer, 2, sample, fout) != sample) return FLAC__STREAM_DECODER_WRITE_ABORT; } + else if(bps == 24) { + if(is_unsigned_samples) { + for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) + for(channel = 0; channel < channels; channel++, sample++) + ulbuffer[sample] = buffer[channel][wide_sample] + 0x800000; + } + else { + for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) + for(channel = 0; channel < channels; channel++, sample++) + slbuffer[sample] = buffer[channel][wide_sample]; + } +/*@@@ + if(is_big_endian != is_big_endian_host) { + unsigned char tmp; + unsigned lbyte; + const unsigned bytes = sample * 4; + for(lbyte = byte = 0; byte < bytes; byte += 4, lbyte += 3) { + tmp = ucbuffer[byte]; + ucbuffer[lbyte] = ucbuffer[byte+2]; + ucbuffer[lbyte+2] = tmp; + ucbuffer[lbyte+1] = ucbuffer[byte+1]; + } + } + else { + unsigned lbyte; + const unsigned bytes = sample * 4; + for(lbyte = byte = 0; byte < bytes; ) { + ucbuffer[lbyte++] = ucbuffer[byte++]; + ucbuffer[lbyte++] = ucbuffer[byte++]; + ucbuffer[lbyte++] = ucbuffer[byte++]; + byte++; + } + } +*/ + if(is_big_endian != is_big_endian_host) { + unsigned char tmp; + const unsigned bytes = sample * 4; + for(byte = 0; byte < bytes; byte += 4) { + tmp = ucbuffer[byte]; + ucbuffer[byte] = ucbuffer[byte+3]; + ucbuffer[byte+3] = tmp; + tmp = ucbuffer[byte+1]; + ucbuffer[byte+1] = ucbuffer[byte+2]; + ucbuffer[byte+2] = tmp; + } + } + if(is_big_endian) { + unsigned lbyte; + const unsigned bytes = sample * 4; + for(lbyte = byte = 0; byte < bytes; ) { + byte++; + ucbuffer[lbyte++] = ucbuffer[byte++]; + ucbuffer[lbyte++] = ucbuffer[byte++]; + ucbuffer[lbyte++] = ucbuffer[byte++]; + } + } + else { + unsigned lbyte; + const unsigned bytes = sample * 4; + for(lbyte = byte = 0; byte < bytes; ) { + ucbuffer[lbyte++] = ucbuffer[byte++]; + ucbuffer[lbyte++] = ucbuffer[byte++]; + ucbuffer[lbyte++] = ucbuffer[byte++]; + byte++; + } + } + if(fwrite(ucbuffer, 3, sample, fout) != sample) + return FLAC__STREAM_DECODER_WRITE_ABORT; + } + else { + assert(0); + } } return FLAC__STREAM_DECODER_WRITE_CONTINUE; } @@ -399,8 +474,8 @@ void metadata_callback(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaD stream_info->channels = metadata->data.stream_info.channels; stream_info->sample_rate = metadata->data.stream_info.sample_rate; - if(stream_info->bps != 8 && stream_info->bps != 16) { - fprintf(stderr, "ERROR: bits per sample is not 8 or 16\n"); + if(stream_info->bps != 8 && stream_info->bps != 16 && stream_info->bps != 24) { + fprintf(stderr, "ERROR: bits per sample is not 8/16/24\n"); stream_info->abort_flag = true; return; } diff --git a/src/flac/encode.c b/src/flac/encode.c index ac021c5..ad81a52 100644 --- a/src/flac/encode.c +++ b/src/flac/encode.c @@ -72,7 +72,7 @@ typedef struct { static bool is_big_endian_host; -static unsigned char ucbuffer[CHUNK_OF_SAMPLES*FLAC__MAX_CHANNELS*(FLAC__MAX_BITS_PER_SAMPLE>>3)]; +static unsigned char ucbuffer[CHUNK_OF_SAMPLES*FLAC__MAX_CHANNELS*((FLAC__MAX_BITS_PER_SAMPLE+7)/8)]; static signed char *scbuffer = (signed char *)ucbuffer; static uint16 *usbuffer = (uint16 *)ucbuffer; static int16 *ssbuffer = (int16 *)ucbuffer; @@ -489,7 +489,7 @@ bool init(encoder_wrapper_struct *encoder_wrapper) bool init_encoder(bool lax, bool do_mid_side, bool loose_mid_side, bool do_exhaustive_model_search, bool do_qlp_coeff_prec_search, unsigned rice_optimization_level, unsigned max_lpc_order, unsigned blocksize, unsigned qlp_coeff_precision, unsigned channels, unsigned bps, unsigned sample_rate, unsigned padding, encoder_wrapper_struct *encoder_wrapper) { - if(channels != 2 || bps > 16) + if(channels != 2 /*@@@ not necessary? || bps > 16*/) do_mid_side = loose_mid_side = false; if(encoder_wrapper->verify) { @@ -550,7 +550,7 @@ void format_input(unsigned wide_samples, bool is_big_endian, bool is_unsigned_sa if(is_unsigned_samples) { for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) for(channel = 0; channel < channels; channel++, sample++) - input[channel][wide_sample] = (int32)ucbuffer[sample] - 128; + input[channel][wide_sample] = (int32)ucbuffer[sample] - 0x80; } else { for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) @@ -558,7 +558,7 @@ void format_input(unsigned wide_samples, bool is_big_endian, bool is_unsigned_sa input[channel][wide_sample] = (int32)scbuffer[sample]; } } - else { + else if(bps == 16) { if(is_big_endian != is_big_endian_host) { unsigned char tmp; const unsigned bytes = wide_samples * channels * (bps >> 3); @@ -571,7 +571,7 @@ void format_input(unsigned wide_samples, bool is_big_endian, bool is_unsigned_sa if(is_unsigned_samples) { for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) for(channel = 0; channel < channels; channel++, sample++) - input[channel][wide_sample] = (int32)usbuffer[sample] - 32768; + input[channel][wide_sample] = (int32)usbuffer[sample] - 0x8000; } else { for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) @@ -579,6 +579,37 @@ void format_input(unsigned wide_samples, bool is_big_endian, bool is_unsigned_sa input[channel][wide_sample] = (int32)ssbuffer[sample]; } } + else if(bps == 24) { + if(!is_big_endian) { + unsigned char tmp; + const unsigned bytes = wide_samples * channels * (bps >> 3); + for(byte = 0; byte < bytes; byte += 3) { + tmp = ucbuffer[byte]; + ucbuffer[byte] = ucbuffer[byte+2]; + ucbuffer[byte+2] = tmp; + } + } + if(is_unsigned_samples) { + for(byte = sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) + for(channel = 0; channel < channels; channel++, sample++) { + input[channel][wide_sample] = ucbuffer[byte++]; input[channel][wide_sample] <<= 8; + input[channel][wide_sample] |= ucbuffer[byte++]; input[channel][wide_sample] <<= 8; + input[channel][wide_sample] |= ucbuffer[byte++]; + input[channel][wide_sample] -= 0x800000; + } + } + else { + for(byte = sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++) + for(channel = 0; channel < channels; channel++, sample++) { + input[channel][wide_sample] = scbuffer[byte++]; input[channel][wide_sample] <<= 8; + input[channel][wide_sample] |= ucbuffer[byte++]; input[channel][wide_sample] <<= 8; + input[channel][wide_sample] |= ucbuffer[byte++]; + } + } + } + else { + assert(0); + } if(encoder_wrapper->verify) { for(channel = 0; channel < channels; channel++) @@ -711,6 +742,9 @@ FLAC__StreamDecoderWriteStatus verify_write_callback(const FLAC__StreamDecoder * if(0 != memcmp(buffer[channel], encoder_wrapper->verify_fifo.original[channel], sizeof(int32) * decoder->blocksize)) { fprintf(stderr, "\nERROR: mismatch in decoded data, verify FAILED!\n"); fprintf(stderr, " Please submit a bug report to http://sourceforge.net/bugs/?func=addbug&group_id=13478\n"); +for(l=0;lblocksize;l++) +if(buffer[channel][l]!=encoder_wrapper->verify_fifo.original[channel][l])break; +fprintf(stderr,"@@@channel=%u, sample=%u, expected %08x, got %08x\n",channel,l,buffer[channel][l],encoder_wrapper->verify_fifo.original[channel][l]); return FLAC__STREAM_DECODER_WRITE_ABORT; } } diff --git a/src/flac/main.c b/src/flac/main.c index 45fff12..76415f8 100644 --- a/src/flac/main.c +++ b/src/flac/main.c @@ -240,8 +240,8 @@ int main(int argc, char *argv[]) return usage("ERROR: invalid number of channels '%u', must be > 0 and <= %u\n", format_channels, FLAC__MAX_CHANNELS); } if(format_bps >= 0) { - if(format_bps != 8 && format_bps != 16) - return usage("ERROR: invalid bits per sample '%u' (must be 8 or 16)\n", format_bps); + if(format_bps != 8 && format_bps != 16 && format_bps != 24) + return usage("ERROR: invalid bits per sample '%u' (must be 8/16/24)\n", format_bps); } if(format_sample_rate >= 0) { if(format_sample_rate == 0 || (unsigned)format_sample_rate > FLAC__MAX_SAMPLE_RATE) diff --git a/src/libFLAC/encoder.c b/src/libFLAC/encoder.c index 53b670d..27bfc32 100644 --- a/src/libFLAC/encoder.c +++ b/src/libFLAC/encoder.c @@ -263,8 +263,10 @@ FLAC__EncoderState FLAC__encoder_init(FLAC__Encoder *encoder, FLAC__EncoderWrite if(encoder->do_mid_side_stereo && encoder->channels != 2) return encoder->state = FLAC__ENCODER_MID_SIDE_CHANNELS_MISMATCH; +/*@@@ necessary? if(encoder->do_mid_side_stereo && encoder->bits_per_sample > 16) return encoder->state = FLAC__ENCODER_MID_SIDE_SAMPLE_SIZE_MISMATCH; +*/ if(encoder->loose_mid_side_stereo && !encoder->do_mid_side_stereo) return encoder->state = FLAC__ENCODER_ILLEGAL_MID_SIDE_FORCE; -- 2.7.4