[flac-dev] 16 bits FLAC file data to 32 bit float buffer for CPU processing
Stephen F. Booth
me at sbooth.org
Sat Mar 8 08:47:02 PST 2014
On Sat, Mar 8, 2014 at 7:49 AM, Каримов Родион <rodionkarimov at yandex.ru>wrote:
> I create FLAC file decoding, processing and playing program and have the
> following question : how to convert FLAC 16 bit file data to 32 bit float
> buffer for CPU processing? I've already inplemented sound playing and
> tested it with sine wave - it works without problems; I even made writing
> into decoding buffer values of sine wave, instead of decoded FLAC file
> data, and it also works without problems; now I try different approaches to
> convert FLAC 16 bits sound data to 32 bits float CPU buffer, but they give
> noise or sound with artefacts. I use Stream Decoder from FLAC C API and my
> write_callback is as follows :
>
I've used code like the following to convert decoded FLAC to normalized
floating point audio in the interval [-1,1):
float scaleFactor = (1L << ((((frame->header.bits_per_sample + 7) / 8) * 8)
- 1));
for(unsigned channel = 0; channel < frame->header.channels; ++channel) {
float *floatBuffer = /* target output channel buffer from somewhere */
for(unsigned sample = 0; sample < frame->header.blocksize; ++sample)
*floatBuffer++ = buffer[channel][sample] / scaleFactor;
}
If you don't want to normalize the audio you can just remove the division.
You're obviously on Windows but on Mac OS X this can be done efficiently
using the Accelerate framework's vDSP_vflt16() and vDSP_vsdiv(). I'm sure
there are comparable routines you could use if the above method is too slow.
Stephen
> FLAC__StreamDecoderWriteStatus write_callback ( const FLAC__StreamDecoder
> *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[],
> void * client_data ) {
> size_t i;
>
> BYTE * ChannelDataBuffer;
> WORD * WORDChannelDataBuffer;
> DWORD * DWORDChannelDataBuffer;
> int * IntChannelDataBuffer;
>
>
>
> if ( bps == 16 ) {
> ChannelDataBuffer = ( BYTE * ) buffer [ 0 ];
> WORDChannelDataBuffer = ( WORD * ) buffer [ 0 ];
> DWORDChannelDataBuffer = ( DWORD * ) buffer [ 0 ];
> IntChannelDataBuffer = ( int * ) buffer [ 0 ];
>
> for ( i = 0; i < frame -> header.blocksize; i++ ) {
> //FloatFLACDecodingData.LOut [ FloatFLACDecodingData.WriteAddress +
> i ] = ( 1.0f + ( float ) sin ( ( ( double ) (
> FloatFLACDecodingData.WriteAddress + i ) / ( double ) TABLE_SIZE ) * M_PI *
> 2.0 * 1.0 ) ) * 0.4f;
> //FloatFLACDecodingData.LOut [ FloatFLACDecodingData.WriteAddress +
> i ] = float ( ( FLAC__int16 ) buffer [ 0 ] [ i ] )
> * 65535.0f;
> //FloatFLACDecodingData.LOut [ FloatFLACDecodingData.WriteAddress +
> i ] = ( float ( ( FLAC__int16 ) buffer [ 0 ] [ i ]
> ) / 65535.0f - 0.5f ) * 2.0f;
> //FloatFLACDecodingData.LOut [ FloatFLACDecodingData.WriteAddress +
> i ] = ( float ( _byteswap_ushort ( ( FLAC__int16 )
> buffer [ 0 ] [ i ] ) ) / 65535.0f - 0.5f ) * 2.0f;
>
> //FloatFLACDecodingData.LOut [ FloatFLACDecodingData.WriteAddress +
> i ] = ( float ( WORDChannelDataBuffer [ i ] ) /
> 65535.0f - 0.5f ) * 2.0f;
> //FloatFLACDecodingData.LOut [ FloatFLACDecodingData.WriteAddress +
> i ] = ( float ( _byteswap_ushort (
> WORDChannelDataBuffer [ i ] ) ) / 65535.0f - 0.5f ) * 2.0f;
> FloatFLACDecodingData.LOut [ FloatFLACDecodingData.WriteAddress + i
> ] = ( float ( DWORDChannelDataBuffer [ i ] ) /
> 65535.0f - 0.5f ) * 2.0f;
> //FloatFLACDecodingData.LOut [ FloatFLACDecodingData.WriteAddress +
> i ] = ( float ( _byteswap_ulong (
> DWORDChannelDataBuffer [ i ] ) ) / 65535.0f - 0.5f ) * 2.0f;
>
> //FloatFLACDecodingData.LOut [ FloatFLACDecodingData.WriteAddress +
> i ] = ( float ( IntChannelDataBuffer [ i ] ) /
> 65535.0f - 0.5f ) * 2.0f;
>
> } //-for
>
> FloatFLACDecodingData.WriteAddress =
> FloatFLACDecodingData.WriteAddress + frame -> header.blocksize;
>
> }
>
> return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
>
> }
>
>
>
> The closes results are with looking on buffer variable as
> DWORDChannelDataBuffer ( IntChannelDataBuffer and ( FLAC__int16 ) buffer [
> 0 ] [ i ] give the same results ), but this approach anyway gives wrong
> sound - it is somehow to sharp and bright with some "hard edges"; other
> approaches give very strong noise and some of them give total mess. So, how
> to convert FLAC 16 bit data into 32 bits float data for CPU buffer, so that
> it will work in C ++ ?
> _______________________________________________
> flac-dev mailing list
> flac-dev at xiph.org
> http://lists.xiph.org/mailman/listinfo/flac-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.xiph.org/pipermail/flac-dev/attachments/20140308/897b17f8/attachment.htm
More information about the flac-dev
mailing list