IPB

Welcome Guest ( Log In | Register )

 
Reply to this topicStart new topic
16 bits FLAC file data to 32 bit float buffer for CPU processing
Rodion
post Mar 8 2014, 13:58
Post #1





Group: Members
Posts: 2
Joined: 8-March 14
Member No.: 114881



Hello.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 :

CODE
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 (
                                                                                                              /( ( ( FLAC__int16 ) buffer [ 0 ] [ i ] ) >> 8 ) & 0xff +
                                                                                                              ( ( ( FLAC__int16 ) buffer [ 0 ] [ i ] ) << 8 ) & 0xff00/
                                                                                                              ( ( ( FLAC__int16 ) buffer [ 0 ] [ i ] ) ) & 0xff +
                                                                                                              ( ( ( FLAC__int16 ) buffer [ 0 ] [ i ] ) ) & 0xff00
                                                                                                            ) / 65535.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 too 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 ++ ?
Go to the top of the page
+Quote Post
lithopsian
post Mar 8 2014, 15:01
Post #2





Group: Members
Posts: 221
Joined: 27-February 14
Member No.: 114718



You shouldn't have to do any more than cast each sample from int to float. You'll have to do it sample by sample and into a larger buffer, since the floats are bigger.

This post has been edited by lithopsian: Mar 8 2014, 15:04
Go to the top of the page
+Quote Post
lvqcl
post Mar 8 2014, 15:21
Post #3





Group: Developer
Posts: 3436
Joined: 2-December 07
Member No.: 49183



CODE
FloatFLACDecodingData.LOut[FloatFLACDecodingData.WriteAddress + i] = ((float) buffer[0][i]) / 32768.0f;





Also, relevant link: http://en.wikipedia.org/wiki/Programming_by_permutation
Go to the top of the page
+Quote Post
Rodion
post Mar 8 2014, 17:36
Post #4





Group: Members
Posts: 2
Joined: 8-March 14
Member No.: 114881



QUOTE (lvqcl @ Mar 8 2014, 16:21) *
CODE
FloatFLACDecodingData.LOut[FloatFLACDecodingData.WriteAddress + i] = ((float) buffer[0][i]) / 32768.0f;


Also, relevant link: http://en.wikipedia.org/wiki/Programming_by_permutation


Yes, thank you; doing exactly so solved the problem; output range of audio system is in [ - 1.0f, 1.0f ] range and, it seems, that FLAC data is already signed, so there is need to just divide it by half of MAX_UINT16 and everything works good. It seems that approaches like this ( where I thought that FLAC data is unsigned and moved it from [ 0.0f, 1.0f ] range to [ - 1.0f, 1.0f ] range ) :

CODE
FloatFLACDecodingData.LOut [ FloatFLACDecodingData.WriteAddress + i ]                         = ( float ( DWORDChannelDataBuffer [ i ] ) / 65535.0f - 0.5f ) * 2.0f;


have given clipping and that caused unnatural sound. So, thank you again and issue is resolved.
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 User(s) are reading this topic (1 Guests and 0 Anonymous Users)
0 Members:

 



RSS Lo-Fi Version Time is now: 24th November 2014 - 23:56