1 /* flac - Command-line FLAC encoder/decoder
2 * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 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.
23 #if defined _MSC_VER || defined __MINGW32__
24 #include <sys/types.h> /* for off_t */
25 #if _MSC_VER <= 1600 /* @@@ [2G limit] */
30 #include <stdio.h> /* for FILE etc. */
31 #include <stdlib.h> /* for calloc() etc. */
32 #include <string.h> /* for memcmp() etc. */
33 #include "FLAC/assert.h"
34 #include "FLAC/metadata.h"
35 #include "foreign_metadata.h"
40 #define min(x,y) ((x)<(y)?(x):(y))
43 static const char *FLAC__FOREIGN_METADATA_APPLICATION_ID[2] = { "AIFF" , "RIFF" };
45 static FLAC__uint32 unpack32be_(const FLAC__byte *b)
47 return ((FLAC__uint32)b[0]<<24) + ((FLAC__uint32)b[1]<<16) + ((FLAC__uint32)b[2]<<8) + (FLAC__uint32)b[3];
50 static FLAC__uint32 unpack32le_(const FLAC__byte *b)
52 return (FLAC__uint32)b[0] + ((FLAC__uint32)b[1]<<8) + ((FLAC__uint32)b[2]<<16) + ((FLAC__uint32)b[3]<<24);
55 static FLAC__bool copy_data_(FILE *fin, FILE *fout, size_t size, const char **error, const char * const read_error, const char * const write_error)
57 static FLAC__byte buffer[4096];
59 for(left = size; left > 0; ) {
60 size_t need = min(sizeof(buffer), left);
61 if(fread(buffer, 1, need, fin) < need) {
62 if(error) *error = read_error;
65 if(fwrite(buffer, 1, need, fout) < need) {
66 if(error) *error = write_error;
74 static FLAC__bool append_block_(foreign_metadata_t *fm, off_t offset, FLAC__uint32 size, const char **error)
76 foreign_block_t *fb = realloc(fm->blocks, sizeof(foreign_block_t) * (fm->num_blocks+1));
78 fb[fm->num_blocks].offset = offset;
79 fb[fm->num_blocks].size = size;
82 /*fprintf(stderr,"@@@@@@ appended: block#%u offset=%d size=%u\n",fm->num_blocks-1,(int)fm->blocks[fm->num_blocks-1].offset,(unsigned)fm->blocks[fm->num_blocks-1].size);*/
85 if(error) *error = "out of memory";
89 static FLAC__bool read_from_aiff_(foreign_metadata_t *fm, FILE *f, const char **error)
91 FLAC__byte buffer[12];
92 off_t offset, eof_offset;
93 if((offset = ftello(f)) < 0) {
94 if(error) *error = "ftello() error (001)";
97 if(fread(buffer, 1, 12, f) < 12 || memcmp(buffer, "FORM", 4) || (memcmp(buffer+8, "AIFF", 4) && memcmp(buffer+8, "AIFC", 4))) {
98 if(error) *error = "unsupported FORM layout (002)";
101 if(!append_block_(fm, offset, 12, error))
103 eof_offset = 8 + unpack32be_(buffer+4);
104 /*fprintf(stderr,"@@@@@@ off=%d eof=%d\n",(int)offset,(int)eof_offset);*/
107 if((offset = ftello(f)) < 0) {
108 if(error) *error = "ftello() error (003)";
111 if((size = fread(buffer, 1, 8, f)) < 8) {
112 if(size == 0 && feof(f))
114 if(error) *error = "invalid AIFF file (004)";
117 size = unpack32be_(buffer+4);
118 /* check if pad byte needed */
121 if(!memcmp(buffer, "COMM", 4)) {
122 if(fm->format_block) {
123 if(error) *error = "invalid AIFF file: multiple \"COMM\" chunks (005)";
126 if(fm->audio_block) {
127 if(error) *error = "invalid AIFF file: \"SSND\" chunk before \"COMM\" chunk (006)";
130 fm->format_block = fm->num_blocks;
132 else if(!memcmp(buffer, "SSND", 4)) {
133 if(fm->audio_block) {
134 if(error) *error = "invalid AIFF file: multiple \"SSND\" chunks (007)";
137 if(!fm->format_block) {
138 if(error) *error = "invalid AIFF file: \"SSND\" chunk before \"COMM\" chunk (008)";
141 fm->audio_block = fm->num_blocks;
142 /* read #offset bytes */
143 if(fread(buffer+8, 1, 4, f) < 4) {
144 if(error) *error = "invalid AIFF file (009)";
147 fm->ssnd_offset_size = unpack32be_(buffer+8);
148 if(fseeko(f, -4, SEEK_CUR) < 0) {
149 if(error) *error = "invalid AIFF file: seek error (010)";
153 if(!append_block_(fm, offset, 8 + (memcmp(buffer, "SSND", 4)? size : 8 + fm->ssnd_offset_size), error))
155 /*fprintf(stderr,"@@@@@@ chunk=%c%c%c%c offset=%d size=%d\n",buffer[0],buffer[1],buffer[2],buffer[3],(int)offset,8+(int)size);*/
156 if(fseeko(f, size, SEEK_CUR) < 0) {
157 if(error) *error = "invalid AIFF file: seek error (011)";
161 if(eof_offset != ftello(f)) {
162 if(error) *error = "invalid AIFF file: unexpected EOF (012)";
165 if(!fm->format_block) {
166 if(error) *error = "invalid AIFF file: missing \"COMM\" chunk (013)";
169 if(!fm->audio_block) {
170 if(error) *error = "invalid AIFF file: missing \"SSND\" chunk (014)";
176 static FLAC__bool read_from_wave_(foreign_metadata_t *fm, FILE *f, const char **error)
178 FLAC__byte buffer[12];
179 off_t offset, eof_offset;
180 if((offset = ftello(f)) < 0) {
181 if(error) *error = "ftello() error (001)";
184 if(fread(buffer, 1, 12, f) < 12 || memcmp(buffer, "RIFF", 4) || memcmp(buffer+8, "WAVE", 4)) {
185 if(error) *error = "unsupported RIFF layout (002)";
188 if(!append_block_(fm, offset, 12, error))
190 eof_offset = 8 + unpack32le_(buffer+4);
191 /*fprintf(stderr,"@@@@@@ off=%d eof=%d\n",(int)offset,(int)eof_offset);*/
194 if((offset = ftello(f)) < 0) {
195 if(error) *error = "ftello() error (003)";
198 if((size = fread(buffer, 1, 8, f)) < 8) {
199 if(size == 0 && feof(f))
201 if(error) *error = "invalid WAVE file (004)";
204 size = unpack32le_(buffer+4);
205 /* check if pad byte needed */
208 if(!memcmp(buffer, "fmt ", 4)) {
209 if(fm->format_block) {
210 if(error) *error = "invalid WAVE file: multiple \"fmt \" chunks (005)";
213 if(fm->audio_block) {
214 if(error) *error = "invalid WAVE file: \"data\" chunk before \"fmt \" chunk (006)";
217 fm->format_block = fm->num_blocks;
219 else if(!memcmp(buffer, "data", 4)) {
220 if(fm->audio_block) {
221 if(error) *error = "invalid WAVE file: multiple \"data\" chunks (007)";
224 if(!fm->format_block) {
225 if(error) *error = "invalid WAVE file: \"data\" chunk before \"fmt \" chunk (008)";
228 fm->audio_block = fm->num_blocks;
230 if(!append_block_(fm, offset, 8 + (memcmp(buffer, "data", 4)? size : 0), error))
232 /*fprintf(stderr,"@@@@@@ chunk=%c%c%c%c offset=%d size=%d\n",buffer[0],buffer[1],buffer[2],buffer[3],(int)offset,8+(int)size);*/
233 if(fseeko(f, size, SEEK_CUR) < 0) {
234 if(error) *error = "invalid WAVE file: seek error (009)";
238 if(eof_offset != ftello(f)) {
239 if(error) *error = "invalid WAVE file: unexpected EOF (010)";
242 if(!fm->format_block) {
243 if(error) *error = "invalid WAVE file: missing \"fmt \" chunk (011)";
246 if(!fm->audio_block) {
247 if(error) *error = "invalid WAVE file: missing \"data\" chunk (012)";
253 static FLAC__bool write_to_flac_(foreign_metadata_t *fm, FILE *fin, FILE *fout, FLAC__Metadata_SimpleIterator *it, const char **error)
255 FLAC__byte buffer[4];
256 const unsigned ID_LEN = FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8;
257 size_t block_num = 0;
258 FLAC__ASSERT(sizeof(buffer) >= ID_LEN);
259 while(block_num < fm->num_blocks) {
260 /* find next matching padding block */
262 /* even on the first chunk's loop there will be a skippable STREAMINFO block, on subsequent loops we are first moving past the PADDING we just used */
263 if(!FLAC__metadata_simple_iterator_next(it)) {
264 if(error) *error = "no matching PADDING block found (004)";
267 } while(FLAC__metadata_simple_iterator_get_block_type(it) != FLAC__METADATA_TYPE_PADDING);
268 if(FLAC__metadata_simple_iterator_get_block_length(it) != ID_LEN+fm->blocks[block_num].size) {
269 if(error) *error = "PADDING block with wrong size found (005)";
272 /*fprintf(stderr,"@@@@@@ flac offset = %d\n",(int)FLAC__metadata_simple_iterator_get_block_offset(it));*/
273 /* transfer chunk into APPLICATION block */
274 /* first set up the file pointers */
275 if(fseeko(fin, fm->blocks[block_num].offset, SEEK_SET) < 0) {
276 if(error) *error = "seek failed in WAVE/AIFF file (006)";
279 if(fseeko(fout, FLAC__metadata_simple_iterator_get_block_offset(it), SEEK_SET) < 0) {
280 if(error) *error = "seek failed in FLAC file (007)";
283 /* update the type */
284 buffer[0] = FLAC__METADATA_TYPE_APPLICATION;
285 if(FLAC__metadata_simple_iterator_is_last(it))
286 buffer[0] |= 0x80; /*MAGIC number*/
287 if(fwrite(buffer, 1, 1, fout) < 1) {
288 if(error) *error = "write failed in FLAC file (008)";
291 /* length stays the same so skip over it */
292 if(fseeko(fout, FLAC__STREAM_METADATA_LENGTH_LEN/8, SEEK_CUR) < 0) {
293 if(error) *error = "seek failed in FLAC file (009)";
296 /* write the APPLICATION ID */
297 memcpy(buffer, FLAC__FOREIGN_METADATA_APPLICATION_ID[fm->type], ID_LEN);
298 if(fwrite(buffer, 1, ID_LEN, fout) < ID_LEN) {
299 if(error) *error = "write failed in FLAC file (010)";
302 /* transfer the foreign metadata */
303 if(!copy_data_(fin, fout, fm->blocks[block_num].size, error, "read failed in WAVE/AIFF file (011)", "write failed in FLAC file (012)"))
310 static FLAC__bool read_from_flac_(foreign_metadata_t *fm, FILE *f, FLAC__Metadata_SimpleIterator *it, const char **error)
312 FLAC__byte id[4], buffer[12];
314 FLAC__bool type_found = false;
316 FLAC__ASSERT(FLAC__STREAM_METADATA_APPLICATION_ID_LEN == sizeof(id)*8);
318 while(FLAC__metadata_simple_iterator_next(it)) {
319 if(FLAC__metadata_simple_iterator_get_block_type(it) != FLAC__METADATA_TYPE_APPLICATION)
321 if(!FLAC__metadata_simple_iterator_get_application_id(it, id)) {
322 if(error) *error = "FLAC__metadata_simple_iterator_get_application_id() error (003)";
325 if(memcmp(id, FLAC__FOREIGN_METADATA_APPLICATION_ID[fm->type], sizeof(id)))
327 offset = FLAC__metadata_simple_iterator_get_block_offset(it);
328 /* skip over header and app ID */
329 offset += (FLAC__STREAM_METADATA_IS_LAST_LEN + FLAC__STREAM_METADATA_TYPE_LEN + FLAC__STREAM_METADATA_LENGTH_LEN) / 8;
330 offset += sizeof(id);
331 /* look for format or audio blocks */
332 if(fseek(f, offset, SEEK_SET) < 0) {
333 if(error) *error = "seek error (004)";
336 if(fread(buffer, 1, 4, f) != 4) {
337 if(error) *error = "read error (005)";
340 if(fm->num_blocks == 0) {
341 if(fm->type == FOREIGN_BLOCK_TYPE__RIFF && 0 == memcmp(buffer, "RIFF", 4))
343 else if(fm->type == FOREIGN_BLOCK_TYPE__AIFF && 0 == memcmp(buffer, "FORM", 4))
346 if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (005)";
350 else if(!type_found) {
352 /* double protection: */
353 if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (006)";
356 else if(fm->type == FOREIGN_BLOCK_TYPE__RIFF) {
357 if(!memcmp(buffer, "fmt ", 4)) {
358 if(fm->format_block) {
359 if(error) *error = "invalid WAVE metadata: multiple \"fmt \" chunks (007)";
362 if(fm->audio_block) {
363 if(error) *error = "invalid WAVE metadata: \"data\" chunk before \"fmt \" chunk (008)";
366 fm->format_block = fm->num_blocks;
368 else if(!memcmp(buffer, "data", 4)) {
369 if(fm->audio_block) {
370 if(error) *error = "invalid WAVE metadata: multiple \"data\" chunks (009)";
373 if(!fm->format_block) {
374 if(error) *error = "invalid WAVE metadata: \"data\" chunk before \"fmt \" chunk (010)";
377 fm->audio_block = fm->num_blocks;
380 else if(fm->type == FOREIGN_BLOCK_TYPE__AIFF) {
381 if(!memcmp(buffer, "COMM", 4)) {
382 if(fm->format_block) {
383 if(error) *error = "invalid AIFF metadata: multiple \"COMM\" chunks (011)";
386 if(fm->audio_block) {
387 if(error) *error = "invalid AIFF metadata: \"SSND\" chunk before \"COMM\" chunk (012)";
390 fm->format_block = fm->num_blocks;
392 else if(!memcmp(buffer, "SSND", 4)) {
393 if(fm->audio_block) {
394 if(error) *error = "invalid AIFF metadata: multiple \"SSND\" chunks (013)";
397 if(!fm->format_block) {
398 if(error) *error = "invalid AIFF metadata: \"SSND\" chunk before \"COMM\" chunk (014)";
401 fm->audio_block = fm->num_blocks;
402 /* read SSND offset size */
403 if(fread(buffer+4, 1, 8, f) != 8) {
404 if(error) *error = "read error (015)";
407 fm->ssnd_offset_size = unpack32be_(buffer+8);
412 /* double protection: */
413 if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (016)";
416 if(!append_block_(fm, offset, FLAC__metadata_simple_iterator_get_block_length(it)-sizeof(id), error))
420 if(error) *error = "no foreign metadata found (017)";
423 if(!fm->format_block) {
424 if(error) *error = fm->type==FOREIGN_BLOCK_TYPE__RIFF? "invalid WAVE file: missing \"fmt \" chunk (018)" : "invalid AIFF file: missing \"COMM\" chunk (018)";
427 if(!fm->audio_block) {
428 if(error) *error = fm->type==FOREIGN_BLOCK_TYPE__RIFF? "invalid WAVE file: missing \"data\" chunk (019)" : "invalid AIFF file: missing \"SSND\" chunk (019)";
434 static FLAC__bool write_to_iff_(foreign_metadata_t *fm, FILE *fin, FILE *fout, off_t offset1, off_t offset2, off_t offset3, const char **error)
437 if(fseeko(fout, offset1, SEEK_SET) < 0) {
438 if(error) *error = "seek failed in WAVE/AIFF file (002)";
441 for(i = 1; i < fm->format_block; i++) {
442 if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) {
443 if(error) *error = "seek failed in FLAC file (003)";
446 if(!copy_data_(fin, fout, fm->blocks[i].size, error, "read failed in WAVE/AIFF file (004)", "write failed in FLAC file (005)"))
449 if(fseeko(fout, offset2, SEEK_SET) < 0) {
450 if(error) *error = "seek failed in WAVE/AIFF file (006)";
453 for(i = fm->format_block+1; i < fm->audio_block; i++) {
454 if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) {
455 if(error) *error = "seek failed in FLAC file (007)";
458 if(!copy_data_(fin, fout, fm->blocks[i].size, error, "read failed in WAVE/AIFF file (008)", "write failed in FLAC file (009)"))
461 if(fseeko(fout, offset3, SEEK_SET) < 0) {
462 if(error) *error = "seek failed in WAVE/AIFF file (010)";
465 for(i = fm->audio_block+1; i < fm->num_blocks; i++) {
466 if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) {
467 if(error) *error = "seek failed in FLAC file (011)";
470 if(!copy_data_(fin, fout, fm->blocks[i].size, error, "read failed in WAVE/AIFF file (012)", "write failed in FLAC file (013)"))
476 foreign_metadata_t *flac__foreign_metadata_new(foreign_block_type_t type)
478 foreign_metadata_t *x = (foreign_metadata_t*)calloc(sizeof(foreign_metadata_t), 1);
484 void flac__foreign_metadata_delete(foreign_metadata_t *fm)
493 FLAC__bool flac__foreign_metadata_read_from_aiff(foreign_metadata_t *fm, const char *filename, const char **error)
496 FILE *f = fopen(filename, "rb");
498 if(error) *error = "can't open AIFF file for reading (000)";
501 ok = read_from_aiff_(fm, f, error);
506 FLAC__bool flac__foreign_metadata_read_from_wave(foreign_metadata_t *fm, const char *filename, const char **error)
509 FILE *f = fopen(filename, "rb");
511 if(error) *error = "can't open WAVE file for reading (000)";
514 ok = read_from_wave_(fm, f, error);
519 FLAC__bool flac__foreign_metadata_write_to_flac(foreign_metadata_t *fm, const char *infilename, const char *outfilename, const char **error)
523 FLAC__Metadata_SimpleIterator *it = FLAC__metadata_simple_iterator_new();
525 if(error) *error = "out of memory (000)";
528 if(!FLAC__metadata_simple_iterator_init(it, outfilename, /*read_only=*/true, /*preserve_file_stats=*/false)) {
529 if(error) *error = "can't initialize iterator (001)";
530 FLAC__metadata_simple_iterator_delete(it);
533 if(0 == (fin = fopen(infilename, "rb"))) {
534 if(error) *error = "can't open WAVE/AIFF file for reading (002)";
535 FLAC__metadata_simple_iterator_delete(it);
538 if(0 == (fout = fopen(outfilename, "r+b"))) {
539 if(error) *error = "can't open FLAC file for updating (003)";
540 FLAC__metadata_simple_iterator_delete(it);
544 ok = write_to_flac_(fm, fin, fout, it, error);
545 FLAC__metadata_simple_iterator_delete(it);
551 FLAC__bool flac__foreign_metadata_read_from_flac(foreign_metadata_t *fm, const char *filename, const char **error)
555 FLAC__Metadata_SimpleIterator *it = FLAC__metadata_simple_iterator_new();
557 if(error) *error = "out of memory (000)";
560 if(!FLAC__metadata_simple_iterator_init(it, filename, /*read_only=*/true, /*preserve_file_stats=*/false)) {
561 if(error) *error = "can't initialize iterator (001)";
562 FLAC__metadata_simple_iterator_delete(it);
565 if(0 == (f = fopen(filename, "rb"))) {
566 if(error) *error = "can't open FLAC file for reading (002)";
567 FLAC__metadata_simple_iterator_delete(it);
570 ok = read_from_flac_(fm, f, it, error);
571 FLAC__metadata_simple_iterator_delete(it);
576 FLAC__bool flac__foreign_metadata_write_to_iff(foreign_metadata_t *fm, const char *infilename, const char *outfilename, off_t offset1, off_t offset2, off_t offset3, const char **error)
580 if(0 == (fin = fopen(infilename, "rb"))) {
581 if(error) *error = "can't open FLAC file for reading (000)";
584 if(0 == (fout = fopen(outfilename, "r+b"))) {
585 if(error) *error = "can't open WAVE/AIFF file for updating (001)";
589 ok = write_to_iff_(fm, fin, fout, offset1, offset2, offset3, error);