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 if(verbose) { printf("\n"); fflush(stdout); }
99 fprintf(stderr, "%s: ERROR during decoding\n", infile);
102 if(decoder->state != FLAC__FILE_DECODER_OK && decoder->state != FLAC__FILE_DECODER_END_OF_FILE) {
103 if(verbose) { printf("\n"); fflush(stdout); }
104 fprintf(stderr, "%s: ERROR during decoding\n", infile);
109 if(!FLAC__file_decoder_process_whole_file(decoder)) {
110 if(verbose) { printf("\n"); fflush(stdout); }
111 fprintf(stderr, "%s: ERROR during decoding\n", infile);
114 if(decoder->state != FLAC__FILE_DECODER_OK && decoder->state != FLAC__FILE_DECODER_END_OF_FILE) {
115 if(verbose) { printf("\n"); fflush(stdout); }
116 fprintf(stderr, "%s: ERROR during decoding, state=%d:%s\n", infile, decoder->state, FLAC__FileDecoderStateString[decoder->state]);
122 if(decoder->state != FLAC__FILE_DECODER_UNINITIALIZED)
123 md5_failure = !FLAC__file_decoder_finish(decoder);
124 print_stats(&stream_info);
125 FLAC__file_decoder_free_instance(decoder);
127 if(!stream_info.test_only)
128 fclose(stream_info.fout);
133 fprintf(stderr, "%s: WARNING, MD5 signature mismatch\n", infile);
137 if(stream_info.test_only)
138 printf("%s: ok\n", infile);
143 if(decoder->state != FLAC__FILE_DECODER_UNINITIALIZED)
144 FLAC__file_decoder_finish(decoder);
145 FLAC__file_decoder_free_instance(decoder);
147 if(!stream_info.test_only) {
148 fclose(stream_info.fout);
154 int decode_raw(const char *infile, const char *outfile, bool verbose, uint64 skip, bool is_big_endian, bool is_unsigned_samples)
156 bool md5_failure = false;
157 stream_info_struct stream_info;
160 stream_info.abort_flag = false;
161 stream_info.test_only = (outfile == 0);
162 stream_info.is_wave_out = false;
163 stream_info.is_big_endian = is_big_endian;
164 stream_info.is_unsigned_samples = is_unsigned_samples;
165 stream_info.verbose = verbose;
166 stream_info.skip = skip;
167 stream_info.samples_processed = 0;
168 stream_info.frame_counter = 0;
170 if(!stream_info.test_only) {
171 if(0 == strcmp(outfile, "-")) {
172 stream_info.fout = stdout;
175 if(0 == (stream_info.fout = fopen(outfile, "wb"))) {
176 fprintf(stderr, "ERROR: can't open output file %s\n", outfile);
182 if(!init(infile, &stream_info))
186 if(!FLAC__file_decoder_process_metadata(decoder)) {
187 fprintf(stderr, "%s: ERROR during decoding\n", infile);
190 if(!FLAC__file_decoder_seek_absolute(decoder, skip)) {
191 fprintf(stderr, "%s: ERROR seeking while skipping bytes\n", infile);
194 if(!FLAC__file_decoder_process_remaining_frames(decoder)) {
195 if(verbose) { printf("\n"); fflush(stdout); }
196 fprintf(stderr, "%s: ERROR during decoding\n", infile);
199 if(decoder->state != FLAC__FILE_DECODER_OK && decoder->state != FLAC__FILE_DECODER_END_OF_FILE) {
200 if(verbose) { printf("\n"); fflush(stdout); }
201 fprintf(stderr, "%s: ERROR during decoding\n", infile);
206 if(!FLAC__file_decoder_process_whole_file(decoder)) {
207 if(verbose) { printf("\n"); fflush(stdout); }
208 fprintf(stderr, "%s: ERROR during decoding\n", infile);
211 if(decoder->state != FLAC__FILE_DECODER_OK && decoder->state != FLAC__FILE_DECODER_END_OF_FILE) {
212 if(verbose) { printf("\n"); fflush(stdout); }
213 fprintf(stderr, "%s: ERROR during decoding\n", infile);
219 if(decoder->state != FLAC__FILE_DECODER_UNINITIALIZED)
220 md5_failure = !FLAC__file_decoder_finish(decoder);
221 print_stats(&stream_info);
222 FLAC__file_decoder_free_instance(decoder);
224 if(!stream_info.test_only)
225 fclose(stream_info.fout);
230 fprintf(stderr, "%s: WARNING, MD5 signature mismatch\n", infile);
234 if(stream_info.test_only)
235 printf("%s: ok\n", infile);
240 if(decoder->state != FLAC__FILE_DECODER_UNINITIALIZED)
241 FLAC__file_decoder_finish(decoder);
242 FLAC__file_decoder_free_instance(decoder);
244 if(!stream_info.test_only) {
245 fclose(stream_info.fout);
251 bool init(const char *infile, stream_info_struct *stream_info)
255 is_big_endian_host = (*((byte*)(&test)))? false : true;
257 decoder = FLAC__file_decoder_get_new_instance();
259 fprintf(stderr, "ERROR creating the decoder instance\n");
262 decoder->check_md5 = true;
264 if(FLAC__file_decoder_init(decoder, infile, write_callback, metadata_callback, error_callback, stream_info) != FLAC__FILE_DECODER_OK) {
265 fprintf(stderr, "ERROR initializing decoder, state = %d\n", decoder->state);
272 bool write_little_endian_uint16(FILE *f, uint16 val)
274 byte *b = (byte*)(&val);
275 if(is_big_endian_host) {
277 tmp = b[1]; b[1] = b[0]; b[0] = tmp;
279 return fwrite(b, 1, 2, f) == 2;
282 bool write_little_endian_uint32(FILE *f, uint32 val)
284 byte *b = (byte*)(&val);
285 if(is_big_endian_host) {
287 tmp = b[3]; b[3] = b[0]; b[0] = tmp;
288 tmp = b[2]; b[2] = b[1]; b[1] = tmp;
290 return fwrite(b, 1, 4, f) == 4;
293 FLAC__StreamDecoderWriteStatus write_callback(const FLAC__FileDecoder *decoder, const FLAC__FrameHeader *header, const int32 *buffer[], void *client_data)
295 stream_info_struct *stream_info = (stream_info_struct *)client_data;
296 FILE *fout = stream_info->fout;
297 unsigned bps = stream_info->bps, channels = stream_info->channels;
298 bool is_big_endian = (stream_info->is_wave_out? false : stream_info->is_big_endian);
299 bool is_unsigned_samples = (stream_info->is_wave_out? bps==8 : stream_info->is_unsigned_samples);
300 unsigned wide_samples = header->blocksize, wide_sample, sample, channel, byte;
301 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 */
302 unsigned char *ucbuffer = (unsigned char *)scbuffer;
303 signed short *ssbuffer = (signed short *)scbuffer;
304 unsigned short *usbuffer = (unsigned short *)scbuffer;
308 if(stream_info->abort_flag)
309 return FLAC__STREAM_DECODER_WRITE_ABORT;
311 stream_info->samples_processed += wide_samples;
312 stream_info->frame_counter++;
314 if(stream_info->verbose && !(stream_info->frame_counter & 0x1f))
315 print_stats(stream_info);
317 if(!stream_info->test_only) {
319 if(is_unsigned_samples) {
320 for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
321 for(channel = 0; channel < channels; channel++, sample++)
322 ucbuffer[sample] = buffer[channel][wide_sample] + 128;
325 for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
326 for(channel = 0; channel < channels; channel++, sample++)
327 scbuffer[sample] = buffer[channel][wide_sample];
329 if(fwrite(ucbuffer, 1, sample, fout) != sample)
330 return FLAC__STREAM_DECODER_WRITE_ABORT;
332 else { /* bps == 16 */
333 if(is_unsigned_samples) {
334 for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
335 for(channel = 0; channel < channels; channel++, sample++)
336 usbuffer[sample] = buffer[channel][wide_sample] + 32768;
339 for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
340 for(channel = 0; channel < channels; channel++, sample++)
341 ssbuffer[sample] = buffer[channel][wide_sample];
343 if(is_big_endian != is_big_endian_host) {
345 for(byte = 0; byte < sample<<1; byte += 2) {
346 tmp = ucbuffer[byte];
347 ucbuffer[byte] = ucbuffer[byte+1];
348 ucbuffer[byte+1] = tmp;
351 if(fwrite(usbuffer, 2, sample, fout) != sample)
352 return FLAC__STREAM_DECODER_WRITE_ABORT;
355 return FLAC__STREAM_DECODER_WRITE_CONTINUE;
358 void metadata_callback(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data)
360 stream_info_struct *stream_info = (stream_info_struct *)client_data;
362 if(metadata->type == FLAC__METADATA_TYPE_ENCODING) {
363 stream_info->total_samples = metadata->data.encoding.total_samples - stream_info->skip;
364 stream_info->bps = metadata->data.encoding.bits_per_sample;
365 stream_info->channels = metadata->data.encoding.channels;
366 stream_info->sample_rate = metadata->data.encoding.sample_rate;
368 if(stream_info->bps != 8 && stream_info->bps != 16) {
369 fprintf(stderr, "ERROR: bits per sample is not 8 or 16\n");
370 stream_info->abort_flag = true;
374 /* write the WAVE headers if necessary */
375 if(!stream_info->test_only && stream_info->is_wave_out) {
376 uint64 data_size = stream_info->total_samples * stream_info->channels * ((stream_info->bps+7)/8);
377 if(data_size >= 0xFFFFFFDC) {
378 fprintf(stderr, "ERROR: stream is too big for a wave file\n");
379 stream_info->abort_flag = true;
382 if(fwrite("RIFF", 1, 4, stream_info->fout) != 4) stream_info->abort_flag = true;
383 if(!write_little_endian_uint32(stream_info->fout, (uint32)(data_size+36))) stream_info->abort_flag = true; /* filesize-8 */
384 if(fwrite("WAVEfmt ", 1, 8, stream_info->fout) != 8) stream_info->abort_flag = true;
385 if(fwrite("\020\000\000\000", 1, 4, stream_info->fout) != 4) stream_info->abort_flag = true; /* chunk size = 16 */
386 if(fwrite("\001\000", 1, 2, stream_info->fout) != 2) stream_info->abort_flag = true; /* compression code == 1 */
387 if(!write_little_endian_uint16(stream_info->fout, (uint16)(stream_info->channels))) stream_info->abort_flag = true;
388 if(!write_little_endian_uint32(stream_info->fout, stream_info->sample_rate)) stream_info->abort_flag = true;
389 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 ??? */
390 if(!write_little_endian_uint16(stream_info->fout, (uint16)(stream_info->channels * ((stream_info->bps+7) / 8)))) stream_info->abort_flag = true; /* block align */
391 if(!write_little_endian_uint16(stream_info->fout, (uint16)(stream_info->bps))) stream_info->abort_flag = true; /* bits per sample */
392 if(fwrite("data", 1, 4, stream_info->fout) != 4) stream_info->abort_flag = true;
393 if(!write_little_endian_uint32(stream_info->fout, (uint32)data_size)) stream_info->abort_flag = true; /* data size */
398 void error_callback(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
400 stream_info_struct *stream_info = (stream_info_struct *)client_data;
402 fprintf(stderr, "*** Got error code %d\n", status);
403 stream_info->abort_flag = true;
406 void print_stats(const stream_info_struct *stream_info)
408 if(stream_info->verbose) {
409 printf("\r%s %u of %u samples, %6.2f%% complete",
410 stream_info->test_only? "tested" : "wrote",
411 (unsigned)stream_info->samples_processed,
412 (unsigned)stream_info->total_samples,
414 /* with VC++ you have to spoon feed it the casting */
415 (double)(int64)stream_info->samples_processed / (double)(int64)stream_info->total_samples * 100.0
417 (double)stream_info->samples_processed / (double)stream_info->total_samples * 100.0