Add support for decoding to AIFF-C NONE and sowt

Also, add the option to force decoding to WAVE_FORMAT_EXTENSIBLE
This commit is contained in:
Martijn van Beurden 2023-01-30 15:03:04 +01:00
parent a8c20a6af1
commit 692f2ebe93
5 changed files with 165 additions and 65 deletions

View File

@ -544,22 +544,29 @@ the HTML documentation.
: Force input (when encoding) or output (when decoding) to be treated
as raw samples (even if filename ends in *.wav*).
**\--force-aiff-format**
: Force the decoder to output AIFF format. This option is not needed if
the output filename (as set by -o) ends with *.aif* or *.aiff*. Also,
this option has no effect when encoding since input AIFF is
auto-detected.
**\--force-rf64-format**
: Force the decoder to output RF64 format. This option is not needed if
the output filename (as set by -o) ends with *.rf64*. Also, this
option has no effect when encoding since input RF64 is auto-detected.
**\--force-aiff-format**
**\--force-rf64-format**
**\--force-wave64-format**
: Force the decoder to output Wave64 format. This option is not needed
if the output filename (as set by -o) ends with *.w64*. Also, this
option has no effect when encoding since input Wave64 is
auto-detected.
: Force the decoder to output AIFF/RF64/WAVE64 format respectively.
This option is not needed if the output filename (as set by -o)
ends with *.aif* or *.aiff*, *.rf64* and *.w64* respectively. Also,
this option has no effect when encoding since input is
auto-detected. When none of these options nor
--keep-foreign-metadata are given and no output filename is set,
the output format is WAV by default.
**\--force-legacy-wave-format**
**\--force-extensible-wave-format**
: Instruct the decoder to output a WAVE file with WAVE_FORMAT_PCM and
WAVE_FORMAT_EXTENSIBLE respectively. If none of these options nor
--keep-foreign-metadata are given, FLAC outputs WAVE_FORMAT_PCM
for mono or stereo with a bit depth of 8 or 16 bits, and
WAVE_FORMAT_EXTENSIBLE for all other audio formats.
**\--force-aiff-c-none-format**
**\--force-aiff-c-sowt-format**
: Instruct the decoder to output an AIFF-C file with format NONE and
sowt respectively.
## NEGATIVE OPTIONS

View File

