~ubuntu-branches/ubuntu/gutsy/flac/gutsy-updates

« back to all changes in this revision

Viewing changes to src/flac/decode.c

  • Committer: Bazaar Package Importer
  • Author(s): Matt Zimmerman
  • Date: 2004-04-16 15:14:31 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040416151431-eyloggqxpwbwpogz
Tags: 1.1.0-11
Ensure that libFLAC is linked with -lm on all architectures, and
regardless of whether nasm is present

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* flac - Command-line FLAC encoder/decoder
2
 
 * Copyright (C) 2000,2001  Josh Coalson
 
2
 * Copyright (C) 2000,2001,2002,2003  Josh Coalson
3
3
 *
4
4
 * This program is free software; you can redistribute it and/or
5
5
 * modify it under the terms of the GNU General Public License
16
16
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17
17
 */
18
18
 
 
19
#ifdef HAVE_CONFIG_H
 
20
#include <config.h>
 
21
#endif
 
22
 
19
23
#if defined _WIN32 && !defined __CYGWIN__
20
24
/* where MSVC puts unlink() */
21
25
# include <io.h>
26
30
#include <stdio.h> /* for FILE et al. */
27
31
#include <string.h> /* for strcmp() */
28
32
#include "FLAC/all.h"
 
33
#include "share/grabbag.h"
29
34
#include "decode.h"
30
 
#include "file.h"
31
 
#ifdef FLAC__HAS_OGG
32
 
#include "ogg/ogg.h"
33
 
#endif
34
 
 
35
 
#ifdef FLAC__HAS_OGG
36
 
typedef struct {
37
 
        ogg_sync_state oy;
38
 
        ogg_stream_state os;
39
 
} ogg_info_struct;
40
 
#endif
41
 
 
42
 
typedef struct {
 
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
 
43
55
        const char *inbasefilename;
44
 
#ifdef FLAC__HAS_OGG
45
 
        FILE *fin;
46
 
#endif
47
 
        FILE *fout;
 
56
        const char *outfilename;
 
57
 
 
58
        FLAC__uint64 samples_processed;
 
59
        unsigned frame_counter;
48
60
        FLAC__bool abort_flag;
49
 
        FLAC__bool analysis_mode;
50
 
        analysis_options aopts;
51
 
        FLAC__bool test_only;
52
 
        FLAC__bool is_wave_out;
 
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
 
53
69
        FLAC__bool is_big_endian;
54
70
        FLAC__bool is_unsigned_samples;
55
71
        FLAC__uint64 total_samples;
56
72
        unsigned bps;
57
73
        unsigned channels;
58
74
        unsigned sample_rate;
59
 
        FLAC__bool verbose;
60
 
        FLAC__uint64 skip;
61
 
        FLAC__bool skip_count_too_high;
62
 
        FLAC__uint64 samples_processed;
63
 
        unsigned frame_counter;
64
 
#ifdef FLAC__HAS_OGG
65
 
        FLAC__bool is_ogg;
66
 
#endif
 
75
 
67
76
        union {
68
 
                FLAC__FileDecoder *file;
69
 
                FLAC__StreamDecoder *stream;
 
77
                union {
 
78
                        FLAC__FileDecoder *file;
 
79
                } flac;
 
80
#ifdef FLAC__HAS_OGG
 
81
                union {
 
82
                        OggFLAC__StreamDecoder *stream;
 
83
                } ogg;
 
84
#endif
70
85
        } decoder;
 
86
 
71
87
#ifdef FLAC__HAS_OGG
72
 
        ogg_info_struct ogg;
 
88
        FILE *fin;
73
89
#endif
74
 
} stream_info_struct;
75
 
 
76
 
static FLAC__bool is_big_endian_host;
77
 
 
78
 
/* local routines */
79
 
static FLAC__bool init(const char *infilename, stream_info_struct *stream_info);
 
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);
80
107
static FLAC__bool write_little_endian_uint16(FILE *f, FLAC__uint16 val);
81
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);
82
113
#ifdef FLAC__HAS_OGG
83
 
static FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
 
114
static FLAC__StreamDecoderReadStatus read_callback(const OggFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data);
84
115
#endif
85
116
/*
86
117
 * We use 'void *' so that we can use the same callbacks for the
87
118
 * FLAC__StreamDecoder and FLAC__FileDecoder.  The 'decoder' argument is
88
119
 * actually never used in the callbacks.
89
120
 */
90
 
static FLAC__StreamDecoderWriteStatus write_callback(const void *decoder, const FLAC__Frame *frame, const FLAC__int32 *buffer[], void *client_data);
91
 
static void metadata_callback(const void *decoder, const FLAC__StreamMetaData *metadata, void *client_data);
 
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);
92
123
static void error_callback(const void *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
93
 
static void print_stats(const stream_info_struct *stream_info);
94
 
 
 
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
}
95
165
 
