1 /* flac - Command-line FLAC encoder/decoder
2 * Copyright (C) 2000,2001,2002 Josh Coalson
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 #if defined _WIN32 && !defined __CYGWIN__
20 /* where MSVC puts unlink() */
25 #include <math.h> /* for floor() */
26 #include <stdio.h> /* for FILE et al. */
27 #include <string.h> /* for strcmp() */
43 const char *inbasefilename;
48 FLAC__bool abort_flag;
49 FLAC__bool analysis_mode;
50 analysis_options aopts;
52 FLAC__bool is_wave_out;
53 FLAC__bool is_big_endian;
54 FLAC__bool is_unsigned_samples;
55 FLAC__uint64 total_samples;
60 FLAC__bool continue_through_decode_errors;
62 FLAC__bool needs_fixup;
65 } wave_chunk_size_fixup;
67 FLAC__uint64 samples_processed;
68 unsigned frame_counter;
73 FLAC__FileDecoder *file;
74 FLAC__StreamDecoder *stream;
81 static FLAC__bool is_big_endian_host;
84 static FLAC__bool init(const char *infilename, stream_info_struct *stream_info);
85 static FLAC__bool write_little_endian_uint16(FILE *f, FLAC__uint16 val);
86 static FLAC__bool write_little_endian_uint32(FILE *f, FLAC__uint32 val);
87 static FLAC__bool fixup_wave_chunk_size(const char *outfilename, unsigned riff_offset, unsigned data_offset, FLAC__uint32 data_size);
89 static FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
92 * We use 'void *' so that we can use the same callbacks for the
93 * FLAC__StreamDecoder and FLAC__FileDecoder. The 'decoder' argument is
94 * actually never used in the callbacks.
96 static FLAC__StreamDecoderWriteStatus write_callback(const void *decoder, const FLAC__Frame *frame, const FLAC__int32 *buffer[], void *client_data);
97 static void metadata_callback(const void *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
98 static void error_callback(const void *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
99 static void print_stats(const stream_info_struct *stream_info);
102 int flac__decode_wav(const char *infilename, const char *outfilename, FLAC__bool analysis_mode, analysis_options aopts, wav_decode_options_t options)
104 FLAC__bool md5_failure = false;
105 stream_info_struct stream_info;
107 stream_info.abort_flag = false;
108 stream_info.analysis_mode = analysis_mode;
109 stream_info.aopts = aopts;
110 stream_info.test_only = (outfilename == 0);
111 stream_info.is_wave_out = true;
112 stream_info.verbose = options.common.verbose;
113 stream_info.continue_through_decode_errors = options.common.continue_through_decode_errors;
114 stream_info.wave_chunk_size_fixup.needs_fixup = false;
115 stream_info.skip = options.common.skip;
116 stream_info.samples_processed = 0;
117 stream_info.frame_counter = 0;
119 stream_info.is_ogg = options.common.is_ogg;
121 stream_info.decoder.file = 0; /* this zeroes stream_info.decoder.stream also */
122 stream_info.inbasefilename = flac__file_get_basename(infilename);
123 stream_info.fout = 0; /* initialized with an open file later if necessary */
125 FLAC__ASSERT(!(stream_info.test_only && stream_info.analysis_mode));
127 if(!stream_info.test_only) {
128 if(0 == strcmp(outfilename, "-")) {
129 stream_info.fout = file__get_binary_stdout();
132 if(0 == (stream_info.fout = fopen(outfilename, "wb"))) {
133 fprintf(stderr, "%s: ERROR: can't open output file %s\n", stream_info.inbasefilename, outfilename);
140 if(stream_info.is_ogg) {
141 if (0 == strcmp(infilename, "-")) {
142 stream_info.fin = file__get_binary_stdin();
144 if (0 == (stream_info.fin = fopen(infilename, "rb"))) {
145 fprintf(stderr, "%s: ERROR: can't open input file %s\n", stream_info.inbasefilename, infilename);
146 if(0 != stream_info.fout && stream_info.fout != stdout)
147 fclose(stream_info.fout);
155 flac__analyze_init(aopts);
157 if(!init(infilename, &stream_info))
160 if(stream_info.skip > 0) {
162 if(stream_info.is_ogg) { /*@@@ (move this check into main.c) */
163 fprintf(stderr, "%s: ERROR, can't skip when decoding Ogg-FLAC yet; convert to native-FLAC first\n", stream_info.inbasefilename);
167 if(!FLAC__file_decoder_process_metadata(stream_info.decoder.file)) {
168 fprintf(stderr, "%s: ERROR while decoding metadata, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
171 if(stream_info.abort_flag)
173 if(!FLAC__file_decoder_seek_absolute(stream_info.decoder.file, stream_info.skip)) {
174 fprintf(stderr, "%s: ERROR seeking while skipping bytes, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
177 if(!FLAC__file_decoder_process_remaining_frames(stream_info.decoder.file)) {
178 if(stream_info.verbose) fprintf(stderr, "\n");
179 fprintf(stderr, "%s: ERROR while decoding frames, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
182 if(FLAC__file_decoder_get_state(stream_info.decoder.file) != FLAC__FILE_DECODER_OK && FLAC__file_decoder_get_state(stream_info.decoder.file) != FLAC__FILE_DECODER_END_OF_FILE) {
183 if(stream_info.verbose) fprintf(stderr, "\n");
184 fprintf(stderr, "%s: ERROR during decoding, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
190 if(stream_info.is_ogg) {
191 if(!FLAC__stream_decoder_process_whole_stream(stream_info.decoder.stream)) {
192 if(stream_info.verbose) fprintf(stderr, "\n");
193 fprintf(stderr, "%s: ERROR while decoding data, state=%d:%s\n", stream_info.inbasefilename, FLAC__stream_decoder_get_state(stream_info.decoder.stream), FLAC__StreamDecoderStateString[FLAC__stream_decoder_get_state(stream_info.decoder.stream)]);
196 if(FLAC__stream_decoder_get_state(stream_info.decoder.stream) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA && FLAC__stream_decoder_get_state(stream_info.decoder.stream) != FLAC__STREAM_DECODER_END_OF_STREAM) {
197 if(stream_info.verbose) fprintf(stderr, "\n");
198 fprintf(stderr, "%s: ERROR during decoding, state=%d:%s\n", stream_info.inbasefilename, FLAC__stream_decoder_get_state(stream_info.decoder.stream), FLAC__StreamDecoderStateString[FLAC__stream_decoder_get_state(stream_info.decoder.stream)]);
205 if(!FLAC__file_decoder_process_whole_file(stream_info.decoder.file)) {
206 if(stream_info.verbose) fprintf(stderr, "\n");
207 fprintf(stderr, "%s: ERROR while decoding data, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
210 if(FLAC__file_decoder_get_state(stream_info.decoder.file) != FLAC__FILE_DECODER_OK && FLAC__file_decoder_get_state(stream_info.decoder.file) != FLAC__FILE_DECODER_END_OF_FILE) {
211 if(stream_info.verbose) fprintf(stderr, "\n");
212 fprintf(stderr, "%s: ERROR during decoding, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
219 if(stream_info.is_ogg) {
220 if(stream_info.decoder.stream) {
221 FLAC__stream_decoder_finish(stream_info.decoder.stream);
223 print_stats(&stream_info);
224 FLAC__stream_decoder_delete(stream_info.decoder.stream);
230 if(stream_info.decoder.file) {
231 md5_failure = !FLAC__file_decoder_finish(stream_info.decoder.file);
232 print_stats(&stream_info);
233 FLAC__file_decoder_delete(stream_info.decoder.file);
236 if(0 != stream_info.fout && stream_info.fout != stdout)
237 fclose(stream_info.fout);
239 if(stream_info.is_ogg) {
240 if(0 != stream_info.fin && stream_info.fin != stdin)
241 fclose(stream_info.fin);
245 flac__analyze_finish(aopts);
246 if(stream_info.wave_chunk_size_fixup.needs_fixup)
247 if(!fixup_wave_chunk_size(outfilename, stream_info.wave_chunk_size_fixup.riff_offset, stream_info.wave_chunk_size_fixup.data_offset, (FLAC__uint32)stream_info.samples_processed))
250 fprintf(stderr, "\r%s: WARNING, MD5 signature mismatch\n", stream_info.inbasefilename);
253 if(stream_info.verbose)
254 fprintf(stderr, "\r%s: %s \n", stream_info.inbasefilename, stream_info.test_only? "ok ":analysis_mode?"done ":"done");
259 if(stream_info.is_ogg) {
260 if(stream_info.decoder.stream) {
261 FLAC__stream_decoder_finish(stream_info.decoder.stream);
262 FLAC__stream_decoder_delete(stream_info.decoder.stream);
268 if(stream_info.decoder.file) {
269 FLAC__file_decoder_finish(stream_info.decoder.file);
270 FLAC__file_decoder_delete(stream_info.decoder.file);
273 if(0 != stream_info.fout && stream_info.fout != stdout) {
274 fclose(stream_info.fout);
278 if(stream_info.is_ogg) {
279 if(0 != stream_info.fin && stream_info.fin != stdin)
280 fclose(stream_info.fin);
284 flac__analyze_finish(aopts);
288 int flac__decode_raw(const char *infilename, const char *outfilename, FLAC__bool analysis_mode, analysis_options aopts, raw_decode_options_t options)
290 FLAC__bool md5_failure = false;
291 stream_info_struct stream_info;
293 stream_info.abort_flag = false;
294 stream_info.analysis_mode = analysis_mode;
295 stream_info.aopts = aopts;
296 stream_info.test_only = (outfilename == 0);
297 stream_info.is_wave_out = false;
298 stream_info.is_big_endian = options.is_big_endian;
299 stream_info.is_unsigned_samples = options.is_unsigned_samples;
300 stream_info.verbose = options.common.verbose;
301 stream_info.continue_through_decode_errors = options.common.continue_through_decode_errors;
302 stream_info.wave_chunk_size_fixup.needs_fixup = false;
303 stream_info.skip = options.common.skip;
304 stream_info.samples_processed = 0;
305 stream_info.frame_counter = 0;
307 stream_info.is_ogg = options.common.is_ogg;
309 stream_info.decoder.file = 0; /* this zeroes stream_info.decoder.stream also */
310 stream_info.inbasefilename = flac__file_get_basename(infilename);
311 stream_info.fout = 0; /* initialized with an open file later if necessary */
313 FLAC__ASSERT(!(stream_info.test_only && stream_info.analysis_mode));
315 if(!stream_info.test_only) {
316 if(0 == strcmp(outfilename, "-")) {
317 stream_info.fout = file__get_binary_stdout();
320 if(0 == (stream_info.fout = fopen(outfilename, "wb"))) {
321 fprintf(stderr, "%s: ERROR: can't open output file %s\n", stream_info.inbasefilename, outfilename);
328 if(stream_info.is_ogg) {
329 if (0 == strcmp(infilename, "-")) {
330 stream_info.fin = file__get_binary_stdin();
332 if (0 == (stream_info.fin = fopen(infilename, "rb"))) {
333 fprintf(stderr, "%s: ERROR: can't open input file %s\n", stream_info.inbasefilename, infilename);
334 if(0 != stream_info.fout && stream_info.fout != stdout)
335 fclose(stream_info.fout);
343 flac__analyze_init(aopts);
345 if(!init(infilename, &stream_info))
348 if(stream_info.skip > 0) {
350 if(stream_info.is_ogg) { /*@@@ (move this check into main.c) */
351 fprintf(stderr, "%s: ERROR, can't skip when decoding Ogg-FLAC yet; convert to native-FLAC first\n", stream_info.inbasefilename);
355 if(!FLAC__file_decoder_process_metadata(stream_info.decoder.file)) {
356 fprintf(stderr, "%s: ERROR while decoding metadata, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
359 if(stream_info.abort_flag)
361 if(!FLAC__file_decoder_seek_absolute(stream_info.decoder.file, stream_info.skip)) {
362 fprintf(stderr, "%s: ERROR seeking while skipping bytes, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
365 if(!FLAC__file_decoder_process_remaining_frames(stream_info.decoder.file)) {
366 if(stream_info.verbose) fprintf(stderr, "\n");
367 fprintf(stderr, "%s: ERROR while decoding frames, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
370 if(FLAC__file_decoder_get_state(stream_info.decoder.file) != FLAC__FILE_DECODER_OK && FLAC__file_decoder_get_state(stream_info.decoder.file) != FLAC__FILE_DECODER_END_OF_FILE) {
371 if(stream_info.verbose) fprintf(stderr, "\n");
372 fprintf(stderr, "%s: ERROR during decoding, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
378 if(stream_info.is_ogg) {
379 if(!FLAC__stream_decoder_process_whole_stream(stream_info.decoder.stream)) {
380 if(stream_info.verbose) fprintf(stderr, "\n");
381 fprintf(stderr, "%s: ERROR while decoding data, state=%d:%s\n", stream_info.inbasefilename, FLAC__stream_decoder_get_state(stream_info.decoder.stream), FLAC__StreamDecoderStateString[FLAC__stream_decoder_get_state(stream_info.decoder.stream)]);
384 if(FLAC__stream_decoder_get_state(stream_info.decoder.stream) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA && FLAC__stream_decoder_get_state(stream_info.decoder.stream) != FLAC__STREAM_DECODER_END_OF_STREAM) {
385 if(stream_info.verbose) fprintf(stderr, "\n");
386 fprintf(stderr, "%s: ERROR during decoding, state=%d:%s\n", stream_info.inbasefilename, FLAC__stream_decoder_get_state(stream_info.decoder.stream), FLAC__StreamDecoderStateString[FLAC__stream_decoder_get_state(stream_info.decoder.stream)]);
393 if(!FLAC__file_decoder_process_whole_file(stream_info.decoder.file)) {
394 if(stream_info.verbose) fprintf(stderr, "\n");
395 fprintf(stderr, "%s: ERROR while decoding data, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
398 if(FLAC__file_decoder_get_state(stream_info.decoder.file) != FLAC__FILE_DECODER_OK && FLAC__file_decoder_get_state(stream_info.decoder.file) != FLAC__FILE_DECODER_END_OF_FILE) {
399 if(stream_info.verbose) fprintf(stderr, "\n");
400 fprintf(stderr, "%s: ERROR during decoding, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
407 if(stream_info.is_ogg) {
408 if(stream_info.decoder.stream) {
409 FLAC__stream_decoder_finish(stream_info.decoder.stream);
411 print_stats(&stream_info);
412 FLAC__stream_decoder_delete(stream_info.decoder.stream);
418 if(stream_info.decoder.file) {
419 md5_failure = !FLAC__file_decoder_finish(stream_info.decoder.file);
420 print_stats(&stream_info);
421 FLAC__file_decoder_delete(stream_info.decoder.file);
424 if(0 != stream_info.fout && stream_info.fout != stdout)
425 fclose(stream_info.fout);
427 if(stream_info.is_ogg) {
428 if(0 != stream_info.fin && stream_info.fin != stdin)
429 fclose(stream_info.fin);
433 flac__analyze_finish(aopts);
435 fprintf(stderr, "\r%s: WARNING, MD5 signature mismatch\n", stream_info.inbasefilename);
438 if(stream_info.verbose)
439 fprintf(stderr, "\r%s: %s \n", stream_info.inbasefilename, stream_info.test_only? "ok ":analysis_mode?"done ":"done");
444 if(stream_info.is_ogg) {
445 if(stream_info.decoder.stream) {
446 FLAC__stream_decoder_finish(stream_info.decoder.stream);
447 FLAC__stream_decoder_delete(stream_info.decoder.stream);
453 if(stream_info.decoder.file) {
454 FLAC__file_decoder_finish(stream_info.decoder.file);
455 FLAC__file_decoder_delete(stream_info.decoder.file);
458 if(0 != stream_info.fout && stream_info.fout != stdout) {
459 fclose(stream_info.fout);
463 if(stream_info.is_ogg) {
464 if(0 != stream_info.fin && stream_info.fin != stdin)
465 fclose(stream_info.fin);
469 flac__analyze_finish(aopts);
473 FLAC__bool init(const char *infilename, stream_info_struct *stream_info)
475 FLAC__uint32 test = 1;
477 is_big_endian_host = (*((FLAC__byte*)(&test)))? false : true;
480 if(stream_info->is_ogg) {
481 stream_info->decoder.stream = FLAC__stream_decoder_new();
483 if(0 == stream_info->decoder.stream) {
484 fprintf(stderr, "%s: ERROR creating the decoder instance\n", stream_info->inbasefilename);
488 FLAC__stream_decoder_set_read_callback(stream_info->decoder.stream, read_callback);
490 * The three ugly casts here are to 'downcast' the 'void *' argument of
491 * the callback down to 'FLAC__StreamDecoder *'. In C++ this would be
492 * unnecessary but here the cast makes the C compiler happy.
494 FLAC__stream_decoder_set_write_callback(stream_info->decoder.stream, (FLAC__StreamDecoderWriteStatus (*)(const FLAC__StreamDecoder *, const FLAC__Frame *, const FLAC__int32 *[], void *))write_callback);
495 FLAC__stream_decoder_set_metadata_callback(stream_info->decoder.stream, (void (*)(const FLAC__StreamDecoder *, const FLAC__StreamMetadata *, void *))metadata_callback);
496 FLAC__stream_decoder_set_error_callback(stream_info->decoder.stream, (void (*)(const FLAC__StreamDecoder *, FLAC__StreamDecoderErrorStatus, void *))error_callback);
497 FLAC__stream_decoder_set_client_data(stream_info->decoder.stream, stream_info);
499 if(FLAC__stream_decoder_init(stream_info->decoder.stream) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA) {
500 fprintf(stderr, "%s: ERROR initializing decoder, state=%d:%s\n", stream_info->inbasefilename, FLAC__stream_decoder_get_state(stream_info->decoder.stream), FLAC__StreamDecoderStateString[FLAC__stream_decoder_get_state(stream_info->decoder.stream)]);
504 ogg_stream_init(&stream_info->ogg.os, 0);
505 ogg_sync_init(&stream_info->ogg.oy);
510 stream_info->decoder.file = FLAC__file_decoder_new();
512 if(0 == stream_info->decoder.file) {
513 fprintf(stderr, "%s: ERROR creating the decoder instance\n", stream_info->inbasefilename);
517 FLAC__file_decoder_set_md5_checking(stream_info->decoder.file, true);
518 FLAC__file_decoder_set_filename(stream_info->decoder.file, infilename);
520 * The three ugly casts here are to 'downcast' the 'void *' argument of
521 * the callback down to 'FLAC__FileDecoder *'.
523 FLAC__file_decoder_set_write_callback(stream_info->decoder.file, (FLAC__StreamDecoderWriteStatus (*)(const FLAC__FileDecoder *, const FLAC__Frame *, const FLAC__int32 * const [], void *))write_callback);
524 FLAC__file_decoder_set_metadata_callback(stream_info->decoder.file, (void (*)(const FLAC__FileDecoder *, const FLAC__StreamMetadata *, void *))metadata_callback);
525 FLAC__file_decoder_set_error_callback(stream_info->decoder.file, (void (*)(const FLAC__FileDecoder *, FLAC__StreamDecoderErrorStatus, void *))error_callback);
526 FLAC__file_decoder_set_client_data(stream_info->decoder.file, stream_info);
528 if(FLAC__file_decoder_init(stream_info->decoder.file) != FLAC__FILE_DECODER_OK) {
529 fprintf(stderr, "%s: ERROR initializing decoder, state=%d:%s\n", stream_info->inbasefilename, FLAC__file_decoder_get_state(stream_info->decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info->decoder.file)]);
537 FLAC__bool write_little_endian_uint16(FILE *f, FLAC__uint16 val)
539 FLAC__byte *b = (FLAC__byte*)(&val);
540 if(is_big_endian_host) {
542 tmp = b[1]; b[1] = b[0]; b[0] = tmp;
544 return fwrite(b, 1, 2, f) == 2;
547 FLAC__bool write_little_endian_uint32(FILE *f, FLAC__uint32 val)
549 FLAC__byte *b = (FLAC__byte*)(&val);
550 if(is_big_endian_host) {
552 tmp = b[3]; b[3] = b[0]; b[0] = tmp;
553 tmp = b[2]; b[2] = b[1]; b[1] = tmp;
555 return fwrite(b, 1, 4, f) == 4;
558 FLAC__bool fixup_wave_chunk_size(const char *outfilename, unsigned riff_offset, unsigned data_offset, FLAC__uint32 data_size)
560 FILE *f = fopen(outfilename, "r+b");
562 fprintf(stderr, "ERROR, couldn't open file %s while fixing up WAVE chunk size\n", outfilename);
565 if(fseek(f, riff_offset, SEEK_SET) < 0) {
566 fprintf(stderr, "ERROR, couldn't seek in file %s while fixing up WAVE chunk size\n", outfilename);
570 if(!write_little_endian_uint32(f, data_size + 36)) {
571 fprintf(stderr, "ERROR, couldn't write size in file %s while fixing up WAVE chunk size\n", outfilename);
575 if(fseek(f, data_offset, SEEK_SET) < 0) {
576 fprintf(stderr, "ERROR, couldn't seek in file %s while fixing up WAVE chunk size\n", outfilename);
580 if(!write_little_endian_uint32(f, data_size)) {
581 fprintf(stderr, "ERROR, couldn't write size in file %s while fixing up WAVE chunk size\n", outfilename);
590 #define OGG_READ_BUFFER_SIZE 4096
591 FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
593 stream_info_struct *stream_info = (stream_info_struct *)client_data;
594 FILE *fin = stream_info->fin;
598 unsigned int offset = 0;
602 if (stream_info->abort_flag)
603 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
605 oggbuf = ogg_sync_buffer(&stream_info->ogg.oy, OGG_READ_BUFFER_SIZE);
607 (void)decoder; /* avoid compiler warning */
610 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
612 bytes_read = fread(oggbuf, 1, OGG_READ_BUFFER_SIZE, fin);
615 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
617 if(ogg_sync_wrote(&stream_info->ogg.oy, bytes_read) < 0)
618 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
620 while(ogg_sync_pageout(&stream_info->ogg.oy, &og) == 1) {
621 if(ogg_stream_pagein(&stream_info->ogg.os, &og) == 0) {
624 while(ogg_stream_packetout(&stream_info->ogg.os, &op) == 1) {
625 memcpy(buffer + offset, op.packet, op.bytes);
630 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
634 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
638 FLAC__StreamDecoderWriteStatus write_callback(const void *decoder, const FLAC__Frame *frame, const FLAC__int32 *buffer[], void *client_data)
640 stream_info_struct *stream_info = (stream_info_struct *)client_data;
641 FILE *fout = stream_info->fout;
642 unsigned bps = stream_info->bps, channels = stream_info->channels;
643 FLAC__bool is_big_endian = (stream_info->is_wave_out? false : stream_info->is_big_endian);
644 FLAC__bool is_unsigned_samples = (stream_info->is_wave_out? bps<=8 : stream_info->is_unsigned_samples);
645 unsigned wide_samples = frame->header.blocksize, wide_sample, sample, channel, byte;
646 static FLAC__int8 s8buffer[FLAC__MAX_BLOCK_SIZE * FLAC__MAX_CHANNELS * sizeof(FLAC__int32)]; /* WATCHOUT: can be up to 2 megs */
647 FLAC__uint8 *u8buffer = (FLAC__uint8 *)s8buffer;
648 FLAC__int16 *s16buffer = (FLAC__int16 *)s8buffer;
649 FLAC__uint16 *u16buffer = (FLAC__uint16 *)s8buffer;
650 FLAC__int32 *s32buffer = (FLAC__int32 *)s8buffer;
651 FLAC__uint32 *u32buffer = (FLAC__uint32 *)s8buffer;
655 if(stream_info->abort_flag)
656 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
658 stream_info->samples_processed += wide_samples;
659 stream_info->frame_counter++;
661 if(stream_info->verbose && !(stream_info->frame_counter & 0x7f))
662 print_stats(stream_info);
664 if(stream_info->analysis_mode) {
665 flac__analyze_frame(frame, stream_info->frame_counter-1, stream_info->aopts, fout);
667 else if(!stream_info->test_only) {
669 if(is_unsigned_samples) {
670 for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
671 for(channel = 0; channel < channels; channel++, sample++)
672 u8buffer[sample] = (FLAC__uint8)(buffer[channel][wide_sample] + 0x80);
675 for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
676 for(channel = 0; channel < channels; channel++, sample++)
677 s8buffer[sample] = (FLAC__int8)(buffer[channel][wide_sample]);
679 if(fwrite(u8buffer, 1, sample, fout) != sample)
680 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
683 if(is_unsigned_samples) {
684 for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
685 for(channel = 0; channel < channels; channel++, sample++)
686 u16buffer[sample] = (FLAC__uint16)(buffer[channel][wide_sample] + 0x8000);
689 for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
690 for(channel = 0; channel < channels; channel++, sample++)
691 s16buffer[sample] = (FLAC__int16)(buffer[channel][wide_sample]);
693 if(is_big_endian != is_big_endian_host) {
695 const unsigned bytes = sample * 2;
696 for(byte = 0; byte < bytes; byte += 2) {
697 tmp = u8buffer[byte];
698 u8buffer[byte] = u8buffer[byte+1];
699 u8buffer[byte+1] = tmp;
702 if(fwrite(u16buffer, 2, sample, fout) != sample)
703 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
706 if(is_unsigned_samples) {
707 for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
708 for(channel = 0; channel < channels; channel++, sample++)
709 u32buffer[sample] = buffer[channel][wide_sample] + 0x800000;
712 for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
713 for(channel = 0; channel < channels; channel++, sample++)
714 s32buffer[sample] = buffer[channel][wide_sample];
716 if(is_big_endian != is_big_endian_host) {
718 const unsigned bytes = sample * 4;
719 for(byte = 0; byte < bytes; byte += 4) {
720 tmp = u8buffer[byte];
721 u8buffer[byte] = u8buffer[byte+3];
722 u8buffer[byte+3] = tmp;
723 tmp = u8buffer[byte+1];
724 u8buffer[byte+1] = u8buffer[byte+2];
725 u8buffer[byte+2] = tmp;
730 const unsigned bytes = sample * 4;
731 for(lbyte = byte = 0; byte < bytes; ) {
733 u8buffer[lbyte++] = u8buffer[byte++];
734 u8buffer[lbyte++] = u8buffer[byte++];
735 u8buffer[lbyte++] = u8buffer[byte++];
740 const unsigned bytes = sample * 4;
741 for(lbyte = byte = 0; byte < bytes; ) {
742 u8buffer[lbyte++] = u8buffer[byte++];
743 u8buffer[lbyte++] = u8buffer[byte++];
744 u8buffer[lbyte++] = u8buffer[byte++];
748 if(fwrite(u8buffer, 3, sample, fout) != sample)
749 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
755 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
758 void metadata_callback(const void *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
760 stream_info_struct *stream_info = (stream_info_struct *)client_data;
762 if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
763 /* remember, metadata->data.stream_info.total_samples can be 0, meaning 'unknown' */
764 if(metadata->data.stream_info.total_samples > 0 && stream_info->skip >= metadata->data.stream_info.total_samples) {
765 fprintf(stderr, "%s: ERROR trying to skip more samples than in stream\n", stream_info->inbasefilename);
766 stream_info->abort_flag = true;
769 else if(metadata->data.stream_info.total_samples == 0 && stream_info->skip > 0) {
770 fprintf(stderr, "%s: ERROR, can't skip when FLAC metadata has total sample count of 0\n", stream_info->inbasefilename);
771 stream_info->abort_flag = true;
775 stream_info->total_samples = metadata->data.stream_info.total_samples - stream_info->skip;
776 stream_info->bps = metadata->data.stream_info.bits_per_sample;
777 stream_info->channels = metadata->data.stream_info.channels;
778 stream_info->sample_rate = metadata->data.stream_info.sample_rate;
780 if(stream_info->bps != 8 && stream_info->bps != 16 && stream_info->bps != 24) {
781 fprintf(stderr, "%s: ERROR: bits per sample is not 8/16/24\n", stream_info->inbasefilename);
782 stream_info->abort_flag = true;
786 /* write the WAVE headers if necessary */
787 if(!stream_info->analysis_mode && !stream_info->test_only && stream_info->is_wave_out) {
788 FLAC__uint64 data_size = stream_info->total_samples * stream_info->channels * ((stream_info->bps+7)/8);
789 if(stream_info->total_samples == 0) {
790 if(stream_info->fout == stdout) {
791 fprintf(stderr, "%s: WARNING, don't have accurate sample count available for WAVE header.\n", stream_info->inbasefilename);
792 fprintf(stderr, " Generated WAVE file will have a data chunk size of 0. Try\n");
793 fprintf(stderr, " decoding directly to a file instead.\n");
796 stream_info->wave_chunk_size_fixup.needs_fixup = true;
799 if(data_size >= 0xFFFFFFDC) {
800 fprintf(stderr, "%s: ERROR: stream is too big to fit in a single WAVE file chunk\n", stream_info->inbasefilename);
801 stream_info->abort_flag = true;
804 if(fwrite("RIFF", 1, 4, stream_info->fout) != 4) stream_info->abort_flag = true;
805 if(stream_info->wave_chunk_size_fixup.needs_fixup)
806 stream_info->wave_chunk_size_fixup.riff_offset = ftell(stream_info->fout);
807 if(!write_little_endian_uint32(stream_info->fout, (FLAC__uint32)(data_size+36))) stream_info->abort_flag = true; /* filesize-8 */
808 if(fwrite("WAVEfmt ", 1, 8, stream_info->fout) != 8) stream_info->abort_flag = true;
809 if(fwrite("\020\000\000\000", 1, 4, stream_info->fout) != 4) stream_info->abort_flag = true; /* chunk size = 16 */
810 if(fwrite("\001\000", 1, 2, stream_info->fout) != 2) stream_info->abort_flag = true; /* compression code == 1 */
811 if(!write_little_endian_uint16(stream_info->fout, (FLAC__uint16)(stream_info->channels))) stream_info->abort_flag = true;
812 if(!write_little_endian_uint32(stream_info->fout, stream_info->sample_rate)) stream_info->abort_flag = true;
813 if(!write_little_endian_uint32(stream_info->fout, stream_info->sample_rate * stream_info->channels * ((stream_info->bps+7) / 8))) stream_info->abort_flag = true; /* @@@ or is it (sample_rate*channels*bps) / 8 ??? */
814 if(!write_little_endian_uint16(stream_info->fout, (FLAC__uint16)(stream_info->channels * ((stream_info->bps+7) / 8)))) stream_info->abort_flag = true; /* block align */
815 if(!write_little_endian_uint16(stream_info->fout, (FLAC__uint16)(stream_info->bps))) stream_info->abort_flag = true; /* bits per sample */
816 if(fwrite("data", 1, 4, stream_info->fout) != 4) stream_info->abort_flag = true;
817 if(stream_info->wave_chunk_size_fixup.needs_fixup)
818 stream_info->wave_chunk_size_fixup.data_offset = ftell(stream_info->fout);
819 if(!write_little_endian_uint32(stream_info->fout, (FLAC__uint32)data_size)) stream_info->abort_flag = true; /* data size */
824 void error_callback(const void *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
826 stream_info_struct *stream_info = (stream_info_struct *)client_data;
828 fprintf(stderr, "%s: *** Got error code %d:%s\n", stream_info->inbasefilename, status, FLAC__StreamDecoderErrorStatusString[status]);
829 if(!stream_info->continue_through_decode_errors)
830 stream_info->abort_flag = true;
833 void print_stats(const stream_info_struct *stream_info)
835 if(stream_info->verbose) {
836 #if defined _MSC_VER || defined __MINGW32__
837 /* with VC++ you have to spoon feed it the casting */
838 const double progress = (double)(FLAC__int64)stream_info->samples_processed / (double)(FLAC__int64)stream_info->total_samples * 100.0;
840 const double progress = (double)stream_info->samples_processed / (double)stream_info->total_samples * 100.0;
842 if(stream_info->total_samples > 0) {
843 fprintf(stderr, "\r%s: %s%u%% complete",
844 stream_info->inbasefilename,
845 stream_info->test_only? "testing, " : stream_info->analysis_mode? "analyzing, " : "",
846 (unsigned)floor(progress + 0.5)
850 fprintf(stderr, "\r%s: %s %u samples",
851 stream_info->inbasefilename,
852 stream_info->test_only? "tested" : stream_info->analysis_mode? "analyzed" : "wrote",
853 (unsigned)stream_info->samples_processed
859 void metadata_callback(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data)
861 encoder_wrapper_struct *encoder_wrapper = (encoder_wrapper_struct *)client_data;
863 FILE *f = encoder_wrapper->fout;
864 const FLAC__uint64 samples = metadata->data.stream_info.total_samples;
865 const unsigned min_framesize = metadata->data.stream_info.min_framesize;
866 const unsigned max_framesize = metadata->data.stream_info.max_framesize;
868 FLAC__ASSERT(metadata->type == FLAC__METADATA_TYPE_STREAMINFO);
871 * If we are writing to an ogg stream, there is no need to go back
872 * and update the STREAMINFO or SEEKTABLE blocks; the values we would
873 * update are not necessary with Ogg as the transport. We can't do
874 * it reliably anyway without knowing the Ogg structure.
877 if(encoder_wrapper->use_ogg)
882 * we get called by the encoder when the encoding process has
883 * finished so that we can update the STREAMINFO and SEEKTABLE
887 (void)encoder; /* silence compiler warning about unused parameter */
890 fclose(encoder_wrapper->fout);
891 if(0 == (f = fopen(encoder_wrapper->outfilename, "r+b")))
895 /* all this is based on intimate knowledge of the stream header
896 * layout, but a change to the header format that would break this
897 * would also break all streams encoded in the previous format.
900 if(-1 == fseek(f, 26, SEEK_SET)) goto end_;
901 fwrite(metadata->data.stream_info.md5sum, 1, 16, f);
904 /* if we get this far we know we can seek so no need to check the
905 * return value from fseek()
907 fseek(f, 21, SEEK_SET);
908 if(fread(&b, 1, 1, f) != 1) goto framesize_;
909 fseek(f, 21, SEEK_SET);
910 b = (b & 0xf0) | (FLAC__byte)((samples >> 32) & 0x0F);
911 if(fwrite(&b, 1, 1, f) != 1) goto framesize_;
912 b = (FLAC__byte)((samples >> 24) & 0xFF);
913 if(fwrite(&b, 1, 1, f) != 1) goto framesize_;
914 b = (FLAC__byte)((samples >> 16) & 0xFF);
915 if(fwrite(&b, 1, 1, f) != 1) goto framesize_;
916 b = (FLAC__byte)((samples >> 8) & 0xFF);
917 if(fwrite(&b, 1, 1, f) != 1) goto framesize_;
918 b = (FLAC__byte)(samples & 0xFF);
919 if(fwrite(&b, 1, 1, f) != 1) goto framesize_;
922 fseek(f, 12, SEEK_SET);
923 b = (FLAC__byte)((min_framesize >> 16) & 0xFF);
924 if(fwrite(&b, 1, 1, f) != 1) goto seektable_;
925 b = (FLAC__byte)((min_framesize >> 8) & 0xFF);
926 if(fwrite(&b, 1, 1, f) != 1) goto seektable_;
927 b = (FLAC__byte)(min_framesize & 0xFF);
928 if(fwrite(&b, 1, 1, f) != 1) goto seektable_;
929 b = (FLAC__byte)((max_framesize >> 16) & 0xFF);
930 if(fwrite(&b, 1, 1, f) != 1) goto seektable_;
931 b = (FLAC__byte)((max_framesize >> 8) & 0xFF);
932 if(fwrite(&b, 1, 1, f) != 1) goto seektable_;
933 b = (FLAC__byte)(max_framesize & 0xFF);
934 if(fwrite(&b, 1, 1, f) != 1) goto seektable_;
937 if(encoder_wrapper->seek_table.num_points > 0) {
941 /* convert any unused seek points to placeholders */
942 for(i = 0; i < encoder_wrapper->seek_table.num_points; i++) {
943 if(encoder_wrapper->seek_table.points[i].sample_number == FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER)
945 else if(encoder_wrapper->seek_table.points[i].frame_samples == 0)
946 encoder_wrapper->seek_table.points[i].sample_number = FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER;
949 /* the offset of the seek table data 'pos' should be after then stream sync and STREAMINFO block and SEEKTABLE header */
950 pos = (FLAC__STREAM_SYNC_LEN + FLAC__STREAM_METADATA_IS_LAST_LEN + FLAC__STREAM_METADATA_TYPE_LEN + FLAC__STREAM_METADATA_LENGTH_LEN) / 8;
951 pos += metadata->length;
952 pos += (FLAC__STREAM_METADATA_IS_LAST_LEN + FLAC__STREAM_METADATA_TYPE_LEN + FLAC__STREAM_METADATA_LENGTH_LEN) / 8;
953 fseek(f, pos, SEEK_SET);
954 for(i = 0; i < encoder_wrapper->seek_table.num_points; i++) {
955 if(!write_big_endian_uint64(f, encoder_wrapper->seek_table.points[i].sample_number)) goto end_;
956 if(!write_big_endian_uint64(f, encoder_wrapper->seek_table.points[i].stream_offset)) goto end_;
957 if(!write_big_endian_uint16(f, (FLAC__uint16)encoder_wrapper->seek_table.points[i].frame_samples)) goto end_;