add Brady's better write_sane_extended()
[platform/upstream/flac.git] / src / flac / decode.c
1 /* flac - Command-line FLAC encoder/decoder
2  * Copyright (C) 2000,2001,2002,2003  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         /* Write to 'f' a SANE extended representation of 'val'.  Return false if
636         * the write succeeds; return true otherwise.
637         *
638         * SANE extended is an 80-bit IEEE-754 representation with sign bit, 15 bits
639         * of exponent, and 64 bits of significand (mantissa).  Unlike most IEEE-754
640         * representations, it does not imply a 1 above the MSB of the significand.
641         *
642         * Preconditions:
643         *  val!=0U
644         */
645 {
646         unsigned int shift, exponent;
647
648         FLAC__ASSERT(val!=0U); /* handling 0 would require a special case */
649
650         for(shift= 0U; (val>>(31-shift))==0U; ++shift)
651                 ;
652         val<<= shift;
653         exponent= 63U-(shift+32U); /* add 32 for unused second word */
654
655         if(!write_big_endian_uint16(f, (FLAC__uint16)(exponent+0x3FFF)))
656                 return false;
657         if(!write_big_endian_uint32(f, val))
658                 return false;
659         if(!write_big_endian_uint32(f, 0)) /* unused second word */
660                 return false;
661
662         return true;
663 }
664
665 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)
666 {
667         const char *fmt_desc = (is_wave_out? "WAVE" : "AIFF");
668         FLAC__bool (*write_it)(FILE *, FLAC__uint32) = (is_wave_out? write_little_endian_uint32 : write_big_endian_uint32);
669         FILE *f = fopen(outfilename, "r+b");
670         FLAC__uint32 data_size, aligned_data_size;
671
672         if(0 == f) {
673                 fprintf(stderr, "ERROR, couldn't open file %s while fixing up %s chunk size\n", outfilename, fmt_desc);
674                 return false;
675         }
676
677         data_size = aligned_data_size = total_samples * channels * ((bps+7)/8);
678         if(!is_wave_out && (aligned_data_size & 1))
679                 aligned_data_size++;
680
681         if(fseek(f, riff_offset, SEEK_SET) < 0) {
682                 fprintf(stderr, "ERROR, couldn't seek in file %s while fixing up %s chunk size\n", outfilename, fmt_desc);
683                 fclose(f);
684                 return false;
685         }
686         if(!write_it(f, aligned_data_size + (is_wave_out? 36 : 46))) {
687                 fprintf(stderr, "ERROR, couldn't write size in file %s while fixing up %s chunk size\n", outfilename, fmt_desc);
688                 fclose(f);
689                 return false;
690         }
691         if(!is_wave_out) {
692                 if(fseek(f, frames_offset, SEEK_SET) < 0) {
693                         fprintf(stderr, "ERROR, couldn't seek in file %s while fixing up %s chunk size\n", outfilename, fmt_desc);
694                         fclose(f);
695                         return false;
696                 }
697                 if(!write_it(f, total_samples)) {
698                         fprintf(stderr, "ERROR, couldn't write size in file %s while fixing up %s chunk size\n", outfilename, fmt_desc);
699                         fclose(f);
700                         return false;
701                 }
702         }
703         if(fseek(f, data_offset, SEEK_SET) < 0) {
704                 fprintf(stderr, "ERROR, couldn't seek in file %s while fixing up %s chunk size\n", outfilename, fmt_desc);
705                 fclose(f);
706                 return false;
707         }
708         if(!write_it(f, data_size + (is_wave_out? 0 : 8))) {
709                 fprintf(stderr, "ERROR, couldn't write size in file %s while fixing up %s chunk size\n", outfilename, fmt_desc);
710                 fclose(f);
711                 return false;
712         }
713         fclose(f);
714         return true;
715 }
716
717 #ifdef FLAC__HAS_OGG
718 FLAC__StreamDecoderReadStatus read_callback(const OggFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
719 {
720         DecoderSession *decoder_session = (DecoderSession*)client_data;
721         FILE *fin = decoder_session->fin;
722         size_t bytes_read;
723
724         (void)decoder; /* avoid compiler warning */
725
726         if (decoder_session->abort_flag)
727                 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
728
729         if(feof(fin))
730                 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
731
732         bytes_read = fread(buffer, 1, *bytes, fin);
733
734         if(ferror(fin))
735                 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
736
737         *bytes = (unsigned)bytes_read;
738
739         return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
740 }
741 #endif
742
743 FLAC__StreamDecoderWriteStatus write_callback(const void *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
744 {
745         DecoderSession *decoder_session = (DecoderSession*)client_data;
746         FILE *fout = decoder_session->fout;
747         const unsigned bps = frame->header.bits_per_sample, channels = frame->header.channels;
748         FLAC__bool is_big_endian = (decoder_session->is_aiff_out? true : (decoder_session->is_wave_out? false : decoder_session->is_big_endian));
749         FLAC__bool is_unsigned_samples = (decoder_session->is_aiff_out? false : (decoder_session->is_wave_out? bps<=8 : decoder_session->is_unsigned_samples));
750         unsigned wide_samples = frame->header.blocksize, wide_sample, sample, channel, byte;
751         static FLAC__int8 s8buffer[FLAC__MAX_BLOCK_SIZE * FLAC__MAX_CHANNELS * sizeof(FLAC__int32)]; /* WATCHOUT: can be up to 2 megs */
752         FLAC__uint8  *u8buffer  = (FLAC__uint8  *)s8buffer;
753         FLAC__int16  *s16buffer = (FLAC__int16  *)s8buffer;
754         FLAC__uint16 *u16buffer = (FLAC__uint16 *)s8buffer;
755         FLAC__int32  *s32buffer = (FLAC__int32  *)s8buffer;
756         FLAC__uint32 *u32buffer = (FLAC__uint32 *)s8buffer;
757
758         (void)decoder;
759
760         if(decoder_session->abort_flag)
761                 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
762
763         if(bps != decoder_session->bps) {
764                 fprintf(stderr, "%s: ERROR, bits-per-sample is %u in frame but %u in STREAMINFO\n", decoder_session->inbasefilename, bps, decoder_session->bps);
765                 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
766         }
767         if(channels != decoder_session->channels) {
768                 fprintf(stderr, "%s: ERROR, channels is %u in frame but %u in STREAMINFO\n", decoder_session->inbasefilename, channels, decoder_session->channels);
769                 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
770         }
771         if(frame->header.sample_rate != decoder_session->sample_rate) {
772                 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);
773                 return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
774         }
775
776         /*
777          * limit the number of samples to accept based on --until
778          */
779         FLAC__ASSERT(!decoder_session->skip_specification->is_relative);
780         FLAC__ASSERT(decoder_session->skip_specification->value.samples >= 0);
781         FLAC__ASSERT(!decoder_session->until_specification->is_relative);
782         FLAC__ASSERT(decoder_session->until_specification->value.samples >= 0);
783         if(decoder_session->until_specification->value.samples > 0) {
784                 const FLAC__uint64 skip = (FLAC__uint64)decoder_session->skip_specification->value.samples;
785                 const FLAC__uint64 until = (FLAC__uint64)decoder_session->until_specification->value.samples;
786                 const FLAC__uint64 input_samples_passed = skip + decoder_session->samples_processed;
787                 FLAC__ASSERT(until >= input_samples_passed);
788                 if(input_samples_passed + wide_samples > until)
789                         wide_samples = (unsigned)(until - input_samples_passed);
790         }
791
792         if(wide_samples > 0) {
793                 decoder_session->samples_processed += wide_samples;
794                 decoder_session->frame_counter++;
795
796                 if(decoder_session->verbose && !(decoder_session->frame_counter & 0x3f))
797                         print_stats(decoder_session);
798
799                 if(decoder_session->analysis_mode) {
800                         flac__analyze_frame(frame, decoder_session->frame_counter-1, decoder_session->aopts, fout);
801                 }
802                 else if(!decoder_session->test_only) {
803                         if(bps == 8) {
804                                 if(is_unsigned_samples) {
805                                         for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
806                                                 for(channel = 0; channel < channels; channel++, sample++)
807                                                         u8buffer[sample] = (FLAC__uint8)(buffer[channel][wide_sample] + 0x80);
808                                 }
809                                 else {
810                                         for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
811                                                 for(channel = 0; channel < channels; channel++, sample++)
812                                                         s8buffer[sample] = (FLAC__int8)(buffer[channel][wide_sample]);
813                                 }
814                                 if(flac__utils_fwrite(u8buffer, 1, sample, fout) != sample)
815                                         return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
816                         }
817                         else if(bps == 16) {
818                                 if(is_unsigned_samples) {
819                                         for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
820                                                 for(channel = 0; channel < channels; channel++, sample++)
821                                                         u16buffer[sample] = (FLAC__uint16)(buffer[channel][wide_sample] + 0x8000);
822                                 }
823                                 else {
824                                         for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
825                                                 for(channel = 0; channel < channels; channel++, sample++)
826                                                         s16buffer[sample] = (FLAC__int16)(buffer[channel][wide_sample]);
827                                 }
828                                 if(is_big_endian != is_big_endian_host_) {
829                                         unsigned char tmp;
830                                         const unsigned bytes = sample * 2;
831                                         for(byte = 0; byte < bytes; byte += 2) {
832                                                 tmp = u8buffer[byte];
833                                                 u8buffer[byte] = u8buffer[byte+1];
834                                                 u8buffer[byte+1] = tmp;
835                                         }
836                                 }
837                                 if(flac__utils_fwrite(u16buffer, 2, sample, fout) != sample)
838                                         return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
839                         }
840                         else if(bps == 24) {
841                                 if(is_unsigned_samples) {
842                                         for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
843                                                 for(channel = 0; channel < channels; channel++, sample++)
844                                                         u32buffer[sample] = buffer[channel][wide_sample] + 0x800000;
845                                 }
846                                 else {
847                                         for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
848                                                 for(channel = 0; channel < channels; channel++, sample++)
849                                                         s32buffer[sample] = buffer[channel][wide_sample];
850                                 }
851                                 if(is_big_endian != is_big_endian_host_) {
852                                         unsigned char tmp;
853                                         const unsigned bytes = sample * 4;
854                                         for(byte = 0; byte < bytes; byte += 4) {
855                                                 tmp = u8buffer[byte];
856                                                 u8buffer[byte] = u8buffer[byte+3];
857                                                 u8buffer[byte+3] = tmp;
858                                                 tmp = u8buffer[byte+1];
859                                                 u8buffer[byte+1] = u8buffer[byte+2];
860                                                 u8buffer[byte+2] = tmp;
861                                         }
862                                 }
863                                 if(is_big_endian) {
864                                         unsigned lbyte;
865                                         const unsigned bytes = sample * 4;
866                                         for(lbyte = byte = 0; byte < bytes; ) {
867                                                 byte++;
868                                                 u8buffer[lbyte++] = u8buffer[byte++];
869                                                 u8buffer[lbyte++] = u8buffer[byte++];
870                                                 u8buffer[lbyte++] = u8buffer[byte++];
871                                         }
872                                 }
873                                 else {
874                                         unsigned lbyte;
875                                         const unsigned bytes = sample * 4;
876                                         for(lbyte = byte = 0; byte < bytes; ) {
877                                                 u8buffer[lbyte++] = u8buffer[byte++];
878                                                 u8buffer[lbyte++] = u8buffer[byte++];
879                                                 u8buffer[lbyte++] = u8buffer[byte++];
880                                                 byte++;
881                                         }
882                                 }
883                                 if(flac__utils_fwrite(u8buffer, 3, sample, fout) != sample)
884                                         return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
885                         }
886                         else {
887                                 FLAC__ASSERT(0);
888                         }
889                 }
890         }
891         return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
892 }
893
894 void metadata_callback(const void *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
895 {
896         DecoderSession *decoder_session = (DecoderSession*)client_data;
897         (void)decoder;
898         if(metadata->type == FLAC__METADATA_TYPE_STREAMINFO) {
899                 FLAC__uint64 skip, until;
900                 decoder_session->bps = metadata->data.stream_info.bits_per_sample;
901                 decoder_session->channels = metadata->data.stream_info.channels;
902                 decoder_session->sample_rate = metadata->data.stream_info.sample_rate;
903
904                 flac__utils_canonicalize_skip_until_specification(decoder_session->skip_specification, decoder_session->sample_rate);
905                 FLAC__ASSERT(decoder_session->skip_specification->value.samples >= 0);
906                 skip = (FLAC__uint64)decoder_session->skip_specification->value.samples;
907
908                 /* remember, metadata->data.stream_info.total_samples can be 0, meaning 'unknown' */
909                 if(metadata->data.stream_info.total_samples > 0 && skip >= metadata->data.stream_info.total_samples) {
910                         fprintf(stderr, "%s: ERROR trying to --skip more samples than in stream\n", decoder_session->inbasefilename);
911                         decoder_session->abort_flag = true;
912                         return;
913                 }
914                 else if(metadata->data.stream_info.total_samples == 0 && skip > 0) {
915                         fprintf(stderr, "%s: ERROR, can't --skip when FLAC metadata has total sample count of 0\n", decoder_session->inbasefilename);
916                         decoder_session->abort_flag = true;
917                         return;
918                 }
919                 decoder_session->total_samples = metadata->data.stream_info.total_samples - skip;
920
921                 /* note that we use metadata->data.stream_info.total_samples instead of decoder_session->total_samples */
922                 if(!canonicalize_until_specification(decoder_session->until_specification, decoder_session->inbasefilename, decoder_session->sample_rate, skip, metadata->data.stream_info.total_samples)) {
923                         decoder_session->abort_flag = true;
924                         return;
925                 }
926                 FLAC__ASSERT(decoder_session->until_specification->value.samples >= 0);
927                 until = (FLAC__uint64)decoder_session->until_specification->value.samples;
928
929                 if(until > 0)
930                         decoder_session->total_samples -= (metadata->data.stream_info.total_samples - until);
931
932                 if(decoder_session->bps != 8 && decoder_session->bps != 16 && decoder_session->bps != 24) {
933                         fprintf(stderr, "%s: ERROR: bits per sample is not 8/16/24\n", decoder_session->inbasefilename);
934                         decoder_session->abort_flag = true;
935                         return;
936                 }
937
938                 /* write the WAVE/AIFF headers if necessary */
939                 if(!decoder_session->analysis_mode && !decoder_session->test_only && (decoder_session->is_wave_out || decoder_session->is_aiff_out)) {
940                         const char *fmt_desc = decoder_session->is_wave_out? "WAVE" : "AIFF";
941                         FLAC__uint64 data_size = decoder_session->total_samples * decoder_session->channels * ((decoder_session->bps+7)/8);
942                         if(decoder_session->total_samples == 0) {
943                                 if(decoder_session->fout == stdout) {
944                                         fprintf(stderr, "%s: WARNING, don't have accurate sample count available for %s header.\n", decoder_session->inbasefilename, fmt_desc);
945                                         fprintf(stderr, "             Generated %s file will have a data chunk size of 0.  Try\n", fmt_desc);
946                                         fprintf(stderr, "             decoding directly to a file instead.\n");
947                                 }
948                                 else {
949                                         decoder_session->wave_chunk_size_fixup.needs_fixup = true;
950                                 }
951                         }
952                         if(data_size >= 0xFFFFFFDC) {
953                                 fprintf(stderr, "%s: ERROR: stream is too big to fit in a single %s file chunk\n", decoder_session->inbasefilename, fmt_desc);
954                                 decoder_session->abort_flag = true;
955                                 return;
956                         }
957                         if(decoder_session->is_wave_out) {
958                                 if(flac__utils_fwrite("RIFF", 1, 4, decoder_session->fout) != 4)
959                                         decoder_session->abort_flag = true;
960
961                                 if(decoder_session->wave_chunk_size_fixup.needs_fixup)
962                                         decoder_session->wave_chunk_size_fixup.riff_offset = ftell(decoder_session->fout);
963
964                                 if(!write_little_endian_uint32(decoder_session->fout, (FLAC__uint32)(data_size+36))) /* filesize-8 */
965                                         decoder_session->abort_flag = true;
966
967                                 if(flac__utils_fwrite("WAVEfmt ", 1, 8, decoder_session->fout) != 8)
968                                         decoder_session->abort_flag = true;
969
970                                 if(flac__utils_fwrite("\020\000\000\000", 1, 4, decoder_session->fout) != 4) /* chunk size = 16 */
971                                         decoder_session->abort_flag = true;
972
973                                 if(flac__utils_fwrite("\001\000", 1, 2, decoder_session->fout) != 2) /* compression code == 1 */
974                                         decoder_session->abort_flag = true;
975
976                                 if(!write_little_endian_uint16(decoder_session->fout, (FLAC__uint16)(decoder_session->channels)))
977                                         decoder_session->abort_flag = true;
978
979                                 if(!write_little_endian_uint32(decoder_session->fout, decoder_session->sample_rate))
980                                         decoder_session->abort_flag = true;
981
982                                 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 ??? */
983                                         decoder_session->abort_flag = true;
984
985                                 if(!write_little_endian_uint16(decoder_session->fout, (FLAC__uint16)(decoder_session->channels * ((decoder_session->bps+7) / 8)))) /* block align */
986                                         decoder_session->abort_flag = true;
987
988                                 if(!write_little_endian_uint16(decoder_session->fout, (FLAC__uint16)(decoder_session->bps))) /* bits per sample */
989                                         decoder_session->abort_flag = true;
990
991                                 if(flac__utils_fwrite("data", 1, 4, decoder_session->fout) != 4)
992                                         decoder_session->abort_flag = true;
993
994                                 if(decoder_session->wave_chunk_size_fixup.needs_fixup)
995                                         decoder_session->wave_chunk_size_fixup.data_offset = ftell(decoder_session->fout);
996
997                                 if(!write_little_endian_uint32(decoder_session->fout, (FLAC__uint32)data_size)) /* data size */
998                                         decoder_session->abort_flag = true;
999                         }
1000                         else {
1001                                 const FLAC__uint32 aligned_data_size = (FLAC__uint32)((data_size+1) & (~1U));
1002
1003                                 if(flac__utils_fwrite("FORM", 1, 4, decoder_session->fout) != 4)
1004                                         decoder_session->abort_flag = true;
1005
1006                                 if(decoder_session->wave_chunk_size_fixup.needs_fixup)
1007                                         decoder_session->wave_chunk_size_fixup.riff_offset = ftell(decoder_session->fout);
1008
1009                                 if(!write_big_endian_uint32(decoder_session->fout, (FLAC__uint32)(aligned_data_size+46))) /* filesize-8 */
1010                                         decoder_session->abort_flag = true;
1011
1012                                 if(flac__utils_fwrite("AIFFCOMM", 1, 8, decoder_session->fout) != 8)
1013                                         decoder_session->abort_flag = true;
1014
1015                                 if(flac__utils_fwrite("\000\000\000\022", 1, 4, decoder_session->fout) != 4) /* chunk size = 18 */
1016                                         decoder_session->abort_flag = true;
1017
1018                                 if(!write_big_endian_uint16(decoder_session->fout, (FLAC__uint16)(decoder_session->channels)))
1019                                         decoder_session->abort_flag = true;
1020
1021                                 if(decoder_session->wave_chunk_size_fixup.needs_fixup)
1022                                         decoder_session->wave_chunk_size_fixup.frames_offset = ftell(decoder_session->fout);
1023
1024                                 if(!write_big_endian_uint32(decoder_session->fout, (FLAC__uint32)decoder_session->total_samples))
1025                                         decoder_session->abort_flag = true;
1026
1027                                 if(!write_big_endian_uint16(decoder_session->fout, (FLAC__uint16)(decoder_session->bps)))
1028                                         decoder_session->abort_flag = true;
1029
1030                                 if(!write_sane_extended(decoder_session->fout, decoder_session->sample_rate))
1031                                         decoder_session->abort_flag = true;
1032
1033                                 if(flac__utils_fwrite("SSND", 1, 4, decoder_session->fout) != 4)
1034                                         decoder_session->abort_flag = true;
1035
1036                                 if(decoder_session->wave_chunk_size_fixup.needs_fixup)
1037                                         decoder_session->wave_chunk_size_fixup.data_offset = ftell(decoder_session->fout);
1038
1039                                 if(!write_big_endian_uint32(decoder_session->fout, (FLAC__uint32)data_size+8)) /* data size */
1040                                         decoder_session->abort_flag = true;
1041
1042                                 if(!write_big_endian_uint32(decoder_session->fout, 0/*offset*/))
1043                                         decoder_session->abort_flag = true;
1044
1045                                 if(!write_big_endian_uint32(decoder_session->fout, 0/*block_size*/))
1046                                         decoder_session->abort_flag = true;
1047                         }
1048                 }
1049         }
1050 }
1051
1052 void error_callback(const void *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
1053 {
1054         DecoderSession *decoder_session = (DecoderSession*)client_data;
1055         (void)decoder;
1056         fprintf(stderr, "%s: *** Got error code %d:%s\n", decoder_session->inbasefilename, status, FLAC__StreamDecoderErrorStatusString[status]);
1057         if(!decoder_session->continue_through_decode_errors)
1058                 decoder_session->abort_flag = true;
1059 }
1060
1061 void print_error_with_state(const DecoderSession *d, const char *message)
1062 {
1063         const int ilen = strlen(d->inbasefilename) + 1;
1064
1065         fprintf(stderr, "\n%s: %s\n", d->inbasefilename, message);
1066
1067 #ifdef FLAC__HAS_OGG
1068         if(d->is_ogg) {
1069                 const OggFLAC__StreamDecoderState osd_state = OggFLAC__stream_decoder_get_state(d->decoder.ogg.stream);
1070                 if(osd_state != OggFLAC__STREAM_DECODER_FLAC_STREAM_DECODER_ERROR) {
1071                         fprintf(stderr, "%*s state = %d:%s\n", ilen, "", (int)osd_state, OggFLAC__StreamDecoderStateString[osd_state]);
1072                 }
1073                 else {
1074                         const FLAC__StreamDecoderState fsd_state = OggFLAC__stream_decoder_get_FLAC_stream_decoder_state(d->decoder.ogg.stream);
1075                         fprintf(stderr, "%*s state = %d:%s\n", ilen, "", (int)fsd_state, FLAC__StreamDecoderStateString[fsd_state]);
1076                 }
1077         }
1078         else
1079 #endif
1080         {
1081                 const FLAC__FileDecoderState ffd_state = FLAC__file_decoder_get_state(d->decoder.flac.file);
1082                 if(ffd_state != FLAC__FILE_DECODER_SEEKABLE_STREAM_DECODER_ERROR) {
1083                         fprintf(stderr, "%*s state = %d:%s\n", ilen, "", (int)ffd_state, FLAC__FileDecoderStateString[ffd_state]);
1084                 }
1085                 else {
1086                         const FLAC__SeekableStreamDecoderState fssd_state = FLAC__file_decoder_get_seekable_stream_decoder_state(d->decoder.flac.file);
1087                         if(fssd_state != FLAC__SEEKABLE_STREAM_DECODER_STREAM_DECODER_ERROR) {
1088                                 fprintf(stderr, "%*s state = %d:%s\n", ilen, "", (int)fssd_state, FLAC__SeekableStreamDecoderStateString[fssd_state]);
1089                         }
1090                         else {
1091                                 const FLAC__StreamDecoderState fsd_state = FLAC__file_decoder_get_stream_decoder_state(d->decoder.flac.file);
1092                                 fprintf(stderr, "%*s state = %d:%s\n", ilen, "", (int)fsd_state, FLAC__StreamDecoderStateString[fsd_state]);
1093                         }
1094                 }
1095         }
1096 }
1097
1098 void print_stats(const DecoderSession *decoder_session)
1099 {
1100         if(decoder_session->verbose) {
1101 #if defined _MSC_VER || defined __MINGW32__
1102                 /* with VC++ you have to spoon feed it the casting */
1103                 const double progress = (double)(FLAC__int64)decoder_session->samples_processed / (double)(FLAC__int64)decoder_session->total_samples * 100.0;
1104 #else
1105                 const double progress = (double)decoder_session->samples_processed / (double)decoder_session->total_samples * 100.0;
1106 #endif
1107                 if(decoder_session->total_samples > 0) {
1108                         fprintf(stderr, "\r%s: %s%u%% complete",
1109                                 decoder_session->inbasefilename,
1110                                 decoder_session->test_only? "testing, " : decoder_session->analysis_mode? "analyzing, " : "",
1111                                 (unsigned)floor(progress + 0.5)
1112                         );
1113                 }
1114                 else {
1115                         fprintf(stderr, "\r%s: %s %u samples",
1116                                 decoder_session->inbasefilename,
1117                                 decoder_session->test_only? "tested" : decoder_session->analysis_mode? "analyzed" : "wrote",
1118                                 (unsigned)decoder_session->samples_processed
1119                         );
1120                 }
1121         }
1122 }