1 /* flac - Command-line FLAC encoder/decoder
2 * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007,2008,2009 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[3] = { "aiff" , "riff", "w64 " };
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__uint64 unpack64le_(const FLAC__byte *b)
58 return (FLAC__uint64)b[0] + ((FLAC__uint64)b[1]<<8) + ((FLAC__uint64)b[2]<<16) + ((FLAC__uint64)b[3]<<24) + ((FLAC__uint64)b[4]<<32) + ((FLAC__uint64)b[5]<<40) + ((FLAC__uint64)b[6]<<48) + ((FLAC__uint64)b[7]<<56);
61 /* copies 'size' bytes from file 'fin' to 'fout', filling in *error with 'read_error' or 'write_error' as necessary */
62 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)
64 FLAC__byte buffer[4096];
66 for(left = size; left > 0; ) {
67 size_t need = min(sizeof(buffer), left);
68 if(fread(buffer, 1, need, fin) < need) {
69 if(error) *error = read_error;
72 if(fwrite(buffer, 1, need, fout) < need) {
73 if(error) *error = write_error;
81 static FLAC__bool append_block_(foreign_metadata_t *fm, off_t offset, FLAC__uint32 size, const char **error)
83 foreign_block_t *fb = safe_realloc_muladd2_(fm->blocks, sizeof(foreign_block_t), /*times (*/fm->num_blocks, /*+*/1/*)*/);
85 fb[fm->num_blocks].offset = offset;
86 fb[fm->num_blocks].size = size;
91 if(error) *error = "out of memory";
95 static FLAC__bool read_from_aiff_(foreign_metadata_t *fm, FILE *f, const char **error)
97 FLAC__byte buffer[12];
98 off_t offset, eof_offset;
99 if((offset = ftello(f)) < 0) {
100 if(error) *error = "ftello() error (001)";
103 if(fread(buffer, 1, 12, f) < 12 || memcmp(buffer, "FORM", 4) || (memcmp(buffer+8, "AIFF", 4) && memcmp(buffer+8, "AIFC", 4))) {
104 if(error) *error = "unsupported FORM layout (002)";
107 if(!append_block_(fm, offset, 12, error))
109 eof_offset = (off_t)8 + (off_t)unpack32be_(buffer+4);
112 if((offset = ftello(f)) < 0) {
113 if(error) *error = "ftello() error (003)";
116 if((size = fread(buffer, 1, 8, f)) < 8) {
117 if(size == 0 && feof(f))
119 if(error) *error = "invalid AIFF file (004)";
122 size = unpack32be_(buffer+4);
123 /* check if pad byte needed */
126 if(!memcmp(buffer, "COMM", 4)) {
127 if(fm->format_block) {
128 if(error) *error = "invalid AIFF file: multiple \"COMM\" chunks (005)";
131 if(fm->audio_block) {
132 if(error) *error = "invalid AIFF file: \"SSND\" chunk before \"COMM\" chunk (006)";
135 fm->format_block = fm->num_blocks;
137 else if(!memcmp(buffer, "SSND", 4)) {
138 if(fm->audio_block) {
139 if(error) *error = "invalid AIFF file: multiple \"SSND\" chunks (007)";
142 if(!fm->format_block) {
143 if(error) *error = "invalid AIFF file: \"SSND\" chunk before \"COMM\" chunk (008)";
146 fm->audio_block = fm->num_blocks;
147 /* read #offset bytes */
148 if(fread(buffer+8, 1, 4, f) < 4) {
149 if(error) *error = "invalid AIFF file (009)";
152 fm->ssnd_offset_size = unpack32be_(buffer+8);
153 if(fseeko(f, -4, SEEK_CUR) < 0) {
154 if(error) *error = "invalid AIFF file: seek error (010)";
157 /* WATCHOUT: For SSND we ignore the blockSize and are not saving any
158 * unaligned part at the end of the chunk. In retrospect it is pretty
159 * pointless to save the unaligned data before the PCM but now it is
160 * done and cast in stone.
163 if(!append_block_(fm, offset, 8 + (memcmp(buffer, "SSND", 4)? size : 8 + fm->ssnd_offset_size), error))
165 /* skip to next chunk */
166 if(fseeko(f, size, SEEK_CUR) < 0) {
167 if(error) *error = "invalid AIFF file: seek error (011)";
171 if(eof_offset != ftello(f)) {
172 if(error) *error = "invalid AIFF file: unexpected EOF (012)";
175 if(!fm->format_block) {
176 if(error) *error = "invalid AIFF file: missing \"COMM\" chunk (013)";
179 if(!fm->audio_block) {
180 if(error) *error = "invalid AIFF file: missing \"SSND\" chunk (014)";
186 static FLAC__bool read_from_wave_(foreign_metadata_t *fm, FILE *f, const char **error)
188 FLAC__byte buffer[12];
189 off_t offset, eof_offset = -1, ds64_data_size = -1;
190 if((offset = ftello(f)) < 0) {
191 if(error) *error = "ftello() error (001)";
194 if(fread(buffer, 1, 12, f) < 12 || (memcmp(buffer, "RIFF", 4) && memcmp(buffer, "RF64", 4)) || memcmp(buffer+8, "WAVE", 4)) {
195 if(error) *error = "unsupported RIFF layout (002)";
198 if(!memcmp(buffer, "RF64", 4))
200 if(fm->is_rf64 && sizeof(off_t) < 8) {
201 if(error) *error = "RF64 is not supported on this compile (r00)";
204 if(!append_block_(fm, offset, 12, error))
206 if(!fm->is_rf64 || unpack32le_(buffer+4) != 0xffffffffu)
207 eof_offset = (off_t)8 + (off_t)unpack32le_(buffer+4);
210 if((offset = ftello(f)) < 0) {
211 if(error) *error = "ftello() error (003)";
214 if((size = fread(buffer, 1, 8, f)) < 8) {
215 if(size == 0 && feof(f))
217 if(error) *error = "invalid WAVE file (004)";
220 size = unpack32le_(buffer+4);
221 /* check if pad byte needed */
224 if(!memcmp(buffer, "fmt ", 4)) {
225 if(fm->format_block) {
226 if(error) *error = "invalid WAVE file: multiple \"fmt \" chunks (005)";
229 if(fm->audio_block) {
230 if(error) *error = "invalid WAVE file: \"data\" chunk before \"fmt \" chunk (006)";
233 fm->format_block = fm->num_blocks;
235 else if(!memcmp(buffer, "data", 4)) {
236 if(fm->audio_block) {
237 if(error) *error = "invalid WAVE file: multiple \"data\" chunks (007)";
240 if(!fm->format_block) {
241 if(error) *error = "invalid WAVE file: \"data\" chunk before \"fmt \" chunk (008)";
244 fm->audio_block = fm->num_blocks;
245 if(fm->is_rf64 && fm->num_blocks < 2) {
246 if(error) *error = "invalid RF64 file: \"data\" chunk before \"ds64\" chunk (r01)";
250 if(!append_block_(fm, offset, 8 + (memcmp(buffer, "data", 4)? size : 0), error))
252 /* parse ds64 chunk if necessary */
253 if(fm->is_rf64 && fm->num_blocks == 2) {
254 FLAC__byte buffer2[7*4];
255 if(memcmp(buffer, "ds64", 4)) {
256 if(error) *error = "invalid RF64 file: \"ds64\" chunk does not immediately follow \"WAVE\" marker (r02)";
259 /* unpack the size again since we don't want the padding byte effect */
260 size = unpack32le_(buffer+4);
261 if(size < sizeof(buffer2)) {
262 if(error) *error = "invalid RF64 file: \"ds64\" chunk size is < 28 (r03)";
265 if(size > sizeof(buffer2)) {
266 if(error) *error = "RF64 file has \"ds64\" chunk with extra size table, which is not currently supported (r04)";
269 if(fread(buffer2, 1, sizeof(buffer2), f) < sizeof(buffer2)) {
270 if(error) *error = "unexpected EOF reading \"ds64\" chunk data in RF64 file (r05)";
273 ds64_data_size = (off_t)unpack64le_(buffer2+8);
274 if(ds64_data_size == (off_t)(-1)) {
275 if(error) *error = "RF64 file has \"ds64\" chunk with data size == -1 (r08)";
278 /* check if pad byte needed */
279 if(ds64_data_size & 1)
281 /* @@@ [2^63 limit] */
282 if(ds64_data_size < 0) {
283 if(error) *error = "RF64 file too large (r09)";
286 if(unpack32le_(buffer2+24)) {
287 if(error) *error = "RF64 file has \"ds64\" chunk with extra size table, which is not currently supported (r06)";
290 eof_offset = (off_t)8 + (off_t)unpack64le_(buffer2);
291 /* @@@ [2^63 limit] */
292 if((off_t)unpack64le_(buffer2) < 0 || eof_offset < 0) {
293 if(error) *error = "RF64 file too large (r07)";
297 else { /* skip to next chunk */
298 if(fm->is_rf64 && !memcmp(buffer, "data", 4) && unpack32le_(buffer+4) == 0xffffffffu) {
299 if(fseeko(f, ds64_data_size, SEEK_CUR) < 0) {
300 if(error) *error = "invalid RF64 file: seek error (r10)";
305 if(fseeko(f, size, SEEK_CUR) < 0) {
306 if(error) *error = "invalid WAVE file: seek error (009)";
312 if(fm->is_rf64 && eof_offset == (off_t)(-1)) {
313 if(error) *error = "invalid RF64 file: all RIFF sizes are -1 (r11)";
316 if(eof_offset != ftello(f)) {
317 if(error) *error = "invalid WAVE file: unexpected EOF (010)";
320 if(!fm->format_block) {
321 if(error) *error = "invalid WAVE file: missing \"fmt \" chunk (011)";
324 if(!fm->audio_block) {
325 if(error) *error = "invalid WAVE file: missing \"data\" chunk (012)";
331 static FLAC__bool read_from_wave64_(foreign_metadata_t *fm, FILE *f, const char **error)
333 FLAC__byte buffer[40];
334 off_t offset, eof_offset = -1;
335 if((offset = ftello(f)) < 0) {
336 if(error) *error = "ftello() error (001)";
340 fread(buffer, 1, 40, f) < 40 ||
341 /* RIFF GUID 66666972-912E-11CF-A5D6-28DB04C10000 */
342 memcmp(buffer, "\x72\x69\x66\x66\x2E\x91\xCF\x11\xD6\xA5\x28\xDB\x04\xC1\x00\x00", 16) ||
343 /* WAVE GUID 65766177-ACF3-11D3-8CD1-00C04F8EDB8A */
344 memcmp(buffer+24, "\x77\x61\x76\x65\xF3\xAC\xD3\x11\xD1\x8C\x00\xC0\x4F\x8E\xDB\x8A", 16)
346 if(error) *error = "unsupported Wave64 layout (002)";
349 if(sizeof(off_t) < 8) {
350 if(error) *error = "Wave64 is not supported on this compile (r00)";
353 if(!append_block_(fm, offset, 40, error))
355 eof_offset = (off_t)unpack64le_(buffer+16); /*@@@ [2^63 limit] */
358 if((offset = ftello(f)) < 0) {
359 if(error) *error = "ftello() error (003)";
362 if((size = fread(buffer, 1, 24, f)) < 24) {
363 if(size == 0 && feof(f))
365 if(error) *error = "invalid Wave64 file (004)";
368 size = unpack64le_(buffer+16);
369 /* check if pad bytes needed */
371 size = (size+7) & (~((FLAC__uint64)7));
372 /* fmt GUID 20746D66-ACF3-11D3-8CD1-00C04F8EDB8A */
373 if(!memcmp(buffer, "\x66\x6D\x74\x20\xF3\xAC\xD3\x11\xD1\x8C\x00\xC0\x4F\x8E\xDB\x8A", 16)) {
374 if(fm->format_block) {
375 if(error) *error = "invalid Wave64 file: multiple \"fmt \" chunks (005)";
378 if(fm->audio_block) {
379 if(error) *error = "invalid Wave64 file: \"data\" chunk before \"fmt \" chunk (006)";
382 fm->format_block = fm->num_blocks;
384 /* data GUID 61746164-ACF3-11D3-8CD1-00C04F8EDB8A */
385 else if(!memcmp(buffer, "\x64\x61\x74\x61\xF3\xAC\xD3\x11\xD1\x8C\x00\xC0\x4F\x8E\xDB\x8A", 16)) {
386 if(fm->audio_block) {
387 if(error) *error = "invalid Wave64 file: multiple \"data\" chunks (007)";
390 if(!fm->format_block) {
391 if(error) *error = "invalid Wave64 file: \"data\" chunk before \"fmt \" chunk (008)";
394 fm->audio_block = fm->num_blocks;
396 if(!append_block_(fm, offset, memcmp(buffer, "\x64\x61\x74\x61\xF3\xAC\xD3\x11\xD1\x8C\x00\xC0\x4F\x8E\xDB\x8A", 16)? (FLAC__uint32)size : 16+8, error))
398 /* skip to next chunk */
399 if(fseeko(f, size-24, SEEK_CUR) < 0) {
400 if(error) *error = "invalid Wave64 file: seek error (009)";
404 if(eof_offset != ftello(f)) {
405 if(error) *error = "invalid Wave64 file: unexpected EOF (010)";
408 if(!fm->format_block) {
409 if(error) *error = "invalid Wave64 file: missing \"fmt \" chunk (011)";
412 if(!fm->audio_block) {
413 if(error) *error = "invalid Wave64 file: missing \"data\" chunk (012)";
419 static FLAC__bool write_to_flac_(foreign_metadata_t *fm, FILE *fin, FILE *fout, FLAC__Metadata_SimpleIterator *it, const char **error)
421 FLAC__byte buffer[4];
422 const unsigned ID_LEN = FLAC__STREAM_METADATA_APPLICATION_ID_LEN/8;
423 size_t block_num = 0;
424 FLAC__ASSERT(sizeof(buffer) >= ID_LEN);
425 while(block_num < fm->num_blocks) {
426 /* find next matching padding block */
428 /* 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 */
429 if(!FLAC__metadata_simple_iterator_next(it)) {
430 if(error) *error = "no matching PADDING block found (004)";
433 } while(FLAC__metadata_simple_iterator_get_block_type(it) != FLAC__METADATA_TYPE_PADDING);
434 if(FLAC__metadata_simple_iterator_get_block_length(it) != ID_LEN+fm->blocks[block_num].size) {
435 if(error) *error = "PADDING block with wrong size found (005)";
438 /* transfer chunk into APPLICATION block */
439 /* first set up the file pointers */
440 if(fseeko(fin, fm->blocks[block_num].offset, SEEK_SET) < 0) {
441 if(error) *error = "seek failed in WAVE/AIFF file (006)";
444 if(fseeko(fout, FLAC__metadata_simple_iterator_get_block_offset(it), SEEK_SET) < 0) {
445 if(error) *error = "seek failed in FLAC file (007)";
448 /* update the type */
449 buffer[0] = FLAC__METADATA_TYPE_APPLICATION;
450 if(FLAC__metadata_simple_iterator_is_last(it))
451 buffer[0] |= 0x80; /*MAGIC number*/
452 if(fwrite(buffer, 1, 1, fout) < 1) {
453 if(error) *error = "write failed in FLAC file (008)";
456 /* length stays the same so skip over it */
457 if(fseeko(fout, FLAC__STREAM_METADATA_LENGTH_LEN/8, SEEK_CUR) < 0) {
458 if(error) *error = "seek failed in FLAC file (009)";
461 /* write the APPLICATION ID */
462 memcpy(buffer, FLAC__FOREIGN_METADATA_APPLICATION_ID[fm->type], ID_LEN);
463 if(fwrite(buffer, 1, ID_LEN, fout) < ID_LEN) {
464 if(error) *error = "write failed in FLAC file (010)";
467 /* transfer the foreign metadata */
468 if(!copy_data_(fin, fout, fm->blocks[block_num].size, error, "read failed in WAVE/AIFF file (011)", "write failed in FLAC file (012)"))
475 static FLAC__bool read_from_flac_(foreign_metadata_t *fm, FILE *f, FLAC__Metadata_SimpleIterator *it, const char **error)
477 FLAC__byte id[4], buffer[12];
479 FLAC__bool type_found = false, ds64_found = false;
481 FLAC__ASSERT(FLAC__STREAM_METADATA_APPLICATION_ID_LEN == sizeof(id)*8);
483 while(FLAC__metadata_simple_iterator_next(it)) {
484 if(FLAC__metadata_simple_iterator_get_block_type(it) != FLAC__METADATA_TYPE_APPLICATION)
486 if(!FLAC__metadata_simple_iterator_get_application_id(it, id)) {
487 if(error) *error = "FLAC__metadata_simple_iterator_get_application_id() error (002)";
490 if(memcmp(id, FLAC__FOREIGN_METADATA_APPLICATION_ID[fm->type], sizeof(id)))
492 offset = FLAC__metadata_simple_iterator_get_block_offset(it);
493 /* skip over header and app ID */
494 offset += (FLAC__STREAM_METADATA_IS_LAST_LEN + FLAC__STREAM_METADATA_TYPE_LEN + FLAC__STREAM_METADATA_LENGTH_LEN) / 8;
495 offset += sizeof(id);
496 /* look for format or audio blocks */
497 if(fseek(f, offset, SEEK_SET) < 0) {
498 if(error) *error = "seek error (003)";
501 if(fread(buffer, 1, 4, f) != 4) {
502 if(error) *error = "read error (004)";
505 if(fm->num_blocks == 0) { /* first block? */
506 fm->is_rf64 = 0 == memcmp(buffer, "RF64", 4);
507 if(fm->type == FOREIGN_BLOCK_TYPE__RIFF && (0 == memcmp(buffer, "RIFF", 4) || fm->is_rf64))
509 else if(fm->type == FOREIGN_BLOCK_TYPE__WAVE64 && 0 == memcmp(buffer, "riff", 4)) /* use first 4 bytes instead of whole GUID */
511 else if(fm->type == FOREIGN_BLOCK_TYPE__AIFF && 0 == memcmp(buffer, "FORM", 4))
514 if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (005)";
518 else if(!type_found) {
520 /* double protection: */
521 if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (006)";
524 else if(fm->type == FOREIGN_BLOCK_TYPE__RIFF) {
525 if(!memcmp(buffer, "fmt ", 4)) {
526 if(fm->format_block) {
527 if(error) *error = "invalid WAVE metadata: multiple \"fmt \" chunks (007)";
530 if(fm->audio_block) {
531 if(error) *error = "invalid WAVE metadata: \"data\" chunk before \"fmt \" chunk (008)";
534 fm->format_block = fm->num_blocks;
536 else if(!memcmp(buffer, "data", 4)) {
537 if(fm->audio_block) {
538 if(error) *error = "invalid WAVE metadata: multiple \"data\" chunks (009)";
541 if(!fm->format_block) {
542 if(error) *error = "invalid WAVE metadata: \"data\" chunk before \"fmt \" chunk (010)";
545 fm->audio_block = fm->num_blocks;
547 else if(fm->is_rf64 && fm->num_blocks == 1) {
548 if(memcmp(buffer, "ds64", 4)) {
549 if(error) *error = "invalid RF64 metadata: second chunk is not \"ds64\" (011)";
555 else if(fm->type == FOREIGN_BLOCK_TYPE__WAVE64) {
556 if(!memcmp(buffer, "fmt ", 4)) { /* use first 4 bytes instead of whole GUID */
557 if(fm->format_block) {
558 if(error) *error = "invalid Wave64 metadata: multiple \"fmt \" chunks (012)";
561 if(fm->audio_block) {
562 if(error) *error = "invalid Wave64 metadata: \"data\" chunk before \"fmt \" chunk (013)";
565 fm->format_block = fm->num_blocks;
567 else if(!memcmp(buffer, "data", 4)) { /* use first 4 bytes instead of whole GUID */
568 if(fm->audio_block) {
569 if(error) *error = "invalid Wave64 metadata: multiple \"data\" chunks (014)";
572 if(!fm->format_block) {
573 if(error) *error = "invalid Wave64 metadata: \"data\" chunk before \"fmt \" chunk (015)";
576 fm->audio_block = fm->num_blocks;
579 else if(fm->type == FOREIGN_BLOCK_TYPE__AIFF) {
580 if(!memcmp(buffer, "COMM", 4)) {
581 if(fm->format_block) {
582 if(error) *error = "invalid AIFF metadata: multiple \"COMM\" chunks (016)";
585 if(fm->audio_block) {
586 if(error) *error = "invalid AIFF metadata: \"SSND\" chunk before \"COMM\" chunk (017)";
589 fm->format_block = fm->num_blocks;
591 else if(!memcmp(buffer, "SSND", 4)) {
592 if(fm->audio_block) {
593 if(error) *error = "invalid AIFF metadata: multiple \"SSND\" chunks (018)";
596 if(!fm->format_block) {
597 if(error) *error = "invalid AIFF metadata: \"SSND\" chunk before \"COMM\" chunk (019)";
600 fm->audio_block = fm->num_blocks;
601 /* read SSND offset size */
602 if(fread(buffer+4, 1, 8, f) != 8) {
603 if(error) *error = "read error (020)";
606 fm->ssnd_offset_size = unpack32be_(buffer+8);
611 /* double protection: */
612 if(error) *error = "unsupported foreign metadata found, may need newer FLAC decoder (021)";
615 if(!append_block_(fm, offset, FLAC__metadata_simple_iterator_get_block_length(it)-sizeof(id), error))
619 if(error) *error = "no foreign metadata found (022)";
622 if(fm->is_rf64 && !ds64_found) {
623 if(error) *error = "invalid RF64 file: second chunk is not \"ds64\" (023)";
626 if(!fm->format_block) {
629 fm->type==FOREIGN_BLOCK_TYPE__RIFF? "invalid WAVE file: missing \"fmt \" chunk (024)" :
630 fm->type==FOREIGN_BLOCK_TYPE__WAVE64? "invalid Wave64 file: missing \"fmt \" chunk (025)" :
631 "invalid AIFF file: missing \"COMM\" chunk (026)";
634 if(!fm->audio_block) {
637 fm->type==FOREIGN_BLOCK_TYPE__RIFF? "invalid WAVE file: missing \"data\" chunk (027)" :
638 fm->type==FOREIGN_BLOCK_TYPE__WAVE64? "invalid Wave64 file: missing \"data\" chunk (028)" :
639 "invalid AIFF file: missing \"SSND\" chunk (029)";
645 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)
648 if(fseeko(fout, offset1, SEEK_SET) < 0) {
649 if(error) *error = "seek failed in WAVE/AIFF file (002)";
652 /* don't write first (RIFF/RF64/FORM) chunk, or ds64 chunk in the case of RF64 */
653 for(i = fm->is_rf64?2:1; i < fm->format_block; i++) {
654 if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) {
655 if(error) *error = "seek failed in FLAC file (003)";
658 if(!copy_data_(fin, fout, fm->blocks[i].size, error, "read failed in WAVE/AIFF file (004)", "write failed in FLAC file (005)"))
661 if(fseeko(fout, offset2, SEEK_SET) < 0) {
662 if(error) *error = "seek failed in WAVE/AIFF file (006)";
665 for(i = fm->format_block+1; i < fm->audio_block; i++) {
666 if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) {
667 if(error) *error = "seek failed in FLAC file (007)";
670 if(!copy_data_(fin, fout, fm->blocks[i].size, error, "read failed in WAVE/AIFF file (008)", "write failed in FLAC file (009)"))
673 if(fseeko(fout, offset3, SEEK_SET) < 0) {
674 if(error) *error = "seek failed in WAVE/AIFF file (010)";
677 for(i = fm->audio_block+1; i < fm->num_blocks; i++) {
678 if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) {
679 if(error) *error = "seek failed in FLAC file (011)";
682 if(!copy_data_(fin, fout, fm->blocks[i].size, error, "read failed in WAVE/AIFF file (012)", "write failed in FLAC file (013)"))
688 foreign_metadata_t *flac__foreign_metadata_new(foreign_block_type_t type)
690 /* calloc() to zero all the member variables */
691 foreign_metadata_t *x = (foreign_metadata_t*)calloc(sizeof(foreign_metadata_t), 1);
699 void flac__foreign_metadata_delete(foreign_metadata_t *fm)
708 FLAC__bool flac__foreign_metadata_read_from_aiff(foreign_metadata_t *fm, const char *filename, const char **error)
711 FILE *f = fopen(filename, "rb");
713 if(error) *error = "can't open AIFF file for reading (000)";
716 ok = read_from_aiff_(fm, f, error);
721 FLAC__bool flac__foreign_metadata_read_from_wave(foreign_metadata_t *fm, const char *filename, const char **error)
724 FILE *f = fopen(filename, "rb");
726 if(error) *error = "can't open WAVE file for reading (000)";
729 ok = read_from_wave_(fm, f, error);
734 FLAC__bool flac__foreign_metadata_read_from_wave64(foreign_metadata_t *fm, const char *filename, const char **error)
737 FILE *f = fopen(filename, "rb");
739 if(error) *error = "can't open Wave64 file for reading (000)";
742 ok = read_from_wave64_(fm, f, error);
747 FLAC__bool flac__foreign_metadata_write_to_flac(foreign_metadata_t *fm, const char *infilename, const char *outfilename, const char **error)
751 FLAC__Metadata_SimpleIterator *it = FLAC__metadata_simple_iterator_new();
753 if(error) *error = "out of memory (000)";
756 if(!FLAC__metadata_simple_iterator_init(it, outfilename, /*read_only=*/true, /*preserve_file_stats=*/false)) {
757 if(error) *error = "can't initialize iterator (001)";
758 FLAC__metadata_simple_iterator_delete(it);
761 if(0 == (fin = fopen(infilename, "rb"))) {
762 if(error) *error = "can't open WAVE/AIFF file for reading (002)";
763 FLAC__metadata_simple_iterator_delete(it);
766 if(0 == (fout = fopen(outfilename, "r+b"))) {
767 if(error) *error = "can't open FLAC file for updating (003)";
768 FLAC__metadata_simple_iterator_delete(it);
772 ok = write_to_flac_(fm, fin, fout, it, error);
773 FLAC__metadata_simple_iterator_delete(it);
779 FLAC__bool flac__foreign_metadata_read_from_flac(foreign_metadata_t *fm, const char *filename, const char **error)
783 FLAC__Metadata_SimpleIterator *it = FLAC__metadata_simple_iterator_new();
785 if(error) *error = "out of memory (000)";
788 if(!FLAC__metadata_simple_iterator_init(it, filename, /*read_only=*/true, /*preserve_file_stats=*/false)) {
789 if(error) *error = "can't initialize iterator (001)";
790 FLAC__metadata_simple_iterator_delete(it);
793 if(0 == (f = fopen(filename, "rb"))) {
794 if(error) *error = "can't open FLAC file for reading (002)";
795 FLAC__metadata_simple_iterator_delete(it);
798 ok = read_from_flac_(fm, f, it, error);
799 FLAC__metadata_simple_iterator_delete(it);
804 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)
808 if(0 == (fin = fopen(infilename, "rb"))) {
809 if(error) *error = "can't open FLAC file for reading (000)";
812 if(0 == (fout = fopen(outfilename, "r+b"))) {
813 if(error) *error = "can't open WAVE/AIFF file for updating (001)";
817 ok = write_to_iff_(fm, fin, fout, offset1, offset2, offset3, error);