@ -40,11 +40,11 @@ typedef struct {
#endif
FileFormat format;
FileSubFormat subformat;
FLAC__bool treat_warnings_as_errors;
FLAC__bool continue_through_decode_errors;
FLAC__bool channel_map_none;
FLAC__bool relaxed_foreign_metadata_handling;
FLAC__bool force_legacy_wave_format;
struct {
replaygain_synthesis_spec_t spec;
@ -104,7 +104,7 @@ static FLAC__bool is_big_endian_host_;
/*
* local routines
*/
static FLAC__bool DecoderSession_construct(DecoderSession *d, FLAC__bool is_ogg, FLAC__bool use_first_serial_number, long serial_number, FileFormat format, FLAC__bool treat_warnings_as_errors, FLAC__bool continue_through_decode_errors, FLAC__bool channel_map_none, FLAC__bool relaxed_foreign_metadata_handling, FLAC__bool force_legacy_wave_format, replaygain_synthesis_spec_t replaygain_synthesis_spec, FLAC__bool analysis_mode, analysis_options aopts, utils__SkipUntilSpecification *skip_specification, utils__SkipUntilSpecification *until_specification, utils__CueSpecification *cue_specification, foreign_metadata_t *foreign_metadata, const char *infilename, const char *outfilename);
static FLAC__bool DecoderSession_construct(DecoderSession *d, FLAC__bool is_ogg, FLAC__bool use_first_serial_number, long serial_number, FileFormat format, FileSubFormat subformat, FLAC__bool treat_warnings_as_errors, FLAC__bool continue_through_decode_errors, FLAC__bool channel_map_none, FLAC__bool relaxed_foreign_metadata_handling, replaygain_synthesis_spec_t replaygain_synthesis_spec, FLAC__bool analysis_mode, analysis_options aopts, utils__SkipUntilSpecification *skip_specification, utils__SkipUntilSpecification *until_specification, utils__CueSpecification *cue_specification, foreign_metadata_t *foreign_metadata, const char *infilename, const char *outfilename);
static void DecoderSession_destroy(DecoderSession *d, FLAC__bool error_occurred);
static FLAC__bool DecoderSession_init_decoder(DecoderSession *d, const char *infilename);
static FLAC__bool DecoderSession_process(DecoderSession *d);
@ -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);
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_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);
@ -163,11 +163,11 @@ int flac__decode_file(const char *infilename, const char *outfilename, FLAC__boo
/*serial_number=*/0,
#endif
options.format,
options.force_subformat,
options.treat_warnings_as_errors,
options.continue_through_decode_errors,
options.channel_map_none,
options.relaxed_foreign_metadata_handling,
options.force_legacy_wave_format,
options.replaygain_synthesis_spec,
analysis_mode,
aopts,
@ -191,7 +191,7 @@ int flac__decode_file(const char *infilename, const char *outfilename, FLAC__boo
return DecoderSession_finish_ok(&decoder_session);
}
FLAC__bool DecoderSession_construct(DecoderSession *d, FLAC__bool is_ogg, FLAC__bool use_first_serial_number, long serial_number, FileFormat format, FLAC__bool treat_warnings_as_errors, FLAC__bool continue_through_decode_errors, FLAC__bool channel_map_none, FLAC__bool relaxed_foreign_metadata_handling, FLAC__bool force_legacy_wave_format, replaygain_synthesis_spec_t replaygain_synthesis_spec, FLAC__bool analysis_mode, analysis_options aopts, utils__SkipUntilSpecification *skip_specification, utils__SkipUntilSpecification *until_specification, utils__CueSpecification *cue_specification, foreign_metadata_t *foreign_metadata, const char *infilename, const char *outfilename)
FLAC__bool DecoderSession_construct(DecoderSession *d, FLAC__bool is_ogg, FLAC__bool use_first_serial_number, long serial_number, FileFormat format, FileSubFormat subformat, FLAC__bool treat_warnings_as_errors, FLAC__bool continue_through_decode_errors, FLAC__bool channel_map_none, FLAC__bool relaxed_foreign_metadata_handling, replaygain_synthesis_spec_t replaygain_synthesis_spec, FLAC__bool analysis_mode, analysis_options aopts, utils__SkipUntilSpecification *skip_specification, utils__SkipUntilSpecification *until_specification, utils__CueSpecification *cue_specification, foreign_metadata_t *foreign_metadata, const char *infilename, const char *outfilename)
{
#if FLAC__HAS_OGG
d->is_ogg = is_ogg;
@ -204,11 +204,11 @@ FLAC__bool DecoderSession_construct(DecoderSession *d, FLAC__bool is_ogg, FLAC__
#endif
d->format = format;
d->subformat = subformat;
d->treat_warnings_as_errors = treat_warnings_as_errors;
d->continue_through_decode_errors = continue_through_decode_errors;
d->channel_map_none = channel_map_none;
d->relaxed_foreign_metadata_handling = relaxed_foreign_metadata_handling;
d->force_legacy_wave_format = force_legacy_wave_format;
d->replaygain.spec = replaygain_synthesis_spec;
d->replaygain.apply = false;
d->replaygain.scale = 0.0;
@ -624,19 +624,22 @@ FLAC__bool canonicalize_until_specification(utils__SkipUntilSpecification *spec,
FLAC__bool write_iff_headers(FILE *f, DecoderSession *decoder_session, FLAC__uint64 samples)
{
const FileFormat format = decoder_session->format;
const FileSubFormat subformat = decoder_session->subformat;
const char *fmt_desc =
format==FORMAT_WAVE? "WAVE" :
format==FORMAT_WAVE64? "Wave64" :
format==FORMAT_RF64? "RF64" :
"AIFF";
format==FORMAT_AIFF? "AIFF" :
"AIFC";
const FLAC__bool is_waveformatextensible =
subformat == SUBFORMAT_WAVE_EXTENSIBLE || (
(format == FORMAT_WAVE || format == FORMAT_WAVE64 || format == FORMAT_RF64) &&
!decoder_session->force_legacy_wave_format &&
subformat != SUBFORMAT_WAVE_PCM &&
(
(decoder_session->channel_mask != 0 && decoder_session->channel_mask != 0x0004 && decoder_session->channel_mask != 0x0003) ||
(decoder_session->bps != 8 && decoder_session->bps != 16) ||
decoder_session->channels > 2
);
));
const FLAC__uint64 data_size = samples * decoder_session->channels * ((decoder_session->bps+7)/8);
const FLAC__uint64 aligned_data_size =
format == FORMAT_WAVE64?
@ -694,8 +697,10 @@ FLAC__bool write_iff_headers(FILE *f, DecoderSession *decoder_session, FLAC__uin
/* +16+8+{40,16} for fmt chunk header (GUID and size field) and body */
/* +16+8 for data chunk header (GUID and size field) */
iff_size = 16+8 + 16 + 16+8+(is_waveformatextensible?40:16) + 16+8 + foreign_metadata_size + aligned_data_size;
else /* AIFF */
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;
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);
@ -822,8 +827,13 @@ FLAC__bool write_iff_headers(FILE *f, DecoderSession *decoder_session, FLAC__uin
if(!write_big_endian_uint32(f, (FLAC__uint32)iff_size)) /* filesize-8 */
return false;
if(flac__utils_fwrite("AIFF", 1, 4, f) != 4)
return false;
if(format == FORMAT_AIFF) {
if(flac__utils_fwrite("AIFF", 1, 4, f) != 4)
return false;
}
else
if(flac__utils_fwrite("AIFC", 1, 4, f) != 4)
return false;
decoder_session->fm_offset1 = ftello(f);
@ -837,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))
if(!write_aiff_form_comm_chunk(f, samples, decoder_session->bps, decoder_session->channels, decoder_session->sample_rate, format, subformat))
return false;
decoder_session->fm_offset2 = ftello(f);
@ -908,15 +918,21 @@ 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)
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__ASSERT(samples <= 0xffffffff);
if(flac__utils_fwrite("COMM", 1, 4, f) != 4)
return false;
if(!write_big_endian_uint32(f, 18)) /* chunk size = 18 */
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_uint16(f, (FLAC__uint16)channels))
return false;
@ -930,6 +946,21 @@ FLAC__bool write_aiff_form_comm_chunk(FILE *f, FLAC__uint64 samples, uint32_t bp
if(!write_sane_extended(f, sample_rate))
return false;
if(format == FORMAT_AIFF_C) {
if(subformat == SUBFORMAT_AIFF_C_NONE) {
if(flac__utils_fwrite("NONE", 1, 4, f) != 4)
return false;
}
else if(subformat == SUBFORMAT_AIFF_C_SOWT) {
if(flac__utils_fwrite("sowt", 1, 4, f) != 4)
return false;
}
if(flac__utils_fwrite("\x00\x00", 1, 2, f) != 2)
return false;
}
return true;
}
@ -1049,8 +1080,8 @@ FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder
const uint32_t bps = frame->header.bits_per_sample, channels = frame->header.channels;
const uint32_t shift = (decoder_session->format != FORMAT_RAW && (bps%8))? 8-(bps%8): 0;
FLAC__bool is_big_endian = (
decoder_session->format == FORMAT_AIFF || decoder_session->format == FORMAT_AIFF_C ? true : (
decoder_session->format == FORMAT_WAVE || decoder_session->format == FORMAT_WAVE64 || decoder_session->format == FORMAT_RF64 ? false :
(decoder_session->format == FORMAT_AIFF || (decoder_session->format == FORMAT_AIFF_C && decoder_session->subformat == SUBFORMAT_AIFF_C_NONE)) ? true : (
decoder_session->format == FORMAT_WAVE || decoder_session->format == FORMAT_WAVE64 || decoder_session->format == FORMAT_RF64 || (decoder_session->format == FORMAT_AIFF_C && decoder_session->subformat == SUBFORMAT_AIFF_C_SOWT) ? false :
decoder_session->is_big_endian
));
FLAC__bool is_unsigned_samples = (

View File

@ -53,7 +53,7 @@ typedef struct {
utils__CueSpecification cue_specification;
FLAC__bool channel_map_none; /* --channel-map=none specified, eventually will expand to take actual channel map */
FLAC__bool relaxed_foreign_metadata_handling;
FLAC__bool force_legacy_wave_format;
FileSubFormat force_subformat;
FileFormat format;
union {

View File

@ -144,6 +144,9 @@ static struct share__option long_options_[] = {
{ "force-rf64-format" , share__no_argument, 0, 0 },
{ "force-wave64-format" , share__no_argument, 0, 0 },
{ "force-legacy-wave-format" , share__no_argument, 0, 0 },
{ "force-extensible-wave-format",share__no_argument,0, 0 },
{ "force-aiff-c-none-format" , share__no_argument, 0, 0 },
{ "force-aiff-c-sowt-format" , share__no_argument, 0, 0 },
{ "lax" , share__no_argument, 0, 0 },
{ "replay-gain" , share__no_argument, 0, 0 },
{ "ignore-chunk-sizes" , share__no_argument, 0, 0 },
@ -244,6 +247,9 @@ static struct {
FLAC__bool force_rf64_format;
FLAC__bool force_wave64_format;
FLAC__bool force_legacy_wave_format;
FLAC__bool force_extensible_wave_format;
FLAC__bool force_aiff_c_none_format;
FLAC__bool force_aiff_c_sowt_format;
FLAC__bool delete_input;
FLAC__bool preserve_modtime;
FLAC__bool keep_foreign_metadata;
@ -402,8 +408,16 @@ int do_it(void)
if(!FLAC__format_sample_rate_is_valid(option_values.format_sample_rate))
return usage_error("ERROR: invalid sample rate '%u', must be > 0 and <= %u\n", option_values.format_sample_rate, FLAC__MAX_SAMPLE_RATE);
}
if((option_values.force_raw_format?1:0) + (option_values.force_aiff_format?1:0) + (option_values.force_rf64_format?1:0) + (option_values.force_wave64_format?1:0) > 1)
return usage_error("ERROR: only one of --force-raw-format/--force-aiff-format/--force-rf64-format/--force-wave64-format allowed\n");
if((option_values.force_raw_format?1:0) +
(option_values.force_aiff_format?1:0) +
(option_values.force_rf64_format?1:0) +
(option_values.force_wave64_format?1:0) +
(option_values.force_legacy_wave_format?1:0) +
(option_values.force_extensible_wave_format?1:0) +
(option_values.force_aiff_c_none_format?1:0) +
(option_values.force_aiff_c_sowt_format?1:0)
> 1)
return usage_error("ERROR: only one of force format options allowed\n");
if(option_values.mode_decode) {
if(!option_values.force_raw_format) {
if(option_values.format_is_big_endian >= 0)
@ -574,6 +588,9 @@ FLAC__bool init_options(void)
option_values.force_rf64_format = false;
option_values.force_wave64_format = false;
option_values.force_legacy_wave_format = false;
option_values.force_extensible_wave_format = false;
option_values.force_aiff_c_none_format = false;
option_values.force_aiff_c_sowt_format = false;
option_values.delete_input = false;
option_values.preserve_modtime = true;
option_values.keep_foreign_metadata = false;
@ -781,6 +798,15 @@ int parse_option(int short_option, const char *long_option, const char *option_a
else if(0 == strcmp(long_option, "force-legacy-wave-format")) {
option_values.force_legacy_wave_format = true;
}
else if(0 == strcmp(long_option, "force-extensible-wave-format")) {
option_values.force_extensible_wave_format = true;
}
else if(0 == strcmp(long_option, "force-aiff-c-none-format")) {
option_values.force_aiff_c_none_format = true;
}
else if(0 == strcmp(long_option, "force-aiff-c-sowt-format")) {
option_values.force_aiff_c_sowt_format = true;
}
else if(0 == strcmp(long_option, "lax")) {
option_values.lax = true;
}
@ -1319,11 +1345,14 @@ void show_help(void)
printf(" -r, --rice-partition-order=[#,]# Set [min,]max residual partition order\n");
printf(" --limit-min-bitrate Limit minimum bitrate (for streaming)\n");
printf("format options:\n");
printf(" --force-raw-format Treat input or output as raw samples\n");
printf(" --force-aiff-format Force decoding to AIFF format\n");
printf(" --force-rf64-format Force decoding to RF64 format\n");
printf(" --force-wave64-format Force decoding to Wave64 format\n");
printf(" --force-legacy-wave-format Force decoding to legacy wave format\n");
printf(" --force-raw-format Treat input or output as raw samples\n");
printf(" --force-aiff-format Decode to AIFF format\n");
printf(" --force-rf64-format Decode to RF64 format\n");
printf(" --force-wave64-format Decode to Wave64 format\n");
printf(" --force-legacy-wave-format Decode to legacy wave format\n");
printf(" --force-extensible-wave-format Decode to extensible wave format\n");
printf(" --force-aiff-c-none-format Decode to AIFF-C NONE format\n");
printf(" --force-aiff-c-sowt-format Decode to AIFF-C sowt format\n");
printf("raw format options:\n");
printf(" --endian={big|little} Set byte order for samples\n");
printf(" --channels=# Number of channels\n");
@ -1662,26 +1691,27 @@ void show_explain(void)
printf("format options:\n");
printf(" --force-raw-format Force input (when encoding) or output (when\n");
printf(" decoding) to be treated as raw samples\n");
printf(" --force-aiff-format Force the decoder to output AIFF format. This\n");
printf(" option is not needed if the output filename (as\n");
printf(" set by -o) ends with .aif or .aiff; this option\n");
printf(" has no effect when encoding since input AIFF is\n");
printf(" auto-detected.\n");
printf(" --force-rf64-format Force the decoder to output RF64 format. This\n");
printf(" option is not needed if the output filename (as\n");
printf(" set by -o) ends with .rf64; this option\n");
printf(" has no effect when encoding since input RF64 is\n");
printf(" auto-detected.\n");
printf(" --force-wave64-format Force the decoder to output Wave64 format. This\n");
printf(" option is not needed if the output filename (as\n");
printf(" set by -o) ends with .w64; this option\n");
printf(" has no effect when encoding since input Wave64 is\n");
printf(" auto-detected.\n");
printf(" --force-legacy-wave-format Force the decoder to output to\n");
printf(" WAVE_FORMAT_PCM when WAVE_FORMAT_EXTENSIBLE\n");
printf(" would be appropriate. This is the case for\n");
printf(" audio with 24 or 32 bits per sample or more\n");
printf(" than 2 channels.\n");
printf(" --force-aiff-format\n");
printf(" --force-rf64-format\n");
printf(" --force-wave64-format\n");
printf(" Force the decoder to output AIFF/RF64/WAVE64 format respectively.\n");
printf(" This option is not needed if the output filename (as set by -o)\n");
printf(" ends with *.aif* or *.aiff*, *.rf64* and *.w64* respectively. Also,\n");
printf(" this option has no effect when encoding since input is\n");
printf(" auto-detected. When none of these options nor\n");
printf(" --keep-foreign-metadata are given and no output filename is set,\n");
printf(" the output format is WAV by default.\n");
printf(" --force-legacy-wave-format\n");
printf(" --force-extensible-wave-format\n");
printf(" Instruct the decoder to output a WAVE file with WAVE_FORMAT_PCM and\n");
printf(" WAVE_FORMAT_EXTENSIBLE respectively. If none of these options nor\n");
printf(" --keep-foreign-metadata are given, FLAC outputs WAVE_FORMAT_PCM\n");
printf(" for mono or stereo with a bit depth of 8 or 16 bits, and\n");
printf(" WAVE_FORMAT_EXTENSIBLE for all other audio formats.\n");
printf(" --force-aiff-c-none-format\n");
printf(" --force-aiff-c-sowt-format\n");
printf(" Instruct the decoder to output an AIFF-C file with format NONE and\n");
printf(" sowt respectively.\n");
printf("raw format options:\n");
printf(" --endian={big|little} Set byte order for samples\n");
printf(" --channels=# Number of channels\n");
@ -2106,6 +2136,7 @@ int decode_file(const char *infilename)
int retval;
FLAC__bool treat_as_ogg = false;
FileFormat output_format = FORMAT_WAVE;
FileSubFormat output_subformat = SUBFORMAT_UNSPECIFIED;
decode_options_t decode_options;
foreign_metadata_t foreign_metadata_instance = {0}; /* Allocate space */
foreign_metadata_t *foreign_metadata = 0;
@ -2169,17 +2200,42 @@ int decode_file(const char *infilename)
else if(foreign_metadata->type == FOREIGN_BLOCK_TYPE__AIFF) {
output_format = FORMAT_AIFF;
if(foreign_metadata->is_aifc) {
flac__utils_printf(stderr, 1, "ERROR restoring foreign metadata: restoring AIFF-C files is not yet supported\n");
return 1;
output_format = FORMAT_AIFF_C;
}
}
else
output_format = FORMAT_WAVE;
/* Further split is determined in decode.c */
}
else
output_format = FORMAT_WAVE;
/* Now do subformats */
if(option_values.force_legacy_wave_format)
output_subformat = SUBFORMAT_WAVE_PCM;
else if(option_values.force_extensible_wave_format)
output_subformat = SUBFORMAT_WAVE_EXTENSIBLE;
else if(option_values.force_aiff_c_none_format) {
output_format = FORMAT_AIFF_C;
output_subformat = SUBFORMAT_AIFF_C_NONE;
}
else if(option_values.force_aiff_c_sowt_format) {
output_format = FORMAT_AIFF_C;
output_subformat = SUBFORMAT_AIFF_C_SOWT;
}
else if(foreign_metadata != NULL) {
if(foreign_metadata->is_wavefmtex)
output_subformat = SUBFORMAT_WAVE_EXTENSIBLE;
else if(output_format == FORMAT_WAVE)
output_subformat = SUBFORMAT_WAVE_PCM;
else if(foreign_metadata->is_aifc) {
if(foreign_metadata->is_sowt)
output_subformat = SUBFORMAT_AIFF_C_SOWT;
else
output_subformat = SUBFORMAT_AIFF_C_NONE;
}
}
/* Check whether output format agrees with foreign metadata */
if(foreign_metadata != NULL) {
if((output_format != FORMAT_WAVE && output_format != FORMAT_RF64) && foreign_metadata->type == FOREIGN_BLOCK_TYPE__RIFF)
@ -2245,7 +2301,7 @@ int decode_file(const char *infilename)
decode_options.continue_through_decode_errors = option_values.continue_through_decode_errors;
decode_options.relaxed_foreign_metadata_handling = option_values.keep_foreign_metadata_if_present;
decode_options.replaygain_synthesis_spec = option_values.replaygain_synthesis_spec;
decode_options.force_legacy_wave_format = option_values.force_legacy_wave_format;
decode_options.force_subformat = output_subformat;
#if FLAC__HAS_OGG
decode_options.is_ogg = treat_as_ogg;
decode_options.use_first_serial_number = !option_values.has_serial_number;
@ -2313,6 +2369,9 @@ const char *get_decoded_outfilename(const char *infilename, const FileFormat for
else if(format == FORMAT_AIFF) {
suffix = ".aiff";
}
else if(format == FORMAT_AIFF_C) {
suffix = ".aifc";
}
else if(format == FORMAT_RF64) {
suffix = ".rf64";
}

View File

@ -31,6 +31,9 @@
typedef enum { FORMAT_RAW, FORMAT_WAVE, FORMAT_WAVE64, FORMAT_RF64, FORMAT_AIFF, FORMAT_AIFF_C, FORMAT_FLAC, FORMAT_OGGFLAC } FileFormat;
static const char * const FileFormatString[] = { " raw", " WAVE", " Wave64", "n RF64", "n AIFF", "n AIFF-C", " FLAC", "n Ogg FLAC" };
typedef enum { SUBFORMAT_UNSPECIFIED = 0, SUBFORMAT_WAVE_PCM, SUBFORMAT_WAVE_EXTENSIBLE, SUBFORMAT_AIFF_C_NONE, SUBFORMAT_AIFF_C_SOWT } FileSubFormat;
typedef struct {
FLAC__bool is_relative; /* i.e. specification string started with + or - */
FLAC__bool value_is_samples;