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 "share/alloc.h"
36 #include "foreign_metadata.h"
41 #define min(x,y) ((x)<(y)?(x):(y))
44 static const char *FLAC__FOREIGN_METADATA_APPLICATION_ID
[2] = { "aiff" , "riff" };
46 static FLAC__uint32
unpack32be_(const FLAC__byte
*b
)
48 return ((FLAC__uint32
)b
[0]<<24) + ((FLAC__uint32
)b
[1]<<16) + ((FLAC__uint32
)b
[2]<<8) + (FLAC__uint32
)b
[3];
51 static FLAC__uint32
unpack32le_(const FLAC__byte
*b
)
53 return (FLAC__uint32
)b
[0] + ((FLAC__uint32
)b
[1]<<8) + ((FLAC__uint32
)b
[2]<<16) + ((FLAC__uint32
)b
[3]<<24);
56 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
)
58 static FLAC__byte buffer
[4096];
60 for(left
= size
; left
> 0; ) {
61 size_t need
= min(sizeof(buffer
), left
);
62 if(fread(buffer
, 1, need
, fin
) < need
) {
63 if(error
) *error
= read_error
;
66 if(fwrite(buffer
, 1, need
, fout
) < need
) {
67 if(error
) *error
= write_error
;
75 static FLAC__bool
append_block_(foreign_metadata_t
*fm
, off_t offset
, FLAC__uint32 size
, const char **error
)
77 foreign_block_t
*fb
= safe_realloc_muladd2_(fm
->blocks
, sizeof(foreign_block_t
), /*times (*/fm
->num_blocks
, /*+*/1/*)*/);
79 fb
[fm
->num_blocks
].offset
= offset
;
80 fb
[fm
->num_blocks
].size
= 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);
106 if((offset
= ftello(f
)) < 0) {
107 if(error
) *error
= "ftello() error (003)";
110 if((size
= fread(buffer
, 1, 8, f
)) < 8) {
111 if(size
== 0 && feof(f
))
113 if(error
) *error
= "invalid AIFF file (004)";
116 size
= unpack32be_(buffer
+4);
117 /* check if pad byte needed */
120 if(!memcmp(buffer
, "COMM", 4)) {
121 if(fm
->format_block
) {
122 if(error
) *error
= "invalid AIFF file: multiple \"COMM\" chunks (005)";
125 if(fm
->audio_block
) {
126 if(error
) *error
= "invalid AIFF file: \"SSND\" chunk before \"COMM\" chunk (006)";
129 fm
->format_block
= fm
->num_blocks
;
131 else if(!memcmp(buffer
, "SSND", 4)) {
132 if(fm
->audio_block
) {
133 if(error
) *error
= "invalid AIFF file: multiple \"SSND\" chunks (007)";
136 if(!fm
->format_block
) {
137 if(error
) *error
= "invalid AIFF file: \"SSND\" chunk before \"COMM\" chunk (008)";
140 fm
->audio_block
= fm
->num_blocks
;
141 /* read #offset bytes */
142 if(fread(buffer
+8, 1, 4, f
) < 4) {
143 if(error
) *error
= "invalid AIFF file (009)";
146 fm
->ssnd_offset_size
= unpack32be_(buffer
+8);
147 if(fseeko(f
, -4, SEEK_CUR
) < 0) {
148 if(error
) *error
= "invalid AIFF file: seek error (010)";
152 if(!append_block_(fm
, offset
, 8 + (memcmp(buffer
, "SSND", 4)? size
: 8 + fm
->ssnd_offset_size
), error
))
154 if(fseeko(f
, size
, SEEK_CUR
) < 0) {
155 if(error
) *error
= "invalid AIFF file: seek error (011)";
159 if(eof_offset
!= ftello(f
)) {
160 if(error
) *error
= "invalid AIFF file: unexpected EOF (012)";
163 if(!fm
->format_block
) {
164 if(error
) *error
= "invalid AIFF file: missing \"COMM\" chunk (013)";
167 if(!fm
->audio_block
) {
168 if(error
) *error
= "invalid AIFF file: missing \"SSND\" chunk (014)";
174 static FLAC__bool
read_from_wave_(foreign_metadata_t
*fm
, FILE *f
, const char **error
)
176 FLAC__byte buffer
[12];
177 off_t offset
, eof_offset
;
178 if((offset
= ftello(f
)) < 0) {
179 if(error
) *error
= "ftello() error (001)";
182 if(fread(buffer
, 1, 12, f
) < 12 || memcmp(buffer
, "RIFF", 4) || memcmp(buffer
+8, "WAVE", 4)) {
183 if(error
) *error
= "unsupported RIFF layout (002)";
186 if(!append_block_(fm
, offset
, 12, error
))
188 eof_offset
= 8 + unpack32le_(buffer
+4);
191 if((offset
= ftello(f
)) < 0) {
192 if(error
) *error
= "ftello() error (003)";
195 if((size
= fread(buffer
, 1, 8, f
)) < 8) {
196 if(size
== 0 && feof(f
))
198 if(error
) *error
= "invalid WAVE file (004)";
201 size
= unpack32le_(buffer
+4);
202 /* check if pad byte needed */
205 if(!memcmp(buffer
, "fmt ", 4)) {
206 if(fm
->format_block
) {
207 if(error
) *error
= "invalid WAVE file: multiple \"fmt \" chunks (005)";
210 if(fm
->audio_block
) {
211 if(error
) *error
= "invalid WAVE file: \"data\" chunk before \"fmt \" chunk (006)";
214 fm
->format_block
= fm
->num_blocks
;
216 else if(!memcmp(buffer
, "data", 4)) {
217 if(fm
->audio_block
) {
218 if(error
) *error
= "invalid WAVE file: multiple \"data\" chunks (007)";
221 if(!fm
->format_block
) {
222 if(error
) *error
= "invalid WAVE file: \"data\" chunk before \"fmt \" chunk (008)";
225 fm
->audio_block
= fm
->num_blocks
;
227 if(!append_block_(fm
, offset
, 8 + (memcmp(buffer
, "data", 4)? size
: 0), error
))
229 if(fseeko(f
, size
, SEEK_CUR
) < 0) {
230 if(error
) *error
= "invalid WAVE file: seek error (009)";
234 if(eof_offset
!= ftello(f
)) {
235 if(error
) *error
= "invalid WAVE file: unexpected EOF (010)";
238 if(!fm
->format_block
) {
239 if(error
) *error
= "invalid WAVE file: missing \"fmt \" chunk (011)";
242 if(!fm
->audio_block
) {
243 if(error
) *error
= "invalid WAVE file: missing \"data\" chunk (012)";
249 static FLAC__bool
write_to_flac_(foreign_metadata_t
*fm
, FILE *fin
, FILE *fout
, FLAC__Metadata_SimpleIterator
*it
, const char **error
)
251 FLAC__byte buffer
[4];
252 const unsigned ID_LEN
= FLAC__STREAM_METADATA_APPLICATION_ID_LEN
/8;
253 size_t block_num
= 0;
254 FLAC__ASSERT(sizeof(buffer
) >= ID_LEN
);
255 while(block_num
< fm
->num_blocks
) {
256 /* find next matching padding block */
258 /* 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 */
259 if(!FLAC__metadata_simple_iterator_next(it
)) {
260 if(error
) *error
= "no matching PADDING block found (004)";
263 } while(FLAC__metadata_simple_iterator_get_block_type(it
) != FLAC__METADATA_TYPE_PADDING
);
264 if(FLAC__metadata_simple_iterator_get_block_length(it
) != ID_LEN
+fm
->blocks
[block_num
].size
) {
265 if(error
) *error
= "PADDING block with wrong size found (005)";
268 /* transfer chunk into APPLICATION block */
269 /* first set up the file pointers */
270 if(fseeko(fin
, fm
->blocks
[block_num
].offset
, SEEK_SET
) < 0) {
271 if(error
) *error
= "seek failed in WAVE/AIFF file (006)";
274 if(fseeko(fout
, FLAC__metadata_simple_iterator_get_block_offset(it
), SEEK_SET
) < 0) {
275 if(error
) *error
= "seek failed in FLAC file (007)";
278 /* update the type */
279 buffer
[0] = FLAC__METADATA_TYPE_APPLICATION
;
280 if(FLAC__metadata_simple_iterator_is_last(it
))
281 buffer
[0] |= 0x80; /*MAGIC number*/
282 if(fwrite(buffer
, 1, 1, fout
) < 1) {
283 if(error
) *error
= "write failed in FLAC file (008)";
286 /* length stays the same so skip over it */
287 if(fseeko(fout
, FLAC__STREAM_METADATA_LENGTH_LEN
/8, SEEK_CUR
) < 0) {
288 if(error
) *error
= "seek failed in FLAC file (009)";
291 /* write the APPLICATION ID */
292 memcpy(buffer
, FLAC__FOREIGN_METADATA_APPLICATION_ID
[fm
->type
], ID_LEN
);
293 if(fwrite(buffer
, 1, ID_LEN
, fout
) < ID_LEN
) {
294 if(error
) *error
= "write failed in FLAC file (010)";
297 /* transfer the foreign metadata */
298 if(!copy_data_(fin
, fout
, fm
->blocks
[block_num
].size
, error
, "read failed in WAVE/AIFF file (011)", "write failed in FLAC file (012)"))
305 static FLAC__bool
read_from_flac_(foreign_metadata_t
*fm
, FILE *f
, FLAC__Metadata_SimpleIterator
*it
, const char **error
)
307 FLAC__byte id
[4], buffer
[12];
309 FLAC__bool type_found
= false;
311 FLAC__ASSERT(FLAC__STREAM_METADATA_APPLICATION_ID_LEN
== sizeof(id
)*8);
313 while(FLAC__metadata_simple_iterator_next(it
)) {
314 if(FLAC__metadata_simple_iterator_get_block_type(it
) != FLAC__METADATA_TYPE_APPLICATION
)
316 if(!FLAC__metadata_simple_iterator_get_application_id(it
, id
)) {
317 if(error
) *error
= "FLAC__metadata_simple_iterator_get_application_id() error (003)";
320 if(memcmp(id
, FLAC__FOREIGN_METADATA_APPLICATION_ID
[fm
->type
], sizeof(id
)))
322 offset
= FLAC__metadata_simple_iterator_get_block_offset(it
);
323 /* skip over header and app ID */
324 offset
+= (FLAC__STREAM_METADATA_IS_LAST_LEN
+ FLAC__STREAM_METADATA_TYPE_LEN
+ FLAC__STREAM_METADATA_LENGTH_LEN
) / 8;
325 offset
+= sizeof(id
);
326 /* look for format or audio blocks */
327 if(fseek(f
, offset
, SEEK_SET
) < 0) {
328 if(error
) *error
= "seek error (004)";
331 if(fread(buffer
, 1, 4, f
) != 4) {
332 if(error
) *error
= "read error (005)";
335 if(fm
->num_blocks
== 0) {
336 if(fm
->type
== FOREIGN_BLOCK_TYPE__RIFF
&& 0 == memcmp(buffer
, "RIFF", 4))
338 else if(fm
->type
== FOREIGN_BLOCK_TYPE__AIFF
&& 0 == memcmp(buffer
, "FORM", 4))
341 if(error
) *error
= "unsupported foreign metadata found, may need newer FLAC decoder (005)";
345 else if(!type_found
) {
347 /* double protection: */
348 if(error
) *error
= "unsupported foreign metadata found, may need newer FLAC decoder (006)";
351 else if(fm
->type
== FOREIGN_BLOCK_TYPE__RIFF
) {
352 if(!memcmp(buffer
, "fmt ", 4)) {
353 if(fm
->format_block
) {
354 if(error
) *error
= "invalid WAVE metadata: multiple \"fmt \" chunks (007)";
357 if(fm
->audio_block
) {
358 if(error
) *error
= "invalid WAVE metadata: \"data\" chunk before \"fmt \" chunk (008)";
361 fm
->format_block
= fm
->num_blocks
;
363 else if(!memcmp(buffer
, "data", 4)) {
364 if(fm
->audio_block
) {
365 if(error
) *error
= "invalid WAVE metadata: multiple \"data\" chunks (009)";
368 if(!fm
->format_block
) {
369 if(error
) *error
= "invalid WAVE metadata: \"data\" chunk before \"fmt \" chunk (010)";
372 fm
->audio_block
= fm
->num_blocks
;
375 else if(fm
->type
== FOREIGN_BLOCK_TYPE__AIFF
) {
376 if(!memcmp(buffer
, "COMM", 4)) {
377 if(fm
->format_block
) {
378 if(error
) *error
= "invalid AIFF metadata: multiple \"COMM\" chunks (011)";
381 if(fm
->audio_block
) {
382 if(error
) *error
= "invalid AIFF metadata: \"SSND\" chunk before \"COMM\" chunk (012)";
385 fm
->format_block
= fm
->num_blocks
;
387 else if(!memcmp(buffer
, "SSND", 4)) {
388 if(fm
->audio_block
) {
389 if(error
) *error
= "invalid AIFF metadata: multiple \"SSND\" chunks (013)";
392 if(!fm
->format_block
) {
393 if(error
) *error
= "invalid AIFF metadata: \"SSND\" chunk before \"COMM\" chunk (014)";
396 fm
->audio_block
= fm
->num_blocks
;
397 /* read SSND offset size */
398 if(fread(buffer
+4, 1, 8, f
) != 8) {
399 if(error
) *error
= "read error (015)";
402 fm
->ssnd_offset_size
= unpack32be_(buffer
+8);
407 /* double protection: */
408 if(error
) *error
= "unsupported foreign metadata found, may need newer FLAC decoder (016)";
411 if(!append_block_(fm
, offset
, FLAC__metadata_simple_iterator_get_block_length(it
)-sizeof(id
), error
))
415 if(error
) *error
= "no foreign metadata found (017)";
418 if(!fm
->format_block
) {
419 if(error
) *error
= fm
->type
==FOREIGN_BLOCK_TYPE__RIFF
? "invalid WAVE file: missing \"fmt \" chunk (018)" : "invalid AIFF file: missing \"COMM\" chunk (018)";
422 if(!fm
->audio_block
) {
423 if(error
) *error
= fm
->type
==FOREIGN_BLOCK_TYPE__RIFF
? "invalid WAVE file: missing \"data\" chunk (019)" : "invalid AIFF file: missing \"SSND\" chunk (019)";
429 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
)
432 if(fseeko(fout
, offset1
, SEEK_SET
) < 0) {
433 if(error
) *error
= "seek failed in WAVE/AIFF file (002)";
436 for(i
= 1; i
< fm
->format_block
; i
++) {
437 if(fseeko(fin
, fm
->blocks
[i
].offset
, SEEK_SET
) < 0) {
438 if(error
) *error
= "seek failed in FLAC file (003)";
441 if(!copy_data_(fin
, fout
, fm
->blocks
[i
].size
, error
, "read failed in WAVE/AIFF file (004)", "write failed in FLAC file (005)"))
444 if(fseeko(fout
, offset2
, SEEK_SET
) < 0) {
445 if(error
) *error
= "seek failed in WAVE/AIFF file (006)";
448 for(i
= fm
->format_block
+1; i
< fm
->audio_block
; i
++) {
449 if(fseeko(fin
, fm
->blocks
[i
].offset
, SEEK_SET
) < 0) {
450 if(error
) *error
= "seek failed in FLAC file (007)";
453 if(!copy_data_(fin
, fout
, fm
->blocks
[i
].size
, error
, "read failed in WAVE/AIFF file (008)", "write failed in FLAC file (009)"))
456 if(fseeko(fout
, offset3
, SEEK_SET
) < 0) {
457 if(error
) *error
= "seek failed in WAVE/AIFF file (010)";
460 for(i
= fm
->audio_block
+1; i
< fm
->num_blocks
; i
++) {
461 if(fseeko(fin
, fm
->blocks
[i
].offset
, SEEK_SET
) < 0) {
462 if(error
) *error
= "seek failed in FLAC file (011)";
465 if(!copy_data_(fin
, fout
, fm
->blocks
[i
].size
, error
, "read failed in WAVE/AIFF file (012)", "write failed in FLAC file (013)"))
471 foreign_metadata_t
*flac__foreign_metadata_new(foreign_block_type_t type
)
473 foreign_metadata_t
*x
= (foreign_metadata_t
*)calloc(sizeof(foreign_metadata_t
), 1);
479 void flac__foreign_metadata_delete(foreign_metadata_t
*fm
)
488 FLAC__bool
flac__foreign_metadata_read_from_aiff(foreign_metadata_t
*fm
, const char *filename
, const char **error
)
491 FILE *f
= fopen(filename
, "rb");
493 if(error
) *error
= "can't open AIFF file for reading (000)";
496 ok
= read_from_aiff_(fm
, f
, error
);
501 FLAC__bool
flac__foreign_metadata_read_from_wave(foreign_metadata_t
*fm
, const char *filename
, const char **error
)
504 FILE *f
= fopen(filename
, "rb");
506 if(error
) *error
= "can't open WAVE file for reading (000)";
509 ok
= read_from_wave_(fm
, f
, error
);
514 FLAC__bool
flac__foreign_metadata_write_to_flac(foreign_metadata_t
*fm
, const char *infilename
, const char *outfilename
, const char **error
)
518 FLAC__Metadata_SimpleIterator
*it
= FLAC__metadata_simple_iterator_new();
520 if(error
) *error
= "out of memory (000)";
523 if(!FLAC__metadata_simple_iterator_init(it
, outfilename
, /*read_only=*/true, /*preserve_file_stats=*/false)) {
524 if(error
) *error
= "can't initialize iterator (001)";
525 FLAC__metadata_simple_iterator_delete(it
);
528 if(0 == (fin
= fopen(infilename
, "rb"))) {
529 if(error
) *error
= "can't open WAVE/AIFF file for reading (002)";
530 FLAC__metadata_simple_iterator_delete(it
);
533 if(0 == (fout
= fopen(outfilename
, "r+b"))) {
534 if(error
) *error
= "can't open FLAC file for updating (003)";
535 FLAC__metadata_simple_iterator_delete(it
);
539 ok
= write_to_flac_(fm
, fin
, fout
, it
, error
);
540 FLAC__metadata_simple_iterator_delete(it
);
546 FLAC__bool
flac__foreign_metadata_read_from_flac(foreign_metadata_t
*fm
, const char *filename
, const char **error
)
550 FLAC__Metadata_SimpleIterator
*it
= FLAC__metadata_simple_iterator_new();
552 if(error
) *error
= "out of memory (000)";
555 if(!FLAC__metadata_simple_iterator_init(it
, filename
, /*read_only=*/true, /*preserve_file_stats=*/false)) {
556 if(error
) *error
= "can't initialize iterator (001)";
557 FLAC__metadata_simple_iterator_delete(it
);
560 if(0 == (f
= fopen(filename
, "rb"))) {
561 if(error
) *error
= "can't open FLAC file for reading (002)";
562 FLAC__metadata_simple_iterator_delete(it
);
565 ok
= read_from_flac_(fm
, f
, it
, error
);
566 FLAC__metadata_simple_iterator_delete(it
);
571 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
)
575 if(0 == (fin
= fopen(infilename
, "rb"))) {
576 if(error
) *error
= "can't open FLAC file for reading (000)";
579 if(0 == (fout
= fopen(outfilename
, "r+b"))) {
580 if(error
) *error
= "can't open WAVE/AIFF file for updating (001)";
584 ok
= write_to_iff_(fm
, fin
, fout
, offset1
, offset2
, offset3
, error
);