2

I am trying to get the dB level of incoming audio samples. On every video frame, I update the dB level and draw a bar representing a 0 - 100% value (0% being something arbitrary such as -20.0dB and 100% being 0dB.)

gdouble sum, rms;
sum = 0.0;
guint16 *data_16 = (guint16 *)amap.data;
for (gint i = 0; i < amap.size; i = i + 2)
{
    gdouble sample = ((guint16)data_16[i]) / 32768.0;
    sum += (sample * sample);
}
rms = sqrt(sum / (amap.size / 2));
dB = 10 * log10(rms);

This was adapted to C from a code sample, marked as the answer, from here. I am wondering what it is that I am missing from this very simple equation.

Answered: jacket was correct about the code loosing the sign, so everything ended up being positive. Also the code 10 * log(rms) is incorrect. It should be 20 * log(rms) as I am converting amplitude to decibels (as a measure of outputted power).

Community
  • 1
  • 1
Daniel L.
  • 437
  • 3
  • 15
  • Because I am an idiot, I forgot to describe what exactly the problem is. The dB value returned from this equation is always anywhere from +1 to +5, even for very quiet audio. – Daniel L. Sep 26 '15 at 00:17
  • The code looks correct so the problem is something subtle. Since dB is positive that means rms is coming out to be greater than 1. maybe sum is too large which would implicate the conversion to `gdouble` – jaket Sep 26 '15 at 00:55
  • Can't you use the level element or at least the math from it? – ensonic Sep 27 '15 at 09:49
  • may i please ask for code to read from the stream – Ossama Dec 21 '17 at 08:54

1 Answers1

3

The level element is best for this task (as @ensonic already mentioned) its intended for exactly what you need..

So basically you add to your pipe element called "level", then enable the messages triggering.

Level element then emits messages which contains values of RMS Peak and Decay. RMS is what you need.

You can setup callback function connected to such message event:

audio_level = gst_element_factory_make ("level", "audiolevel");
g_object_set(audio_level, "message", TRUE, NULL);
...
g_signal_connect (bus, "message::element", G_CALLBACK (callback_function), this);

bus variable is of type GstBus.. I hope you know how to work with buses

Then in callback function check for the element name and get the RMS like is described here

There is also normalization algorithm with pow() function to convert to value between 0.0 -> 1.0 which you can use to convert to % as you stated in your question.

nayana
  • 3,787
  • 3
  • 20
  • 51
  • Thanks for that last bit. I have a nice little bar being rendered out that gives a rough idea of what the dB level is. – Daniel L. Sep 28 '15 at 17:10
  • Just to clarify, "message" is deprecated, just use "post-messages", would edit but I have not enough points. – Ariel M. Jun 02 '22 at 23:05