96
166
int flac__decode_wav(const char *infilename, const char *outfilename, FLAC__bool analysis_mode, analysis_options aopts, wav_decode_options_t options)
97
167
{
98
 
        FLAC__bool md5_failure = false;
99
 
        stream_info_struct stream_info;
100
 
 
101
 
        stream_info.abort_flag = false;
102
 
        stream_info.analysis_mode = analysis_mode;
103
 
        stream_info.aopts = aopts;
104
 
        stream_info.test_only = (outfilename == 0);
105
 
        stream_info.is_wave_out = true;
106
 
        stream_info.verbose = options.common.verbose;
107
 
        stream_info.skip = options.common.skip;
108
 
        stream_info.skip_count_too_high = false;
109
 
        stream_info.samples_processed = 0;
110
 
        stream_info.frame_counter = 0;
111
 
#ifdef FLAC__HAS_OGG
112
 
        stream_info.is_ogg = options.common.is_ogg;
113
 
#endif
114
 
        stream_info.decoder.file = 0; /* this zeroes stream_info.decoder.stream also */
115
 
        stream_info.inbasefilename = flac__file_get_basename(infilename);
116
 
        stream_info.fout = 0; /* initialized with an open file later if necessary */
117
 
 
118
 
        FLAC__ASSERT(!(stream_info.test_only && stream_info.analysis_mode));
119
 
 
120
 
        if(!stream_info.test_only) {
121
 
                if(0 == strcmp(outfilename, "-")) {
122
 
                        stream_info.fout = stdout;
123
 
                }
124
 
                else {
125
 
                        if(0 == (stream_info.fout = fopen(outfilename, "wb"))) {
126
 
                                fprintf(stderr, "%s: ERROR: can't open output file %s\n", stream_info.inbasefilename, outfilename);
127
 
                                return 1;
128
 
                        }
129
 
                }
130
 
        }
131
 
 
132
 
#ifdef FLAC__HAS_OGG
133
 
        if(stream_info.is_ogg) {
134
 
                if (0 == strcmp(infilename, "-")) {
135
 
                        stream_info.fin = stdin;
136
 
                } else {
137
 
                        if (0 == (stream_info.fin = fopen(infilename, "rb"))) {
138
 
                                fprintf(stderr, "%s: ERROR: can't open input file %s\n", stream_info.inbasefilename, infilename);
139
 
                                if(stream_info.fout != stdout)
140
 
                                        fclose(stream_info.fout);
141
 
                                return 1;
142
 
                        }
143
 
                }
144
 
        }
145
 
#endif
146
 
 
147
 
        if(analysis_mode)
148
 
                flac__analyze_init(aopts);
149
 
 
150
 
        if(!init(infilename, &stream_info))
151
 
                goto wav_abort_;
152
 
 
153
 
        if(stream_info.skip > 0) {
154
 
#ifdef FLAC__HAS_OGG
155
 
                if(stream_info.is_ogg) { //@@@ (move this check into main.c)
156
 
                        fprintf(stderr, "%s: ERROR, can't skip when decoding Ogg-FLAC yet; convert to native-FLAC first\n", stream_info.inbasefilename);
157
 
                        goto wav_abort_;
158
 
                }
159
 
#endif
160
 
                if(!FLAC__file_decoder_process_metadata(stream_info.decoder.file)) {
161
 
                        fprintf(stderr, "%s: ERROR while decoding metadata, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
162
 
                        goto wav_abort_;
163
 
                }
164
 
                if(stream_info.skip_count_too_high) {
165
 
                        fprintf(stderr, "%s: ERROR trying to skip more samples than in stream\n", stream_info.inbasefilename);
166
 
                        goto wav_abort_;
167
 
                }
168
 
                if(!FLAC__file_decoder_seek_absolute(stream_info.decoder.file, stream_info.skip)) {
169
 
                        fprintf(stderr, "%s: ERROR seeking while skipping bytes, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
170
 
                        goto wav_abort_;
171
 
                }
172
 
                if(!FLAC__file_decoder_process_remaining_frames(stream_info.decoder.file)) {
173
 
                        if(stream_info.verbose) fprintf(stderr, "\n");
174
 
                        fprintf(stderr, "%s: ERROR while decoding frames, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
175
 
                        goto wav_abort_;
176
 
                }
177
 
                if(FLAC__file_decoder_get_state(stream_info.decoder.file) != FLAC__FILE_DECODER_OK && FLAC__file_decoder_get_state(stream_info.decoder.file) != FLAC__FILE_DECODER_END_OF_FILE) {
178
 
                        if(stream_info.verbose) fprintf(stderr, "\n");
179
 
                        fprintf(stderr, "%s: ERROR during decoding, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
180
 
                        goto wav_abort_;
181
 
                }
182
 
        }
183
 
        else {
184
 
#ifdef FLAC__HAS_OGG
185
 
                if(stream_info.is_ogg) {
186
 
                        if(!FLAC__stream_decoder_process_whole_stream(stream_info.decoder.stream)) {
187
 
                                if(stream_info.verbose) fprintf(stderr, "\n");
188
 
                                fprintf(stderr, "%s: ERROR while decoding data, state=%d:%s\n", stream_info.inbasefilename, FLAC__stream_decoder_get_state(stream_info.decoder.stream), FLAC__StreamDecoderStateString[FLAC__stream_decoder_get_state(stream_info.decoder.stream)]);
189
 
                                goto wav_abort_;
190
 
                        }
191
 
                        if(FLAC__stream_decoder_get_state(stream_info.decoder.stream) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA && FLAC__stream_decoder_get_state(stream_info.decoder.stream) != FLAC__STREAM_DECODER_END_OF_STREAM) {
192
 
                                if(stream_info.verbose) fprintf(stderr, "\n");
193
 
                                fprintf(stderr, "%s: ERROR during decoding, state=%d:%s\n", stream_info.inbasefilename, FLAC__stream_decoder_get_state(stream_info.decoder.stream), FLAC__StreamDecoderStateString[FLAC__stream_decoder_get_state(stream_info.decoder.stream)]);
194
 
                                goto wav_abort_;
195
 
                        }
196
 
                }
197
 
                else
198
 
#endif
199
 
                {
200
 
                        if(!FLAC__file_decoder_process_whole_file(stream_info.decoder.file)) {
201
 
                                if(stream_info.verbose) fprintf(stderr, "\n");
202
 
                                fprintf(stderr, "%s: ERROR while decoding data, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
203
 
                                goto wav_abort_;
204
 
                        }
205
 
                        if(FLAC__file_decoder_get_state(stream_info.decoder.file) != FLAC__FILE_DECODER_OK && FLAC__file_decoder_get_state(stream_info.decoder.file) != FLAC__FILE_DECODER_END_OF_FILE) {
206
 
                                if(stream_info.verbose) fprintf(stderr, "\n");
207
 
                                fprintf(stderr, "%s: ERROR during decoding, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
208
 
                                goto wav_abort_;
209
 
                        }
210
 
                }
211
 
        }
212
 
 
213
 
#ifdef FLAC__HAS_OGG
214
 
        if(stream_info.is_ogg) {
215
 
                if(stream_info.decoder.stream) {
216
 
                        FLAC__stream_decoder_finish(stream_info.decoder.stream);
217
 
                        md5_failure = false;
218
 
                        print_stats(&stream_info);
219
 
                        FLAC__stream_decoder_delete(stream_info.decoder.stream);
220
 
                }
221
 
        }
222
 
        else
223
 
#endif
224
 
        {
225
 
                if(stream_info.decoder.file) {
226
 
                        md5_failure = !FLAC__file_decoder_finish(stream_info.decoder.file);
227
 
                        print_stats(&stream_info);
228
 
                        FLAC__file_decoder_delete(stream_info.decoder.file);
229
 
                }
230
 
        }
231
 
        if(0 != stream_info.fout && stream_info.fout != stdout)
232
 
                fclose(stream_info.fout);
233
 
#ifdef FLAC__HAS_OGG
234
 
        if(stream_info.is_ogg) {
235
 
                if(0 != stream_info.fin && stream_info.fin != stdin)
236
 
                        fclose(stream_info.fin);
237
 
        }
238
 
#endif
239
 
        if(analysis_mode)
240
 
                flac__analyze_finish(aopts);
241
 
        if(md5_failure) {
242
 
                fprintf(stderr, "\r%s: WARNING, MD5 signature mismatch\n", stream_info.inbasefilename);
243
 
        }
244
 
        else {
245
 
                if(stream_info.verbose)
246
 
                        fprintf(stderr, "\r%s: %s         \n", stream_info.inbasefilename, stream_info.test_only? "ok           ":analysis_mode?"done           ":"done");
247
 
        }
248
 
        return 0;
249
 
wav_abort_:
250
 
#ifdef FLAC__HAS_OGG
251
 
        if(stream_info.is_ogg) {
252
 
                if(stream_info.decoder.stream) {
253
 
                        FLAC__stream_decoder_finish(stream_info.decoder.stream);
254
 
                        FLAC__stream_decoder_delete(stream_info.decoder.stream);
255
 
                }
256
 
        }
257
 
        else
258
 
#endif
259
 
        {
260
 
                if(stream_info.decoder.file) {
261
 
                        FLAC__file_decoder_finish(stream_info.decoder.file);
262
 
                        FLAC__file_decoder_delete(stream_info.decoder.file);
263
 
                }
264
 
        }
265
 
        if(0 != stream_info.fout && stream_info.fout != stdout) {
266
 
                fclose(stream_info.fout);
267
 
                unlink(outfilename);
268
 
        }
269
 
#ifdef FLAC__HAS_OGG
270
 
        if(stream_info.is_ogg) {
271
 
                if(0 != stream_info.fin && stream_info.fin != stdin)
272
 
                        fclose(stream_info.fin);
273
 
        }
274
 
#endif
275
 
        if(analysis_mode)
276
 
                flac__analyze_finish(aopts);
277
 
        return 1;
 
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);
278
199
}
279
200
 
280
201
int flac__decode_raw(const char *infilename, const char *outfilename, FLAC__bool analysis_mode, analysis_options aopts, raw_decode_options_t options)
281
202
{
282
 
        FLAC__bool md5_failure = false;
283
 
        stream_info_struct stream_info;
284
 
 
285
 
        stream_info.abort_flag = false;
286
 
        stream_info.analysis_mode = analysis_mode;
287
 
        stream_info.aopts = aopts;
288
 
        stream_info.test_only = (outfilename == 0);
289
 
        stream_info.is_wave_out = false;
290
 
        stream_info.is_big_endian = options.is_big_endian;
291
 
        stream_info.is_unsigned_samples = options.is_unsigned_samples;
292
 
        stream_info.verbose = options.common.verbose;
293
 
        stream_info.skip = options.common.skip;
294
 
        stream_info.skip_count_too_high = false;
295
 
        stream_info.samples_processed = 0;
296
 
        stream_info.frame_counter = 0;
297
 
#ifdef FLAC__HAS_OGG
298
 
        stream_info.is_ogg = options.common.is_ogg;
299
 
#endif
300
 
        stream_info.decoder.file = 0; /* this zeroes stream_info.decoder.stream also */
301
 
        stream_info.inbasefilename = flac__file_get_basename(infilename);
302
 
        stream_info.fout = 0; /* initialized with an open file later if necessary */
303
 
 
304
 
        FLAC__ASSERT(!(stream_info.test_only && stream_info.analysis_mode));
305
 
 
306
 
        if(!stream_info.test_only) {
 
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) {
307
279
                if(0 == strcmp(outfilename, "-")) {
308
 
                        stream_info.fout = stdout;
 
280
                        d->fout = grabbag__file_get_binary_stdout();
309
281
                }
310
282
                else {
311
 
                        if(0 == (stream_info.fout = fopen(outfilename, "wb"))) {
312
 
                                fprintf(stderr, "%s: ERROR: can't open output file %s\n", stream_info.inbasefilename, outfilename);
313
 
                                return 1;
 
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;
314
287
                        }
315
288
                }
316
289
        }
317
290
 
318
291
#ifdef FLAC__HAS_OGG
319
 
        if(stream_info.is_ogg) {
 
292
        if(d->is_ogg) {
320
293
                if (0 == strcmp(infilename, "-")) {
321
 
                        stream_info.fin = stdin;
 
294
                        d->fin = grabbag__file_get_binary_stdin();
322
295
                } else {
323
 
                        if (0 == (stream_info.fin = fopen(infilename, "rb"))) {
324
 
                                fprintf(stderr, "%s: ERROR: can't open input file %s\n", stream_info.inbasefilename, infilename);
325
 
                                if(stream_info.fout != stdout)
326
 
                                        fclose(stream_info.fout);
327
 
                                return 1;
 
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;
328
300
                        }
329
301
                }
330
302
        }
333
305
        if(analysis_mode)
334
306
                flac__analyze_init(aopts);
335
307
 
336
 
        if(!init(infilename, &stream_info))
337
 
                goto raw_abort_;
338
 
 
339
 
        if(stream_info.skip > 0) {
340
 
#ifdef FLAC__HAS_OGG
341
 
                if(stream_info.is_ogg) { //@@@ (move this check into main.c)
342
 
                        fprintf(stderr, "%s: ERROR, can't skip when decoding Ogg-FLAC yet; convert to native-FLAC first\n", stream_info.inbasefilename);
343
 
                        goto raw_abort_;
344
 
                }
345
 
#endif
346
 
                if(!FLAC__file_decoder_process_metadata(stream_info.decoder.file)) {
347
 
                        fprintf(stderr, "%s: ERROR while decoding metadata, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
348
 
                        goto raw_abort_;
349
 
                }
350
 
                if(stream_info.skip_count_too_high) {
351
 
                        fprintf(stderr, "%s: ERROR trying to skip more samples than in stream\n", stream_info.inbasefilename);
352
 
                        goto raw_abort_;
353
 
                }
354
 
                if(!FLAC__file_decoder_seek_absolute(stream_info.decoder.file, stream_info.skip)) {
355
 
                        fprintf(stderr, "%s: ERROR seeking while skipping bytes, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
356
 
                        goto raw_abort_;
357
 
                }
358
 
                if(!FLAC__file_decoder_process_remaining_frames(stream_info.decoder.file)) {
359
 
                        if(stream_info.verbose) fprintf(stderr, "\n");
360
 
                        fprintf(stderr, "%s: ERROR while decoding frames, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
361
 
                        goto raw_abort_;
362
 
                }
363
 
                if(FLAC__file_decoder_get_state(stream_info.decoder.file) != FLAC__FILE_DECODER_OK && FLAC__file_decoder_get_state(stream_info.decoder.file) != FLAC__FILE_DECODER_END_OF_FILE) {
364
 
                        if(stream_info.verbose) fprintf(stderr, "\n");
365
 
                        fprintf(stderr, "%s: ERROR during decoding, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
366
 
                        goto raw_abort_;
367
 
                }
368
 
        }
369
 
        else {
370
 
#ifdef FLAC__HAS_OGG
371
 
                if(stream_info.is_ogg) {
372
 
                        if(!FLAC__stream_decoder_process_whole_stream(stream_info.decoder.stream)) {
373
 
                                if(stream_info.verbose) fprintf(stderr, "\n");
374
 
                                fprintf(stderr, "%s: ERROR while decoding data, state=%d:%s\n", stream_info.inbasefilename, FLAC__stream_decoder_get_state(stream_info.decoder.stream), FLAC__StreamDecoderStateString[FLAC__stream_decoder_get_state(stream_info.decoder.stream)]);
375
 
                                goto raw_abort_;
376
 
                        }
377
 
                        if(FLAC__stream_decoder_get_state(stream_info.decoder.stream) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA && FLAC__stream_decoder_get_state(stream_info.decoder.stream) != FLAC__STREAM_DECODER_END_OF_STREAM) {
378
 
                                if(stream_info.verbose) fprintf(stderr, "\n");
379
 
                                fprintf(stderr, "%s: ERROR during decoding, state=%d:%s\n", stream_info.inbasefilename, FLAC__stream_decoder_get_state(stream_info.decoder.stream), FLAC__StreamDecoderStateString[FLAC__stream_decoder_get_state(stream_info.decoder.stream)]);
380
 
                                goto raw_abort_;
381
 
                        }
382
 
                }
383
 
                else
384
 
#endif
385
 
                {
386
 
                        if(!FLAC__file_decoder_process_whole_file(stream_info.decoder.file)) {
387
 
                                if(stream_info.verbose) fprintf(stderr, "\n");
388
 
                                fprintf(stderr, "%s: ERROR while decoding data, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
389
 
                                goto raw_abort_;
390
 
                        }
391
 
                        if(FLAC__file_decoder_get_state(stream_info.decoder.file) != FLAC__FILE_DECODER_OK && FLAC__file_decoder_get_state(stream_info.decoder.file) != FLAC__FILE_DECODER_END_OF_FILE) {
392
 
                                if(stream_info.verbose) fprintf(stderr, "\n");
393
 
                                fprintf(stderr, "%s: ERROR during decoding, state=%d:%s\n", stream_info.inbasefilename, FLAC__file_decoder_get_state(stream_info.decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info.decoder.file)]);
394
 
                                goto raw_abort_;
395
 
                        }
396
 
                }
397
 
        }
398
 
 
399
 
#ifdef FLAC__HAS_OGG
400
 
        if(stream_info.is_ogg) {
401
 
                if(stream_info.decoder.stream) {
402
 
                        FLAC__stream_decoder_finish(stream_info.decoder.stream);
403
 
                        md5_failure = false;
404
 
                        print_stats(&stream_info);
405
 
                        FLAC__stream_decoder_delete(stream_info.decoder.stream);
406
 
                }
407
 
        }
408
 
        else
409
 
#endif
410
 
        {
411
 
                if(stream_info.decoder.file) {
412
 
                        md5_failure = !FLAC__file_decoder_finish(stream_info.decoder.file);
413
 
                        print_stats(&stream_info);
414
 
                        FLAC__file_decoder_delete(stream_info.decoder.file);
415
 
                }
416
 
        }
417
 
        if(0 != stream_info.fout && stream_info.fout != stdout)
418
 
                fclose(stream_info.fout);
419
 
#ifdef FLAC__HAS_OGG
420
 
        if(stream_info.is_ogg) {
421
 
                if(0 != stream_info.fin && stream_info.fin != stdin)
422
 
                        fclose(stream_info.fin);
423
 
        }
424
 
#endif
425
 
        if(analysis_mode)
426
 
                flac__analyze_finish(aopts);
427
 
        if(md5_failure) {
428
 
                fprintf(stderr, "\r%s: WARNING, MD5 signature mismatch\n", stream_info.inbasefilename);
429
 
        }
430
 
        else {
431
 
                if(stream_info.verbose)
432
 
                        fprintf(stderr, "\r%s: %s         \n", stream_info.inbasefilename, stream_info.test_only? "ok           ":analysis_mode?"done           ":"done");
433
 
        }
434
 
        return 0;
435
 
raw_abort_:
436
 
#ifdef FLAC__HAS_OGG
437
 
        if(stream_info.is_ogg) {
438
 
                if(stream_info.decoder.stream) {
439
 
                        FLAC__stream_decoder_finish(stream_info.decoder.stream);
440
 
                        FLAC__stream_decoder_delete(stream_info.decoder.stream);
441
 
                }
442
 
        }
443
 
        else
444
 
#endif
445
 
        {
446
 
                if(stream_info.decoder.file) {
447
 
                        FLAC__file_decoder_finish(stream_info.decoder.file);
448
 
                        FLAC__file_decoder_delete(stream_info.decoder.file);
449
 
                }
450
 
        }
451
 
        if(0 != stream_info.fout && stream_info.fout != stdout) {
452
 
                fclose(stream_info.fout);
453
 
                unlink(outfilename);
454
 
        }
455
 
#ifdef FLAC__HAS_OGG
456
 
        if(stream_info.is_ogg) {
457
 
                if(0 != stream_info.fin && stream_info.fin != stdin)
458
 
                        fclose(stream_info.fin);
459
 
        }
460
 
#endif
461
 
        if(analysis_mode)
462
 
                flac__analyze_finish(aopts);
463
 
        return 1;
464
 
}
465
 
 
466
 
FLAC__bool init(const char *infilename, stream_info_struct *stream_info)
 
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)
467
325
{
468
326
        FLAC__uint32 test = 1;
469
327
 
470
 
        is_big_endian_host = (*((FLAC__byte*)(&test)))? false : true;
 
328
        is_big_endian_host_ = (*((FLAC__byte*)(&test)))? false : true;
471
329
 
472
330
#ifdef FLAC__HAS_OGG
473
 
        if(stream_info->is_ogg) {
474
 
                stream_info->decoder.stream = FLAC__stream_decoder_new();
 
331
        if(decoder_session->is_ogg) {
 
332
                decoder_session->decoder.ogg.stream = OggFLAC__stream_decoder_new();
475
333
 
476
 
                if(0 == stream_info->decoder.stream) {
477
 
                        fprintf(stderr, "%s: ERROR creating the decoder instance\n", stream_info->inbasefilename);
 
334
                if(0 == decoder_session->decoder.ogg.stream) {
 
335
                        fprintf(stderr, "%s: ERROR creating the decoder instance\n", decoder_session->inbasefilename);
478
336
                        return false;
479
337
                }
480
338
 
481
 
                FLAC__stream_decoder_set_read_callback(stream_info->decoder.stream, read_callback);
 
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);
482
343
                /*
483
344
                 * The three ugly casts here are to 'downcast' the 'void *' argument of
484
345
                 * the callback down to 'FLAC__StreamDecoder *'.  In C++ this would be
485
346
                 * unnecessary but here the cast makes the C compiler happy.
486
347
                 */
487
 
                FLAC__stream_decoder_set_write_callback(stream_info->decoder.stream, (FLAC__StreamDecoderWriteStatus (*)(const FLAC__StreamDecoder *, const FLAC__Frame *, const FLAC__int32 *[], void *))write_callback);
488
 
                FLAC__stream_decoder_set_metadata_callback(stream_info->decoder.stream, (void (*)(const FLAC__StreamDecoder *, const FLAC__StreamMetaData *, void *))metadata_callback);
489
 
                FLAC__stream_decoder_set_error_callback(stream_info->decoder.stream, (void (*)(const FLAC__StreamDecoder *, FLAC__StreamDecoderErrorStatus, void *))error_callback);
490
 
                FLAC__stream_decoder_set_client_data(stream_info->decoder.stream, stream_info);
 
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);
491
352
 
492
 
                if(FLAC__stream_decoder_init(stream_info->decoder.stream) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA) {
493
 
                        fprintf(stderr, "%s: ERROR initializing decoder, state=%d:%s\n", stream_info->inbasefilename, FLAC__stream_decoder_get_state(stream_info->decoder.stream), FLAC__StreamDecoderStateString[FLAC__stream_decoder_get_state(stream_info->decoder.stream)]);
 
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");
494
355
                        return false;
495
356
                }
496
 
 
497
 
                ogg_stream_init(&stream_info->ogg.os, 0);
498
 
                ogg_sync_init(&stream_info->ogg.oy);
499
357
        }
500
358
        else
 
359
#else
 
360
        (void)decode_options;
501
361
#endif
502
362
        {
503
 
                stream_info->decoder.file = FLAC__file_decoder_new();
 
363
                decoder_session->decoder.flac.file = FLAC__file_decoder_new();
504
364
 
505
 
                if(0 == stream_info->decoder.file) {
506
 
                        fprintf(stderr, "%s: ERROR creating the decoder instance\n", stream_info->inbasefilename);
 
365
                if(0 == decoder_session->decoder.flac.file) {
 
366
                        fprintf(stderr, "%s: ERROR creating the decoder instance\n", decoder_session->inbasefilename);
507
367
                        return false;
508
368
                }
509
369
 
510
 
                FLAC__file_decoder_set_md5_checking(stream_info->decoder.file, true);
511
 
                FLAC__file_decoder_set_filename(stream_info->decoder.file, infilename);
 
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);
512
372
                /*
513
373
                 * The three ugly casts here are to 'downcast' the 'void *' argument of
514
 
                 * the callback down to 'FLAC__FileDecoder *'.  In C++ this would be
515
 
                 * unnecessary but here the cast makes the C compiler happy.
 
374
                 * the callback down to 'FLAC__FileDecoder *'.
516
375
                 */
517
 
                FLAC__file_decoder_set_write_callback(stream_info->decoder.file, (FLAC__StreamDecoderWriteStatus (*)(const FLAC__FileDecoder *, const FLAC__Frame *, const FLAC__int32 *[], void *))write_callback);
518
 
                FLAC__file_decoder_set_metadata_callback(stream_info->decoder.file, (void (*)(const FLAC__FileDecoder *, const FLAC__StreamMetaData *, void *))metadata_callback);
519
 
                FLAC__file_decoder_set_error_callback(stream_info->decoder.file, (void (*)(const FLAC__FileDecoder *, FLAC__StreamDecoderErrorStatus, void *))error_callback);
520
 
                FLAC__file_decoder_set_client_data(stream_info->decoder.file, stream_info);
521
 
 
522
 
                if(FLAC__file_decoder_init(stream_info->decoder.file) != FLAC__FILE_DECODER_OK) {
523
 
                        fprintf(stderr, "%s: ERROR initializing decoder, state=%d:%s\n", stream_info->inbasefilename, FLAC__file_decoder_get_state(stream_info->decoder.file), FLAC__FileDecoderStateString[FLAC__file_decoder_get_state(stream_info->decoder.file)]);
524
 
                        return false;
525
 
                }
 
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;
526
587
        }
527
588
 
528
589
        return true;
531
592
FLAC__bool write_little_endian_uint16(FILE *f, FLAC__uint16 val)
532
593
{
533
594
        FLAC__byte *b = (FLAC__byte*)(&val);
534
 
        if(is_big_endian_host) {
 
595
        if(is_big_endian_host_) {
535
596
                FLAC__byte tmp;
536
597
                tmp = b[1]; b[1] = b[0]; b[0] = tmp;
537
598
        }
538
 
        return fwrite(b, 1, 2, f) == 2;
 
599
        return flac__utils_fwrite(b, 1, 2, f) == 2;
539
600
}
540
601
 
541
602
FLAC__bool write_little_endian_uint32(FILE *f, FLAC__uint32 val)
542
603
{
543
604
        FLAC__byte *b = (FLAC__byte*)(&val);
544
 
        if(is_big_endian_host) {
545
 
                FLAC__byte tmp;
546
 
                tmp = b[3]; b[3] = b[0]; b[0] = tmp;
547
 
                tmp = b[2]; b[2] = b[1]; b[1] = tmp;
548
 
        }
549
 
        return fwrite(b, 1, 4, f) == 4;
 
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;
550
711
}
551
712
 
552
713
#ifdef FLAC__HAS_OGG
553
 
#define OGG_READ_BUFFER_SIZE 4096
554
 
FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
 
714
FLAC__StreamDecoderReadStatus read_callback(const OggFLAC__StreamDecoder *decoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
555
715
{
556
 
        stream_info_struct *stream_info = (stream_info_struct *)client_data;
557
 
        FILE *fin = stream_info->fin;
 
716
        DecoderSession *decoder_session = (DecoderSession*)client_data;
 
717
        FILE *fin = decoder_session->fin;
558
718
        size_t bytes_read;
559
 
        ogg_page og;
560
 
        char *oggbuf;
561
 
        unsigned int offset = 0;
562
 
 
563
 
        *bytes = 0;
564
 
 
565
 
        if (stream_info->abort_flag)
566
 
                return FLAC__STREAM_DECODER_READ_ABORT;
567
 
 
568
 
        oggbuf = ogg_sync_buffer(&stream_info->ogg.oy, OGG_READ_BUFFER_SIZE);
569
719
 
570
720
        (void)decoder; /* avoid compiler warning */
571
721
 
 
722
        if (decoder_session->abort_flag)
 
723
                return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
 
724
 
572
725
        if(feof(fin))
573
 
                return FLAC__STREAM_DECODER_READ_END_OF_STREAM;
 
726
                return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
574
727
 
575
 
        bytes_read = fread(oggbuf, 1, OGG_READ_BUFFER_SIZE, fin);
 
728
        bytes_read = fread(buffer, 1, *bytes, fin);
576
729
 
577
730
        if(ferror(fin))
578
 
                return FLAC__STREAM_DECODER_READ_ABORT;
579
 
 
580
 
        if(ogg_sync_wrote(&stream_info->ogg.oy, bytes_read) < 0)
581
 
                return FLAC__STREAM_DECODER_READ_ABORT;
582
 
 
583
 
        while(ogg_sync_pageout(&stream_info->ogg.oy, &og) == 1) {
584
 
                if(ogg_stream_pagein(&stream_info->ogg.os, &og) == 0) {
585
 
                        ogg_packet op;
586
 
 
587
 
                        while(ogg_stream_packetout(&stream_info->ogg.os, &op) == 1) {
588
 
                                memcpy(buffer + offset, op.packet, op.bytes);
589
 
                                *bytes += op.bytes;
590
 
                                offset += op.bytes;
591
 
                        }
592
 
                } else {
593
 
                        return FLAC__STREAM_DECODER_READ_ABORT;
594
 
                }
595
 
        }
596
 
 
597
 
        return FLAC__STREAM_DECODER_READ_CONTINUE;
 
731
                return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
 
732
 
 
733
        *bytes = (unsigned)bytes_read;
 
734
 
 
735
        return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
598
736
}
599
737
#endif
600
738
 
601
 
FLAC__StreamDecoderWriteStatus write_callback(const void *decoder, const FLAC__Frame *frame, const FLAC__int32 *buffer[], void *client_data)
 
739
FLAC__StreamDecoderWriteStatus write_callback(const void *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
602
740
{
603
 
        stream_info_struct *stream_info = (stream_info_struct *)client_data;
604
 
        FILE *fout = stream_info->fout;
605
 
        unsigned bps = stream_info->bps, channels = stream_info->channels;
606
 
        FLAC__bool is_big_endian = (stream_info->is_wave_out? false : stream_info->is_big_endian);
607
 
        FLAC__bool is_unsigned_samples = (stream_info->is_wave_out? bps<=8 : stream_info->is_unsigned_samples);
 
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));
608
746
        unsigned wide_samples = frame->header.blocksize, wide_sample, sample, channel, byte;
609
747
        static FLAC__int8 s8buffer[FLAC__MAX_BLOCK_SIZE * FLAC__MAX_CHANNELS * sizeof(FLAC__int32)]; /* WATCHOUT: can be up to 2 megs */
610
 
        /* WATCHOUT: we say 'sizeof(FLAC__int32)' above instead of '(FLAC__MAX_BITS_PER_SAMPLE+7)/8' because we have to use an array FLAC__int32 even for 24 bps */
611
748
        FLAC__uint8  *u8buffer  = (FLAC__uint8  *)s8buffer;
612
749
        FLAC__int16  *s16buffer = (FLAC__int16  *)s8buffer;
613
750
        FLAC__uint16 *u16buffer = (FLAC__uint16 *)s8buffer;
616
753
 
617
754
        (void)decoder;
618
755
 
619
 
        if(stream_info->abort_flag)
620
 
                return FLAC__STREAM_DECODER_WRITE_ABORT;
621
 
 
622
 
        stream_info->samples_processed += wide_samples;
623
 
        stream_info->frame_counter++;
624
 
 
625
 
        if(stream_info->verbose && !(stream_info->frame_counter & 0x7f))
626
 
                print_stats(stream_info);
627
 
 
628
 
        if(stream_info->analysis_mode) {
629
 
                flac__analyze_frame(frame, stream_info->frame_counter-1, stream_info->aopts, fout);
630
 
        }
631
 
        else if(!stream_info->test_only) {
632
 
                if(bps == 8) {
633
 
                        if(is_unsigned_samples) {
634
 
                                for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
635
 
                                        for(channel = 0; channel < channels; channel++, sample++)
636
 
                                                u8buffer[sample] = (FLAC__uint8)(buffer[channel][wide_sample] + 0x80);
637
 
                        }
638
 
                        else {
639
 
                                for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
640
 
                                        for(channel = 0; channel < channels; channel++, sample++)
641
 
                                                s8buffer[sample] = (FLAC__int8)(buffer[channel][wide_sample]);
642
 
                        }
643
 
                        if(fwrite(u8buffer, 1, sample, fout) != sample)
644
 
                                return FLAC__STREAM_DECODER_WRITE_ABORT;
645
 
                }
646
 
                else if(bps == 16) {
647
 
                        if(is_unsigned_samples) {
648
 
                                for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
649
 
                                        for(channel = 0; channel < channels; channel++, sample++)
650
 
                                                u16buffer[sample] = (FLAC__uint16)(buffer[channel][wide_sample] + 0x8000);
651
 
                        }
652
 
                        else {
653
 
                                for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
654
 
                                        for(channel = 0; channel < channels; channel++, sample++)
655
 
                                                s16buffer[sample] = (FLAC__int16)(buffer[channel][wide_sample]);
656
 
                        }
657
 
                        if(is_big_endian != is_big_endian_host) {
658
 
                                unsigned char tmp;
659
 
                                const unsigned bytes = sample * 2;
660
 
                                for(byte = 0; byte < bytes; byte += 2) {
661
 
                                        tmp = u8buffer[byte];
662
 
                                        u8buffer[byte] = u8buffer[byte+1];
663
 
                                        u8buffer[byte+1] = tmp;
664
 
                                }
665
 
                        }
666
 
                        if(fwrite(u16buffer, 2, sample, fout) != sample)
667
 
                                return FLAC__STREAM_DECODER_WRITE_ABORT;
668
 
                }
669
 
                else if(bps == 24) {
670
 
                        if(is_unsigned_samples) {
671
 
                                for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
672
 
                                        for(channel = 0; channel < channels; channel++, sample++)
673
 
                                                u32buffer[sample] = buffer[channel][wide_sample] + 0x800000;
674
 
                        }
675
 
                        else {
676
 
                                for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
677
 
                                        for(channel = 0; channel < channels; channel++, sample++)
678
 
                                                s32buffer[sample] = buffer[channel][wide_sample];
679
 
                        }
680
 
                        if(is_big_endian != is_big_endian_host) {
681
 
                                unsigned char tmp;
682
 
                                const unsigned bytes = sample * 4;
683
 
                                for(byte = 0; byte < bytes; byte += 4) {
684
 
                                        tmp = u8buffer[byte];
685
 
                                        u8buffer[byte] = u8buffer[byte+3];
686
 
                                        u8buffer[byte+3] = tmp;
687
 
                                        tmp = u8buffer[byte+1];
688
 
                                        u8buffer[byte+1] = u8buffer[byte+2];
689
 
                                        u8buffer[byte+2] = tmp;
690
 
                                }
691
 
                        }
692
 
                        if(is_big_endian) {
693
 
                                unsigned lbyte;
694
 
                                const unsigned bytes = sample * 4;
695
 
                                for(lbyte = byte = 0; byte < bytes; ) {
696
 
                                        byte++;
697
 
                                        u8buffer[lbyte++] = u8buffer[byte++];
698
 
                                        u8buffer[lbyte++] = u8buffer[byte++];
699
 
                                        u8buffer[lbyte++] = u8buffer[byte++];
700
 
                                }
701
 
                        }
702
 
                        else {
703
 
                                unsigned lbyte;
704
 
                                const unsigned bytes = sample * 4;
705
 
                                for(lbyte = byte = 0; byte < bytes; ) {
706
 
                                        u8buffer[lbyte++] = u8buffer[byte++];
707
 
                                        u8buffer[lbyte++] = u8buffer[byte++];
708
 
                                        u8buffer[lbyte++] = u8buffer[byte++];
709
 
                                        byte++;
710
 
                                }
711
 
                        }
712
 
                        if(fwrite(u8buffer, 3, sample, fout) != sample)
713
 
                                return FLAC__STREAM_DECODER_WRITE_ABORT;
714
 
                }
715
 
                else {
716
 
                        FLAC__ASSERT(0);
717
 
                }
718
 
        }
719
 
        return FLAC__STREAM_DECODER_WRITE_CONTINUE;
 
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;
720
888
}
721
889
 
722
 
void metadata_callback(const void *decoder, const FLAC__StreamMetaData *metadata, void *client_data)
 
890
void metadata_callback(const void *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
723
891
{
724
 
        stream_info_struct *stream_info = (stream_info_struct *)client_data;
 
892
        DecoderSession *decoder_session = (DecoderSession*)client_data;
725
893
        (void)decoder;
726
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
 
727
904
                /* remember, metadata->data.stream_info.total_samples can be 0, meaning 'unknown' */
728
 
                if(metadata->data.stream_info.total_samples > 0 && stream_info->skip >= metadata->data.stream_info.total_samples) {
729
 
                        stream_info->total_samples = 0;
730
 
                        stream_info->skip_count_too_high = true;
731
 
                }
732
 
                else
733
 
                        stream_info->total_samples = metadata->data.stream_info.total_samples - stream_info->skip;
734
 
                stream_info->bps = metadata->data.stream_info.bits_per_sample;
735
 
                stream_info->channels = metadata->data.stream_info.channels;
736
 
                stream_info->sample_rate = metadata->data.stream_info.sample_rate;
737
 
 
738
 
                if(stream_info->bps != 8 && stream_info->bps != 16 && stream_info->bps != 24) {
739
 
                        fprintf(stderr, "%s: ERROR: bits per sample is not 8/16/24\n", stream_info->inbasefilename);
740
 
                        stream_info->abort_flag = true;
741
 
                        return;
742
 
                }
743
 
 
744
 
                /* write the WAVE headers if necessary */
745
 
                if(!stream_info->analysis_mode && !stream_info->test_only && stream_info->is_wave_out) {
746
 
                        FLAC__uint64 data_size = stream_info->total_samples * stream_info->channels * ((stream_info->bps+7)/8);
 
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
                        }
747
948
                        if(data_size >= 0xFFFFFFDC) {
748
 
                                fprintf(stderr, "%s: ERROR: stream is too big to fit in a single WAVE file chunk\n", stream_info->inbasefilename);
749
 
                                stream_info->abort_flag = true;
 
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;
750
951
                                return;
751
952
                        }
752
 
                        if(fwrite("RIFF", 1, 4, stream_info->fout) != 4) stream_info->abort_flag = true;
753
 
                        if(!write_little_endian_uint32(stream_info->fout, (FLAC__uint32)(data_size+36))) stream_info->abort_flag = true; /* filesize-8 */
754
 
                        if(fwrite("WAVEfmt ", 1, 8, stream_info->fout) != 8) stream_info->abort_flag = true;
755
 
                        if(fwrite("\020\000\000\000", 1, 4, stream_info->fout) != 4) stream_info->abort_flag = true; /* chunk size = 16 */
756
 
                        if(fwrite("\001\000", 1, 2, stream_info->fout) != 2) stream_info->abort_flag = true; /* compression code == 1 */
757
 
                        if(!write_little_endian_uint16(stream_info->fout, (FLAC__uint16)(stream_info->channels))) stream_info->abort_flag = true;
758
 
                        if(!write_little_endian_uint32(stream_info->fout, stream_info->sample_rate)) stream_info->abort_flag = true;
759
 
                        if(!write_little_endian_uint32(stream_info->fout, stream_info->sample_rate * stream_info->channels * ((stream_info->bps+7) / 8))) stream_info->abort_flag = true; /* @@@ or is it (sample_rate*channels*bps) / 8 ??? */
760
 
                        if(!write_little_endian_uint16(stream_info->fout, (FLAC__uint16)(stream_info->channels * ((stream_info->bps+7) / 8)))) stream_info->abort_flag = true; /* block align */
761
 
                        if(!write_little_endian_uint16(stream_info->fout, (FLAC__uint16)(stream_info->bps))) stream_info->abort_flag = true; /* bits per sample */
762
 
                        if(fwrite("data", 1, 4, stream_info->fout) != 4) stream_info->abort_flag = true;
763
 
                        if(!write_little_endian_uint32(stream_info->fout, (FLAC__uint32)data_size)) stream_info->abort_flag = true; /* data size */
 
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
                        }
764
1044
                }
765
1045
        }
766
1046
}
767
1047
 
768
1048
void error_callback(const void *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
769
1049
{
770
 
        stream_info_struct *stream_info = (stream_info_struct *)client_data;
 
1050
        DecoderSession *decoder_session = (DecoderSession*)client_data;
771
1051
        (void)decoder;
772
 
        fprintf(stderr, "%s: *** Got error code %d:%s\n", stream_info->inbasefilename, status, FLAC__StreamDecoderErrorStatusString[status]);
773
 
        stream_info->abort_flag = true;
774
 
}
775
 
 
776
 
void print_stats(const stream_info_struct *stream_info)
777
 
{
778
 
        if(stream_info->verbose) {
 
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) {
779
1097
#if defined _MSC_VER || defined __MINGW32__
780
1098
                /* with VC++ you have to spoon feed it the casting */
781
 
                const double progress = (double)(FLAC__int64)stream_info->samples_processed / (double)(FLAC__int64)stream_info->total_samples * 100.0;
 
1099
                const double progress = (double)(FLAC__int64)decoder_session->samples_processed / (double)(FLAC__int64)decoder_session->total_samples * 100.0;
782
1100
#else
783
 
                const double progress = (double)stream_info->samples_processed / (double)stream_info->total_samples * 100.0;
 
1101
                const double progress = (double)decoder_session->samples_processed / (double)decoder_session->total_samples * 100.0;
784
1102
#endif
785
 
                if(stream_info->total_samples > 0) {
 
1103
                if(decoder_session->total_samples > 0) {
786
1104
                        fprintf(stderr, "\r%s: %s%u%% complete",
787
 
                                stream_info->inbasefilename,
788
 
                                stream_info->test_only? "testing, " : stream_info->analysis_mode? "analyzing, " : "",
 
1105
                                decoder_session->inbasefilename,
 
1106
                                decoder_session->test_only? "testing, " : decoder_session->analysis_mode? "analyzing, " : "",
789
1107
                                (unsigned)floor(progress + 0.5)
790
1108
                        );
791
1109
                }
792
1110
                else {
793
1111
                        fprintf(stderr, "\r%s: %s %u samples",
794
 
                                stream_info->inbasefilename,
795
 
                                stream_info->test_only? "tested" : stream_info->analysis_mode? "analyzed" : "wrote",
796
 
                                (unsigned)stream_info->samples_processed
 
1112
                                decoder_session->inbasefilename,
 
1113
                                decoder_session->test_only? "tested" : decoder_session->analysis_mode? "analyzed" : "wrote",
 
1114
                                (unsigned)decoder_session->samples_processed
797
1115
                        );
798
1116
                }
799
1117
        }