How to convert pcm samples in byte array as floating point numbers in the range -1.0 to 1.0 and back?

后端 未结 2 1496
轮回少年
轮回少年 2020-12-02 08:18

The resampling algorithm i use expects float array containing input samples in the range -1.0 to 1.0 . The audio data is 16 bit

2条回答
  •  一整个雨季
    2020-12-02 09:13

    16 bit PCM has a range - 32768 to 32767. So, multiply each of your PCM samples by (1.0f/32768.0f) into a new array of floats, and pass that to your resample.

    Going back to float after resampling, multiply by 32768.0, saturate (clip anything outside the range - 32768 to 32767), round (or dither as Björn mentioned) and then cast back to short.

    Test code that shows conversion forward and back using multiplies with no bit errors:

    // PcmConvertTest.cpp : Defines the entry point for the console application.
    //
    
    #include 
    #include 
    #include 
    #define SZ 65536
    #define MAX(x,y) ((x)>(y)) ? (x) : (y)
    #define MIN(x,y) ((x)<(y)) ? (x) : (y)
    int main(int argc, char* argv[])
    {
      int16_t *pIntBuf1 = new int16_t[SZ];
      int16_t *pIntBuf2 = new int16_t[SZ];
      float   *pFloatBuf = new float[SZ];
    
      // Create an initial short buffer for testing
      for( int i = 0; i < SZ; i++) {
        pIntBuf1[i] = (int16_t)(-32768 + i);
      }
    
      // Convert the buffer to floats. (before resampling)
      const float div = (1.0f/32768.0f);
      for( int i = 0; i < SZ; i++) {
        pFloatBuf[i] = div * (float)pIntBuf1[i];
      }
    
      // Convert back to shorts
      const float mul = (32768.0f);
      for( int i = 0; i < SZ; i++) {
        int32_t tmp = (int32_t)(mul * pFloatBuf[i]);
        tmp = MAX( tmp, -32768 ); // CLIP < 32768
        tmp = MIN( tmp, 32767 );  // CLIP > 32767
        pIntBuf2[i] = tmp;
      }
    
      // Check that the conversion went int16_t to float and back to int for every PCM value without any errors.
      assert( 0 == memcmp( pIntBuf1, pIntBuf2, sizeof(int16_t) * SZ) );
    
      delete pIntBuf1;
      delete pIntBuf2;
      delete pFloatBuf;
      return 0;
    }
    

提交回复
热议问题