[flac-dev] Encoder example for 24-bit files

Jose Pablo Carballo jose.carballo at ridgerun.com
Thu Aug 14 10:55:48 PDT 2014

Ian's explanation below was helpful:

On Thu, Aug 14, 2014 at 7:53 AM, Ian Nartowicz <ian at nartowicz.co.uk> wrote:
> The sample rate should take care of itself.  I suspect your difficulty is how
> the 24 bit samples are represented in the WAV data and how to pack them into
> the Flac buffer?
> WAV samples are stored in either 8, 16, or 32 bit words, using the smallest
> word size that will fit the sample bits. The words are always little-endian
> formatted and samples smaller than the word size are padded with zero bits.
> Samples are stored with the channels interleaved.
> There are two formats to construct the buffer to be submitted to the Flac
> encoder.  The sample program uses the interleaved format which is submitted to
> FLAC__stream_encoder_process_interleaved().  In this format, multiple channels
> are all contained in the same buffer, with the the sample values for each
> channel arranged one after the other, followed by the values for all the
> channels of the next sample, etc.  Aka interleaved.  The other format is
> non-interleaved, where the samples for each channel are stored in separate
> buffers, and an array of those buffers is passed to
> FLAC__stream_encoder_process().  Use whichever is more convenient for you to
> construct from your input data.  Note that the channel order for Flac is not
> the same as for WAVE, although they happen to match for 2 channels.
> Each sample value (ie. the 8-24 bits representing a single channel for a single
> sample) is constructed by storing the bits in the low order (the documentation
> calls it "right-justified") of the smallest word that will contain them.  In
> the specific case of 24-bit samples, they need to be stored in the four bytes
> of an int32 with the most significant byte being zero.  This may look identical
> to the WAVE input, but the endianness is native instead of little-endian so it
> isn't safe to simply copy a WAVE sample into the Flac buffer unless you can
> guarantee you are on a little-endian platform.
> A cross-platform 24-bit sample packing into a FLAC__int32 would look something
> like this:
> input_buffer[sample * 3 + 2] << 16 |
> input_buffer[sample * 3 + 1] << 8 |
> input_buffer[sample * 3 + 0]
> Or you may choose a different method for mapping the sample words from WAVE to
> Flac. The sample word sizes should match and the interleaved buffer formats
> should match (for two channels, not for larger channel counts), only the
> endianness of each word is different. You may even write different code for the
> two endianness cases, which would probably be more efficient.
> --ian

Based on this, the code I wrote to fill the pcm buffer looks like this:

pcm[i] = (FLAC__int32)buffer[3*i+2];
pcm[i] <<= 8;
pcm[i] |= (FLAC__int32)buffer[3*i+1];
pcm[i] <<= 8;
pcm[i] |= (FLAC__int32)buffer[3*i];

Thanks for your help.

More information about the flac-dev mailing list