From fe975fe17574bf2484bfc2a2e3f60b6d4feb6afc Mon Sep 17 00:00:00 2001 From: Josh Coalson Date: Thu, 20 Sep 2007 00:04:13 +0000 Subject: [PATCH] code reorg in prep for simplification, more format support --- src/flac/encode.c | 377 +++++++++++++++++++++------------------------- src/flac/encode.h | 4 +- src/flac/main.c | 103 ++++++------- src/flac/utils.h | 2 + 4 files changed, 224 insertions(+), 262 deletions(-) diff --git a/src/flac/encode.c b/src/flac/encode.c index 8d243499..ca7ea4c3 100644 --- a/src/flac/encode.c +++ b/src/flac/encode.c @@ -147,11 +147,10 @@ static void print_stats(const EncoderSession *encoder_session); static void print_error_with_init_status(const EncoderSession *e, const char *message, FLAC__StreamEncoderInitStatus init_status); static void print_error_with_state(const EncoderSession *e, const char *message); static void print_verify_error(EncoderSession *e); -static FLAC__bool read_little_endian_uint16(FILE *f, FLAC__uint16 *val, FLAC__bool eof_ok, const char *fn); -static FLAC__bool read_little_endian_uint32(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn); -static FLAC__bool read_big_endian_uint16(FILE *f, FLAC__uint16 *val, FLAC__bool eof_ok, const char *fn); -static FLAC__bool read_big_endian_uint32(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn); -static FLAC__bool read_sane_extended(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn); +static FLAC__bool read_bytes(FILE *f, FLAC__byte *buf, size_t n, FLAC__bool eof_ok, const char *fn); +static FLAC__bool read_uint16(FILE *f, FLAC__bool big_endian, FLAC__uint16 *val, const char *fn); +static FLAC__bool read_uint32(FILE *f, FLAC__bool big_endian, FLAC__uint32 *val, const char *fn); +static FLAC__bool read_sane_extended(FILE *f, FLAC__uint32 *val, const char *fn); static FLAC__bool fskip_ahead(FILE *f, FLAC__uint64 offset); static unsigned count_channel_mask_bits(FLAC__uint32 mask); #if 0 @@ -161,15 +160,15 @@ static FLAC__uint32 limit_channel_mask(FLAC__uint32 mask, unsigned channels); /* * public routines */ -int flac__encode_aif(FILE *infile, off_t infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, wav_encode_options_t options, FLAC__bool is_aifc) +int flac__encode_aiff(FILE *infile, off_t infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, wav_encode_options_t options, FLAC__bool is_aifc) { EncoderSession encoder_session; + unsigned channels = 0, bps = 0, sample_rate = 0, shift = 0, sample_frames = 0; + size_t channel_map[FLAC__MAX_CHANNELS]; FLAC__uint16 x; FLAC__uint32 xx; - unsigned int channels= 0U, bps= 0U, shift= 0U, sample_rate= 0U, sample_frames= 0U; - size_t channel_map[FLAC__MAX_CHANNELS]; - FLAC__bool got_comm_chunk= false, got_ssnd_chunk= false; - int info_align_carry= -1, info_align_zero= -1; + FLAC__bool got_comm_chunk = false, got_ssnd_chunk = false; + int info_align_carry = -1, info_align_zero = -1; FLAC__bool is_big_endian_pcm = true; (void)infilesize; /* silence compiler warning about unused parameter */ @@ -209,42 +208,40 @@ int flac__encode_aif(FILE *infile, off_t infilesize, const char *infilename, con } } - /* lookahead[] already has "FORMxxxxAIFF", do sub-chunks */ - - while(1) { - size_t c= 0U; + /* + * lookahead[] already has "FORMxxxxAIFF", do chunks + */ + while(!feof(infile)) { char chunk_id[5] = { '\0', '\0', '\0', '\0', '\0' }; /* one extra byte for terminating NUL so we can also treat it like a C string */ - - /* chunk identifier; really conservative about behavior of fread() and feof() */ - if(feof(infile) || ((c= fread(chunk_id, 1U, 4U, infile)), c==0U && feof(infile))) - break; - else if(c<4U || feof(infile)) { + if(!read_bytes(infile, (FLAC__byte*)chunk_id, 4, /*eof_ok=*/true, encoder_session.inbasefilename)) { flac__utils_printf(stderr, 1, "%s: ERROR: incomplete chunk identifier\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } + if(feof(infile)) + break; - if(got_comm_chunk==false && !memcmp(chunk_id, "COMM", 4)) { /* common chunk */ + if(!memcmp(chunk_id, "COMM", 4) && !got_comm_chunk) { /* common chunk */ unsigned long skip; const FLAC__uint32 minimum_comm_size = (is_aifc? 22 : 18); /* COMM chunk size */ - if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + if(!read_uint32(infile, /*big_endian=*/true, &xx, encoder_session.inbasefilename)) return EncoderSession_finish_error(&encoder_session); - else if(xxFLAC__MAX_CHANNELS) { + else if(x ==0U || x>FLAC__MAX_CHANNELS) { flac__utils_printf(stderr, 1, "%s: ERROR: unsupported number channels %u\n", encoder_session.inbasefilename, (unsigned int)x); return EncoderSession_finish_error(&encoder_session); } @@ -256,15 +253,15 @@ int flac__encode_aif(FILE *infile, off_t infilesize, const char *infilename, con flac__utils_printf(stderr, 1, "%s: ERROR: file has %u channels, must be 2 for --sector-align\n", encoder_session.inbasefilename, (unsigned int)x); return EncoderSession_finish_error(&encoder_session); } - channels= x; + channels = x; /* number of sample frames */ - if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + if(!read_uint32(infile, /*big_endian=*/true, &xx, encoder_session.inbasefilename)) return EncoderSession_finish_error(&encoder_session); - sample_frames= xx; + sample_frames = xx; /* bits per sample */ - if(!read_big_endian_uint16(infile, &x, false, encoder_session.inbasefilename)) + if(!read_uint16(infile, /*big_endian=*/true, &x, encoder_session.inbasefilename)) return EncoderSession_finish_error(&encoder_session); else if(x<4U || x>24U) { flac__utils_printf(stderr, 1, "%s: ERROR: unsupported bits-per-sample %u\n", encoder_session.inbasefilename, (unsigned int)x); @@ -274,12 +271,12 @@ int flac__encode_aif(FILE *infile, off_t infilesize, const char *infilename, con flac__utils_printf(stderr, 1, "%s: ERROR: file has %u bits-per-sample, must be 16 for --sector-align\n", encoder_session.inbasefilename, (unsigned int)x); return EncoderSession_finish_error(&encoder_session); } - bps= x; - shift= (bps%8)? 8-(bps%8) : 0; /* SSND data is always byte-aligned, left-justified but format_input() will double-check */ - bps+= shift; + bps = x; + shift = (bps%8)? 8-(bps%8) : 0; /* SSND data is always byte-aligned, left-justified but format_input() will double-check */ + bps += shift; /* sample rate */ - if(!read_sane_extended(infile, &xx, false, encoder_session.inbasefilename)) + if(!read_sane_extended(infile, &xx, encoder_session.inbasefilename)) return EncoderSession_finish_error(&encoder_session); else if(!FLAC__format_sample_rate_is_valid(xx)) { flac__utils_printf(stderr, 1, "%s: ERROR: unsupported sample rate %u\n", encoder_session.inbasefilename, (unsigned int)xx); @@ -289,11 +286,11 @@ int flac__encode_aif(FILE *infile, off_t infilesize, const char *infilename, con flac__utils_printf(stderr, 1, "%s: ERROR: file's sample rate is %u, must be 44100 for --sector-align\n", encoder_session.inbasefilename, (unsigned int)xx); return EncoderSession_finish_error(&encoder_session); } - sample_rate= xx; + sample_rate = xx; /* check compression type for AIFF-C */ if(is_aifc) { - if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + if(!read_uint32(infile, /*big_endian=*/true, &xx, encoder_session.inbasefilename)) return EncoderSession_finish_error(&encoder_session); if(xx == 0x736F7774) /* "sowt" */ is_big_endian_pcm = false; @@ -349,46 +346,46 @@ int flac__encode_aif(FILE *infile, off_t infilesize, const char *infilename, con encoder_session.skip = (FLAC__uint64)options.common.skip_specification.value.samples; FLAC__ASSERT(!options.common.sector_align || encoder_session.skip == 0); - got_comm_chunk= true; + got_comm_chunk = true; } - else if(got_ssnd_chunk==false && !memcmp(chunk_id, "SSND", 4)) { /* sound data chunk */ - unsigned int offset= 0U, block_size= 0U, align_remainder= 0U, data_bytes; - const size_t bytes_per_frame= channels*(bps>>3); + else if(!memcmp(chunk_id, "SSND", 4) && !got_ssnd_chunk) { /* sound data chunk */ + unsigned offset = 0, block_size = 0, align_remainder = 0, data_bytes; FLAC__uint64 total_samples_in_input, trim = 0; - FLAC__bool pad= false; + FLAC__bool pad = false; + const size_t bytes_per_wide_sample = channels * (bps >> 3); - if(got_comm_chunk==false) { + if(got_comm_chunk == false) { flac__utils_printf(stderr, 1, "%s: ERROR: got 'SSND' chunk before 'COMM' chunk\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } /* SSND chunk size */ - if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + if(!read_uint32(infile, /*big_endian=*/true, &xx, encoder_session.inbasefilename)) return EncoderSession_finish_error(&encoder_session); if(options.common.ignore_chunk_sizes) { FLAC__ASSERT(!options.common.sector_align); - data_bytes = (unsigned)(-(int)bytes_per_frame); /* max out data_bytes; we'll use EOF as signal to stop reading */ + data_bytes = (unsigned)(-(int)bytes_per_wide_sample); /* max out data_bytes; we'll use EOF as signal to stop reading */ } else { - data_bytes= xx; + data_bytes = xx; data_bytes-= 8U; /* discount the offset and block size fields */ } - pad= (data_bytes & 1U) ? true : false; + pad = (data_bytes & 1U) ? true : false; /* offset */ - if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + if(!read_uint32(infile, /*big_endian=*/true, &xx, encoder_session.inbasefilename)) return EncoderSession_finish_error(&encoder_session); - offset= xx; + offset = xx; data_bytes-= offset; /* block size */ - if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + if(!read_uint32(infile, /*big_endian=*/true, &xx, encoder_session.inbasefilename)) return EncoderSession_finish_error(&encoder_session); else if(xx!=0U) { flac__utils_printf(stderr, 1, "%s: ERROR: block size is %u; must be 0\n", encoder_session.inbasefilename, (unsigned int)xx); return EncoderSession_finish_error(&encoder_session); } - block_size= xx; + block_size = xx; /* skip any SSND offset bytes */ FLAC__ASSERT(offset<=LONG_MAX); @@ -396,14 +393,14 @@ int flac__encode_aif(FILE *infile, off_t infilesize, const char *infilename, con flac__utils_printf(stderr, 1, "%s: ERROR: skipping offset in SSND chunk\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } - if(data_bytes!=(sample_frames*bytes_per_frame)) { + if(data_bytes!=(sample_frames*bytes_per_wide_sample)) { flac__utils_printf(stderr, 1, "%s: ERROR: SSND chunk size inconsistent with sample frame count\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } /* *options.common.align_reservoir_samples will be 0 unless --sector-align is used */ FLAC__ASSERT(options.common.sector_align || *options.common.align_reservoir_samples == 0); - total_samples_in_input = data_bytes / bytes_per_frame + *options.common.align_reservoir_samples; + total_samples_in_input = data_bytes / bytes_per_wide_sample + *options.common.align_reservoir_samples; /* * now that we know the input size, canonicalize the @@ -415,30 +412,30 @@ int flac__encode_aif(FILE *infile, off_t infilesize, const char *infilename, con FLAC__ASSERT(!options.common.sector_align || encoder_session.until == 0); if(encoder_session.skip>0U) { - if(!fskip_ahead(infile, encoder_session.skip*bytes_per_frame)) { + if(!fskip_ahead(infile, encoder_session.skip*bytes_per_wide_sample)) { flac__utils_printf(stderr, 1, "%s: ERROR during read while skipping samples\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } } - data_bytes-= (unsigned int)encoder_session.skip*bytes_per_frame; /*@@@ WATCHOUT: 4GB limit */ + data_bytes-= (unsigned int)encoder_session.skip*bytes_per_wide_sample; /*@@@ WATCHOUT: 4GB limit */ if(options.common.ignore_chunk_sizes) { - encoder_session.total_samples_to_encode= 0; + encoder_session.total_samples_to_encode = 0; flac__utils_printf(stderr, 2, "(No runtime statistics possible; please wait for encoding to finish...)\n"); FLAC__ASSERT(0 == encoder_session.until); } else { - encoder_session.total_samples_to_encode= total_samples_in_input - encoder_session.skip; + encoder_session.total_samples_to_encode = total_samples_in_input - encoder_session.skip; } if(encoder_session.until > 0) { trim = total_samples_in_input - encoder_session.until; FLAC__ASSERT(total_samples_in_input > 0); FLAC__ASSERT(!options.common.sector_align); - data_bytes-= (unsigned int)trim*bytes_per_frame; + data_bytes-= (unsigned int)trim*bytes_per_wide_sample; encoder_session.total_samples_to_encode-= trim; } if(options.common.sector_align) { - align_remainder= (unsigned int)(encoder_session.total_samples_to_encode % 588U); + align_remainder = (unsigned int)(encoder_session.total_samples_to_encode % 588U); if(options.common.is_last_file) encoder_session.total_samples_to_encode+= (588U-align_remainder); /* will pad with zeroes */ else @@ -446,7 +443,7 @@ int flac__encode_aif(FILE *infile, off_t infilesize, const char *infilename, con } /* +54 for the size of the AIFF headers; this is just an estimate for the progress indicator and doesn't need to be exact */ - encoder_session.unencoded_size= encoder_session.total_samples_to_encode*bytes_per_frame+54; + encoder_session.unencoded_size = encoder_session.total_samples_to_encode*bytes_per_wide_sample+54; if(!EncoderSession_init_encoder(&encoder_session, options.common, /*channel_mask=*/0, channels, bps-shift, sample_rate, options.foreign_metadata, /*flac_decoder_data=*/0)) return EncoderSession_finish_error(&encoder_session); @@ -463,18 +460,18 @@ int flac__encode_aif(FILE *infile, off_t infilesize, const char *infilename, con /* decrement the data_bytes counter if we need to align the file */ if(options.common.sector_align) { if(options.common.is_last_file) - *options.common.align_reservoir_samples= 0U; + *options.common.align_reservoir_samples = 0U; else { - *options.common.align_reservoir_samples= align_remainder; - data_bytes-= (*options.common.align_reservoir_samples)*bytes_per_frame; + *options.common.align_reservoir_samples = align_remainder; + data_bytes-= (*options.common.align_reservoir_samples)*bytes_per_wide_sample; } } /* now do from the file */ while(data_bytes>0) { - size_t bytes_read= fread(ucbuffer_, 1U, min(data_bytes, CHUNK_OF_SAMPLES*bytes_per_frame), infile); + size_t bytes_read = fread(ucbuffer_, 1U, min(data_bytes, CHUNK_OF_SAMPLES*bytes_per_wide_sample), infile); - if(bytes_read==0U) { + if(bytes_read == 0U) { if(ferror(infile)) { flac__utils_printf(stderr, 1, "%s: ERROR during read\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); @@ -488,16 +485,16 @@ int flac__encode_aif(FILE *infile, off_t infilesize, const char *infilename, con if(encoder_session.treat_warnings_as_errors) return EncoderSession_finish_error(&encoder_session); } - data_bytes= 0; + data_bytes = 0; } } else { - if(bytes_read % bytes_per_frame != 0U) { + if(bytes_read % bytes_per_wide_sample != 0U) { flac__utils_printf(stderr, 1, "%s: ERROR: got partial sample\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } else { - unsigned int frames= bytes_read/bytes_per_frame; + unsigned int frames = bytes_read/bytes_per_wide_sample; if(!format_input(input_, frames, is_big_endian_pcm, /*is_unsigned_samples=*/false, channels, bps, shift, channel_map)) return EncoderSession_finish_error(&encoder_session); @@ -513,7 +510,7 @@ int flac__encode_aif(FILE *infile, off_t infilesize, const char *infilename, con if(trim>0) { FLAC__ASSERT(!options.common.sector_align); - if(!fskip_ahead(infile, trim*bytes_per_frame)) { + if(!fskip_ahead(infile, trim*bytes_per_wide_sample)) { flac__utils_printf(stderr, 1, "%s: ERROR during read while skipping samples\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } @@ -522,13 +519,13 @@ int flac__encode_aif(FILE *infile, off_t infilesize, const char *infilename, con /* now read unaligned samples into reservoir or pad with zeroes if necessary */ if(options.common.sector_align) { if(options.common.is_last_file) { - unsigned int pad_frames= 588U-align_remainder; + unsigned int pad_frames = 588U-align_remainder; if(pad_frames<588U) { unsigned int i; - info_align_zero= pad_frames; - for(i= 0U; i 0) { - size_t bytes_read= fread(ucbuffer_, 1U, (*options.common.align_reservoir_samples)*bytes_per_frame, infile); + size_t bytes_read = fread(ucbuffer_, 1U, (*options.common.align_reservoir_samples)*bytes_per_wide_sample, infile); FLAC__ASSERT(CHUNK_OF_SAMPLES>=588U); - if(bytes_read==0U && ferror(infile)) { + if(bytes_read == 0U && ferror(infile)) { flac__utils_printf(stderr, 1, "%s: ERROR during read\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } - else if(bytes_read != (*options.common.align_reservoir_samples) * bytes_per_frame) { + else if(bytes_read != (*options.common.align_reservoir_samples) * bytes_per_wide_sample) { flac__utils_printf(stderr, 1, "%s: WARNING: unexpected EOF; read %u bytes; expected %u samples, got %u samples\n", encoder_session.inbasefilename, (unsigned int)bytes_read, (unsigned int)encoder_session.total_samples_to_encode, (unsigned int)encoder_session.samples_written); if(encoder_session.treat_warnings_as_errors) return EncoderSession_finish_error(&encoder_session); } else { - info_align_carry= *options.common.align_reservoir_samples; + info_align_carry = *options.common.align_reservoir_samples; if(!format_input(options.common.align_reservoir, *options.common.align_reservoir_samples, is_big_endian_pcm, /*is_unsigned_samples=*/false, channels, bps, shift, channel_map)) return EncoderSession_finish_error(&encoder_session); } @@ -560,45 +557,50 @@ int flac__encode_aif(FILE *infile, off_t infilesize, const char *infilename, con } } - if(pad==true) { + if(pad == true) { unsigned char tmp; - if(fread(&tmp, 1U, 1U, infile)<1U) { + if(fread(&tmp, 1U, 1U, infile) < 1U) { flac__utils_printf(stderr, 1, "%s: ERROR during read of SSND pad byte\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } } - got_ssnd_chunk= true; + got_ssnd_chunk = true; } - else { /* other chunk */ + else { + if(!memcmp(chunk_id, "SSND", 4) && !got_comm_chunk) { + flac__utils_printf(stderr, 1, "%s: ERROR: got 'SSND' chunk before 'COMM' chunk\n", encoder_session.inbasefilename); + return EncoderSession_finish_error(&encoder_session); + } + if(!options.foreign_metadata) { if(!memcmp(chunk_id, "COMM", 4)) flac__utils_printf(stderr, 1, "%s: WARNING: skipping extra 'COMM' chunk (use --keep-foreign-metadata to keep)\n", encoder_session.inbasefilename); else if(!memcmp(chunk_id, "SSND", 4)) flac__utils_printf(stderr, 1, "%s: WARNING: skipping extra 'SSND' chunk (use --keep-foreign-metadata to keep)\n", encoder_session.inbasefilename); - else if(!options.foreign_metadata) + else flac__utils_printf(stderr, 1, "%s: WARNING: skipping unknown chunk '%s' (use --keep-foreign-metadata to keep)\n", encoder_session.inbasefilename, chunk_id); if(encoder_session.treat_warnings_as_errors) return EncoderSession_finish_error(&encoder_session); } /* chunk size */ - if(!read_big_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + if(!read_uint32(infile, /*big_endian=*/true, &xx, encoder_session.inbasefilename)) return EncoderSession_finish_error(&encoder_session); else { - unsigned long skip= xx+(xx & 1U); + unsigned long skip = xx+(xx & 1U); FLAC__ASSERT(skip<=LONG_MAX); if(!fskip_ahead(infile, skip)) { - fprintf(stderr, "%s: ERROR during read while skipping over unknown chunk\n", encoder_session.inbasefilename); + flac__utils_printf(stderr, 1, "%s: ERROR during read while skipping over unsupported chunk\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } } } } - if(got_ssnd_chunk==false && sample_frames!=0U) { + if(got_ssnd_chunk == false && sample_frames != 0U) { flac__utils_printf(stderr, 1, "%s: ERROR: missing SSND chunk\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } @@ -606,22 +608,20 @@ int flac__encode_aif(FILE *infile, off_t infilesize, const char *infilename, con return EncoderSession_finish_ok(&encoder_session, info_align_carry, info_align_zero, options.foreign_metadata); } -int flac__encode_wav(FILE *infile, off_t infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, wav_encode_options_t options) +int flac__encode_wave(FILE *infile, off_t infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, wav_encode_options_t options) { EncoderSession encoder_session; FLAC__bool is_unsigned_samples = false; unsigned channels = 0, bps = 0, sample_rate = 0, shift = 0; - size_t bytes_read; size_t channel_map[FLAC__MAX_CHANNELS]; FLAC__uint16 x, format; /* format is the wFormatTag word from the 'fmt ' chunk */ FLAC__uint32 xx, channel_mask = 0; FLAC__bool got_fmt_chunk = false, got_data_chunk = false; - unsigned align_remainder = 0; int info_align_carry = -1, info_align_zero = -1; - (void)infilesize; - (void)lookahead; - (void)lookahead_length; + (void)infilesize; /* silence compiler warning about unused parameter */ + (void)lookahead; /* silence compiler warning about unused parameter */ + (void)lookahead_length; /* silence compiler warning about unused parameter */ if(! EncoderSession_construct( @@ -657,14 +657,18 @@ int flac__encode_wav(FILE *infile, off_t infilesize, const char *infilename, con } /* - * lookahead[] already has "RIFFxxxxWAVE", do sub-chunks + * lookahead[] already has "RIFFxxxxWAVE", do chunks */ while(!feof(infile)) { - if(!read_little_endian_uint32(infile, &xx, true, encoder_session.inbasefilename)) + char chunk_id[5] = { '\0', '\0', '\0', '\0', '\0' }; /* one extra byte for terminating NUL so we can also treat it like a C string */ + if(!read_bytes(infile, (FLAC__byte*)chunk_id, 4, /*eof_ok=*/true, encoder_session.inbasefilename)) { + flac__utils_printf(stderr, 1, "%s: ERROR: incomplete chunk identifier\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); + } if(feof(infile)) break; - if(xx == 0x20746d66 && !got_fmt_chunk) { /* "fmt " */ + + if(!memcmp(chunk_id, "fmt ", 4) && !got_fmt_chunk) { /* format chunk */ unsigned block_align, data_bytes; /* see @@ -673,7 +677,7 @@ int flac__encode_wav(FILE *infile, off_t infilesize, const char *infilename, con * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/audio_r/hh/Audio_r/aud-prop_d40f094e-44f9-4baa-8a15-03e4fb369501.xml.asp * * WAVEFORMAT is - * 4 byte: subchunk size + * 4 byte: chunk size * 2 byte: format type: 1 for WAVE_FORMAT_PCM, 65534 for WAVE_FORMAT_EXTENSIBLE * 2 byte: # channels * 4 byte: sample rate (Hz) @@ -698,23 +702,23 @@ int flac__encode_wav(FILE *infile, off_t infilesize, const char *infilename, con * Data is supposed to be unsigned for bps <= 8 else signed. */ - /* fmt sub-chunk size */ - if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + /* fmt chunk size */ + if(!read_uint32(infile, /*big_endian=*/false, &xx, encoder_session.inbasefilename)) return EncoderSession_finish_error(&encoder_session); data_bytes = xx; if(data_bytes < 16) { - flac__utils_printf(stderr, 1, "%s: ERROR: found non-standard 'fmt ' sub-chunk which has length = %u\n", encoder_session.inbasefilename, data_bytes); + flac__utils_printf(stderr, 1, "%s: ERROR: found non-standard 'fmt ' chunk which has length = %u\n", encoder_session.inbasefilename, data_bytes); return EncoderSession_finish_error(&encoder_session); } /* format code */ - if(!read_little_endian_uint16(infile, &format, false, encoder_session.inbasefilename)) + if(!read_uint16(infile, /*big_endian=*/false, &format, encoder_session.inbasefilename)) return EncoderSession_finish_error(&encoder_session); if(format != 1 /*WAVE_FORMAT_PCM*/ && format != 65534 /*WAVE_FORMAT_EXTENSIBLE*/) { flac__utils_printf(stderr, 1, "%s: ERROR: unsupported format type %u\n", encoder_session.inbasefilename, (unsigned)format); return EncoderSession_finish_error(&encoder_session); } /* number of channels */ - if(!read_little_endian_uint16(infile, &x, false, encoder_session.inbasefilename)) + if(!read_uint16(infile, /*big_endian=*/false, &x, encoder_session.inbasefilename)) return EncoderSession_finish_error(&encoder_session); channels = (unsigned)x; if(channels == 0 || channels > FLAC__MAX_CHANNELS) { @@ -726,7 +730,7 @@ int flac__encode_wav(FILE *infile, off_t infilesize, const char *infilename, con return EncoderSession_finish_error(&encoder_session); } /* sample rate */ - if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + if(!read_uint32(infile, /*big_endian=*/false, &xx, encoder_session.inbasefilename)) return EncoderSession_finish_error(&encoder_session); sample_rate = xx; if(!FLAC__format_sample_rate_is_valid(sample_rate)) { @@ -738,14 +742,14 @@ int flac__encode_wav(FILE *infile, off_t infilesize, const char *infilename, con return EncoderSession_finish_error(&encoder_session); } /* avg bytes per second (ignored) */ - if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + if(!read_uint32(infile, /*big_endian=*/false, &xx, encoder_session.inbasefilename)) return EncoderSession_finish_error(&encoder_session); /* block align */ - if(!read_little_endian_uint16(infile, &x, false, encoder_session.inbasefilename)) + if(!read_uint16(infile, /*big_endian=*/false, &x, encoder_session.inbasefilename)) return EncoderSession_finish_error(&encoder_session); block_align = (unsigned)x; /* bits per sample */ - if(!read_little_endian_uint16(infile, &x, false, encoder_session.inbasefilename)) + if(!read_uint16(infile, /*big_endian=*/false, &x, encoder_session.inbasefilename)) return EncoderSession_finish_error(&encoder_session); bps = (unsigned)x; is_unsigned_samples = (bps <= 8); @@ -796,14 +800,14 @@ int flac__encode_wav(FILE *infile, off_t infilesize, const char *infilename, con return EncoderSession_finish_error(&encoder_session); } /* cbSize */ - if(!read_little_endian_uint16(infile, &x, false, encoder_session.inbasefilename)) + if(!read_uint16(infile, /*big_endian=*/false, &x, encoder_session.inbasefilename)) return EncoderSession_finish_error(&encoder_session); if(x < 22) { flac__utils_printf(stderr, 1, "%s: ERROR: invalid WAVEFORMATEXTENSIBLE chunk with cbSize %u\n", encoder_session.inbasefilename, (unsigned)x); return EncoderSession_finish_error(&encoder_session); } /* valid bps */ - if(!read_little_endian_uint16(infile, &x, false, encoder_session.inbasefilename)) + if(!read_uint16(infile, /*big_endian=*/false, &x, encoder_session.inbasefilename)) return EncoderSession_finish_error(&encoder_session); if((unsigned)x > bps) { flac__utils_printf(stderr, 1, "%s: ERROR: invalid WAVEFORMATEXTENSIBLE chunk with wValidBitsPerSample (%u) > wBitsPerSample (%u)\n", encoder_session.inbasefilename, (unsigned)x, bps); @@ -811,7 +815,7 @@ int flac__encode_wav(FILE *infile, off_t infilesize, const char *infilename, con } shift = bps - (unsigned)x; /* channel mask */ - if(!read_little_endian_uint32(infile, &channel_mask, false, encoder_session.inbasefilename)) + if(!read_uint32(infile, /*big_endian=*/false, &channel_mask, encoder_session.inbasefilename)) return EncoderSession_finish_error(&encoder_session); /* for mono/stereo and unassigned channels, we fake the mask */ if(channel_mask == 0) { @@ -872,7 +876,7 @@ int flac__encode_wav(FILE *infile, off_t infilesize, const char *infilename, con } #endif else { - flac__utils_printf(stderr, 1, "%s: ERROR: WAVEFORMATEXTENSIBLE chunk with unsupported channel mask=0x%04X\n", encoder_session.inbasefilename, (unsigned)channel_mask); + flac__utils_printf(stderr, 1, "%s: ERROR: WAVEFORMATEXTENSIBLE chunk with unsupported channel mask=0x%04X\n\nUse --channel-map=none option to store channels in current order; FLAC files\nmust also be decoded with --channel-map=none to restore correct order.\n", encoder_session.inbasefilename, (unsigned)channel_mask); return EncoderSession_finish_error(&encoder_session); } if(!options.common.channel_map_none) { @@ -895,7 +899,7 @@ int flac__encode_wav(FILE *infile, off_t infilesize, const char *infilename, con #endif } /* first part of GUID */ - if(!read_little_endian_uint16(infile, &x, false, encoder_session.inbasefilename)) + if(!read_uint16(infile, /*big_endian=*/false, &x, encoder_session.inbasefilename)) return EncoderSession_finish_error(&encoder_session); if(x != 1) { flac__utils_printf(stderr, 1, "%s: ERROR: unsupported WAVEFORMATEXTENSIBLE chunk with non-PCM format %u\n", encoder_session.inbasefilename, (unsigned)x); @@ -913,7 +917,7 @@ int flac__encode_wav(FILE *infile, off_t infilesize, const char *infilename, con return EncoderSession_finish_error(&encoder_session); } - /* skip any extra data in the fmt sub-chunk */ + /* skip any extra data in the fmt chunk */ if(!fskip_ahead(infile, data_bytes)) { flac__utils_printf(stderr, 1, "%s: ERROR during read while skipping over extra 'fmt' data\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); @@ -930,14 +934,14 @@ int flac__encode_wav(FILE *infile, off_t infilesize, const char *infilename, con got_fmt_chunk = true; } - else if(xx == 0x61746164 && !got_data_chunk && got_fmt_chunk) { /* "data" */ + else if(!memcmp(chunk_id, "data", 4) && !got_data_chunk && got_fmt_chunk) { /* data chunk */ + unsigned align_remainder = 0, data_bytes; FLAC__uint64 total_samples_in_input, trim = 0; FLAC__bool pad = false; const size_t bytes_per_wide_sample = channels * (bps >> 3); - unsigned data_bytes; /* data size */ - if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + if(!read_uint32(infile, /*big_endian=*/false, &xx, encoder_session.inbasefilename)) return EncoderSession_finish_error(&encoder_session); if(options.common.ignore_chunk_sizes) { FLAC__ASSERT(!options.common.sector_align); @@ -946,7 +950,7 @@ int flac__encode_wav(FILE *infile, off_t infilesize, const char *infilename, con else { data_bytes = xx; if(0 == data_bytes) { - flac__utils_printf(stderr, 1, "%s: ERROR: 'data' subchunk has size of 0\n", encoder_session.inbasefilename); + flac__utils_printf(stderr, 1, "%s: ERROR: 'data' chunk has size of 0\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } } @@ -1029,7 +1033,7 @@ int flac__encode_wav(FILE *infile, off_t infilesize, const char *infilename, con * now do from the file */ while(data_bytes > 0) { - bytes_read = fread(ucbuffer_, sizeof(unsigned char), min(data_bytes, CHUNK_OF_SAMPLES * bytes_per_wide_sample), infile); + size_t bytes_read = fread(ucbuffer_, sizeof(unsigned char), min(data_bytes, CHUNK_OF_SAMPLES * bytes_per_wide_sample), infile); if(bytes_read == 0) { if(ferror(infile)) { flac__utils_printf(stderr, 1, "%s: ERROR during read\n", encoder_session.inbasefilename); @@ -1095,6 +1099,7 @@ int flac__encode_wav(FILE *infile, off_t infilesize, const char *infilename, con } else { if(*options.common.align_reservoir_samples > 0) { + size_t bytes_read; FLAC__ASSERT(CHUNK_OF_SAMPLES >= 588); bytes_read = fread(ucbuffer_, sizeof(unsigned char), (*options.common.align_reservoir_samples) * bytes_per_wide_sample, infile); if(bytes_read == 0 && ferror(infile)) { @@ -1127,31 +1132,31 @@ int flac__encode_wav(FILE *infile, off_t infilesize, const char *infilename, con got_data_chunk = true; } else { - if(xx == 0x61746164 && !got_fmt_chunk) { /* "data" */ - flac__utils_printf(stderr, 1, "%s: ERROR: got 'data' sub-chunk before 'fmt' sub-chunk\n", encoder_session.inbasefilename); + if(!memcmp(chunk_id, "data", 4) && !got_fmt_chunk) { + flac__utils_printf(stderr, 1, "%s: ERROR: got 'data' chunk before 'fmt' chunk\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } if(!options.foreign_metadata) { - if(xx == 0x20746d66 && got_fmt_chunk) /* "fmt " */ - flac__utils_printf(stderr, 1, "%s: WARNING: skipping extra 'fmt ' sub-chunk (use --keep-foreign-metadata to keep)\n", encoder_session.inbasefilename); - else if(xx == 0x61746164) /* "data" */ - flac__utils_printf(stderr, 1, "%s: WARNING: skipping extra 'data' sub-chunk (use --keep-foreign-metadata to keep)\n", encoder_session.inbasefilename); + if(!memcmp(chunk_id, "fmt ", 4) && got_fmt_chunk) + flac__utils_printf(stderr, 1, "%s: WARNING: skipping extra 'fmt ' chunk (use --keep-foreign-metadata to keep)\n", encoder_session.inbasefilename); + else if(!memcmp(chunk_id, "data", 4)) + flac__utils_printf(stderr, 1, "%s: WARNING: skipping extra 'data' chunk (use --keep-foreign-metadata to keep)\n", encoder_session.inbasefilename); else - flac__utils_printf(stderr, 1, "%s: WARNING: skipping unknown sub-chunk '%c%c%c%c' (use --keep-foreign-metadata to keep)\n", encoder_session.inbasefilename, (char)(xx&255), (char)((xx>>8)&255), (char)((xx>>16)&255), (char)(xx>>24)); + flac__utils_printf(stderr, 1, "%s: WARNING: skipping unknown chunk '%s' (use --keep-foreign-metadata to keep)\n", encoder_session.inbasefilename, chunk_id); if(encoder_session.treat_warnings_as_errors) return EncoderSession_finish_error(&encoder_session); } - /* sub-chunk size */ - if(!read_little_endian_uint32(infile, &xx, false, encoder_session.inbasefilename)) + /* chunk size */ + if(!read_uint32(infile, /*big_endian=*/false, &xx, encoder_session.inbasefilename)) return EncoderSession_finish_error(&encoder_session); else { unsigned long skip = xx+(xx & 1U); FLAC__ASSERT(skip<=LONG_MAX); if(!fskip_ahead(infile, skip)) { - flac__utils_printf(stderr, 1, "%s: ERROR during read while skipping over unsupported sub-chunk\n", encoder_session.inbasefilename); + flac__utils_printf(stderr, 1, "%s: ERROR during read while skipping over unsupported chunk\n", encoder_session.inbasefilename); return EncoderSession_finish_error(&encoder_session); } } @@ -1632,6 +1637,9 @@ FLAC__bool EncoderSession_construct(EncoderSession *e, FLAC__bool use_ogg, FLAC_ e->outfilename = outfilename; e->skip = 0; /* filled in later after the sample_rate is known */ + e->channels = 0; + e->bits_per_sample = 0; + e->sample_rate = 0; e->unencoded_size = 0; e->total_samples_to_encode = 0; e->bytes_written = 0; @@ -2241,7 +2249,7 @@ FLAC__bool convert_to_seek_table_template(const char *requested_seek_points, int /*@@@@@@ workaround ogg bug: too many seekpoints makes table not fit in one page */ if(e->use_ogg && e->total_samples_to_encode > 0 && e->total_samples_to_encode / e->sample_rate / 10 > 230) requested_seek_points = "230x;"; - else + else #endif requested_seek_points = "10s;"; num_requested_seek_points = 1; @@ -2756,9 +2764,9 @@ void print_verify_error(EncoderSession *e) flac__utils_printf(stderr, 1, "Verify FAILED! Do not trust %s\n", e->outfilename); } -FLAC__bool read_little_endian_uint16(FILE *f, FLAC__uint16 *val, FLAC__bool eof_ok, const char *fn) +FLAC__bool read_bytes(FILE *f, FLAC__byte *buf, size_t n, FLAC__bool eof_ok, const char *fn) { - size_t bytes_read = fread(val, 1, 2, f); + size_t bytes_read = fread(buf, 1, n, f); if(bytes_read == 0) { if(!eof_ok) { @@ -2768,111 +2776,62 @@ FLAC__bool read_little_endian_uint16(FILE *f, FLAC__uint16 *val, FLAC__bool eof_ else return true; } - else if(bytes_read < 2) { + if(bytes_read < n) { flac__utils_printf(stderr, 1, "%s: ERROR: unexpected EOF\n", fn); return false; } - else { - if(is_big_endian_host_) { - FLAC__byte tmp, *b = (FLAC__byte*)val; - tmp = b[1]; b[1] = b[0]; b[0] = tmp; - } - return true; - } -} - -FLAC__bool read_little_endian_uint32(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn) -{ - size_t bytes_read = fread(val, 1, 4, f); - - if(bytes_read == 0) { - if(!eof_ok) { - flac__utils_printf(stderr, 1, "%s: ERROR: unexpected EOF\n", fn); - return false; - } - else - return true; - } - else if(bytes_read < 4) { - flac__utils_printf(stderr, 1, "%s: ERROR: unexpected EOF\n", fn); - return false; - } - else { - if(is_big_endian_host_) { - FLAC__byte tmp, *b = (FLAC__byte*)val; - tmp = b[3]; b[3] = b[0]; b[0] = tmp; - tmp = b[2]; b[2] = b[1]; b[1] = tmp; - } - return true; - } -} - -FLAC__bool read_big_endian_uint16(FILE *f, FLAC__uint16 *val, FLAC__bool eof_ok, const char *fn) -{ - unsigned char buf[4]; - size_t bytes_read= fread(buf, 1, 2, f); - - if(bytes_read==0U && eof_ok) - return true; - else if(bytes_read<2U) { - flac__utils_printf(stderr, 1, "%s: ERROR: unexpected EOF\n", fn); - return false; - } - - /* this is independent of host endianness */ - *val= (FLAC__uint16)(buf[0])<<8 | buf[1]; - return true; } -FLAC__bool read_big_endian_uint32(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn) +FLAC__bool read_uint16(FILE *f, FLAC__bool big_endian, FLAC__uint16 *val, const char *fn) { - unsigned char buf[4]; - size_t bytes_read= fread(buf, 1, 4, f); - - if(bytes_read==0U && eof_ok) - return true; - else if(bytes_read<4U) { - flac__utils_printf(stderr, 1, "%s: ERROR: unexpected EOF\n", fn); + if(!read_bytes(f, (FLAC__byte*)val, 2, /*eof_ok=*/false, fn)) return false; + if(is_big_endian_host_ != big_endian) { + FLAC__byte tmp, *b = (FLAC__byte*)val; + tmp = b[1]; b[1] = b[0]; b[0] = tmp; } - - /* this is independent of host endianness */ - *val= (FLAC__uint32)(buf[0])<<24 | (FLAC__uint32)(buf[1])<<16 | - (FLAC__uint32)(buf[2])<<8 | buf[3]; - return true; } -FLAC__bool read_sane_extended(FILE *f, FLAC__uint32 *val, FLAC__bool eof_ok, const char *fn) +FLAC__bool read_uint32(FILE *f, FLAC__bool big_endian, FLAC__uint32 *val, const char *fn) +{ + if(!read_bytes(f, (FLAC__byte*)val, 4, /*eof_ok=*/false, fn)) + return false; + if(is_big_endian_host_ != big_endian) { + FLAC__byte tmp, *b = (FLAC__byte*)val; + tmp = b[3]; b[3] = b[0]; b[0] = tmp; + tmp = b[2]; b[2] = b[1]; b[1] = tmp; + } + return true; +} + +FLAC__bool read_sane_extended(FILE *f, FLAC__uint32 *val, const char *fn) /* Read an IEEE 754 80-bit (aka SANE) extended floating point value from 'f', * convert it into an integral value and store in 'val'. Return false if only - * between 1 and 9 bytes remain in 'f', if 0 bytes remain in 'f' and 'eof_ok' is - * false, or if the value is negative, between zero and one, or too large to be - * represented by 'val'; return true otherwise. + * between 1 and 9 bytes remain in 'f', if 0 bytes remain in 'f', or if the + * value is negative, between zero and one, or too large to be represented by + * 'val'; return true otherwise. */ { unsigned int i; - unsigned char buf[10]; - size_t bytes_read= fread(buf, 1U, 10U, f); - FLAC__int16 e= ((FLAC__uint16)(buf[0])<<8 | (FLAC__uint16)(buf[1]))-0x3FFF; - FLAC__int16 shift= 63-e; - FLAC__uint64 p= 0U; + FLAC__byte buf[10]; + FLAC__uint64 p = 0; + FLAC__int16 e; + FLAC__int16 shift; - if(bytes_read==0U && eof_ok) - return true; - else if(bytes_read<10U) { - flac__utils_printf(stderr, 1, "%s: ERROR: unexpected EOF\n", fn); + if(!read_bytes(f, buf, sizeof(buf), /*eof_ok=*/false, fn)) return false; - } - else if((buf[0]>>7)==1U || e<0 || e>63) { + e = ((FLAC__uint16)(buf[0])<<8 | (FLAC__uint16)(buf[1]))-0x3FFF; + shift = 63-e; + if((buf[0]>>7)==1U || e<0 || e>63) { flac__utils_printf(stderr, 1, "%s: ERROR: invalid floating-point value\n", fn); return false; } - for(i= 0U; i<8U; ++i) - p|= (FLAC__uint64)(buf[i+2])<<(56U-i*8); - *val= (FLAC__uint32)((p>>shift)+(p>>(shift-1) & 0x1)); + for(i = 0; i < 8; ++i) + p |= (FLAC__uint64)(buf[i+2])<<(56U-i*8); + *val = (FLAC__uint32)((p>>shift)+(p>>(shift-1) & 0x1)); return true; } diff --git a/src/flac/encode.h b/src/flac/encode.h index 13ee7d39..95f4829f 100644 --- a/src/flac/encode.h +++ b/src/flac/encode.h @@ -114,8 +114,8 @@ typedef struct { encode_options_t common; } flac_encode_options_t; -int flac__encode_aif(FILE *infile, off_t infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, wav_encode_options_t options, FLAC__bool is_aifc); -int flac__encode_wav(FILE *infile, off_t infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, wav_encode_options_t options); +int flac__encode_aiff(FILE *infile, off_t infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, wav_encode_options_t options, FLAC__bool is_aifc); +int flac__encode_wave(FILE *infile, off_t infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, wav_encode_options_t options); int flac__encode_raw(FILE *infile, off_t infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, raw_encode_options_t options); int flac__encode_flac(FILE *infile, off_t infilesize, const char *infilename, const char *outfilename, const FLAC__byte *lookahead, unsigned lookahead_length, flac_encode_options_t options, FLAC__bool input_is_ogg); diff --git a/src/flac/main.c b/src/flac/main.c index f3716a80..ee94e9a5 100644 --- a/src/flac/main.c +++ b/src/flac/main.c @@ -57,8 +57,6 @@ # include "share/getopt.h" #endif -typedef enum { RAW, WAV, AIF, FLAC, OGGFLAC } FileFormat; - static int do_it(void); static FLAC__bool init_options(void); @@ -1161,6 +1159,9 @@ static void usage_summary(void) printf(" Testing: flac -t [] [FLACFILE [...]]\n"); printf("Analyzing: flac -a [] [] [FLACFILE [...]]\n"); printf("\n"); + printf("Be sure to read the list of known bugs at:\n"); + printf("http://flac.sourceforge.net/documentation_bugs.html\n"); + printf("\n"); } void short_usage(void) @@ -1170,6 +1171,9 @@ void short_usage(void) printf("This is the short help; for all options use 'flac --help'; for even more\n"); printf("instructions use 'flac --explain'\n"); printf("\n"); + printf("Be sure to read the list of known bugs at:\n"); + printf("http://flac.sourceforge.net/documentation_bugs.html\n"); + printf("\n"); printf("To encode:\n"); printf(" flac [-#] [INPUTFILE [...]]\n"); printf("\n"); @@ -1613,8 +1617,8 @@ void show_explain(void) void format_mistake(const char *infilename, FileFormat wrong, FileFormat right) { /* WATCHOUT: indexed by FileFormat */ - static const char * const ff[] = { "raw", "WAVE", "AIFF", "FLAC", "Ogg FLAC" }; - flac__utils_printf(stderr, 1, "WARNING: %s is not a %s file; treating as a %s file\n", infilename, ff[wrong], ff[right]); + static const char * const ff[] = { " raw", " WAVE", "n AIFF", "n AIFF-C", " FLAC", "n Ogg FLAC" }; + flac__utils_printf(stderr, 1, "WARNING: %s is not a%s file; treating as a%s file\n", infilename, ff[wrong], ff[right]); } int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_last_file) @@ -1622,8 +1626,7 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_ FILE *encode_infile; FLAC__byte lookahead[12]; unsigned lookahead_length = 0; - FileFormat input_format = RAW; - FLAC__bool is_aifc = false; + FileFormat input_format = FORMAT_RAW; int retval; off_t infilesize; encode_options_t common_options; @@ -1651,28 +1654,28 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_ if(!option_values.force_raw_format) { /* first set format based on name */ if(strlen(infilename) >= 4 && 0 == FLAC__STRCASECMP(infilename+(strlen(infilename)-4), ".wav")) - input_format = WAV; + input_format = FORMAT_WAVE; else if(strlen(infilename) >= 4 && 0 == FLAC__STRCASECMP(infilename+(strlen(infilename)-4), ".aif")) - input_format = AIF; + input_format = FORMAT_AIFF; else if(strlen(infilename) >= 5 && 0 == FLAC__STRCASECMP(infilename+(strlen(infilename)-5), ".aiff")) - input_format = AIF; + input_format = FORMAT_AIFF; else if(strlen(infilename) >= 5 && 0 == FLAC__STRCASECMP(infilename+(strlen(infilename)-5), ".flac")) - input_format = FLAC; + input_format = FORMAT_FLAC; else if(strlen(infilename) >= 4 && 0 == FLAC__STRCASECMP(infilename+(strlen(infilename)-4), ".oga")) - input_format = OGGFLAC; + input_format = FORMAT_OGGFLAC; else if(strlen(infilename) >= 4 && 0 == FLAC__STRCASECMP(infilename+(strlen(infilename)-4), ".ogg")) - input_format = OGGFLAC; + input_format = FORMAT_OGGFLAC; /* attempt to guess the file type based on the first 12 bytes */ if((lookahead_length = fread(lookahead, 1, 12, encode_infile)) < 12) { - if(input_format != RAW) { - format_mistake(infilename, input_format, RAW); + if(input_format != FORMAT_RAW) { + format_mistake(infilename, input_format, FORMAT_RAW); if(option_values.treat_warnings_as_errors) { conditional_fclose(encode_infile); return 1; } } - input_format = RAW; + input_format = FORMAT_RAW; } else { if(!strncmp((const char *)lookahead, "ID3", 3)) { @@ -1680,27 +1683,25 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_ return 1; } else if(!strncmp((const char *)lookahead, "RIFF", 4) && !strncmp((const char *)lookahead+8, "WAVE", 4)) - input_format = WAV; + input_format = FORMAT_WAVE; else if(!strncmp((const char *)lookahead, "FORM", 4) && !strncmp((const char *)lookahead+8, "AIFF", 4)) - input_format = AIF; - else if(!strncmp((const char *)lookahead, "FORM", 4) && !strncmp((const char *)lookahead+8, "AIFC", 4)) { - input_format = AIF; - is_aifc = true; - } + input_format = FORMAT_AIFF; + else if(!strncmp((const char *)lookahead, "FORM", 4) && !strncmp((const char *)lookahead+8, "AIFC", 4)) + input_format = FORMAT_AIFF_C; else if(!memcmp(lookahead, FLAC__STREAM_SYNC_STRING, sizeof(FLAC__STREAM_SYNC_STRING))) - input_format = FLAC; + input_format = FORMAT_FLAC; /* this could be made more accurate by looking at the first packet */ else if(!memcmp(lookahead, "OggS", 4)) - input_format = OGGFLAC; + input_format = FORMAT_OGGFLAC; else { - if(input_format != RAW) { - format_mistake(infilename, input_format, RAW); + if(input_format != FORMAT_RAW) { + format_mistake(infilename, input_format, FORMAT_RAW); if(option_values.treat_warnings_as_errors) { conditional_fclose(encode_infile); return 1; } } - input_format = RAW; + input_format = FORMAT_RAW; } } } @@ -1710,7 +1711,7 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_ conditional_fclose(encode_infile); return usage_error("ERROR: --keep-foreign-metadata cannot be used when encoding from stdin or to stdout\n"); } - if(input_format != WAV && input_format != AIF) { + if(input_format != FORMAT_WAVE && input_format != FORMAT_AIFF && input_format != FORMAT_AIFF_C) { conditional_fclose(encode_infile); return usage_error("ERROR: --keep-foreign-metadata can only be used with WAVE or AIFF input\n"); } @@ -1721,7 +1722,7 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_ * Use grabbag__file_get_filesize() as a cheap way to check. */ if(!option_values.test_only && !option_values.force_file_overwrite && strcmp(outfilename, "-") && grabbag__file_get_filesize(outfilename) != (off_t)(-1)) { - if(input_format == FLAC) { + if(input_format == FORMAT_FLAC) { /* need more detailed error message when re-flac'ing to avoid confusing the user */ flac__utils_printf(stderr, 1, "ERROR: output file %s already exists.\n\n" @@ -1732,7 +1733,7 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_ outfilename ); } - else if(input_format == OGGFLAC) { + else if(input_format == FORMAT_OGGFLAC) { /* need more detailed error message when re-flac'ing to avoid confusing the user */ flac__utils_printf(stderr, 1, "ERROR: output file %s already exists.\n\n" @@ -1750,7 +1751,7 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_ } if(option_values.format_input_size >= 0) { - if (input_format != RAW || infilesize >= 0) { + if (input_format != FORMAT_RAW || infilesize >= 0) { flac__utils_printf(stderr, 1, "ERROR: can only use --input-size when encoding raw samples from stdin\n"); conditional_fclose(encode_infile); return 1; @@ -1760,18 +1761,18 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_ } } - if(option_values.sector_align && (input_format == FLAC || input_format == OGGFLAC)) { + if(option_values.sector_align && (input_format == FORMAT_FLAC || input_format == FORMAT_OGGFLAC)) { flac__utils_printf(stderr, 1, "ERROR: can't use --sector-align when the input file is FLAC or Ogg FLAC\n"); conditional_fclose(encode_infile); return 1; } - if(option_values.sector_align && input_format == RAW && infilesize < 0) { + if(option_values.sector_align && input_format == FORMAT_RAW && infilesize < 0) { flac__utils_printf(stderr, 1, "ERROR: can't use --sector-align when the input size is unknown\n"); conditional_fclose(encode_infile); return 1; } - if(input_format == RAW) { + if(input_format == FORMAT_RAW) { if(option_values.format_is_big_endian < 0 || option_values.format_is_unsigned_samples < 0 || option_values.format_channels < 0 || option_values.format_bps < 0 || option_values.format_sample_rate < 0) { conditional_fclose(encode_infile); return usage_error("ERROR: for encoding a raw file you must specify a value for --endian, --sign, --channels, --bps, and --sample-rate\n"); @@ -1853,7 +1854,7 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_ strcat(internal_outfilename, tmp_suffix); } - if(input_format == RAW) { + if(input_format == FORMAT_RAW) { raw_encode_options_t options; options.common = common_options; @@ -1865,12 +1866,12 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_ retval = flac__encode_raw(encode_infile, infilesize, infilename, internal_outfilename? internal_outfilename : outfilename, lookahead, lookahead_length, options); } - else if(input_format == FLAC || input_format == OGGFLAC) { + else if(input_format == FORMAT_FLAC || input_format == FORMAT_OGGFLAC) { flac_encode_options_t options; options.common = common_options; - retval = flac__encode_flac(encode_infile, infilesize, infilename, internal_outfilename? internal_outfilename : outfilename, lookahead, lookahead_length, options, input_format==OGGFLAC); + retval = flac__encode_flac(encode_infile, infilesize, infilename, internal_outfilename? internal_outfilename : outfilename, lookahead, lookahead_length, options, input_format==FORMAT_OGGFLAC); } else { wav_encode_options_t options; @@ -1880,17 +1881,17 @@ int encode_file(const char *infilename, FLAC__bool is_first_file, FLAC__bool is_ /* read foreign metadata if requested */ if(option_values.keep_foreign_metadata) { - if(0 == (options.foreign_metadata = flac__foreign_metadata_new(input_format==AIF? FOREIGN_BLOCK_TYPE__AIFF : FOREIGN_BLOCK_TYPE__RIFF))) { + if(0 == (options.foreign_metadata = flac__foreign_metadata_new(input_format==FORMAT_WAVE? FOREIGN_BLOCK_TYPE__RIFF : FOREIGN_BLOCK_TYPE__AIFF))) { flac__utils_printf(stderr, 1, "ERROR: creating foreign metadata object\n"); conditional_fclose(encode_infile); return 1; } } - if(input_format == AIF) - retval = flac__encode_aif(encode_infile, infilesize, infilename, internal_outfilename? internal_outfilename : outfilename, lookahead, lookahead_length, options, is_aifc); + if(input_format == FORMAT_WAVE) + retval = flac__encode_wave(encode_infile, infilesize, infilename, internal_outfilename? internal_outfilename : outfilename, lookahead, lookahead_length, options); else - retval = flac__encode_wav(encode_infile, infilesize, infilename, internal_outfilename? internal_outfilename : outfilename, lookahead, lookahead_length, options); + retval = flac__encode_aiff(encode_infile, infilesize, infilename, internal_outfilename? internal_outfilename : outfilename, lookahead, lookahead_length, options, input_format==FORMAT_AIFF_C); if(options.foreign_metadata) flac__foreign_metadata_delete(options.foreign_metadata); @@ -1949,7 +1950,7 @@ int decode_file(const char *infilename) { int retval; FLAC__bool treat_as_ogg = false; - FileFormat output_format = WAV; + FileFormat output_format = FORMAT_WAVE; decode_options_t common_options; const char *outfilename = get_decoded_outfilename(infilename); @@ -1968,25 +1969,25 @@ int decode_file(const char *infilename) } if(option_values.force_raw_format) - output_format = RAW; + output_format = FORMAT_RAW; else if( option_values.force_aiff_format || (strlen(outfilename) >= 4 && 0 == FLAC__STRCASECMP(outfilename+(strlen(outfilename)-4), ".aif")) || (strlen(outfilename) >= 5 && 0 == FLAC__STRCASECMP(outfilename+(strlen(outfilename)-5), ".aiff")) ) - output_format = AIF; + output_format = FORMAT_AIFF; else - output_format = WAV; + output_format = FORMAT_WAVE; if(!option_values.test_only && !option_values.analyze) { - if(output_format == RAW && (option_values.format_is_big_endian < 0 || option_values.format_is_unsigned_samples < 0)) + if(output_format == FORMAT_RAW && (option_values.format_is_big_endian < 0 || option_values.format_is_unsigned_samples < 0)) return usage_error("ERROR: for decoding to a raw file you must specify a value for --endian and --sign\n"); } if(option_values.keep_foreign_metadata) { if(0 == strcmp(infilename, "-") || 0 == strcmp(outfilename, "-")) return usage_error("ERROR: --keep-foreign-metadata cannot be used when decoding from stdin or to stdout\n"); - if(output_format != WAV && output_format != AIF) + if(output_format != FORMAT_WAVE && output_format != FORMAT_AIFF) return usage_error("ERROR: --keep-foreign-metadata can only be used with WAVE or AIFF output\n"); } @@ -2033,7 +2034,7 @@ int decode_file(const char *infilename) #endif common_options.channel_map_none = option_values.channel_map_none; - if(output_format == RAW) { + if(output_format == FORMAT_RAW) { raw_decode_options_t options; options.common = common_options; @@ -2050,16 +2051,16 @@ int decode_file(const char *infilename) /* read foreign metadata if requested */ if(option_values.keep_foreign_metadata) { - if(0 == (options.foreign_metadata = flac__foreign_metadata_new(output_format==AIF? FOREIGN_BLOCK_TYPE__AIFF : FOREIGN_BLOCK_TYPE__RIFF))) { + if(0 == (options.foreign_metadata = flac__foreign_metadata_new(output_format==FORMAT_WAVE? FOREIGN_BLOCK_TYPE__RIFF : FOREIGN_BLOCK_TYPE__AIFF))) { flac__utils_printf(stderr, 1, "ERROR: creating foreign metadata object\n"); return 1; } } - if(output_format == AIF) - retval = flac__decode_aiff(infilename, option_values.test_only? 0 : outfilename, option_values.analyze, option_values.aopts, options); - else + if(output_format == FORMAT_WAVE) retval = flac__decode_wav(infilename, option_values.test_only? 0 : outfilename, option_values.analyze, option_values.aopts, options); + else + retval = flac__decode_aiff(infilename, option_values.test_only? 0 : outfilename, option_values.analyze, option_values.aopts, options); if(options.foreign_metadata) flac__foreign_metadata_delete(options.foreign_metadata); diff --git a/src/flac/utils.h b/src/flac/utils.h index 74ab29e3..71e5800b 100644 --- a/src/flac/utils.h +++ b/src/flac/utils.h @@ -27,6 +27,8 @@ #include "FLAC/format.h" /* for FLAC__StreamMetadata_CueSheet */ #include /* for FILE */ +typedef enum { FORMAT_RAW, FORMAT_WAVE, FORMAT_AIFF, FORMAT_AIFF_C, FORMAT_FLAC, FORMAT_OGGFLAC } FileFormat; + typedef struct { FLAC__bool is_relative; /* i.e. specification string started with + or - */ FLAC__bool value_is_samples;