minor syntax
[platform/upstream/flac.git] / src / flac / decode.c
1 /* flac - Command-line FLAC encoder/decoder
2  * Copyright (C) 2000,2001,2002  Josh Coalson
3  *
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.
8  *
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.
13  *
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.
17  */
18
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22
23 #if defined _WIN32 && !defined __CYGWIN__
24 /* where MSVC puts unlink() */
25 # include <io.h>
26 #else
27 # include <unistd.h>
28 #endif
29 #include <math.h> /* for floor() */
30 #include <stdio.h> /* for FILE et al. */
31 #include <string.h> /* for strcmp() */
32 #include "FLAC/all.h"
33 #include "share/grabbag.h"
34 #include "decode.h"
35
36 #ifdef FLAC__HAS_OGG
37 #include "OggFLAC/stream_decoder.h"
38 #endif
39
40 typedef struct {
41 #ifdef FLAC__HAS_OGG
42         FLAC__bool is_ogg;
43 #endif
44
45         FLAC__bool verbose;
46         FLAC__bool is_aiff_out;
47         FLAC__bool is_wave_out;
48         FLAC__bool continue_through_decode_errors;
49         FLAC__bool test_only;
50         FLAC__bool analysis_mode;
51         analysis_options aopts;
52         utils__SkipUntilSpecification *skip_specification;
53         utils__SkipUntilSpecification *until_specification; /* a canonicalized value of 0 mean end-of-stream (i.e. --until=-0) */
54
55         const char *inbasefilename;
56         const char *outfilename;
57
58         FLAC__uint64 samples_processed;
59         unsigned frame_counter;
60         FLAC__bool abort_flag;
61
62         struct {
63                 FLAC__bool needs_fixup;
64                 unsigned riff_offset; /* or FORM offset for AIFF */
65                 unsigned data_offset; /* or SSND offset for AIFF */
66                 unsigned frames_offset; /* AIFF only */
67         } wave_chunk_size_fixup;
68
69         FLAC__bool is_big_endian;
70         FLAC__bool is_unsigned_samples;
71         FLAC__uint64 total_samples;
72         unsigned bps;
73         unsigned channels;
74         unsigned sample_rate;
75
76         union {
77                 union {
78                         FLAC__FileDecoder *file;
79                 } flac;
80 #ifdef FLAC__HAS_OGG
81                 union {
82                         OggFLAC__StreamDecoder *stream;
83                 } ogg;
84 #endif
85         } decoder;
86
87 #ifdef FLAC__HAS_OGG
88         FILE *fin;
89 #endif
90         FILE *fout;
91 } DecoderSession;
92
93
94 static FLAC__bool is_big_endian_host_;
95
96
97 /*
98  * local routines
99  */
100 static FLAC__bool DecoderSession_construct(DecoderSession *d, FLAC__bool is_ogg, FLAC__bool verbose, FLAC__bool is_aiff_out, FLAC__bool is_wave_out, FLAC__bool continue_through_decode_errors, FLAC__bool analysis_mode, analysis_options aopts, utils__SkipUntilSpecification *skip_specification, utils__SkipUntilSpecification *until_specification, const char *infilename, const char *outfilename);
101 static void DecoderSession_destroy(DecoderSession *d, FLAC__bool error_occurred);
102 static FLAC__bool DecoderSession_init_decoder(DecoderSession *d, decode_options_t decode_options, const char *infilename);
103 static FLAC__bool DecoderSession_process(DecoderSession *d);
104 static int DecoderSession_finish_ok(DecoderSession *d);
105 static int DecoderSession_finish_error(DecoderSession *d);
106 static FLAC__bool canonicalize_until_specification(utils__SkipUntilSpecification *spec, const char *inbasefilename, unsigned sample_rate, FLAC__uint64 skip, FLAC__uint64 total_samples_in_input);
107 static FLAC__bool write_little_endian_uint16(FILE *f, FLAC__uint16 val);
108 static FLAC__bool write_little_endian_uint32(FILE *f, FLAC__uint32 val);
109 static FLAC__bool write_big_endian_uint16(FILE *f, FLAC__uint16 val);
110 static FLAC__bool write_big_endian_uint32(FILE *f, FLAC__uint32 val);
111 static FLAC__bool write_sane_extended(FILE *f, unsigned val);
112 static FLAC__bool fixup_wave_chunk_size(const char *outfilename, FLAC__bool is_wave_out, unsigned riff_offset, unsigned data_offset, unsigned frames_offset, FLAC__uint32 total_samples, unsigned channels, unsigned bps);
113 #ifdef FLAC__HAS_OGG
114 static FLAC__StreamDecoderReadStatus read_callback(const OggFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
115 #endif
116 /*
117  * We use 'void *' so that we can use the same callbacks for the
118  * FLAC__StreamDecoder and FLAC__FileDecoder.  The 'decoder' argument is
119  * actually never used in the callbacks.
120  */
121 static FLAC__StreamDecoderWriteStatus write_callback(const void *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
122 static void metadata_callback(const void *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
123 static void error_callback(const void *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
124 static void print_error_with_state(const DecoderSession *d, const char *message);
125 static void print_stats(const DecoderSession *decoder_session);
126
127
128 /*
129  * public routines
130  */
131 int flac__decode_aiff(const char *infilename, const char *outfilename, FLAC__bool analysis_mode, analysis_options aopts, wav_decode_options_t options)
132 {
133         DecoderSession decoder_session;
134
135         if(!
136                 DecoderSession_construct(
137                         &decoder_session,
138 #ifdef FLAC__HAS_OGG
139                         options.common.is_ogg,
140 #else
141                         /*is_ogg=*/false,
142 #endif
143                         options.common.verbose,
144                         /*is_aiff_out=*/true,
145                         /*is_wave_out=*/false,
146                         options.common.continue_through_decode_errors,
147                         analysis_mode,
148                         aopts,
149                         &options.common.skip_specification,
150                         &options.common.until_specification,
151                         infilename,
152                         outfilename
153                 )
154         )
155                 return 1;
156
157         if(!DecoderSession_init_decoder(&decoder_session, options.common, infilename))
158                 return DecoderSession_finish_error(&decoder_session);
159
160         if(!DecoderSession_process(&decoder_session))
161                 return DecoderSession_finish_error(&decoder_session);
162
163         return DecoderSession_finish_ok(&decoder_session);
164 }
165
166 int flac__decode_wav(const char *infilename, const char *outfilename, FLAC__bool analysis_mode, analysis_options aopts, wav_decode_options_t options)
167 {
168         DecoderSession decoder_session;
169
170         if(!
171                 DecoderSession_construct(
172                         &decoder_session,
173 #ifdef FLAC__HAS_OGG
174                         options.common.is_ogg,
175 #else
176                         /*is_ogg=*/false,
177 #endif
178                         options.common.verbose,
179                         /*is_aiff_out=*/false,
180                         /*is_wave_out=*/true,
181                         options.common.continue_through_decode_errors,
182                         analysis_mode,
183                         aopts,
184                         &options.common.skip_specification,
185                         &options.common.until_specification,
186                         infilename,
187                         outfilename
188                 )
189         )
190                 return 1;
191
192         if(!DecoderSession_init_decoder(&decoder_session, options.common, infilename))
193                 return DecoderSession_finish_error(&decoder_session);
194
195         if(!DecoderSession_process(&decoder_session))
196                 return DecoderSession_finish_error(&decoder_session);
197
198         return DecoderSession_finish_ok(&decoder_session);
199 }
200
201 int flac__decode_raw(const char *infilename, const char *outfilename, FLAC__bool analysis_mode, analysis_options aopts, raw_decode_options_t options)
202 {
203         DecoderSession decoder_session;
204
205         decoder_session.is_big_endian = options.is_big_endian;
206         decoder_session.is_unsigned_samples = options.is_unsigned_samples;
207
208         if(!
209                 DecoderSession_construct(
210                         &decoder_session,
211 #ifdef FLAC__HAS_OGG
212                         options.common.is_ogg,
213 #else
214                         /*is_ogg=*/false,
215 #endif
216                         options.common.verbose,
217                         /*is_aiff_out=*/false,
218                         /*is_wave_out=*/false,
219                         options.common.continue_through_decode_errors,
220                         analysis_mode,
221                         aopts,
222                         &options.common.skip_specification,
223                         &options.common.until_specification,
224                         infilename,
225                         outfilename
226                 )
227         )
228                 return 1;
229
230         if(!DecoderSession_init_decoder(&decoder_session, options.common, infilename))
231                 return DecoderSession_finish_error(&decoder_session);
232
233         if(!DecoderSession_process(&decoder_session))
234                 return DecoderSession_finish_error(&decoder_session);
235
236         return DecoderSession_finish_ok(&decoder_session);
237 }
238
239 FLAC__bool DecoderSession_construct(DecoderSession *d, FLAC__bool is_ogg, FLAC__bool verbose, FLAC__bool is_aiff_out, FLAC__bool is_wave_out, FLAC__bool continue_through_decode_errors, FLAC__bool analysis_mode, analysis_options aopts, utils__SkipUntilSpecification *skip_specification, utils__SkipUntilSpecification *until_specification, const char *infilename, const char *outfilename)
240 {
241 #ifdef FLAC__HAS_OGG
242         d->is_ogg = is_ogg;
243 #else
244         (void)is_ogg;
245 #endif
246
247         d->verbose = verbose;
248         d->is_aiff_out = is_aiff_out;
249         d->is_wave_out = is_wave_out;
250         d->continue_through_decode_errors = continue_through_decode_errors;
251         d->test_only = (0 == outfilename);
252         d->analysis_mode = analysis_mode;
253         d->aopts = aopts;
254         d->skip_specification = skip_specification;
255         d->until_specification = until_specification;
256
257         d->inbasefilename = grabbag__file_get_basename(infilename);
258         d->outfilename = outfilename;
259
260         d->samples_processed = 0;
261         d->frame_counter = 0;
262         d->abort_flag = false;
263
264         d->wave_chunk_size_fixup.needs_fixup = false;
265
266         d->decoder.flac.file = 0;
267 #ifdef FLAC__HAS_OGG
268         d->decoder.ogg.stream = 0;
269 #endif
270
271 #ifdef FLAC__HAS_OGG
272         d->fin = 0;
273 #endif
274         d->fout = 0; /* initialized with an open file later if necessary */
275
276         FLAC__ASSERT(!(d->test_only && d->analysis_mode));
277
278         if(!d->test_only) {
279                 if(0 == strcmp(outfilename, "-")) {
280                         d->fout = grabbag__file_get_binary_stdout();
281                 }
282                 else {
283                         if(0 == (d->fout = fopen(outfilename, "wb"))) {
284                                 fprintf(stderr, "%s: ERROR: can't open output file %s\n", d->inbasefilename, outfilename);
285                                 DecoderSession_destroy(d, /*error_occurred=*/true);
286                                 return false;
287                         }
288                 }
289         }
290
291 #ifdef FLAC__HAS_OGG
292         if(d->is_ogg) {
293                 if (0 == strcmp(infilename, "-")) {
294                         d->fin = grabbag__file_get_binary_stdin();
295                 } else {
296                         if (0 == (d->fin = fopen(infilename, "rb"))) {
297                                 fprintf(stderr, "%s: ERROR: can't open input file %s\n", d->inbasefilename, infilename);
298                                 DecoderSession_destroy(d, /*error_occurred=*/true);
299                                 return false;
300                         }
301                 }
302         }
303 #endif
304
305         if(analysis_mode)
306                 flac__analyze_init(aopts);
307
308         return true;
309 }
310
311 void DecoderSession_destroy(DecoderSession *d, FLAC__bool error_occurred)
312 {
313         if(0 != d->fout && d->fout != stdout) {
314                 fclose(d->fout);
315                 if(error_occurred)
316                         unlink(d->outfilename);
317         }
318 #ifdef FLAC__HAS_OGG
319         if(0 != d->fin && d->fin != stdin)
320                 fclose(d->fin);
321 #endif
322 }
323
324 FLAC__bool DecoderSession_init_decoder(DecoderSession *decoder_session, decode_options_t decode_options, const char *infilename)
325 {
326         FLAC__uint32 test = 1;
327
328         is_big_endian_host_ = (*((FLAC__byte*)(&test)))? false : true;
329
330 #ifdef FLAC__HAS_OGG
331         if(decoder_session->is_ogg) {
332                 decoder_session->decoder.ogg.stream = OggFLAC__stream_decoder_new();
333
334                 if(0 == decoder_session->decoder.ogg.stream) {
335                         fprintf(stderr, "%s: ERROR creating the decoder instance\n", decoder_session->inbasefilename);
336                         return false;
337                 }
338
339                 if(!decode_options.use_first_serial_number)
340                         OggFLAC__stream_decoder_set_serial_number(decoder_session->decoder.ogg.stream, decode_options.serial_number);
341
342                 OggFLAC__stream_decoder_set_read_callback(decoder_session->decoder.ogg.stream, read_callback);
343                 /*
344                  * The three ugly casts here are to 'downcast' the 'void *' argument of
345                  * the callback down to 'FLAC__StreamDecoder *'.  In C++ this would be
346                  * unnecessary but here the cast makes the C compiler happy.
347                  */
348                 OggFLAC__stream_decoder_set_write_callback(decoder_session->decoder.ogg.stream, (FLAC__StreamDecoderWriteStatus (*)(const OggFLAC__StreamDecoder *, const FLAC__Frame *, const FLAC__int32 * const [], void *))write_callback);
349                 OggFLAC__stream_decoder_set_metadata_callback(decoder_session->decoder.ogg.stream, (void (*)(const OggFLAC__StreamDecoder *, const FLAC__StreamMetadata *, void *))metadata_callback);
350                 OggFLAC__stream_decoder_set_error_callback(decoder_session->decoder.ogg.stream, (void (*)(const OggFLAC__StreamDecoder *, FLAC__StreamDecoderErrorStatus, void *))error_callback);
351                 OggFLAC__stream_decoder_set_client_data(decoder_session->decoder.ogg.stream, decoder_session);
352
353                 if(OggFLAC__stream_decoder_init(decoder_session->decoder.ogg.stream) != OggFLAC__STREAM_DECODER_OK) {
354                         print_error_with_state(decoder_session, "ERROR initializing decoder");
355                         return false;
356                 }
357         }
358         else
359 #else
360         (void)decode_options;
361 #endif
362         {
363                 decoder_session->decoder.flac.file = FLAC__file_decoder_new();
364
365                 if(0 == decoder_session->decoder.flac.file) {
366                         fprintf(stderr, "%s: ERROR creating the decoder instance\n", decoder_session->inbasefilename);
367                         return false;
368                 }
369
370                 FLAC__file_decoder_set_md5_checking(decoder_session->decoder.flac.file, true);
371                 FLAC__file_decoder_set_filename(decoder_session->decoder.flac.file, infilename);
372                 /*
373                  * The three ugly casts here are to 'downcast' the 'void *' argument of
374                  * the callback down to 'FLAC__FileDecoder *'.
375                  */
376                 FLAC__file_decoder_set_write_callback(decoder_session->decoder.flac.file, (FLAC__StreamDecoderWriteStatus (*)(const FLAC__FileDecoder *, const FLAC__Frame *, const FLAC__int32 * const [], void *))write_callback);
377                 FLAC__file_decoder_set_metadata_callback(decoder_session->decoder.flac.file, (void (*)(const FLAC__FileDecoder *, const FLAC__StreamMetadata *, void *))metadata_callback);
378                 FLAC__file_decoder_set_error_callback(decoder_session->decoder.flac.file, (void (*)(const FLAC__FileDecoder *, FLAC__StreamDecoderErrorStatus, void *))error_callback);
379                 FLAC__file_decoder_set_client_data(decoder_session->decoder.flac.file, decoder_session);
380
381                 if(FLAC__file_decoder_init(decoder_session->decoder.flac.file) != FLAC__FILE_DECODER_OK) {
382                         print_error_with_state(decoder_session, "ERROR initializing decoder");
383                         return false;
384                 }
385         }
386
387         return true;
388 }
389
390 FLAC__bool DecoderSession_process(DecoderSession *d)
391 {
392 #ifdef FLAC__HAS_OGG
393         if(d->is_ogg) {
394                 if(!OggFLAC__stream_decoder_process_until_end_of_metadata(d->decoder.ogg.stream)) {
395                         if(d->verbose) fprintf(stderr, "\n");
396                         print_error_with_state(d, "ERROR while decoding metadata");
397                         return false;
398                 }
399                 if(OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(d->decoder.ogg.stream) != FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC && OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(d->decoder.ogg.stream) != FLAC__STREAM_DECODER_END_OF_STREAM) {
400                         if(d->verbose) fprintf(stderr, "\n");
401                         print_error_with_state(d, "ERROR during metadata decoding");
402                         return false;
403                 }
404         }
405         else
406 #endif
407         {
408                 if(!FLAC__file_decoder_process_until_end_of_metadata(d->decoder.flac.file)) {
409                         if(d->verbose) fprintf(stderr, "\n");
410                         print_error_with_state(d, "ERROR while decoding metadata");
411                         return false;
412                 }
413                 if(FLAC__file_decoder_get_state(d->decoder.flac.file) != FLAC__FILE_DECODER_OK && FLAC__file_decoder_get_state(d->decoder.flac.file) != FLAC__FILE_DECODER_END_OF_FILE) {
414                         if(d->verbose) fprintf(stderr, "\n");
415                         print_error_with_state(d, "ERROR during metadata decoding");
416                         return false;
417                 }
418         }
419         if(d->abort_flag)
420                 return false;
421
422         if(d->skip_specification->value.samples > 0) {
423                 const FLAC__uint64 skip = (FLAC__uint64)d->skip_specification->value.samples;
424
425 #ifdef FLAC__HAS_OGG
426                 if(d->is_ogg) { /*@@@ (move this check into main.c) */
427                         fprintf(stderr, "%s: ERROR, can't skip when decoding Ogg-FLAC yet; convert to native-FLAC first\n", d->inbasefilename);
428                         return false;
429                 }
430 #endif
431                 if(!FLAC__file_decoder_seek_absolute(d->decoder.flac.file, skip)) {
432                         print_error_with_state(d, "ERROR seeking while skipping bytes");
433                         return false;
434                 }
435                 if(!FLAC__file_decoder_process_until_end_of_file(d->decoder.flac.file)) {
436                         if(d->verbose) fprintf(stderr, "\n");
437                         print_error_with_state(d, "ERROR while decoding frames");
438                         return false;
439                 }
440                 if(FLAC__file_decoder_get_state(d->decoder.flac.file) != FLAC__FILE_DECODER_OK && FLAC__file_decoder_get_state(d->decoder.flac.file) != FLAC__FILE_DECODER_END_OF_FILE) {
441                         if(d->verbose) fprintf(stderr, "\n");
442                         print_error_with_state(d, "ERROR during decoding");
443                         return false;
444                 }
445         }
446         else {
447 #ifdef FLAC__HAS_OGG
448                 if(d->is_ogg) {
449                         if(!OggFLAC__stream_decoder_process_until_end_of_stream(d->decoder.ogg.stream)) {
450                                 if(d->verbose) fprintf(stderr, "\n");
451                                 print_error_with_state(d, "ERROR while decoding data");
452                                 return false;
453                         }
454                         if(OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(d->decoder.ogg.stream) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA && OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(d->decoder.ogg.stream) != FLAC__STREAM_DECODER_END_OF_STREAM) {
455                                 if(d->verbose) fprintf(stderr, "\n");
456                                 print_error_with_state(d, "ERROR during decoding");
457                                 return false;
458                         }
459                 }
460                 else
461 #endif
462                 {
463                         if(!FLAC__file_decoder_process_until_end_of_file(d->decoder.flac.file)) {
464                                 if(d->verbose) fprintf(stderr, "\n");
465                                 print_error_with_state(d, "ERROR while decoding data");
466                                 return false;
467                         }
468                         if(FLAC__file_decoder_get_state(d->decoder.flac.file) != FLAC__FILE_DECODER_OK && FLAC__file_decoder_get_state(d->decoder.flac.file) != FLAC__FILE_DECODER_END_OF_FILE) {
469                                 if(d->verbose) fprintf(stderr, "\n");
470                                 print_error_with_state(d, "ERROR during decoding");
471                                 return false;
472                         }
473                 }
474         }
475
476         if(d->is_aiff_out && ((d->total_samples * d->channels * ((d->bps+7)/8)) & 1)) {
477                 if(flac__utils_fwrite("\000", 1, 1, d->fout) != 1) {
478                         print_error_with_state(d, "ERROR writing pad byte to AIFF SSND chunk");
479                         return false;
480                 }
481         }
482
483         return true;
484 }
485
486 int DecoderSession_finish_ok(DecoderSession *d)
487 {
488         FLAC__bool md5_failure = false;
489
490 #ifdef FLAC__HAS_OGG
491         if(d->is_ogg) {
492                 if(d->decoder.ogg.stream) {
493                         OggFLAC__stream_decoder_finish(d->decoder.ogg.stream);
494                         md5_failure = false;
495                         print_stats(d);
496                         OggFLAC__stream_decoder_delete(d->decoder.ogg.stream);
497                 }
498         }
499         else
500 #endif
501         {
502                 if(d->decoder.flac.file) {
503                         md5_failure = !FLAC__file_decoder_finish(d->decoder.flac.file);
504                         print_stats(d);
505                         FLAC__file_decoder_delete(d->decoder.flac.file);
506                 }
507         }
508         if(d->analysis_mode)
509                 flac__analyze_finish(d->aopts);
510         if(md5_failure) {
511                 fprintf(stderr, "\r%s: WARNING, MD5 signature mismatch\n", d->inbasefilename);
512         }
513         else {
514                 if(d->verbose)
515                         fprintf(stderr, "\r%s: %s         \n", d->inbasefilename, d->test_only? "ok           ":d->analysis_mode?"done           ":"done");
516         }
517         DecoderSession_destroy(d, /*error_occurred=*/false);
518         if((d->is_wave_out || d->is_aiff_out) && d->wave_chunk_size_fixup.needs_fixup)
519                 if(!fixup_wave_chunk_size(d->outfilename, d->is_wave_out, d->wave_chunk_size_fixup.riff_offset, d->wave_chunk_size_fixup.data_offset, d->wave_chunk_size_fixup.frames_offset, (FLAC__uint32)d->samples_processed, d->channels, d->bps))
520                         return 1;
521         return 0;
522 }
523
524 int DecoderSession_finish_error(DecoderSession *d)
525 {
526 #ifdef FLAC__HAS_OGG
527         if(d->is_ogg) {
528                 if(d->decoder.ogg.stream) {
529                         OggFLAC__stream_decoder_finish(d->decoder.ogg.stream);
530                         OggFLAC__stream_decoder_delete(d->decoder.ogg.stream);
531                 }
532         }
533         else
534 #endif
535         {
536                 if(d->decoder.flac.file) {
537                         FLAC__file_decoder_finish(d->decoder.flac.file);
538                         FLAC__file_decoder_delete(d->decoder.flac.file);
539                 }
540         }
541         if(d->analysis_mode)
542                 flac__analyze_finish(d->aopts);
543         DecoderSession_destroy(d, /*error_occurred=*/true);
544         return 1;
545 }
546
547 FLAC__bool canonicalize_until_specification(utils__SkipUntilSpecification *spec, const char *inbasefilename, unsigned sample_rate, FLAC__uint64 skip, FLAC__uint64 total_samples_in_input)
548 {
549         /* convert from mm:ss.sss to sample number if necessary */
550         flac__utils_canonicalize_skip_until_specification(spec, sample_rate);
551
552         /* special case: if "--until=-0", use the special value '0' to mean "end-of-stream" */
553         if(spec->is_relative && spec->value.samples == 0) {
554                 spec->is_relative = false;
555                 return true;
556         }
557
558         /* in any other case the total samples in the input must be known */
559         if(total_samples_in_input == 0) {
560                 fprintf(stderr, "%s: ERROR, cannot use --until when FLAC metadata has total sample count of 0\n", inbasefilename);
561                 return false;
562         }
563
564         FLAC__ASSERT(spec->value_is_samples);
565
566         /* convert relative specifications to absolute */
567         if(spec->is_relative) {
568                 if(spec->value.samples <= 0)
569                         spec->value.samples += (FLAC__int64)total_samples_in_input;
570                 else
571                         spec->value.samples += skip;
572                 spec->is_relative = false;
573         }
574
575         /* error check */
576         if(spec->value.samples < 0) {
577                 fprintf(stderr, "%s: ERROR, --until value is before beginning of input\n", inbasefilename);
578                 return false;
579         }
580         if((FLAC__uint64)spec->value.samples <= skip) {
581                 fprintf(stderr, "%s: ERROR, --until value is before --skip point\n", inbasefilename);
582                 return false;
583         }
584         if((FLAC__uint64)spec->value.samples > total_samples_in_input) {
585                 fprintf(stderr, "%s: ERROR, --until value is after end of input\n", inbasefilename);
586                 return false;
587         }
588
589         return true;
590 }
591
592 FLAC__bool write_little_endian_uint16(FILE *f, FLAC__uint16 val)
593 {
594         FLAC__byte *b = (FLAC__byte*)(&val);
595         if(is_big_endian_host_) {
596                 FLAC__byte tmp;
597                 tmp = b[1]; b[1] = b[0]; b[0] = tmp;
598         }
599         return flac__utils_fwrite(b, 1, 2, f) == 2;
600 }
601
602 FLAC__bool write_little_endian_uint32(FILE *f, FLAC__uint32 val)
603 {
604         FLAC__byte *b = (FLAC__byte*)(&val);
605         if(is_big_endian_host_) {
606                 FLAC__byte tmp;
607                 tmp = b[3]; b[3] = b[0]; b[0] = tmp;
608                 tmp = b[2]; b[2] = b[1]; b[1] = tmp;
609         }
610         return flac__utils_fwrite(b, 1, 4, f) == 4;
611 }
612
613 FLAC__bool write_big_endian_uint16(FILE *f, FLAC__uint16 val)
614 {
615         FLAC__byte *b = (FLAC__byte*)(&val);
616         if(!is_big_endian_host_) {
617                 FLAC__byte tmp;
618                 tmp = b[1]; b[1] = b[0]; b[0] = tmp;
619         }
620         return flac__utils_fwrite(b, 1, 2, f) == 2;
621 }
622
623 FLAC__bool write_big_endian_uint32(FILE *f, FLAC__uint32 val)
624 {
625         FLAC__byte *b = (FLAC__byte*)(&val);
626         if(!is_big_endian_host_) {
627                 FLAC__byte tmp;
628                 tmp = b[3]; b[3] = b[0]; b[0] = tmp;
629                 tmp = b[2]; b[2] = b[1]; b[1] = tmp;
630         }
631         return flac__utils_fwrite(b, 1, 4, f) == 4;
632 }
633
634 FLAC__bool write_sane_extended(FILE *f, unsigned val)
635 {
636         unsigned i, exponent;
637
638         /* this reasonable limitation make the implementation simpler */
639         FLAC__ASSERT(val < 0x80000000);
640
641         /* we'll use the denormalized form, with no implicit '1' (i bit == 0) */
642
643         for(i = val, exponent = 0; i; i >>= 1, exponent++)
644                 ;
645         if(!write_big_endian_uint16(f, (FLAC__uint16)(exponent + 16383)))
646                 return false;
647
648         for(i = 32; i; i--) {
649                 if(val & 0x40000000)
650                         break;
651                 val <<= 1;
652         }
653         if(!write_big_endian_uint32(f, val))
654                 return false;
655         if(!write_big_endian_uint32(f, 0))
656                 return false;
657
658         return true;
659 }
660
661 FLAC__bool fixup_wave_chunk_size(const char *outfilename, FLAC__bool is_wave_out, unsigned riff_offset, unsigned data_offset, unsigned frames_offset, FLAC__uint32 total_samples, unsigned channels, unsigned bps)
662 {
663         const char *fmt_desc = (is_wave_out? "WAVE" : "AIFF");
664         FLAC__bool (*write_it)(FILE *, FLAC__uint32) = (is_wave_out? write_little_endian_uint32 : write_big_endian_uint32);
665         FILE *f = fopen(outfilename, "r+b");
666         FLAC__uint32 data_size, aligned_data_size;
667
668         if(0 == f) {
669                 fprintf(stderr, "ERROR, couldn't open file %s while fixing up %s chunk size\n", outfilename, fmt_desc);
670                 return false;
671         }
672
673         data_size = aligned_data_size = total_samples * channels * ((bps+7)/8);
674         if(!is_wave_out && (aligned_data_size & 1))
675                 aligned_data_size++;
676
677         if(fseek(f, riff_offset, SEEK_SET) < 0) {
678                 fprintf(stderr, "ERROR, couldn't seek in file %s while fixing up %s chunk size\n", outfilename, fmt_desc);
679                 fclose(f);
680                 return false;
681         }
682         if(!write_it(f, aligned_data_size + (is_wave_out? 36 : 46))) {
683                 fprintf(stderr, "ERROR, couldn't write size in file %s while fixing up %s chunk size\n", outfilename, fmt_desc);
684                 fclose(f);
685                 return false;
686         }
687         if(!is_wave_out) {
688                 if(fseek(f, frames_offset, SEEK_SET) < 0) {
689                         fprintf(stderr, "ERROR, couldn't seek in file %s while fixing up %s chunk size\n", outfilename, fmt_desc);
690                         fclose(f);
691                         return false;
692                 }
693                 if(!write_it(f, total_samples)) {
694                         fprintf(stderr, "ERROR, couldn't write size in file %s while fixing up %s chunk size\n", outfilename, fmt_desc);
695                         fclose(f);
696                         return false;
697                 }
698         }
699         if(fseek(f, data_offset, SEEK_SET) < 0) {
700                 fprintf(stderr, "ERROR, couldn't seek in file %s while fixing up %s chunk size\n", outfilename, fmt_desc);
701                 fclose(f);
702                 return false;
703         }
704         if(!write_it(f, data_size + (is_wave_out? 0 : 8))) {
705                 fprintf(stderr, "ERROR, couldn't write size in file %s while fixing up %s chunk size\n", outfilename, fmt_desc);
706                 fclose(f);
707                 return false;
708         }
709         fclose(f);
710         return true;
711 }
712
713 #ifdef FLAC__HAS_OGG
714 FLAC__StreamDecoderReadStatus read_callback(const OggFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
715 {
716         DecoderSession *decoder_session = (DecoderSession*)client_data;
717         FILE *fin = decoder_session->fin;
718         size_t bytes_read;
719
720         (void)decoder; /* avoid compiler warning */
721
722         if (decoder_session->abort_flag)
723                 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
724
725         if(feof(fin))
726                 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
727
728         bytes_read = fread(buffer, 1, *bytes, fin);
729
730         if(ferror(fin))
731                 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
732
733         *bytes = (unsigned)bytes_read;
734
735         return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
736 }
737 #endif
738
739 FLAC__StreamDecoderWriteStatus write_callback(const void *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
740 {
741         DecoderSession *decoder_session = (DecoderSession*)client_data;
742         FILE *fout = decoder_session->fout;
743         const unsigned bps = frame->header.bits_per_sample, channels = frame->header.channels;
744         FLAC__bool is_big_endian = (decoder_session->is_aiff_out? true : (decoder_session->is_wave_out? false : decoder_session->is_big_endian));
745         FLAC__bool is_unsigned_samples = (decoder_session->is_aiff_out? false : (decoder_session->is_wave_out? bps<=8 : decoder_session->is_unsigned_samples));
746         unsigned wide_samples = frame->header.blocksize, wide_sample, sample, channel, byte;
747         static FLAC__int8 s8buffer[FLAC__MAX_BLOCK_SIZE * FLAC__MAX_CHANNELS * sizeof(FLAC__int32)]; /* WATCHOUT: can be up to 2 megs */
748         FLAC__uint8  *u8buffer  = (FLAC__uint8  *)s8buffer;
749         FLAC__int16  *s16buffer = (FLAC__int16  *)s8buffer;
750         FLAC__uint16 *u16buffer = (FLAC__uint16 *)s8buffer;
751         FLAC__int32  *s32buffer = (FLAC__int32  *)s8buffer;
752         FLAC__uint32 *u32buffer = (FLAC__uint32 *)s8buffer;
753
754         (void)decoder;
755
756         if(decoder_session->abort_flag)
757                 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
758
759         if(bps != decoder_session->bps) {
760                 fprintf(stderr, "%s: ERROR, bits-per-sample is %u in frame but %u in STREAMINFO\n", decoder_session->inbasefilename, bps, decoder_session->bps);
761                 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
762         }
763         if(channels != decoder_session->channels) {
764                 fprintf(stderr, "%s: ERROR, channels is %u in frame but %u in STREAMINFO\n", decoder_session->inbasefilename, channels, decoder_session->channels);
765                 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
766         }
767         if(frame->header.sample_rate != decoder_session->sample_rate) {
768                 fprintf(stderr, "%s: ERROR, sample rate is %u in frame but %u in STREAMINFO\n", decoder_session->inbasefilename, frame->header.sample_rate, decoder_session->sample_rate);
769                 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
770         }
771
772         /*
773          * limit the number of samples to accept based on --until
774          */
775         FLAC__ASSERT(!decoder_session->skip_specification->is_relative);
776         FLAC__ASSERT(decoder_session->skip_specification->value.samples >= 0);
777         FLAC__ASSERT(!decoder_session->until_specification->is_relative);
778         FLAC__ASSERT(decoder_session->until_specification->value.samples >= 0);
779         if(decoder_session->until_specification->value.samples > 0) {
780                 const FLAC__uint64 skip = (FLAC__uint64)decoder_session->skip_specification->value.samples;
781                 const FLAC__uint64 until = (FLAC__uint64)decoder_session->until_specification->value.samples;
782                 const FLAC__uint64 input_samples_passed = skip + decoder_session->samples_processed;
783                 FLAC__ASSERT(until >= input_samples_passed);
784                 if(input_samples_passed + wide_samples > until)
785                         wide_samples = (unsigned)(until - input_samples_passed);
786         }
787
788         if(wide_samples > 0) {
789                 decoder_session->samples_processed += wide_samples;
790                 decoder_session->frame_counter++;
791
792                 if(decoder_session->verbose && !(decoder_session->frame_counter & 0x3f))
793                         print_stats(decoder_session);
794
795                 if(decoder_session->analysis_mode) {
796                         flac__analyze_frame(frame, decoder_session->frame_counter-1, decoder_session->aopts, fout);
797                 }
798                 else if(!decoder_session->test_only) {
799                         if(bps == 8) {
800                                 if(is_unsigned_samples) {
801                                         for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
802                                                 for(channel = 0; channel < channels; channel++, sample++)
803                                                         u8buffer[sample] = (FLAC__uint8)(buffer[channel][wide_sample] + 0x80);
804                                 }
805                                 else {
806                                         for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
807                                                 for(channel = 0; channel < channels; channel++, sample++)
808                                                         s8buffer[sample] = (FLAC__int8)(buffer[channel][wide_sample]);
809                                 }
810                                 if(flac__utils_fwrite(u8buffer, 1, sample, fout) != sample)
811                                         return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
812                         }
813                         else if(bps == 16) {
814                                 if(is_unsigned_samples) {
815                                         for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
816                                                 for(channel = 0; channel < channels; channel++, sample++)
817                                                         u16buffer[sample] = (FLAC__uint16)(buffer[channel][wide_sample] + 0x8000);
818                                 }
819                                 else {
820                                         for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
821                                                 for(channel = 0; channel < channels; channel++, sample++)
822                                                         s16buffer[sample] = (FLAC__int16)(buffer[channel][wide_sample]);
823                                 }
824                                 if(is_big_endian != is_big_endian_host_) {
825                                         unsigned char tmp;
826                                         const unsigned bytes = sample * 2;
827                                         for(byte = 0; byte < bytes; byte += 2) {
828                                                 tmp = u8buffer[byte];
829                                                 u8buffer[byte] = u8buffer[byte+1];
830                                                 u8buffer[byte+1] = tmp;
831                                         }
832                                 }
833                                 if(flac__utils_fwrite(u16buffer, 2, sample, fout) != sample)
834                                         return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
835                         }
836                         else if(bps == 24) {
837                                 if(is_unsigned_samples) {
838                                         for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
839                                                 for(channel = 0; channel < channels; channel++, sample++)
840                                                         u32buffer[sample] = buffer[channel][wide_sample] + 0x800000;
841                                 }
842                                 else {
843                                         for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
844                                                 for(channel = 0; channel < channels; channel++, sample++)
845                                                         s32buffer[sample] = buffer[channel][wide_sample];
846                                 }
847                                 if(is_big_endian != is_big_endian_host_) {
848                                         unsigned char tmp;
849                                         const unsigned bytes = sample * 4;
850                                         for(byte = 0; byte < bytes; byte += 4) {
851                                                 tmp = u8buffer[byte];
852                                                 u8buffer[byte] = u8buffer[byte+3];
853                                                 u8buffer[byte+3] = tmp;
854                                                 tmp = u8buffer[byte+1];
855                                                 u8buffer[byte+1] = u8buffer[byte+2];
856                                                 u8buffer[byte+2] = tmp;
857                                         }
858                                 }
859                                 if(is_big_endian) {
860                                         unsigned lbyte;
861                                         const unsigned bytes = sample * 4;
862                                         for(lbyte = byte = 0; byte < bytes; ) {
863                                                 byte++;
864                                                 u8buffer[lbyte++] = u8buffer[byte++];
865                                                 u8buffer[lbyte++] = u8buffer[byte++];
866                                                 u8buffer[lbyte++] = u8buffer[byte++];
867                                         }
868                                 }
869                                 else {
870                                         unsigned lbyte;
871                                         const unsigned bytes = sample * 4;
872                                         for(lbyte = byte = 0; byte < bytes; ) {
873                                                 u8buffer[lbyte++] = u8buffer[byte++];
874                                                 u8buffer[lbyte++] = u8buffer[byte++];
875                                                 u8buffer[lbyte++] = u8buffer[byte++];
876                                                 byte++;
877                                         }
878                                 }
879                                 if(flac__utils_fwrite(u8buffer, 3, sample, fout) != sample)
880                                         return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
881                         }
882                         else {
883                                 FLAC__ASSERT(0);
884                         }
885                 }
886         }
887         return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
888 }
889
890 void metadata_callback(const void *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
891 {
892         DecoderSession *decoder_session = (DecoderSession*)client_data;
893         (void)decoder;
894         if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
895                 FLAC__uint64 skip, until;
896                 decoder_session->bps = metadata->data.stream_info.bits_per_sample;
897                 decoder_session->channels = metadata->data.stream_info.channels;
898                 decoder_session->sample_rate = metadata->data.stream_info.sample_rate;
899
900                 flac__utils_canonicalize_skip_until_specification(decoder_session->skip_specification, decoder_session->sample_rate);
901                 FLAC__ASSERT(decoder_session->skip_specification->value.samples >= 0);
902                 skip = (FLAC__uint64)decoder_session->skip_specification->value.samples;
903
904                 /* remember, metadata->data.stream_info.total_samples can be 0, meaning 'unknown' */
905                 if(metadata->data.stream_info.total_samples > 0 && skip >= metadata->data.stream_info.total_samples) {
906                         fprintf(stderr, "%s: ERROR trying to --skip more samples than in stream\n", decoder_session->inbasefilename);
907                         decoder_session->abort_flag = true;
908                         return;
909                 }
910                 else if(metadata->data.stream_info.total_samples == 0 && skip > 0) {
911                         fprintf(stderr, "%s: ERROR, can't --skip when FLAC metadata has total sample count of 0\n", decoder_session->inbasefilename);
912                         decoder_session->abort_flag = true;
913                         return;
914                 }
915                 decoder_session->total_samples = metadata->data.stream_info.total_samples - skip;
916
917                 /* note that we use metadata->data.stream_info.total_samples instead of decoder_session->total_samples */
918                 if(!canonicalize_until_specification(decoder_session->until_specification, decoder_session->inbasefilename, decoder_session->sample_rate, skip, metadata->data.stream_info.total_samples)) {
919                         decoder_session->abort_flag = true;
920                         return;
921                 }
922                 FLAC__ASSERT(decoder_session->until_specification->value.samples >= 0);
923                 until = (FLAC__uint64)decoder_session->until_specification->value.samples;
924
925                 if(until > 0)
926                         decoder_session->total_samples -= (metadata->data.stream_info.total_samples - until);
927
928                 if(decoder_session->bps != 8 && decoder_session->bps != 16 && decoder_session->bps != 24) {
929                         fprintf(stderr, "%s: ERROR: bits per sample is not 8/16/24\n", decoder_session->inbasefilename);
930                         decoder_session->abort_flag = true;
931                         return;
932                 }
933
934                 /* write the WAVE/AIFF headers if necessary */
935                 if(!decoder_session->analysis_mode && !decoder_session->test_only && (decoder_session->is_wave_out || decoder_session->is_aiff_out)) {
936                         const char *fmt_desc = decoder_session->is_wave_out? "WAVE" : "AIFF";
937                         FLAC__uint64 data_size = decoder_session->total_samples * decoder_session->channels * ((decoder_session->bps+7)/8);
938                         if(decoder_session->total_samples == 0) {
939                                 if(decoder_session->fout == stdout) {
940                                         fprintf(stderr, "%s: WARNING, don't have accurate sample count available for %s header.\n", decoder_session->inbasefilename, fmt_desc);
941                                         fprintf(stderr, "             Generated %s file will have a data chunk size of 0.  Try\n", fmt_desc);
942                                         fprintf(stderr, "             decoding directly to a file instead.\n");
943                                 }
944                                 else {
945                                         decoder_session->wave_chunk_size_fixup.needs_fixup = true;
946                                 }
947                         }
948                         if(data_size >= 0xFFFFFFDC) {
949                                 fprintf(stderr, "%s: ERROR: stream is too big to fit in a single %s file chunk\n", decoder_session->inbasefilename, fmt_desc);
950                                 decoder_session->abort_flag = true;
951                                 return;
952                         }
953                         if(decoder_session->is_wave_out) {
954                                 if(flac__utils_fwrite("RIFF", 1, 4, decoder_session->fout) != 4)
955                                         decoder_session->abort_flag = true;
956
957                                 if(decoder_session->wave_chunk_size_fixup.needs_fixup)
958                                         decoder_session->wave_chunk_size_fixup.riff_offset = ftell(decoder_session->fout);
959
960                                 if(!write_little_endian_uint32(decoder_session->fout, (FLAC__uint32)(data_size+36))) /* filesize-8 */
961                                         decoder_session->abort_flag = true;
962
963                                 if(flac__utils_fwrite("WAVEfmt ", 1, 8, decoder_session->fout) != 8)
964                                         decoder_session->abort_flag = true;
965
966                                 if(flac__utils_fwrite("\020\000\000\000", 1, 4, decoder_session->fout) != 4) /* chunk size = 16 */
967                                         decoder_session->abort_flag = true;
968
969                                 if(flac__utils_fwrite("\001\000", 1, 2, decoder_session->fout) != 2) /* compression code == 1 */
970                                         decoder_session->abort_flag = true;
971
972                                 if(!write_little_endian_uint16(decoder_session->fout, (FLAC__uint16)(decoder_session->channels)))
973                                         decoder_session->abort_flag = true;
974
975                                 if(!write_little_endian_uint32(decoder_session->fout, decoder_session->sample_rate))
976                                         decoder_session->abort_flag = true;
977
978                                 if(!write_little_endian_uint32(decoder_session->fout, decoder_session->sample_rate * decoder_session->channels * ((decoder_session->bps+7) / 8))) /* @@@ or is it (sample_rate*channels*bps) / 8 ??? */
979                                         decoder_session->abort_flag = true;
980
981                                 if(!write_little_endian_uint16(decoder_session->fout, (FLAC__uint16)(decoder_session->channels * ((decoder_session->bps+7) / 8)))) /* block align */
982                                         decoder_session->abort_flag = true;
983
984                                 if(!write_little_endian_uint16(decoder_session->fout, (FLAC__uint16)(decoder_session->bps))) /* bits per sample */
985                                         decoder_session->abort_flag = true;
986
987                                 if(flac__utils_fwrite("data", 1, 4, decoder_session->fout) != 4)
988                                         decoder_session->abort_flag = true;
989
990                                 if(decoder_session->wave_chunk_size_fixup.needs_fixup)
991                                         decoder_session->wave_chunk_size_fixup.data_offset = ftell(decoder_session->fout);
992
993                                 if(!write_little_endian_uint32(decoder_session->fout, (FLAC__uint32)data_size)) /* data size */
994                                         decoder_session->abort_flag = true;
995                         }
996                         else {
997                                 const FLAC__uint32 aligned_data_size = (FLAC__uint32)((data_size+1) & (~1U));
998
999                                 if(flac__utils_fwrite("FORM", 1, 4, decoder_session->fout) != 4)
1000                                         decoder_session->abort_flag = true;
1001
1002                                 if(decoder_session->wave_chunk_size_fixup.needs_fixup)
1003                                         decoder_session->wave_chunk_size_fixup.riff_offset = ftell(decoder_session->fout);
1004
1005                                 if(!write_big_endian_uint32(decoder_session->fout, (FLAC__uint32)(aligned_data_size+46))) /* filesize-8 */
1006                                         decoder_session->abort_flag = true;
1007
1008                                 if(flac__utils_fwrite("AIFFCOMM", 1, 8, decoder_session->fout) != 8)
1009                                         decoder_session->abort_flag = true;
1010
1011                                 if(flac__utils_fwrite("\000\000\000\022", 1, 4, decoder_session->fout) != 4) /* chunk size = 18 */
1012                                         decoder_session->abort_flag = true;
1013
1014                                 if(!write_big_endian_uint16(decoder_session->fout, (FLAC__uint16)(decoder_session->channels)))
1015                                         decoder_session->abort_flag = true;
1016
1017                                 if(decoder_session->wave_chunk_size_fixup.needs_fixup)
1018                                         decoder_session->wave_chunk_size_fixup.frames_offset = ftell(decoder_session->fout);
1019
1020                                 if(!write_big_endian_uint32(decoder_session->fout, (FLAC__uint32)decoder_session->total_samples))
1021                                         decoder_session->abort_flag = true;
1022
1023                                 if(!write_big_endian_uint16(decoder_session->fout, (FLAC__uint16)(decoder_session->bps)))
1024                                         decoder_session->abort_flag = true;
1025
1026                                 if(!write_sane_extended(decoder_session->fout, decoder_session->sample_rate))
1027                                         decoder_session->abort_flag = true;
1028
1029                                 if(flac__utils_fwrite("SSND", 1, 4, decoder_session->fout) != 4)
1030                                         decoder_session->abort_flag = true;
1031
1032                                 if(decoder_session->wave_chunk_size_fixup.needs_fixup)
1033                                         decoder_session->wave_chunk_size_fixup.data_offset = ftell(decoder_session->fout);
1034
1035                                 if(!write_big_endian_uint32(decoder_session->fout, (FLAC__uint32)data_size+8)) /* data size */
1036                                         decoder_session->abort_flag = true;
1037
1038                                 if(!write_big_endian_uint32(decoder_session->fout, 0/*offset*/))
1039                                         decoder_session->abort_flag = true;
1040
1041                                 if(!write_big_endian_uint32(decoder_session->fout, 0/*block_size*/))
1042                                         decoder_session->abort_flag = true;
1043                         }
1044                 }
1045         }
1046 }
1047
1048 void error_callback(const void *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
1049 {
1050         DecoderSession *decoder_session = (DecoderSession*)client_data;
1051         (void)decoder;
1052         fprintf(stderr, "%s: *** Got error code %d:%s\n", decoder_session->inbasefilename, status, FLAC__StreamDecoderErrorStatusString[status]);
1053         if(!decoder_session->continue_through_decode_errors)
1054                 decoder_session->abort_flag = true;
1055 }
1056
1057 void print_error_with_state(const DecoderSession *d, const char *message)
1058 {
1059         const int ilen = strlen(d->inbasefilename) + 1;
1060
1061         fprintf(stderr, "\n%s: %s\n", d->inbasefilename, message);
1062
1063 #ifdef FLAC__HAS_OGG
1064         if(d->is_ogg) {
1065                 const OggFLAC__StreamDecoderState osd_state = OggFLAC__stream_decoder_get_state(d->decoder.ogg.stream);
1066                 if(osd_state != OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR) {
1067                         fprintf(stderr, "%*s state = %d:%s\n", ilen, "", (int)osd_state, OggFLAC__StreamDecoderStateString[osd_state]);
1068                 }
1069                 else {
1070                         const FLAC__StreamDecoderState fsd_state = OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(d->decoder.ogg.stream);
1071                         fprintf(stderr, "%*s state = %d:%s\n", ilen, "", (int)fsd_state, FLAC__StreamDecoderStateString[fsd_state]);
1072                 }
1073         }
1074         else
1075 #endif
1076         {
1077                 const FLAC__FileDecoderState ffd_state = FLAC__file_decoder_get_state(d->decoder.flac.file);
1078                 if(ffd_state != FLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR) {
1079                         fprintf(stderr, "%*s state = %d:%s\n", ilen, "", (int)ffd_state, FLAC__FileDecoderStateString[ffd_state]);
1080                 }
1081                 else {
1082                         const FLAC__SeekableStreamDecoderState fssd_state = FLAC__file_decoder_get_seekable_stream_decoder_state(d->decoder.flac.file);
1083                         if(fssd_state != FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR) {
1084                                 fprintf(stderr, "%*s state = %d:%s\n", ilen, "", (int)fssd_state, FLAC__SeekableStreamDecoderStateString[fssd_state]);
1085                         }
1086                         else {
1087                                 const FLAC__StreamDecoderState fsd_state = FLAC__file_decoder_get_stream_decoder_state(d->decoder.flac.file);
1088                                 fprintf(stderr, "%*s state = %d:%s\n", ilen, "", (int)fsd_state, FLAC__StreamDecoderStateString[fsd_state]);
1089                         }
1090                 }
1091         }
1092 }
1093
1094 void print_stats(const DecoderSession *decoder_session)
1095 {
1096         if(decoder_session->verbose) {
1097 #if defined _MSC_VER || defined __MINGW32__
1098                 /* with VC++ you have to spoon feed it the casting */
1099                 const double progress = (double)(FLAC__int64)decoder_session->samples_processed / (double)(FLAC__int64)decoder_session->total_samples * 100.0;
1100 #else
1101                 const double progress = (double)decoder_session->samples_processed / (double)decoder_session->total_samples * 100.0;
1102 #endif
1103                 if(decoder_session->total_samples > 0) {
1104                         fprintf(stderr, "\r%s: %s%u%% complete",
1105                                 decoder_session->inbasefilename,
1106                                 decoder_session->test_only? "testing, " : decoder_session->analysis_mode? "analyzing, " : "",
1107                                 (unsigned)floor(progress + 0.5)
1108                         );
1109                 }
1110                 else {
1111                         fprintf(stderr, "\r%s: %s %u samples",
1112                                 decoder_session->inbasefilename,
1113                                 decoder_session->test_only? "tested" : decoder_session->analysis_mode? "analyzed" : "wrote",
1114                                 (unsigned)decoder_session->samples_processed
1115                         );
1116                 }
1117         }
1118 }