Re: How metering is calculated...
Re: How metering is calculated...
- Subject: Re: How metering is calculated...
- From: James McCartney <email@hidden>
- Date: Mon, 1 Mar 2010 15:11:41 -0800
There is also the issue of meter ballistics. A buffer to buffer reporting of RMS gain without any attack/decay smoothing would be too jittery for a user to be able to take a sensible reading from.
On Mar 1, 2010, at 11:51 AM, Brian Willoughby wrote:
>
> 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
_______________________________________________
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