   Audio samples to decibels
  I need to code some vu meters. For this, I have a bunch of raw audio samples -16 bit signed integers- and I need to get the average volume level, in decibels (my reference is +0 at max vol).I have looked at how some tools do this and, as far as I can tell, they are plain wrong.Audacity, for example, works internally with 32 bit floats; it has all samples normalized to -1..+1 and just do the RMS of each value, after applying this formula:value = 20. * log10(sample).I'd say this is absolutely wrong because, AFAIK, the amplitude of the sound wave generated by each two consecutive samples doesn't depends on the absolute values of any of those samples, just on the absolute value of the difference between them. So, adding 10000 to each sample won't modify the resulting sound (assuming there's no clipping, of course), but the decibels would go up.So, perhaps, a better formula would be;value = 20.* log10 (abs(sample - sample))Anyone here can tell if my reasoning is correct, and if not, why?
  You can assume that the audio is a zero-mean signal, meaning that your argument about adding 10000 to the sample values, while technically correct, is a non-issue.I would not calculate these levels on a per-sample basis. What you typically want is the power of the signal, which is energy integrated over time. So calculate a short-time power estimate of the signal instead. Use some simple averaging technique, such as a sliding window or a first order AR-process.A sliding window means you calculate the average power over the last N samples at any time instant. The power is e(n) = 1/N * sum from k=n to n-N+1 of e2(k).The AR-process is simple; for every a sample, calculate the power at sample n as e(n) = (1-g)*e(n-1) + g*x2(n), where g is a forgetting factor, typically on the order of 0.99 to 0.999.The window size, or the forgetting factor, defines the effective integration time. Play with it to achieve desired result. From here, you can calculate the power as P(n) = 10*log10 e(n).   ;  Note that reducing the filter to looking at a single sample -although probably a bad idea- results in Audacity's formula.;Quote:Original post by Brother BobA sliding window means you calculate the average power over the last N samples at any time instant. The power is e(n) = 1/N * sum from k=n to n-N+1 of e2(k).[...]From here, you can calculate the power as P(n) = 10*log10 e(n).Wait, I think this is quite the same I am already doing.If I have correctly understood your message, in the sliding window case I just have to calculate the average of the squared samples, right?Then I calculate the base 10 logarithm of this average, and multiply the result by 10.What I am doing, instead, is calculating the RMS average of the samples, which is the same as calculating the average of the squared samples, and then getting their square root.However, when I get the logarithm of the result, I multiply it by 20 instead of 10 which just cancels the square root.To make it clear:avg = SUM(sample * sample) / N  ; where N is the number of samplesThen your formula is, if I have understood it correctly:10 * log(avg) While mine is:20 * log(sqrt(avg)) = 10 * log (sqrt(avg)^2) = 10 * log(avg)Is this correct?Thank you very much, in any case.   ;Quote:Original post by ravengangrelIf I have correctly understood your message, in the sliding window case I just have to calculate the average of the squared samples, right?Correct.Quote:Original post by ravengangrelThen I calculate the base 10 logarithm of this average, and multiply the result by 10.What I am doing, instead, is calculating the RMS average of the samples, which is the same as calculating the average of the squared samples, and then getting their square root.However, when I get the logarithm of the result, I multiply it by 20 instead of 10 which just cancels the square root.Whether you should multiply by 10 or 20 depends on whether you have a linear or a square unit. Power, for example, is a square unit (sum of amplitudes squared), so you multiply by 10 when converting to dB. When you have a linear unit, you multiply by 20.Quote:Original post by ravengangrelTo make it clear:avg = SUM(sample * sample) / N  ; where N is the number of samplesThen your formula is, if I have understood it correctly:10 * log(avg) While mine is:20 * log(sqrt(avg)) = 10 * log (sqrt(avg)^2) = 10 * log(avg)Is this correct?Thank you very much, in any case.Yes, the RMS value is a linear unit so you multiply by 20, and you can cancel the square root are multiply by 10.   