On Sat, Mar 8, 2014 at 7:49 AM, Каримов Родион <rodionkari...@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@xiph.org > http://lists.xiph.org/mailman/listinfo/flac-dev >
_______________________________________________ flac-dev mailing list flac-dev@xiph.org http://lists.xiph.org/mailman/listinfo/flac-dev