Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iPhone - how to measure amplitude of a PCM coded signal

Tags:

iphone

audio

pcm

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

like image 429
Matthias Schorer Avatar asked Jan 30 '10 10:01

Matthias Schorer


2 Answers

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
like image 53
Paul R Avatar answered Oct 13 '22 07:10

Paul R


AurioTouch is the right example to look at. Unfortunately the code is just terrible. Make sure that you only use it to get to know the concepts behind working with the RemoteIO audio unit.

The actual drawing of the waveform is happening right in the renderProc callback which is called by CoreAudio when PCM data becomes available. Look at PerformThru() in aurioTouchAppDelegate.mm:197... further down, in line 237

SInt8 *data_ptr = (SInt8 *)(ioData->mBuffers[0].mData);

... that's where the actual PCM data is accessed. This is the data you would need to analyze in order to get peak/average power of the signal.

like image 29
VoidPointer Avatar answered Oct 13 '22 09:10

VoidPointer