Restore compression type name to AIFF-C from foreign metadata

This commit is contained in:
Martijn van Beurden 2023-01-31 10:27:45 +01:00
parent 692f2ebe93
commit 92b5292d65
3 changed files with 54 additions and 26 deletions

@ -113,7 +113,7 @@ static int DecoderSession_finish_error(DecoderSession *d);
static FLAC__bool canonicalize_until_specification(utils__SkipUntilSpecification *spec, const char *inbasefilename, uint32_t sample_rate, FLAC__uint64 skip, FLAC__uint64 total_samples_in_input);
static FLAC__bool write_iff_headers(FILE *f, DecoderSession *decoder_session, FLAC__uint64 samples);
static FLAC__bool write_riff_wave_fmt_chunk_body(FILE *f, FLAC__bool is_waveformatextensible, uint32_t bps, uint32_t channels, uint32_t sample_rate, FLAC__uint32 channel_mask);
static FLAC__bool write_aiff_form_comm_chunk(FILE *f, FLAC__uint64 samples, uint32_t bps, uint32_t channels, uint32_t sample_rate, FileFormat format, FileSubFormat subformat);
static FLAC__bool write_aiff_form_comm_chunk(FILE *f, FLAC__uint64 samples, uint32_t bps, uint32_t channels, uint32_t sample_rate, FileFormat format, FileSubFormat subformat, FLAC__uint32 comm_length);
static FLAC__bool write_little_endian_uint16(FILE *f, FLAC__uint16 val);
static FLAC__bool write_little_endian_uint32(FILE *f, FLAC__uint32 val);
static FLAC__bool write_little_endian_uint64(FILE *f, FLAC__uint64 val);
@ -700,7 +700,7 @@ FLAC__bool write_iff_headers(FILE *f, DecoderSession *decoder_session, FLAC__uin
else if(format == FORMAT_AIFF)
iff_size = 46 + foreign_metadata_size + aligned_data_size;
else /* AIFF-C */
iff_size = 52 + foreign_metadata_size + aligned_data_size;
iff_size = 16 + foreign_metadata_size + aligned_data_size + fm->aifc_comm_length;
if(format != FORMAT_WAVE64 && format != FORMAT_RF64 && iff_size >= 0xFFFFFFF4) {
flac__utils_printf(stderr, 1, "%s: ERROR: stream is too big to fit in a single %s file\n", decoder_session->inbasefilename, fmt_desc);
@ -847,7 +847,7 @@ FLAC__bool write_iff_headers(FILE *f, DecoderSession *decoder_session, FLAC__uin
}
}
if(!write_aiff_form_comm_chunk(f, samples, decoder_session->bps, decoder_session->channels, decoder_session->sample_rate, format, subformat))
if(!write_aiff_form_comm_chunk(f, samples, decoder_session->bps, decoder_session->channels, decoder_session->sample_rate, format, subformat, fm?fm->aifc_comm_length:0))
return false;
decoder_session->fm_offset2 = ftello(f);
@ -918,21 +918,23 @@ FLAC__bool write_riff_wave_fmt_chunk_body(FILE *f, FLAC__bool is_waveformatexten
return true;
}
FLAC__bool write_aiff_form_comm_chunk(FILE *f, FLAC__uint64 samples, uint32_t bps, uint32_t channels, uint32_t sample_rate, FileFormat format, FileSubFormat subformat)
FLAC__bool write_aiff_form_comm_chunk(FILE *f, FLAC__uint64 samples, uint32_t bps, uint32_t channels, uint32_t sample_rate, FileFormat format, FileSubFormat subformat, FLAC__uint32 comm_length)
{
FLAC__uint32 i;
FLAC__ASSERT(samples <= 0xffffffff);
if(comm_length == 0) {
if(format == FORMAT_AIFF)
comm_length = 30;
else
comm_length = 36;
}
if(flac__utils_fwrite("COMM", 1, 4, f) != 4)
return false;
if(format == FORMAT_AIFF) {
if(!write_big_endian_uint32(f, 18)) /* chunk size = 18 */
return false;
}
else {
if(!write_big_endian_uint32(f, 24)) /* chunk size = 24 */
return false;
}
if(!write_big_endian_uint32(f, comm_length-12)) /* chunk size = 18 */
return false;
if(!write_big_endian_uint16(f, (FLAC__uint16)channels))
return false;
@ -955,8 +957,10 @@ FLAC__bool write_aiff_form_comm_chunk(FILE *f, FLAC__uint64 samples, uint32_t bp
if(flac__utils_fwrite("sowt", 1, 4, f) != 4)
return false;
}
if(flac__utils_fwrite("\x00\x00", 1, 2, f) != 2)
return false;
for(i = 34; i < comm_length; i++) {
if(flac__utils_fwrite("\x00", 1, 1, f) != 1)
return false;
}
}

@ -498,6 +498,7 @@ static FLAC__bool read_from_flac_(foreign_metadata_t *fm, FILE *f, FLAC__Metadat
{
FLAC__byte id[4], buffer[32];
FLAC__off_t offset;
FLAC__uint32 length;
FLAC__bool first_block = true, type_found = false, ds64_found = false;
FLAC__ASSERT(FLAC__STREAM_METADATA_APPLICATION_ID_LEN == sizeof(id)*8);
@ -522,6 +523,7 @@ static FLAC__bool read_from_flac_(foreign_metadata_t *fm, FILE *f, FLAC__Metadat
else if(memcmp(id, FLAC__FOREIGN_METADATA_APPLICATION_ID[fm->type], sizeof(id)))
continue;
offset = FLAC__metadata_simple_iterator_get_block_offset(it);
length = FLAC__metadata_simple_iterator_get_block_length(it);
/* skip over header and app ID */
offset += (FLAC__STREAM_METADATA_IS_LAST_LEN + FLAC__STREAM_METADATA_TYPE_LEN + FLAC__STREAM_METADATA_LENGTH_LEN) / 8;
offset += sizeof(id);
@ -636,11 +638,12 @@ static FLAC__bool read_from_flac_(foreign_metadata_t *fm, FILE *f, FLAC__Metadat
}
fm->format_block = fm->num_blocks;
if(fm->is_aifc) {
if(fread(buffer+4, 1, 28, f) != 28) {
if(fread(buffer+4, 1, 26, f) != 26) {
if(error) *error = "read error (020)";
return false;
}
fm->is_sowt = 0 == memcmp(buffer+26, "sowt", 2);
fm->aifc_comm_length = length;
}
}
else if(!memcmp(buffer, "SSND", 4)) {
@ -700,48 +703,68 @@ static FLAC__bool write_to_iff_(foreign_metadata_t *fm, FILE *fin, FILE *fout, F
/* don't write first (RIFF/RF64/FORM) chunk, or ds64 chunk in the case of RF64, compare instead */
for(i = 0; i < (fm->is_rf64?2:1); i++) {
if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) {
if(error) *error = "seek failed in FLAC file (003)";
if(error) *error = "seek failed in FLAC file";
return false;
}
if(!compare_data_(fin, fout, fm->blocks[i].size, error, "read failed in WAVE/AIFF file (004)", "write failed in FLAC file (005)", "stored foreign metadata seems invalid"))
if(!compare_data_(fin, fout, fm->blocks[i].size, error, "read failed in FLAC file", "read failed in WAVE/AIFF file", "stored main chunk length differs from written length"))
return false;
}
for(; i < fm->format_block; i++) {
if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) {
if(error) *error = "seek failed in FLAC file (003)";
if(error) *error = "seek failed in FLAC file";
return false;
}
if(!copy_data_(fin, fout, fm->blocks[i].size, error, "read failed in WAVE/AIFF file (004)", "write failed in FLAC file (005)"))
if(!copy_data_(fin, fout, fm->blocks[i].size, error, "read failed in FLAC file", "read failed in WAVE/AIFF file"))
return false;
}
if(fm->is_aifc) {
/* Need to restore compression type name */
if(fseeko(fout, 30, SEEK_CUR) < 0) {
if(error) *error = "seek failed in AIFF-C file";
return false;
}
if(fseeko(fin, fm->blocks[i].offset+30, SEEK_SET) < 0) {
if(error) *error = "seek failed in FLAC file";
return false;
}
if(!copy_data_(fin, fout, fm->aifc_comm_length-34, error, "read failed in FLAC file", "write failed in WAVE/AIFF file"))
return false;
/* Now seek back */
if(fseeko(fout, ((FLAC__int32)(fm->aifc_comm_length) * -1) + 4, SEEK_CUR) < 0) {
if(error) *error = "seek failed in AIFF-C file";
return false;
}
}
/* compare format block */
if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) {
if(error) *error = "seek failed in FLAC file (003)";
if(error) *error = "seek failed in FLAC file";
return false;
}
if(!compare_data_(fin, fout, fm->blocks[i].size, error, "read failed in WAVE/AIFF file (004)", "write failed in FLAC file (005)", "stored foreign format block differs from written block. Perhaps the file is being restored to a different format than that of the original file"))
if(!compare_data_(fin, fout, fm->blocks[i].size, error, "read failed in FLAC file", "read failed in WAVE/AIFF file", "stored foreign format block differs from written block. Perhaps the file is being restored to a different format than that of the original file"))
return false;
i++;
for(; i < fm->audio_block; i++) {
if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) {
if(error) *error = "seek failed in FLAC file (007)";
if(error) *error = "seek failed in FLAC file";
return false;
}
if(!copy_data_(fin, fout, fm->blocks[i].size, error, "read failed in WAVE/AIFF file (008)", "write failed in FLAC file (009)"))
if(!copy_data_(fin, fout, fm->blocks[i].size, error, "read failed in FLAC file", "write failed in WAVE/AIFF file"))
return false;
}
if(fseeko(fout, offset3, SEEK_SET) < 0) {
if(error) *error = "seek failed in WAVE/AIFF file (010)";
if(error) *error = "seek failed in WAVE/AIFF file";
return false;
}
for(i = fm->audio_block+1; i < fm->num_blocks; i++) {
if(fseeko(fin, fm->blocks[i].offset, SEEK_SET) < 0) {
if(error) *error = "seek failed in FLAC file (011)";
if(error) *error = "seek failed in FLAC file";
return false;
}
if(!copy_data_(fin, fout, fm->blocks[i].size, error, "read failed in WAVE/AIFF file (012)", "write failed in FLAC file (013)"))
if(!copy_data_(fin, fout, fm->blocks[i].size, error, "read failed in FLAC file", "write failed in WAVE/AIFF file"))
return false;
}
return true;

@ -63,6 +63,7 @@ typedef struct {
FLAC__bool is_wavefmtex; /* always false if type!=RIFF */
FLAC__bool is_aifc; /* always false if type!=AIFF */
FLAC__bool is_sowt; /* always false if type!=AIFF */
FLAC__uint32 aifc_comm_length;
FLAC__uint32 ssnd_offset_size; /* 0 if type!=AIFF */
} foreign_metadata_t;