Example #1
0
static FLAC__bool read_from_wave_(foreign_metadata_t *fm, FILE *f, const char **error)
{
	FLAC__byte buffer[12];
	FLAC__off_t offset, eof_offset = -1, ds64_data_size = -1;
	if((offset = ftello(f)) < 0) {
		if(error) *error = "ftello() error (001)";
		return false;
	}
	if(fread(buffer, 1, 12, f) < 12 || (memcmp(buffer, "RIFF", 4) && memcmp(buffer, "RF64", 4)) || memcmp(buffer+8, "WAVE", 4)) {
		if(error) *error = "unsupported RIFF layout (002)";
		return false;
	}
	if(!memcmp(buffer, "RF64", 4))
		fm->is_rf64 = true;
	if(fm->is_rf64 && sizeof(FLAC__off_t) < 8) {
		if(error) *error = "RF64 is not supported on this compile (r00)";
		return false;
	}
	if(!append_block_(fm, offset, 12, error))
		return false;
	if(!fm->is_rf64 || unpack32le_(buffer+4) != 0xffffffffu)
		eof_offset = (FLAC__off_t)8 + (FLAC__off_t)unpack32le_(buffer+4);
	while(!feof(f)) {
		FLAC__uint32 size;
		if((offset = ftello(f)) < 0) {
			if(error) *error = "ftello() error (003)";
			return false;
		}
		if((size = fread(buffer, 1, 8, f)) < 8) {
			if(size == 0 && feof(f))
				break;
			if(error) *error = "invalid WAVE file (004)";
			return false;
		}
		size = unpack32le_(buffer+4);
		/* check if pad byte needed */
		if(size & 1)
			size++;
		if(!memcmp(buffer, "fmt ", 4)) {
			if(fm->format_block) {
				if(error) *error = "invalid WAVE file: multiple \"fmt \" chunks (005)";
				return false;
			}
			if(fm->audio_block) {
				if(error) *error = "invalid WAVE file: \"data\" chunk before \"fmt \" chunk (006)";
				return false;
			}
			fm->format_block = fm->num_blocks;
		}
		else if(!memcmp(buffer, "data", 4)) {
			if(fm->audio_block) {
				if(error) *error = "invalid WAVE file: multiple \"data\" chunks (007)";
				return false;
			}
			if(!fm->format_block) {
				if(error) *error = "invalid WAVE file: \"data\" chunk before \"fmt \" chunk (008)";
				return false;
			}
			fm->audio_block = fm->num_blocks;
			if(fm->is_rf64 && fm->num_blocks < 2) {
				if(error) *error = "invalid RF64 file: \"data\" chunk before \"ds64\" chunk (r01)";
				return false;
			}
		}
		if(!append_block_(fm, offset, 8 + (memcmp(buffer, "data", 4)? size : 0), error))
			return false;
		/* parse ds64 chunk if necessary */
		if(fm->is_rf64 && fm->num_blocks == 2) {
			FLAC__byte buffer2[7*4];
			if(memcmp(buffer, "ds64", 4)) {
				if(error) *error = "invalid RF64 file: \"ds64\" chunk does not immediately follow \"WAVE\" marker (r02)";
				return false;
			}
			/* unpack the size again since we don't want the padding byte effect */
			size = unpack32le_(buffer+4);
			if(size < sizeof(buffer2)) {
				if(error) *error = "invalid RF64 file: \"ds64\" chunk size is < 28 (r03)";
				return false;
			}
			if(size > sizeof(buffer2)) {
				if(error) *error = "RF64 file has \"ds64\" chunk with extra size table, which is not currently supported (r04)";
				return false;
			}
			if(fread(buffer2, 1, sizeof(buffer2), f) < sizeof(buffer2)) {
				if(error) *error = "unexpected EOF reading \"ds64\" chunk data in RF64 file (r05)";
				return false;
			}
			ds64_data_size = (FLAC__off_t)unpack64le_(buffer2+8);
			if(ds64_data_size == (FLAC__off_t)(-1)) {
				if(error) *error = "RF64 file has \"ds64\" chunk with data size == -1 (r08)";
				return false;
			}
			/* check if pad byte needed */
			if(ds64_data_size & 1)
				ds64_data_size++;
			/* @@@ [2^63 limit] */
			if(ds64_data_size < 0) {
				if(error) *error = "RF64 file too large (r09)";
				return false;
			}
			if(unpack32le_(buffer2+24)) {
				if(error) *error = "RF64 file has \"ds64\" chunk with extra size table, which is not currently supported (r06)";
				return false;
			}
			eof_offset = (FLAC__off_t)8 + (FLAC__off_t)unpack64le_(buffer2);
			/* @@@ [2^63 limit] */
			if((FLAC__off_t)unpack64le_(buffer2) < 0 || eof_offset < 0) {
				if(error) *error = "RF64 file too large (r07)";
				return false;
			}
		}
		else { /* skip to next chunk */
			if(fm->is_rf64 && !memcmp(buffer, "data", 4) && unpack32le_(buffer+4) == 0xffffffffu) {
				if(fseeko(f, ds64_data_size, SEEK_CUR) < 0) {
					if(error) *error = "invalid RF64 file: seek error (r10)";
					return false;
				}
			}
			else {
				if(fseeko(f, size, SEEK_CUR) < 0) {
					if(error) *error = "invalid WAVE file: seek error (009)";
					return false;
				}
			}
		}
	}
	if(fm->is_rf64 && eof_offset == (FLAC__off_t)(-1)) {
		if(error) *error = "invalid RF64 file: all RIFF sizes are -1 (r11)";
		return false;
	}
	if(eof_offset != ftello(f)) {
		if(error) *error = "invalid WAVE file: unexpected EOF (010)";
		return false;
	}
	if(!fm->format_block) {
		if(error) *error = "invalid WAVE file: missing \"fmt \" chunk (011)";
		return false;
	}
	if(!fm->audio_block) {
		if(error) *error = "invalid WAVE file: missing \"data\" chunk (012)";
		return false;
	}
	return true;
}
Example #2
0
static FLAC__bool read_from_wave64_(foreign_metadata_t *fm, FILE *f, const char **error)
{
	FLAC__byte buffer[40];
	FLAC__off_t offset, eof_offset = -1;
	if((offset = ftello(f)) < 0) {
		if(error) *error = "ftello() error (001)";
		return false;
	}
	if(
		fread(buffer, 1, 40, f) < 40 ||
		/* RIFF GUID 66666972-912E-11CF-A5D6-28DB04C10000 */
		memcmp(buffer, "\x72\x69\x66\x66\x2E\x91\xCF\x11\xA5\xD6\x28\xDB\x04\xC1\x00\x00", 16) ||
		/* WAVE GUID 65766177-ACF3-11D3-8CD1-00C04F8EDB8A */
		memcmp(buffer+24, "\x77\x61\x76\x65\xF3\xAC\xD3\x11\x8C\xD1\x00\xC0\x4F\x8E\xDB\x8A", 16)
	) {
		if(error) *error = "unsupported Wave64 layout (002)";
		return false;
	}
	if(sizeof(FLAC__off_t) < 8) {
		if(error) *error = "Wave64 is not supported on this compile (r00)";
		return false;
	}
	if(!append_block_(fm, offset, 40, error))
		return false;
	eof_offset = (FLAC__off_t)unpack64le_(buffer+16); /*@@@ [2^63 limit] */
	while(!feof(f)) {
		FLAC__uint64 size;
		if((offset = ftello(f)) < 0) {
			if(error) *error = "ftello() error (003)";
			return false;
		}
		if((size = fread(buffer, 1, 24, f)) < 24) {
			if(size == 0 && feof(f))
				break;
			if(error) *error = "invalid Wave64 file (004)";
			return false;
		}
		size = unpack64le_(buffer+16);
		/* check if pad bytes needed */
		if(size & 7)
			size = (size+7) & (~((FLAC__uint64)7));
		/* fmt GUID 20746D66-ACF3-11D3-8CD1-00C04F8EDB8A */
		if(!memcmp(buffer, "\x66\x6D\x74\x20\xF3\xAC\xD3\x11\x8C\xD1\x00\xC0\x4F\x8E\xDB\x8A", 16)) {
			if(fm->format_block) {
				if(error) *error = "invalid Wave64 file: multiple \"fmt \" chunks (005)";
				return false;
			}
			if(fm->audio_block) {
				if(error) *error = "invalid Wave64 file: \"data\" chunk before \"fmt \" chunk (006)";
				return false;
			}
			fm->format_block = fm->num_blocks;
		}
		/* data GUID 61746164-ACF3-11D3-8CD1-00C04F8EDB8A */
		else if(!memcmp(buffer, "\x64\x61\x74\x61\xF3\xAC\xD3\x11\x8C\xD1\x00\xC0\x4F\x8E\xDB\x8A", 16)) {
			if(fm->audio_block) {
				if(error) *error = "invalid Wave64 file: multiple \"data\" chunks (007)";
				return false;
			}
			if(!fm->format_block) {
				if(error) *error = "invalid Wave64 file: \"data\" chunk before \"fmt \" chunk (008)";
				return false;
			}
			fm->audio_block = fm->num_blocks;
		}
		if(!append_block_(fm, offset, memcmp(buffer, "\x64\x61\x74\x61\xF3\xAC\xD3\x11\x8C\xD1\x00\xC0\x4F\x8E\xDB\x8A", 16)? (FLAC__uint32)size : 16+8, error))
			return false;
		/* skip to next chunk */
		if(fseeko(f, size-24, SEEK_CUR) < 0) {
			if(error) *error = "invalid Wave64 file: seek error (009)";
			return false;
		}
	}
	if(eof_offset != ftello(f)) {
		if(error) *error = "invalid Wave64 file: unexpected EOF (010)";
		return false;
	}
	if(!fm->format_block) {
		if(error) *error = "invalid Wave64 file: missing \"fmt \" chunk (011)";
		return false;
	}
	if(!fm->audio_block) {
		if(error) *error = "invalid Wave64 file: missing \"data\" chunk (012)";
		return false;
	}
	return true;
}
Example #3
0
int main(int argc, char *argv[])
{
	FILE *f;
	char buf[36];
	foreign_metadata_t *fm;
	const char *fn, *error;
	size_t i;
	FLAC__uint32 size;

	if(argc != 2) {
		fprintf(stderr, "usage: %s { file.wav | file.aif }\n", argv[0]);
		return 1;
	}
	fn = argv[1];
	if(0 == (f = fopen(fn, "rb")) || fread(buf, 1, 4, f) != 4) {
		fprintf(stderr, "ERROR opening %s for reading\n", fn);
		return 1;
	}
	fclose(f);
	if(0 == (fm = flac__foreign_metadata_new(memcmp(buf, "RIFF", 4) && memcmp(buf, "RF64", 4)? FOREIGN_BLOCK_TYPE__AIFF : FOREIGN_BLOCK_TYPE__RIFF))) {
		fprintf(stderr, "ERROR: out of memory\n");
		return 1;
	}
	if(fm->type == FOREIGN_BLOCK_TYPE__AIFF) {
		if(!flac__foreign_metadata_read_from_aiff(fm, fn, &error)) {
			fprintf(stderr, "ERROR reading chunks from %s: %s\n", fn, error);
			return 1;
		}
	}
	else {
		if(!flac__foreign_metadata_read_from_wave(fm, fn, &error)) {
			fprintf(stderr, "ERROR reading chunks from %s: %s\n", fn, error);
			return 1;
		}
	}
	if(0 == (f = fopen(fn, "rb"))) {
		fprintf(stderr, "ERROR opening %s for reading\n", fn);
		return 1;
	}
	for(i = 0; i < fm->num_blocks; i++) {
		if(fseeko(f, fm->blocks[i].offset, SEEK_SET) < 0) {
			fprintf(stderr, "ERROR seeking in %s\n", fn);
			return 1;
		}
		if(fread(buf, 1, i==0?12:8, f) != (i==0?12:8)) {
			fprintf(stderr, "ERROR reading %s\n", fn);
			return 1;
		}
		size = unpack32_((const FLAC__byte*)buf+4, fm->type);
		printf("block:[%c%c%c%c] size=%08x=(%10u)", buf[0], buf[1], buf[2], buf[3], size, size);
		if(i == 0)
			printf(" type:[%c%c%c%c]", buf[8], buf[9], buf[10], buf[11]);
		else if(fm->type == FOREIGN_BLOCK_TYPE__AIFF && i == fm->audio_block)
			printf(" offset size=%08x=(%10u)", fm->ssnd_offset_size, fm->ssnd_offset_size);
		else if(fm->type == FOREIGN_BLOCK_TYPE__RIFF && i == 1 && !memcmp(buf, "ds64", 4)) {
			if(fread(buf+8, 1, 36-8, f) != 36-8) {
				fprintf(stderr, "ERROR reading %s\n", fn);
				return 1;
			}
#ifdef _MSC_VER
			printf(" RIFF size=%016I64x=(%I64u)", unpack64le_(buf+8), unpack64le_(buf+8));
			printf(" data size=%016I64x=(%I64u)", unpack64le_(buf+16), unpack64le_(buf+16));
			printf(" sample count=%016I64x=(%I64u)", unpack64le_(buf+24), unpack64le_(buf+24));
#else
			printf(" RIFF size=%016llx=(%llu)", unpack64le_(buf+8), unpack64le_(buf+8));
			printf(" data size=%016llx=(%llu)", unpack64le_(buf+16), unpack64le_(buf+16));
			printf(" sample count=%016llx=(%llu)", unpack64le_(buf+24), unpack64le_(buf+24));
#endif
			printf(" table size=%08x=(%u)", unpack32le_(buf+32), unpack32le_(buf+32));
		}
		printf("\n");
	}
	fclose(f);
	flac__foreign_metadata_delete(fm);
	return 0;
}