1 /* flac - Command-line FLAC encoder/decoder
2 * Copyright (C) 2000 Josh Coalson
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 #if defined _WIN32 && !defined __CYGWIN__
20 /* where MSVC puts unlink() */
25 #include <stdio.h> /* for FILE */
26 #include <string.h> /* for strcmp() */
36 bool is_unsigned_samples;
43 uint64 samples_processed;
44 unsigned frame_counter;
47 static FLAC__FileDecoder *decoder;
48 static bool is_big_endian_host;
51 static bool init(const char *infile, stream_info_struct *stream_info);
52 static bool write_little_endian_uint16(FILE *f, uint16 val);
53 static bool write_little_endian_uint32(FILE *f, uint32 val);
54 static FLAC__StreamDecoderWriteStatus write_callback(const FLAC__FileDecoder *decoder, const FLAC__FrameHeader *header, const int32 *buffer[], void *client_data);
55 static void metadata_callback(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data);
56 static void error_callback(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
57 static void print_stats(const stream_info_struct *stream_info);
59 int decode_wav(const char *infile, const char *outfile, bool verbose, uint64 skip)
61 bool md5_failure = false;
62 stream_info_struct stream_info;
65 stream_info.abort_flag = false;
66 stream_info.test_only = (outfile == 0);
67 stream_info.is_wave_out = true;
68 stream_info.verbose = verbose;
69 stream_info.skip = skip;
70 stream_info.samples_processed = 0;
71 stream_info.frame_counter = 0;
73 if(!stream_info.test_only) {
74 if(0 == strcmp(outfile, "-")) {
75 stream_info.fout = stdout;
78 if(0 == (stream_info.fout = fopen(outfile, "wb"))) {
79 fprintf(stderr, "ERROR: can't open output file %s\n", outfile);
85 if(!init(infile, &stream_info))
89 if(!FLAC__file_decoder_process_metadata(decoder)) {
90 fprintf(stderr, "%s: ERROR during decoding\n", infile);
93 if(!FLAC__file_decoder_seek_absolute(decoder, skip)) {
94 fprintf(stderr, "%s: ERROR seeking while skipping bytes\n", infile);
97 if(!FLAC__file_decoder_process_remaining_frames(decoder)) {
98 fprintf(stderr, "%s: ERROR during decoding\n", infile);
101 if(decoder->state != FLAC__FILE_DECODER_OK && decoder->state != FLAC__FILE_DECODER_END_OF_FILE) {
102 fprintf(stderr, "%s: ERROR during decoding\n", infile);
107 if(!FLAC__file_decoder_process_whole_file(decoder)) {
108 fprintf(stderr, "%s: ERROR during decoding\n", infile);
111 if(decoder->state != FLAC__FILE_DECODER_OK && decoder->state != FLAC__FILE_DECODER_END_OF_FILE) {
112 fprintf(stderr, "%s: ERROR during decoding, state=%d:%s\n", infile, decoder->state, FLAC__FileDecoderStateString[decoder->state]);
118 if(decoder->state != FLAC__FILE_DECODER_UNINITIALIZED)
119 md5_failure = !FLAC__file_decoder_finish(decoder);
120 print_stats(&stream_info);
121 FLAC__file_decoder_free_instance(decoder);
123 if(!stream_info.test_only)
124 fclose(stream_info.fout);
129 fprintf(stderr, "%s: WARNING, MD5 signature mismatch\n", infile);
133 if(stream_info.test_only)
134 printf("%s: ok\n", infile);
139 if(decoder->state != FLAC__FILE_DECODER_UNINITIALIZED)
140 FLAC__file_decoder_finish(decoder);
141 FLAC__file_decoder_free_instance(decoder);
143 if(!stream_info.test_only) {
144 fclose(stream_info.fout);
150 int decode_raw(const char *infile, const char *outfile, bool verbose, uint64 skip, bool is_big_endian, bool is_unsigned_samples)
152 bool md5_failure = false;
153 stream_info_struct stream_info;
156 stream_info.abort_flag = false;
157 stream_info.test_only = (outfile == 0);
158 stream_info.is_wave_out = false;
159 stream_info.is_big_endian = is_big_endian;
160 stream_info.is_unsigned_samples = is_unsigned_samples;
161 stream_info.verbose = verbose;
162 stream_info.skip = skip;
163 stream_info.samples_processed = 0;
164 stream_info.frame_counter = 0;
166 if(!stream_info.test_only) {
167 if(0 == strcmp(outfile, "-")) {
168 stream_info.fout = stdout;
171 if(0 == (stream_info.fout = fopen(outfile, "wb"))) {
172 fprintf(stderr, "ERROR: can't open output file %s\n", outfile);
178 if(!init(infile, &stream_info))
182 if(!FLAC__file_decoder_process_metadata(decoder)) {
183 fprintf(stderr, "%s: ERROR during decoding\n", infile);
186 if(!FLAC__file_decoder_seek_absolute(decoder, skip)) {
187 fprintf(stderr, "%s: ERROR seeking while skipping bytes\n", infile);
190 if(!FLAC__file_decoder_process_remaining_frames(decoder)) {
191 fprintf(stderr, "%s: ERROR during decoding\n", infile);
194 if(decoder->state != FLAC__FILE_DECODER_OK && decoder->state != FLAC__FILE_DECODER_END_OF_FILE) {
195 fprintf(stderr, "%s: ERROR during decoding\n", infile);
200 if(!FLAC__file_decoder_process_whole_file(decoder)) {
201 fprintf(stderr, "%s: ERROR during decoding\n", infile);
204 if(decoder->state != FLAC__FILE_DECODER_OK && decoder->state != FLAC__FILE_DECODER_END_OF_FILE) {
205 fprintf(stderr, "%s: ERROR during decoding\n", infile);
211 if(decoder->state != FLAC__FILE_DECODER_UNINITIALIZED)
212 md5_failure = !FLAC__file_decoder_finish(decoder);
213 print_stats(&stream_info);
214 FLAC__file_decoder_free_instance(decoder);
216 if(!stream_info.test_only)
217 fclose(stream_info.fout);
222 fprintf(stderr, "%s: WARNING, MD5 signature mismatch\n", infile);
226 if(stream_info.test_only)
227 printf("%s: ok\n", infile);
232 if(decoder->state != FLAC__FILE_DECODER_UNINITIALIZED)
233 FLAC__file_decoder_finish(decoder);
234 FLAC__file_decoder_free_instance(decoder);
236 if(!stream_info.test_only) {
237 fclose(stream_info.fout);
243 bool init(const char *infile, stream_info_struct *stream_info)
247 is_big_endian_host = (*((byte*)(&test)))? false : true;
249 decoder = FLAC__file_decoder_get_new_instance();
251 fprintf(stderr, "ERROR creating the decoder instance\n");
254 decoder->check_md5 = true;
256 if(FLAC__file_decoder_init(decoder, infile, write_callback, metadata_callback, error_callback, stream_info) != FLAC__FILE_DECODER_OK) {
257 fprintf(stderr, "ERROR initializing decoder, state = %d\n", decoder->state);
264 bool write_little_endian_uint16(FILE *f, uint16 val)
266 byte *b = (byte*)(&val);
267 if(is_big_endian_host) {
269 tmp = b[1]; b[1] = b[0]; b[0] = tmp;
271 return fwrite(b, 1, 2, f) == 2;
274 bool write_little_endian_uint32(FILE *f, uint32 val)
276 byte *b = (byte*)(&val);
277 if(is_big_endian_host) {
279 tmp = b[3]; b[3] = b[0]; b[0] = tmp;
280 tmp = b[2]; b[2] = b[1]; b[1] = tmp;
282 return fwrite(b, 1, 4, f) == 4;
285 FLAC__StreamDecoderWriteStatus write_callback(const FLAC__FileDecoder *decoder, const FLAC__FrameHeader *header, const int32 *buffer[], void *client_data)
287 stream_info_struct *stream_info = (stream_info_struct *)client_data;
288 FILE *fout = stream_info->fout;
289 unsigned bps = stream_info->bps, channels = stream_info->channels;
290 bool is_big_endian = (stream_info->is_wave_out? false : stream_info->is_big_endian);
291 bool is_unsigned_samples = (stream_info->is_wave_out? bps==8 : stream_info->is_unsigned_samples);
292 unsigned wide_samples = header->blocksize, wide_sample, sample, channel, byte;
293 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 */
294 unsigned char *ucbuffer = (unsigned char *)scbuffer;
295 signed short *ssbuffer = (signed short *)scbuffer;
296 unsigned short *usbuffer = (unsigned short *)scbuffer;
300 if(stream_info->abort_flag)
301 return FLAC__STREAM_DECODER_WRITE_ABORT;
303 stream_info->samples_processed += wide_samples;
304 stream_info->frame_counter++;
306 if(stream_info->verbose && !(stream_info->frame_counter & 0x1f))
307 print_stats(stream_info);
309 if(!stream_info->test_only) {
311 if(is_unsigned_samples) {
312 for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
313 for(channel = 0; channel < channels; channel++, sample++)
314 ucbuffer[sample] = buffer[channel][wide_sample] + 128;
317 for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
318 for(channel = 0; channel < channels; channel++, sample++)
319 scbuffer[sample] = buffer[channel][wide_sample];
321 if(fwrite(ucbuffer, 1, sample, fout) != sample)
322 return FLAC__STREAM_DECODER_WRITE_ABORT;
324 else { /* bps == 16 */
325 if(is_unsigned_samples) {
326 for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
327 for(channel = 0; channel < channels; channel++, sample++)
328 usbuffer[sample] = buffer[channel][wide_sample] + 32768;
331 for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
332 for(channel = 0; channel < channels; channel++, sample++)
333 ssbuffer[sample] = buffer[channel][wide_sample];
335 if(is_big_endian != is_big_endian_host) {
337 for(byte = 0; byte < sample<<1; byte += 2) {
338 tmp = ucbuffer[byte];
339 ucbuffer[byte] = ucbuffer[byte+1];
340 ucbuffer[byte+1] = tmp;
343 if(fwrite(usbuffer, 2, sample, fout) != sample)
344 return FLAC__STREAM_DECODER_WRITE_ABORT;
347 return FLAC__STREAM_DECODER_WRITE_CONTINUE;
350 void metadata_callback(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data)
352 stream_info_struct *stream_info = (stream_info_struct *)client_data;
354 if(metadata->type == FLAC__METADATA_TYPE_ENCODING) {
355 stream_info->total_samples = metadata->data.encoding.total_samples - stream_info->skip;
356 stream_info->bps = metadata->data.encoding.bits_per_sample;
357 stream_info->channels = metadata->data.encoding.channels;
358 stream_info->sample_rate = metadata->data.encoding.sample_rate;
360 if(stream_info->bps != 8 && stream_info->bps != 16) {
361 fprintf(stderr, "ERROR: bits per sample is not 8 or 16\n");
362 stream_info->abort_flag = true;
366 /* write the WAVE headers if necessary */
367 if(!stream_info->test_only && stream_info->is_wave_out) {
368 uint64 data_size = stream_info->total_samples * stream_info->channels * ((stream_info->bps+7)/8);
369 if(data_size >= 0xFFFFFFDC) {
370 fprintf(stderr, "ERROR: stream is too big for a wave file\n");
371 stream_info->abort_flag = true;
374 if(fwrite("RIFF", 1, 4, stream_info->fout) != 4) stream_info->abort_flag = true;
375 if(!write_little_endian_uint32(stream_info->fout, (uint32)(data_size+36))) stream_info->abort_flag = true; /* filesize-8 */
376 if(fwrite("WAVEfmt ", 1, 8, stream_info->fout) != 8) stream_info->abort_flag = true;
377 if(fwrite("\020\000\000\000", 1, 4, stream_info->fout) != 4) stream_info->abort_flag = true; /* chunk size = 16 */
378 if(fwrite("\001\000", 1, 2, stream_info->fout) != 2) stream_info->abort_flag = true; /* compression code == 1 */
379 if(!write_little_endian_uint16(stream_info->fout, (uint16)(stream_info->channels))) stream_info->abort_flag = true;
380 if(!write_little_endian_uint32(stream_info->fout, stream_info->sample_rate)) stream_info->abort_flag = true;
381 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 ??? */
382 if(!write_little_endian_uint16(stream_info->fout, (uint16)(stream_info->channels * ((stream_info->bps+7) / 8)))) stream_info->abort_flag = true; /* block align */
383 if(!write_little_endian_uint16(stream_info->fout, (uint16)(stream_info->bps))) stream_info->abort_flag = true; /* bits per sample */
384 if(fwrite("data", 1, 4, stream_info->fout) != 4) stream_info->abort_flag = true;
385 if(!write_little_endian_uint32(stream_info->fout, (uint32)data_size)) stream_info->abort_flag = true; /* data size */
390 void error_callback(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
392 stream_info_struct *stream_info = (stream_info_struct *)client_data;
394 fprintf(stderr, "*** Got error code %d\n", status);
395 stream_info->abort_flag = true;
398 void print_stats(const stream_info_struct *stream_info)
400 if(stream_info->verbose) {
401 printf("\r%s %u of %u samples, %6.2f%% complete",
402 stream_info->test_only? "tested" : "wrote",
403 (unsigned)stream_info->samples_processed,
404 (unsigned)stream_info->total_samples,
406 /* with VC++ you have to spoon feed it the casting */
407 (double)(int64)stream_info->samples_processed / (double)(int64)stream_info->total_samples * 100.0
409 (double)stream_info->samples_processed / (double)stream_info->total_samples * 100.0