Skip to main content

Notice

Please note that most of the software linked on this forum is likely to be safe to use. If you are unsure, feel free to ask in the relevant topics, or send a private message to an administrator or moderator. To help curb the problems of false positives, or in the event that you do find actual malware, you can contribute through the article linked here.
Topic: Flac stream ContentLength (Read 5316 times) previous topic - next topic
0 Members and 1 Guest are viewing this topic.

Flac stream ContentLength

I am developing a music file server that serves up flac streams. Typically it has to read (say) a pcm input file and transcode it to flac. For speed reasons I want to do the transcoding pcm->flac on the fly. But in an Http server I need to supply a ContentLength header that indicates the size of the stream being served. => Is there some way to quickly calculate ContentLength of a flac file before doing the full pcm-flac conversion? Are there any command line switches on the flac converter that you can use in order to force the flac converter to produce an output file with a pre-determinate size? (e.g. if you could turn off the conversion algorithm entirely then presumably the output file has the same number of flac frames as the number of frames in the pcm input file...). I am not so much concerned about getting high compression, but very interested to get the correct ContentLength.

Flac stream ContentLength

Reply #1
flac --max-lpc-order 0 --disable-constant-subframes --disable-fixed-subframes

will disable all compression, which is the only way you'll get something remotely consistent.  That just leaves the frame header / subframe header overhead.  While the subframe headers are 1 additional byte per channel per frame, the frame headers are slightly variable-sized as the frame number increases.  Frames 0-127 add 8 bytes of overhead, frames 128-2047 add 9 bytes of overhead, frames 2048-65535 add 10 bytes of overhead and so on.

So, for example, if your block size is 1152 and you have a 2 channel, 16 bps stream, frame 0 will be (1152(block size) * 2(channels) * (16(bps) / 8)) + 8(for frame header/footer) + 2(for subframe headers) = 4618 bytes.

However, the final frame will likely have an additional 1-2 bytes of overhead to account for its nonstandard block size.  If that frame is between 1-256 samples, add 1 byte.  Otherwise, add 2 bytes.


Flac stream ContentLength

Reply #3
flac --max-lpc-order 0 --disable-constant-subframes --disable-fixed-subframes

will disable all compression, which is the only way you'll get something remotely consistent.  That just leaves the frame header / subframe header overhead.  While the subframe headers are 1 additional byte per channel per frame, the frame headers are slightly variable-sized as the frame number increases.  Frames 0-127 add 8 bytes of overhead, frames 128-2047 add 9 bytes of overhead, frames 2048-65535 add 10 bytes of overhead and so on.

So, for example, if your block size is 1152 and you have a 2 channel, 16 bps stream, frame 0 will be (1152(block size) * 2(channels) * (16(bps) / 8)) + 8(for frame header/footer) + 2(for subframe headers) = 4618 bytes.

However, the final frame will likely have an additional 1-2 bytes of overhead to account for its nonstandard block size.  If that frame is between 1-256 samples, add 1 byte.  Otherwise, add 2 bytes.
Brilliant !! Thank you.

But...

I am using LibFlac.dll and unfortunately I don't know how those --disable command line switches are implemented (if at all) in the LibFlac.dll API. According to the documentation, it supports the following setting functions:
[blockquote]
FLAC__stream_encoder_set_ogg_serial_number (FLAC__StreamEncoder *encoder, long serial_number)
FLAC__stream_encoder_set_verify (FLAC__StreamEncoder *encoder, FLAC__bool value)
FLAC__stream_encoder_set_streamable_subset (FLAC__StreamEncoder *encoder, FLAC__bool value)
FLAC__stream_encoder_set_channels (FLAC__StreamEncoder *encoder, unsigned value)
FLAC__stream_encoder_set_bits_per_sample (FLAC__StreamEncoder *encoder, unsigned value)
FLAC__stream_encoder_set_sample_rate (FLAC__StreamEncoder *encoder, unsigned value)
FLAC__stream_encoder_set_compression_level (FLAC__StreamEncoder *encoder, unsigned value)
FLAC__stream_encoder_set_blocksize (FLAC__StreamEncoder *encoder, unsigned value)
FLAC__stream_encoder_set_do_mid_side_stereo (FLAC__StreamEncoder *encoder, FLAC__bool value)
FLAC__stream_encoder_set_loose_mid_side_stereo (FLAC__StreamEncoder *encoder, FLAC__bool value)
FLAC__stream_encoder_set_apodization (FLAC__StreamEncoder *encoder, const char *specification)
FLAC__stream_encoder_set_max_lpc_order (FLAC__StreamEncoder *encoder, unsigned value)
FLAC__stream_encoder_set_qlp_coeff_precision (FLAC__StreamEncoder *encoder, unsigned value)
FLAC__stream_encoder_set_do_qlp_coeff_prec_search (FLAC__StreamEncoder *encoder, FLAC__bool value)
FLAC__stream_encoder_set_do_escape_coding (FLAC__StreamEncoder *encoder, FLAC__bool value)
FLAC__stream_encoder_set_do_exhaustive_model_search (FLAC__StreamEncoder *encoder, FLAC__bool value)
FLAC__stream_encoder_set_min_residual_partition_order (FLAC__StreamEncoder *encoder, unsigned value)
FLAC__stream_encoder_set_max_residual_partition_order (FLAC__StreamEncoder *encoder, unsigned value)
FLAC__stream_encoder_set_rice_parameter_search_dist (FLAC__StreamEncoder *encoder, unsigned value)
FLAC__stream_encoder_set_total_samples_estimate (FLAC__StreamEncoder *encoder, FLAC__uint64 value)
FLAC__stream_encoder_set_metadata (FLAC__StreamEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks)
[/blockquote]

Flac stream ContentLength

Reply #4
I just looked at the source code, and I am guessing (did not test it yet) that libFlac.dll probably also exports the following (undeclared) API calls:

[blockquote]FLAC__stream_encoder_disable_constant_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value) FLAC__stream_encoder_disable_fixed_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value)
[/blockquote]

Flac stream ContentLength

Reply #5
According to src/libFLAC/stream_encoder.c,

FLAC__stream_encoder_disable_constant_subframes
and
FLAC__stream_encoder_disable_fixed_subframes

are not publically exposed in include/FLAC.  However, they should be trivial to implement separately since they just toggle values in the FLAC__StreamEncoder struct.  That might be one option to try.

Flac stream ContentLength

Reply #6
According to src/libFLAC/stream_encoder.c,

FLAC__stream_encoder_disable_constant_subframes
and
FLAC__stream_encoder_disable_fixed_subframes

are not publically exposed in include/FLAC.
There is a neat little utility that examines which functions are exported by a dll [ http://www.nirsoft.net/utils/dll_export_viewer.html ] and I just ran it on libFlac.dll and it confirms that -- notwithstanding what the documentation says -- those functions ARE exported by libFlac.dll !!

 

Flac stream ContentLength

Reply #7
I can confirm that the solution proposed by tuffy -- as adapted to libFlac.dll -- works perfectly. Thanks tuffy !!