Initial revision
[flac.git] / src / flac / decode.c
1 /* flac - Command-line FLAC encoder/decoder
2  * Copyright (C) 2000  Josh Coalson
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17  */
18
19 #if defined _WIN32 && !defined __CYGWIN__
20 /* where MSVC puts unlink() */
21 # include <io.h>
22 #else
23 # include <unistd.h>
24 #endif
25 #include <stdio.h> /* for FILE */
26 #include <string.h> /* for strcmp() */
27 #include "FLAC/all.h"
28 #include "decode.h"
29
30 typedef struct {
31         FILE *fout;
32         bool abort_flag;
33         bool is_wave_out;
34         bool is_big_endian;
35         bool is_unsigned_samples;
36         uint64 total_samples;
37         unsigned bps;
38         unsigned channels;
39         unsigned sample_rate;
40         bool verbose;
41         uint64 skip;
42         uint64 samples_processed;
43         unsigned frame_counter;
44 } stream_info_struct;
45
46 static FLAC__FileDecoder *decoder;
47 static bool is_big_endian_host;
48
49 /* local routines */
50 static bool init(const char *infile, stream_info_struct *stream_info);
51 static bool write_little_endian_uint16(FILE *f, uint16 val);
52 static bool write_little_endian_uint32(FILE *f, uint32 val);
53 static FLAC__StreamDecoderWriteStatus write_callback(const FLAC__FileDecoder *decoder, const FLAC__FrameHeader *header, const int32 *buffer[], void *client_data);
54 static void metadata_callback(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data);
55 static void error_callback(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
56 static void print_stats(const stream_info_struct *stream_info);
57
58 int decode_wav(const char *infile, const char *outfile, bool verbose, uint64 skip)
59 {
60         stream_info_struct stream_info;
61
62         decoder = 0;
63         stream_info.abort_flag = false;
64         stream_info.is_wave_out = true;
65         stream_info.verbose = verbose;
66         stream_info.skip = skip;
67         stream_info.samples_processed = 0;
68         stream_info.frame_counter = 0;
69
70         if(0 == strcmp(outfile, "-")) {
71                 stream_info.fout = stdout;
72         }
73         else {
74                 if(0 == (stream_info.fout = fopen(outfile, "wb"))) {
75                         fprintf(stderr, "ERROR: can't open output file %s\n", outfile);
76                         return false;
77                 }
78         }
79
80         if(!init(infile, &stream_info))
81                 goto wav_abort_;
82
83         if(skip > 0) {
84                 if(!FLAC__file_decoder_process_metadata(decoder)) {
85                         fprintf(stderr, "ERROR during decoding\n");
86                         goto wav_abort_;
87                 }
88                 if(!FLAC__file_decoder_seek_absolute(decoder, skip)) {
89                         fprintf(stderr, "ERROR seeking while skipping bytes in input file %s\n", infile);
90                         goto wav_abort_;
91                 }
92                 if(!FLAC__file_decoder_process_remaining_frames(decoder)) {
93                         fprintf(stderr, "ERROR during decodingg\n");
94                         goto wav_abort_;
95                 }
96                 if(decoder->state != FLAC__FILE_DECODER_OK && decoder->state != FLAC__FILE_DECODER_END_OF_FILE) {
97                         fprintf(stderr, "ERROR during decodinggg\n");
98                         goto wav_abort_;
99                 }
100         }
101         else {
102                 if(!FLAC__file_decoder_process_whole_file(decoder)) {
103                         fprintf(stderr, "ERROR during decoding\n");
104                         goto wav_abort_;
105                 }
106                 if(decoder->state != FLAC__FILE_DECODER_OK && decoder->state != FLAC__FILE_DECODER_END_OF_FILE) {
107                         fprintf(stderr, "ERROR during decodingg, state=%u\n", decoder->state);
108                         goto wav_abort_;
109                 }
110         }
111
112         if(decoder) {
113                 if(decoder->state != FLAC__FILE_DECODER_UNINITIALIZED)
114                         FLAC__file_decoder_finish(decoder);
115                 print_stats(&stream_info);
116                 FLAC__file_decoder_free_instance(decoder);
117         }
118         fclose(stream_info.fout);
119         if(verbose)
120                 printf("\n");
121         return 0;
122 wav_abort_:
123         if(decoder) {
124                 if(decoder->state != FLAC__FILE_DECODER_UNINITIALIZED)
125                         FLAC__file_decoder_finish(decoder);
126                 FLAC__file_decoder_free_instance(decoder);
127         }
128         fclose(stream_info.fout);
129         unlink(outfile);
130         return 1;
131 }
132
133 int decode_raw(const char *infile, const char *outfile, bool verbose, uint64 skip, bool is_big_endian, bool is_unsigned_samples)
134 {
135         stream_info_struct stream_info;
136
137         decoder = 0;
138         stream_info.abort_flag = false;
139         stream_info.is_wave_out = false;
140         stream_info.is_big_endian = is_big_endian;
141         stream_info.is_unsigned_samples = is_unsigned_samples;
142         stream_info.verbose = verbose;
143         stream_info.skip = skip;
144         stream_info.samples_processed = 0;
145         stream_info.frame_counter = 0;
146
147         if(0 == strcmp(outfile, "-")) {
148                 stream_info.fout = stdout;
149         }
150         else {
151                 if(0 == (stream_info.fout = fopen(outfile, "wb"))) {
152                         fprintf(stderr, "ERROR: can't open output file %s\n", outfile);
153                         return false;
154                 }
155         }
156
157         if(!init(infile, &stream_info))
158                 goto raw_abort_;
159
160         if(skip > 0) {
161                 if(!FLAC__file_decoder_process_metadata(decoder)) {
162                         fprintf(stderr, "ERROR during decoding\n");
163                         goto raw_abort_;
164                 }
165                 if(!FLAC__file_decoder_seek_absolute(decoder, skip)) {
166                         fprintf(stderr, "ERROR seeking while skipping bytes in input file %s\n", infile);
167                         goto raw_abort_;
168                 }
169                 if(!FLAC__file_decoder_process_remaining_frames(decoder)) {
170                         fprintf(stderr, "ERROR during decodingg\n");
171                         goto raw_abort_;
172                 }
173                 if(decoder->state != FLAC__FILE_DECODER_OK && decoder->state != FLAC__FILE_DECODER_END_OF_FILE) {
174                         fprintf(stderr, "ERROR during decodinggg\n");
175                         goto raw_abort_;
176                 }
177         }
178         else {
179                 if(!FLAC__file_decoder_process_whole_file(decoder)) {
180                         fprintf(stderr, "ERROR during decoding\n");
181                         goto raw_abort_;
182                 }
183                 if(decoder->state != FLAC__FILE_DECODER_OK && decoder->state != FLAC__FILE_DECODER_END_OF_FILE) {
184                         fprintf(stderr, "ERROR during decodingg\n");
185                         goto raw_abort_;
186                 }
187         }
188
189         if(decoder) {
190                 if(decoder->state != FLAC__FILE_DECODER_UNINITIALIZED)
191                         FLAC__file_decoder_finish(decoder);
192                 print_stats(&stream_info);
193                 FLAC__file_decoder_free_instance(decoder);
194         }
195         fclose(stream_info.fout);
196         if(verbose)
197                 printf("\n");
198         return 0;
199 raw_abort_:
200         if(decoder) {
201                 if(decoder->state != FLAC__FILE_DECODER_UNINITIALIZED)
202                         FLAC__file_decoder_finish(decoder);
203                 FLAC__file_decoder_free_instance(decoder);
204         }
205         fclose(stream_info.fout);
206         unlink(outfile);
207         return 1;
208 }
209
210 bool init(const char *infile, stream_info_struct *stream_info)
211 {
212         uint32 test = 1;
213
214         is_big_endian_host = (*((byte*)(&test)))? false : true;
215
216         decoder = FLAC__file_decoder_get_new_instance();
217         if(0 == decoder) {
218                 fprintf(stderr, "ERROR creating the decoder instance\n");
219                 return false;
220         }
221
222         if(FLAC__file_decoder_init(decoder, infile, write_callback, metadata_callback, error_callback, stream_info) != FLAC__FILE_DECODER_OK) {
223                 fprintf(stderr, "ERROR initializing decoder, state = %d\n", decoder->state);
224                 return false;
225         }
226
227         return true;
228 }
229
230 bool write_little_endian_uint16(FILE *f, uint16 val)
231 {
232         byte *b = (byte*)(&val);
233         if(is_big_endian_host) {
234                 byte tmp;
235                 tmp = b[1]; b[1] = b[0]; b[0] = tmp;
236         }
237         return fwrite(b, 1, 2, f) == 2;
238 }
239
240 bool write_little_endian_uint32(FILE *f, uint32 val)
241 {
242         byte *b = (byte*)(&val);
243         if(is_big_endian_host) {
244                 byte tmp;
245                 tmp = b[3]; b[3] = b[0]; b[0] = tmp;
246                 tmp = b[2]; b[2] = b[1]; b[1] = tmp;
247         }
248         return fwrite(b, 1, 4, f) == 4;
249 }
250
251 FLAC__StreamDecoderWriteStatus write_callback(const FLAC__FileDecoder *decoder, const FLAC__FrameHeader *header, const int32 *buffer[], void *client_data)
252 {
253         stream_info_struct *stream_info = (stream_info_struct *)client_data;
254         FILE *fout = stream_info->fout;
255         unsigned bps = stream_info->bps, channels = stream_info->channels;
256         bool is_big_endian = (stream_info->is_wave_out? false : stream_info->is_big_endian);
257         bool is_unsigned_samples = (stream_info->is_wave_out? bps==8 : stream_info->is_unsigned_samples);
258         unsigned wide_samples = header->blocksize, wide_sample, sample, channel, byte;
259         static signed char scbuffer[FLAC__MAX_BLOCK_SIZE * FLAC__MAX_CHANNELS * ((FLAC__MAX_BITS_PER_SAMPLE+7)>>3)]; /* WATCHOUT: can be up to 2 megs */
260         unsigned char *ucbuffer = (unsigned char *)scbuffer;
261         signed short *ssbuffer = (signed short *)scbuffer;
262         unsigned short *usbuffer = (unsigned short *)scbuffer;
263
264         (void)decoder;
265
266         if(stream_info->abort_flag)
267                 return FLAC__STREAM_DECODER_WRITE_ABORT;
268
269         stream_info->samples_processed += wide_samples;
270         stream_info->frame_counter++;
271
272         if(stream_info->verbose && !(stream_info->frame_counter & 0x1f))
273                 print_stats(stream_info);
274
275         if(bps == 8) {
276                 if(is_unsigned_samples) {
277                         for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
278                                 for(channel = 0; channel < channels; channel++, sample++)
279                                         ucbuffer[sample] = buffer[channel][wide_sample] + 128;
280                 }
281                 else {
282                         for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
283                                 for(channel = 0; channel < channels; channel++, sample++)
284                                         scbuffer[sample] = buffer[channel][wide_sample];
285                 }
286                 if(fwrite(ucbuffer, 1, sample, fout) != sample)
287                         return FLAC__STREAM_DECODER_WRITE_ABORT;
288         }
289         else { /* bps == 16 */
290                 if(is_unsigned_samples) {
291                         for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
292                                 for(channel = 0; channel < channels; channel++, sample++)
293                                         usbuffer[sample] = buffer[channel][wide_sample] + 32768;
294                 }
295                 else {
296                         for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
297                                 for(channel = 0; channel < channels; channel++, sample++)
298                                         ssbuffer[sample] = buffer[channel][wide_sample];
299                 }
300                 if(is_big_endian != is_big_endian_host) {
301                         unsigned char tmp;
302                         for(byte = 0; byte < sample<<1; byte += 2) {
303                                 tmp = ucbuffer[byte];
304                                 ucbuffer[byte] = ucbuffer[byte+1];
305                                 ucbuffer[byte+1] = tmp;
306                         }
307                 }
308                 if(fwrite(usbuffer, 2, sample, fout) != sample)
309                         return FLAC__STREAM_DECODER_WRITE_ABORT;
310         }
311         return FLAC__STREAM_DECODER_WRITE_CONTINUE;
312 }
313
314 void metadata_callback(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data)
315 {
316         stream_info_struct *stream_info = (stream_info_struct *)client_data;
317         (void)decoder;
318         if(metadata->type == FLAC__METADATA_TYPE_ENCODING) {
319                 stream_info->total_samples = metadata->data.encoding.total_samples - stream_info->skip;
320                 stream_info->bps = metadata->data.encoding.bits_per_sample;
321                 stream_info->channels = metadata->data.encoding.channels;
322                 stream_info->sample_rate = metadata->data.encoding.sample_rate;
323
324                 if(stream_info->bps != 8 && stream_info->bps != 16) {
325                         fprintf(stderr, "ERROR: bits per sample is not 8 or 16\n");
326                         stream_info->abort_flag = true;
327                         return;
328                 }
329
330                 /* write the WAVE headers if necessary */
331                 if(stream_info->is_wave_out) {
332                         uint64 data_size = stream_info->total_samples * stream_info->channels * ((stream_info->bps+7)/8);
333                         if(data_size >= 0xFFFFFFDC) {
334                                 fprintf(stderr, "ERROR: stream is too big for a wave file\n");
335                                 stream_info->abort_flag = true;
336                                 return;
337                         }
338                         if(fwrite("RIFF", 1, 4, stream_info->fout) != 4) stream_info->abort_flag = true;
339                         if(!write_little_endian_uint32(stream_info->fout, (uint32)(data_size+36))) stream_info->abort_flag = true; /* filesize-8 */
340                         if(fwrite("WAVEfmt ", 1, 8, stream_info->fout) != 8) stream_info->abort_flag = true;
341                         if(fwrite("\020\000\000\000", 1, 4, stream_info->fout) != 4) stream_info->abort_flag = true; /* chunk size = 16 */
342                         if(fwrite("\001\000", 1, 2, stream_info->fout) != 2) stream_info->abort_flag = true; /* compression code == 1 */
343                         if(!write_little_endian_uint16(stream_info->fout, (uint16)(stream_info->channels))) stream_info->abort_flag = true;
344                         if(!write_little_endian_uint32(stream_info->fout, stream_info->sample_rate)) stream_info->abort_flag = true;
345                         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 ??? */
346                         if(!write_little_endian_uint16(stream_info->fout, (uint16)(stream_info->channels * ((stream_info->bps+7) / 8)))) stream_info->abort_flag = true; /* block align */
347                         if(!write_little_endian_uint16(stream_info->fout, (uint16)(stream_info->bps))) stream_info->abort_flag = true; /* bits per sample */
348                         if(fwrite("data", 1, 4, stream_info->fout) != 4) stream_info->abort_flag = true;
349                         if(!write_little_endian_uint32(stream_info->fout, (uint32)data_size)) stream_info->abort_flag = true; /* data size */
350                 }
351         }
352 }
353
354 void error_callback(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
355 {
356         stream_info_struct *stream_info = (stream_info_struct *)client_data;
357         (void)decoder;
358         fprintf(stderr, "*** Got error code %d\n", status);
359         stream_info->abort_flag = true;
360 }
361
362 void print_stats(const stream_info_struct *stream_info)
363 {
364         if(stream_info->verbose) {
365                 printf("\rwrote %u of %u samples, %6.2f%% complete",
366                         (unsigned)stream_info->samples_processed,
367                         (unsigned)stream_info->total_samples,
368 #ifdef _MSC_VER
369                         /* with VC++ you have to spoon feed it the casting */
370                         (double)(int64)stream_info->samples_processed / (double)(int64)stream_info->total_samples * 100.0
371 #else
372                         (double)stream_info->samples_processed / (double)stream_info->total_samples * 100.0
373 #endif
374                 );
375                 fflush(stdout);
376         }
377 }