<LI><B><TT>total_samples_estimate</TT></B> - May be set to 0 if unknown. Otherwise, set this to the number of samples to be encoded. This will allow the STREAMINFO block to be more accurate during the first pass in the event that the encoder can't seek back to the beginning of the output file to write the updated STREAMINFO block.</LI>
<LI><B><TT>seek_table</TT></B> - Optional seek table to prepend; NULL implies no seek table.</LI>
<LI><B><TT>padding</TT></B> - Size of PADDING block to add (goes after seek table); 0 implies do not add a PADDING block.</LI>
+ <LI><B><TT>last_metadata_is_last</TT></B> - The value the encoder will use for the 'is_last' flag of the last metadata block it writes. In normal usage you would set this to true, but if you will be manually inserting more metadata blocks between the time of the first write callback (when the encoder sends the <TT>fLaC</TT> header and metadata) and the time actual audio encoding starts then set this to false.</LI>
</UL>
</P>
<P>
uint64 total_samples_estimate, /* may be 0 if unknown. this will be a placeholder in the metadata block until the actual total is calculated */
const FLAC__StreamMetaData_SeekTable *seek_table, /* optional seek_table to prepend, 0 => no seek table */
unsigned padding, /* size of PADDING block to add (goes after seek table); 0 => do not add a PADDING block */
+ bool last_metadata_is_last, /* the value the encoder will use for the 'is_last' flag of the last metadata block it writes; set this to false */
+ /* if you will be adding more metadata blocks before the audio frames, else true */
FLAC__StreamEncoderWriteStatus (*write_callback)(const FLAC__StreamEncoder *encoder, const byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data),
void (*metadata_callback)(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetaData *metadata, void *client_data),
void *client_data
fprintf(stderr, "WARNING: skipping extra 'fmt ' sub-chunk\n");
}
else {
- /* fmt chunk size */
+ /* fmt sub-chunk size */
if(!read_little_endian_uint32(infile, &xx, false))
goto wav_abort_;
if(xx != 16) {
- fprintf(stderr, "ERROR: unsupported chunk\n");
+ fprintf(stderr, "ERROR: unsupported non-standard 'fmt ' sub-chunk has length %u != 16\n", (unsigned)xx);
goto wav_abort_;
}
/* compression code */
}
else {
if(bytes_read > data_bytes)
- bytes_read = data_bytes; /* chop off anything after the end of the data chunk */
+ bytes_read = data_bytes; /* chop off anything after the end of the data sub-chunk */
if(bytes_read % bytes_per_wide_sample != 0) {
fprintf(stderr, "ERROR, got partial sample from input file %s\n", infilename);
goto wav_abort_;
}
else {
fprintf(stderr, "WARNING: skipping unknown sub-chunk '%c%c%c%c'\n", (char)(xx&255), (char)((xx>>8)&255), (char)((xx>>16)&255), (char)(xx>>24));
- /* chunk size */
+ /* sub-chunk size */
if(!read_little_endian_uint32(infile, &xx, false))
goto wav_abort_;
if(infile != stdin) {
return false;
}
- if(FLAC__stream_encoder_init(encoder_wrapper->encoder, !lax, do_mid_side, loose_mid_side, channels, bps, sample_rate, blocksize, max_lpc_order, qlp_coeff_precision, do_qlp_coeff_prec_search, do_exhaustive_model_search, min_residual_partition_order, max_residual_partition_order, rice_parameter_search_dist, encoder_wrapper->total_samples_to_encode, (encoder_wrapper->seek_table.num_points > 0)? &encoder_wrapper->seek_table : 0, padding, write_callback, metadata_callback, encoder_wrapper) != FLAC__STREAM_ENCODER_OK) {
+ if(FLAC__stream_encoder_init(encoder_wrapper->encoder, !lax, do_mid_side, loose_mid_side, channels, bps, sample_rate, blocksize, max_lpc_order, qlp_coeff_precision, do_qlp_coeff_prec_search, do_exhaustive_model_search, min_residual_partition_order, max_residual_partition_order, rice_parameter_search_dist, encoder_wrapper->total_samples_to_encode, (encoder_wrapper->seek_table.num_points > 0)? &encoder_wrapper->seek_table : 0, padding, true /*last_metadata_is_last*/, write_callback, metadata_callback, encoder_wrapper) != FLAC__STREAM_ENCODER_OK) {
fprintf(stderr, "ERROR initializing encoder, state = %d:%s\n", FLAC__stream_encoder_state(encoder_wrapper->encoder), FLAC__StreamEncoderStateString[FLAC__stream_encoder_state(encoder_wrapper->encoder)]);
return false;
}
uint64 total_samples_estimate,
const FLAC__StreamMetaData_SeekTable *seek_table,
unsigned padding,
+ bool last_metadata_is_last,
FLAC__StreamEncoderWriteStatus (*write_callback)(const FLAC__StreamEncoder *encoder, const byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data),
void (*metadata_callback)(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetaData *metadata, void *client_data),
void *client_data)
encoder->protected->rice_parameter_search_dist = rice_parameter_search_dist;
encoder->protected->total_samples_estimate = total_samples_estimate;
encoder->protected->seek_table = seek_table;
- encoder->protected->padding = padding;
if(encoder->protected->channels == 0 || encoder->protected->channels > FLAC__MAX_CHANNELS)
return encoder->protected->state = FLAC__STREAM_ENCODER_INVALID_NUMBER_OF_CHANNELS;
return encoder->protected->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
encoder->private->metadata.type = FLAC__METADATA_TYPE_STREAMINFO;
- encoder->private->metadata.is_last = (encoder->protected->seek_table == 0 && encoder->protected->padding == 0);
+ encoder->private->metadata.is_last = (encoder->protected->seek_table == 0 && padding == 0 && last_metadata_is_last);
encoder->private->metadata.length = FLAC__STREAM_METADATA_STREAMINFO_LENGTH;
encoder->private->metadata.data.stream_info.min_blocksize = encoder->protected->blocksize; /* this encoder uses the same blocksize for the whole stream */
encoder->private->metadata.data.stream_info.max_blocksize = encoder->protected->blocksize;
if(!FLAC__seek_table_is_valid(encoder->protected->seek_table))
return encoder->protected->state = FLAC__STREAM_ENCODER_INVALID_SEEK_TABLE;
seek_table_block.type = FLAC__METADATA_TYPE_SEEKTABLE;
- seek_table_block.is_last = (encoder->protected->padding == 0);
+ seek_table_block.is_last = (padding == 0 && last_metadata_is_last);
seek_table_block.length = encoder->protected->seek_table->num_points * FLAC__STREAM_METADATA_SEEKPOINT_LEN;
seek_table_block.data.seek_table = *encoder->protected->seek_table;
if(!FLAC__add_metadata_block(&seek_table_block, &encoder->private->frame))
}
/* add a PADDING block if requested */
- if(encoder->protected->padding > 0) {
+ if(padding > 0) {
padding_block.type = FLAC__METADATA_TYPE_PADDING;
- padding_block.is_last = true;
- padding_block.length = encoder->protected->padding;
+ padding_block.is_last = last_metadata_is_last;
+ padding_block.length = padding;
if(!FLAC__add_metadata_block(&padding_block, &encoder->private->frame))
return encoder->protected->state = FLAC__STREAM_ENCODER_FRAMING_ERROR;
}