typedef struct {
FILE *fout;
bool abort_flag;
+ bool test_only;
bool is_wave_out;
bool is_big_endian;
bool is_unsigned_samples;
int decode_wav(const char *infile, const char *outfile, bool verbose, uint64 skip)
{
+ bool md5_failure = false;
stream_info_struct stream_info;
decoder = 0;
stream_info.abort_flag = false;
+ stream_info.test_only = (outfile == 0);
stream_info.is_wave_out = true;
stream_info.verbose = verbose;
stream_info.skip = skip;
stream_info.samples_processed = 0;
stream_info.frame_counter = 0;
- if(0 == strcmp(outfile, "-")) {
- stream_info.fout = stdout;
- }
- else {
- if(0 == (stream_info.fout = fopen(outfile, "wb"))) {
- fprintf(stderr, "ERROR: can't open output file %s\n", outfile);
- return false;
+ if(!stream_info.test_only) {
+ if(0 == strcmp(outfile, "-")) {
+ stream_info.fout = stdout;
+ }
+ else {
+ if(0 == (stream_info.fout = fopen(outfile, "wb"))) {
+ fprintf(stderr, "ERROR: can't open output file %s\n", outfile);
+ return false;
+ }
}
}
if(skip > 0) {
if(!FLAC__file_decoder_process_metadata(decoder)) {
- fprintf(stderr, "ERROR during decoding\n");
+ fprintf(stderr, "%s: ERROR during decoding\n", infile);
goto wav_abort_;
}
if(!FLAC__file_decoder_seek_absolute(decoder, skip)) {
- fprintf(stderr, "ERROR seeking while skipping bytes in input file %s\n", infile);
+ fprintf(stderr, "%s: ERROR seeking while skipping bytes\n", infile);
goto wav_abort_;
}
if(!FLAC__file_decoder_process_remaining_frames(decoder)) {
- fprintf(stderr, "ERROR during decoding\n");
+ fprintf(stderr, "%s: ERROR during decoding\n", infile);
goto wav_abort_;
}
if(decoder->state != FLAC__FILE_DECODER_OK && decoder->state != FLAC__FILE_DECODER_END_OF_FILE) {
- fprintf(stderr, "ERROR during decoding\n");
+ fprintf(stderr, "%s: ERROR during decoding\n", infile);
goto wav_abort_;
}
}
else {
if(!FLAC__file_decoder_process_whole_file(decoder)) {
- fprintf(stderr, "ERROR during decoding\n");
+ fprintf(stderr, "%s: ERROR during decoding\n", infile);
goto wav_abort_;
}
if(decoder->state != FLAC__FILE_DECODER_OK && decoder->state != FLAC__FILE_DECODER_END_OF_FILE) {
- fprintf(stderr, "ERROR during decoding, state=%d:%s\n", decoder->state, FLAC__FileDecoderStateString[decoder->state]);
+ fprintf(stderr, "%s: ERROR during decoding, state=%d:%s\n", infile, decoder->state, FLAC__FileDecoderStateString[decoder->state]);
goto wav_abort_;
}
}
if(decoder) {
if(decoder->state != FLAC__FILE_DECODER_UNINITIALIZED)
- FLAC__file_decoder_finish(decoder);
+ md5_failure = !FLAC__file_decoder_finish(decoder);
print_stats(&stream_info);
FLAC__file_decoder_free_instance(decoder);
}
- fclose(stream_info.fout);
+ if(!stream_info.test_only)
+ fclose(stream_info.fout);
if(verbose)
printf("\n");
+ fflush(stdout);
+ if(md5_failure) {
+ fprintf(stderr, "%s: WARNING, MD5 signature mismatch\n", infile);
+ return 1;
+ }
+ else {
+ if(stream_info.test_only)
+ printf("%s: ok\n", infile);
+ }
return 0;
wav_abort_:
if(decoder) {
FLAC__file_decoder_finish(decoder);
FLAC__file_decoder_free_instance(decoder);
}
- fclose(stream_info.fout);
- unlink(outfile);
+ if(!stream_info.test_only) {
+ fclose(stream_info.fout);
+ unlink(outfile);
+ }
return 1;
}
int decode_raw(const char *infile, const char *outfile, bool verbose, uint64 skip, bool is_big_endian, bool is_unsigned_samples)
{
+ bool md5_failure = false;
stream_info_struct stream_info;
decoder = 0;
stream_info.abort_flag = false;
+ stream_info.test_only = (outfile == 0);
stream_info.is_wave_out = false;
stream_info.is_big_endian = is_big_endian;
stream_info.is_unsigned_samples = is_unsigned_samples;
stream_info.samples_processed = 0;
stream_info.frame_counter = 0;
- if(0 == strcmp(outfile, "-")) {
- stream_info.fout = stdout;
- }
- else {
- if(0 == (stream_info.fout = fopen(outfile, "wb"))) {
- fprintf(stderr, "ERROR: can't open output file %s\n", outfile);
- return false;
+ if(!stream_info.test_only) {
+ if(0 == strcmp(outfile, "-")) {
+ stream_info.fout = stdout;
+ }
+ else {
+ if(0 == (stream_info.fout = fopen(outfile, "wb"))) {
+ fprintf(stderr, "ERROR: can't open output file %s\n", outfile);
+ return false;
+ }
}
}
if(skip > 0) {
if(!FLAC__file_decoder_process_metadata(decoder)) {
- fprintf(stderr, "ERROR during decoding\n");
+ fprintf(stderr, "%s: ERROR during decoding\n", infile);
goto raw_abort_;
}
if(!FLAC__file_decoder_seek_absolute(decoder, skip)) {
- fprintf(stderr, "ERROR seeking while skipping bytes in input file %s\n", infile);
+ fprintf(stderr, "%s: ERROR seeking while skipping bytes\n", infile);
goto raw_abort_;
}
if(!FLAC__file_decoder_process_remaining_frames(decoder)) {
- fprintf(stderr, "ERROR during decoding\n");
+ fprintf(stderr, "%s: ERROR during decoding\n", infile);
goto raw_abort_;
}
if(decoder->state != FLAC__FILE_DECODER_OK && decoder->state != FLAC__FILE_DECODER_END_OF_FILE) {
- fprintf(stderr, "ERROR during decoding\n");
+ fprintf(stderr, "%s: ERROR during decoding\n", infile);
goto raw_abort_;
}
}
else {
if(!FLAC__file_decoder_process_whole_file(decoder)) {
- fprintf(stderr, "ERROR during decoding\n");
+ fprintf(stderr, "%s: ERROR during decoding\n", infile);
goto raw_abort_;
}
if(decoder->state != FLAC__FILE_DECODER_OK && decoder->state != FLAC__FILE_DECODER_END_OF_FILE) {
- fprintf(stderr, "ERROR during decoding\n");
+ fprintf(stderr, "%s: ERROR during decoding\n", infile);
goto raw_abort_;
}
}
if(decoder) {
if(decoder->state != FLAC__FILE_DECODER_UNINITIALIZED)
- FLAC__file_decoder_finish(decoder);
+ md5_failure = !FLAC__file_decoder_finish(decoder);
print_stats(&stream_info);
FLAC__file_decoder_free_instance(decoder);
}
- fclose(stream_info.fout);
+ if(!stream_info.test_only)
+ fclose(stream_info.fout);
if(verbose)
printf("\n");
+ fflush(stdout);
+ if(md5_failure) {
+ fprintf(stderr, "%s: WARNING, MD5 signature mismatch\n", infile);
+ return 1;
+ }
+ else {
+ if(stream_info.test_only)
+ printf("%s: ok\n", infile);
+ }
return 0;
raw_abort_:
if(decoder) {
FLAC__file_decoder_finish(decoder);
FLAC__file_decoder_free_instance(decoder);
}
- fclose(stream_info.fout);
- unlink(outfile);
+ if(!stream_info.test_only) {
+ fclose(stream_info.fout);
+ unlink(outfile);
+ }
return 1;
}
fprintf(stderr, "ERROR creating the decoder instance\n");
return false;
}
+ decoder->check_md5 = true;
if(FLAC__file_decoder_init(decoder, infile, write_callback, metadata_callback, error_callback, stream_info) != FLAC__FILE_DECODER_OK) {
fprintf(stderr, "ERROR initializing decoder, state = %d\n", decoder->state);
if(stream_info->verbose && !(stream_info->frame_counter & 0x1f))
print_stats(stream_info);
- if(bps == 8) {
- 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;
- }
- else {
- for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
- for(channel = 0; channel < channels; channel++, sample++)
- scbuffer[sample] = buffer[channel][wide_sample];
- }
- if(fwrite(ucbuffer, 1, sample, fout) != sample)
- return FLAC__STREAM_DECODER_WRITE_ABORT;
- }
- else { /* 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;
- }
- else {
- for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
- for(channel = 0; channel < channels; channel++, sample++)
- ssbuffer[sample] = buffer[channel][wide_sample];
+ if(!stream_info->test_only) {
+ if(bps == 8) {
+ 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;
+ }
+ else {
+ for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
+ for(channel = 0; channel < channels; channel++, sample++)
+ scbuffer[sample] = buffer[channel][wide_sample];
+ }
+ if(fwrite(ucbuffer, 1, sample, fout) != sample)
+ return FLAC__STREAM_DECODER_WRITE_ABORT;
}
- if(is_big_endian != is_big_endian_host) {
- unsigned char tmp;
- for(byte = 0; byte < sample<<1; byte += 2) {
- tmp = ucbuffer[byte];
- ucbuffer[byte] = ucbuffer[byte+1];
- ucbuffer[byte+1] = tmp;
+ else { /* 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;
+ }
+ else {
+ for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
+ for(channel = 0; channel < channels; channel++, sample++)
+ ssbuffer[sample] = buffer[channel][wide_sample];
+ }
+ if(is_big_endian != is_big_endian_host) {
+ unsigned char tmp;
+ for(byte = 0; byte < sample<<1; byte += 2) {
+ tmp = ucbuffer[byte];
+ ucbuffer[byte] = ucbuffer[byte+1];
+ ucbuffer[byte+1] = tmp;
+ }
}
+ if(fwrite(usbuffer, 2, sample, fout) != sample)
+ return FLAC__STREAM_DECODER_WRITE_ABORT;
}
- if(fwrite(usbuffer, 2, sample, fout) != sample)
- return FLAC__STREAM_DECODER_WRITE_ABORT;
}
return FLAC__STREAM_DECODER_WRITE_CONTINUE;
}
}
/* write the WAVE headers if necessary */
- if(stream_info->is_wave_out) {
+ if(!stream_info->test_only && stream_info->is_wave_out) {
uint64 data_size = stream_info->total_samples * stream_info->channels * ((stream_info->bps+7)/8);
if(data_size >= 0xFFFFFFDC) {
fprintf(stderr, "ERROR: stream is too big for a wave file\n");
void print_stats(const stream_info_struct *stream_info)
{
if(stream_info->verbose) {
- printf("\rwrote %u of %u samples, %6.2f%% complete",
+ printf("\r%s %u of %u samples, %6.2f%% complete",
+ stream_info->test_only? "tested" : "wrote",
(unsigned)stream_info->samples_processed,
(unsigned)stream_info->total_samples,
#ifdef _MSC_VER
int main(int argc, char *argv[])
{
int i;
- bool verify = false, verbose = true, lax = false, mode_decode = false, do_mid_side = true, do_exhaustive_model_search = false, do_qlp_coeff_prec_search = false;
+ bool verify = false, verbose = true, lax = false, mode_decode = false, test_only = false;
+ bool do_mid_side = true, do_exhaustive_model_search = false, do_qlp_coeff_prec_search = false;
unsigned max_lpc_order = 8;
unsigned qlp_coeff_precision = 0;
uint64 skip = 0;
break;
if(0 == strcmp(argv[i], "-d"))
mode_decode = true;
+ else if(0 == strcmp(argv[i], "-t")) {
+ mode_decode = true;
+ test_only = true;
+ }
else if(0 == strcmp(argv[i], "-s"))
verbose = false;
else if(0 == strcmp(argv[i], "-s-"))
return usage("ERROR: invalid option '%s'\n", argv[i]);
}
}
- if(i + 2 != argc)
- return usage("ERROR: invalid arguments (more/less than 2 filenames?)\n");
+ if(i + (test_only? 1:2) != argc)
+ return usage("ERROR: invalid arguments (more/less than %d filename%s?)\n", (test_only? 1:2), (test_only? "":"s"));
/* tweak options based on the filenames; validate the values */
if(!mode_decode) {
}
}
else {
- if(format_is_wave < 0) {
- if(strstr(argv[i+1], ".wav") == argv[i+1] + (strlen(argv[i+1]) - strlen(".wav")))
- format_is_wave = true;
- else
- format_is_wave = false;
- }
- if(!format_is_wave) {
- if(format_is_big_endian < 0)
- return usage("ERROR: for decoding to a raw file you must specify -fb or -fl\n");
+ if(!test_only) {
+ if(format_is_wave < 0) {
+ if(strstr(argv[i+1], ".wav") == argv[i+1] + (strlen(argv[i+1]) - strlen(".wav")))
+ format_is_wave = true;
+ else
+ format_is_wave = false;
+ }
+ if(!format_is_wave) {
+ if(format_is_big_endian < 0)
+ return usage("ERROR: for decoding to a raw file you must specify -fb or -fl\n");
+ }
}
}
}
/* turn off verbosity if the output stream is going to stdout */
- if(0 == strcmp(argv[i+1], "-"))
+ if(!test_only && 0 == strcmp(argv[i+1], "-"))
verbose = false;
if(verbose) {
if(mode_decode)
if(format_is_wave)
- return decode_wav(argv[i], argv[i+1], verbose, skip);
+ return decode_wav(argv[i], test_only? 0 : argv[i+1], verbose, skip);
else
- return decode_raw(argv[i], argv[i+1], verbose, skip, format_is_big_endian, format_is_unsigned_samples);
+ return decode_raw(argv[i], test_only? 0 : argv[i+1], verbose, skip, format_is_big_endian, format_is_unsigned_samples);
else
if(format_is_wave)
return encode_wav(argv[i], argv[i+1], verbose, skip, verify, lax, do_mid_side, do_exhaustive_model_search, do_qlp_coeff_prec_search, rice_optimization_level, max_lpc_order, (unsigned)blocksize, qlp_coeff_precision);
va_list args;
if(message) {
- fprintf(stderr, message);
- fprintf(stderr, "\n");
va_start(args, message);
(void) vfprintf(stderr, message, args);