iPhone - how to measure amplitude of a PCM coded signal

Matthias Schorer picture Matthias Schorer · Jan 30, 2010 · Viewed 7.6k times · Source

here's my problem at hand:

  1. I need to analyze audio data in realtime to find out the amplitude of the signal
  2. I can't use the AudioQueue metering functionality because it has too much delay for detecting peaks
  3. I have studied the aurioTouch example..... however...

I simply don't understand how the PCM coded buffer is converted back to the waveform displayed in the oscilloscope view. It would be exactly this wavefore I want to analyze for amplitude.

In my callback when I analyze the buffer it only has 0 and -1 in it - when using NSLog(@"%d"). This makes sense I guess because it is PCM.

I can't find the place in aurioTouch where the magic of transforming the 0 / -1 stream into a waveform happens :-((

Also once I have the waveform in memory how do I analyze the amplitude and how to convert this reading into dB?

I don't want to use FFT because I am not interested in the frequency and I hope there are other ways.

Cheers

Mat

Answer

Paul R picture Paul R · Jan 30, 2010

Once you have a chunk of the waveform in memory then it's fairly easy to calculate magnitude values in dB (although you'll need to decide what you reference magnitude for 0 dB is). Typically if you want the kind of short term magnitude that you might see displayed on a VU meter then you need to rectify the instantaneous values of the waveform (you can use abs for this) and then pass these rectified values through a simple low pass filter with a time constant of the order of, say, 100 ms. To convert the values to dB you'll do this:

amplitude_dB = 20 * log10(amplitude) + calibration_dB;

where amplitude is the rectified and filtered magnitude, and calibration_dB is an offset to give you the correct amplitude for 0 dB, whatever that might be in your particular application (e.g. dB re full scale, or a calibrated dBV or dBm value).

A simple but effective low pass filter can be implemented as follows. This will be a single pole IIR (recursive) filter. Each output is dependent on the previous output value and the current input value. We have a constant factor, alpha, which effectively determines the time constant or cut-off frequency of this low pass filter.

y = alpha * x + (1.0 - alpha) * y_old;
y_old = y;
  • x = current input value
  • y = new output value
  • y_old = previous output value
  • alpha = constant which determines response of filter - a small positive number - try 0.001 to start off with and experiment