Re: How metering is calculated...
Re: How metering is calculated...
- Subject: Re: How metering is calculated...
- From: Brian Willoughby <email@hidden>
- Date: Mon, 1 Mar 2010 11:51:53 -0800
On Mar 1, 2010, at 10:07, Grant Robinson wrote:
On Mon, Mar 1, 2010 at 10:38 AM, Brian Willoughby <email@hidden
> wrote:
You left out a critical aspect of your algorithm. The 'M' in RMS
stands for
Mean, but you don't mention how you are calculating the mean. I
suspect
this is where your problem lies.
From what I have read, RMS is the square root of the mathematical mean
of the sum of the values squared. So, for each channel, I do the
following:
float sum = 0.0;
while (looping) {
int16_t val = *data;
float normalVal = val / 32767.0;
sum += (normalVal * normalVal);
numSamples++;
}
float rms = sqrtf(sum/numSamples);
float power = 20*log10f(rms/base);
You basically have it right, except you still have no indication of
how many audio samples are involved in your loop. The size of the
buffer that is averaged will affect the result. You cannot simply use
the buffer size provided by the audio system, because that can be
different under certain conditions. In other words, numSamples cannot
vary or else your results will differ.
In order to emulate an analog meter, you must calculate the Mean value
over a specific amount of time. Typically, this is 300 milliseconds,
if I recall correctly. I cannot say what time duration Apple is using
for their meters, but 300 ms is probably a good starting point. Note
that you must account for the sample rate when calculating the
duration of the averaging, so your metering code must therefor adapt
to sample rate.
One thing to keep in mind is that if the buffers you're provided do
not evenly divide into 300 ms, then you will have to handle this
carefully. If you are calculating peak hold, then you'll have to find
a way to carry the 300 ms average across buffers, otherwise you might
miss a maximum that happens to fall in a time which spans two
buffers. Thankfully, you do not necessarily need to update the RMS
meter on every sample, so you can perhaps make some optimizations for
providing fewer results and thus saving on calculations. Keep in mind
that optimizations can cause your code to miss peak values, though.
Also, I am surprised that you mention 'normalized.' In my book,
that is a
verb, so I am concerned that you are normalizing the values, which
would
alter them. In other words, 'normalized' usually refers to a
process, so
you should be clear as to whether you are processing the values in
some way
at that stage.
From my understanding, raw 16-bit signed integer audio values are a
fixed-point number representing the voltage at the time the audio
stream was sampled. So, by normalizing, I mean turning it from a
fixed-point integer number into a float decimal number in the range
-1.0 to 1.0 (which you can see in the above calculation). Is that
more-or-less correct?
Perhaps I am being pedantic, but the music industry definition of
'normalize' is a process which searches for the maximum peak in a
selection of audio and then applies a gain to bring that peak to the
maximum possible value - i.e. full scale. But that would alter the
data before metering and you don't want to do that.
What you want, and what you're basically doing, is to 'convert'
whenever you start with integer and desire float.
In your specific case, the 32767.0 constant is incorrect. The correct
conversion value between integer and float is always a power of two,
no matter the bit depth. Thus, you should be using 32768.0 (if you
doubt this, the topic has been covered many, many times in the
archives of this mailing list).
If you were writing an AudioUnit or using CoreAudio's AudioFile
classes, then the conversion to float would be properly handled for
you. Looking back at your original message, I see that you're writing
this on Windows, so I suppose it is necessary for you to handle the
conversion yourself.
Good luck!
Brian Willoughby
Sound Consulting
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden