Search code examples
c#.netaudioaudio-streamingpcm

How to find audio power (db) in pcm stream (c#)


I have a pcm 16 bit stream and I need to know when the audio pass a specific power. Do I need the fft for this or I can know it in a simpler way?

Thanks


Solution

  • I think you need FFT.

    The following methods are available in a FFT. (Usually)

      /* Calculate normal power
    
       NumSamples : Number of sample 
       pReal : Real coefficient buffer 
       pImag : Imaginary coefficient buffer 
       pAmpl :  Working buffer to hold amplitude Xps(m) = | X(m)^2 | = Xreal(m)^2  + Ximag(m)^2</param>
        */ 
        public static void NormalPower(UInt32 NumSamples, Double[] pReal, Double[] pImag, Double[] pAmpl)
        {
            // Calculate amplitude values in the buffer provided
            for (UInt32 i = 0; i < NumSamples; i++)
            {
                pAmpl[i] = pReal[i]*pReal[i] + pImag[i]*pImag[i];
            }
        }
    
        /* Find Peak frequency in Hz
    
        NumSamples : Number of samples 
        pAmpl : Current amplitude 
        samplingRate : Sampling rate in samples/second (Hz) 
        index : Frequency index 
        <returns>Peak frequency in Hz</returns>
         * */
        public static Double PeakFrequency(UInt32 NumSamples, Double[] pAmpl, Double samplingRate, ref UInt32 index)
        {
            UInt32 N = NumSamples >> 1;   // number of positive frequencies. (numSamples/2)
            double maxAmpl = -1.0;
            double peakFreq = -1.0;
            index = 0;
    
            for (UInt32 i = 0; i < N; i++)
            {
                if ( pAmpl[i] > maxAmpl )
                {
                    maxAmpl = (double)pAmpl[i];
                    index = i;
                    peakFreq = (double)(i);
                }
            }
          return samplingRate * peakFreq / (double)(NumSamples);
        }
    

    And you can use them like this:

       FFT.Compute(_numSamples, RealIn, null, RealOut, ImagOut, false);
                   FFT.NormalPower(_numSamples / 2, RealOut, ImagOut, AmplOut);
    
                   double maxAmpl = (32767.0 * 32767.0);  //Max power used for 16 bit audio
                   int centerFreq = (Rate / 2);
                   for (int i = 0; i < NUM_FREQUENCY; ++i)
                   {
                       if (METER_FREQUENCY[i] > centerFreq)
                           _meterData[i] = 0;
                       else
                       {
                           var indice = (int)(METER_FREQUENCY[i] * _numSamples / Rate);
                           var metervalue = (int)(20.0 * Math.Log10(AmplOut[indice] / maxAmpl));
                           _meterData[i] = metervalue;
                       }
                   }
    

    Note: To get the sound intensity in dB the following formula is used:

    level = 20 Log (P2/P1)

    P1=Max Power

    P2=Current Power