Audio Codec Shield output as dB

Hi,

we are waiting for Audio Codec Shield to be shipped to our lab. The product webpage is at audio codec sheild for arduino and maple | Open Music Labs

What we will be trying to do is to have a microphone giving input to this board and have the output measured in dB.

Before to buy this shield, we had only the microphone MAX4466 giving output directly in the sketch, but this way was judged not trustable as the Arduino YUN can't elaborate sound up to 44 kHz (it is up to 10 kHz).

We could not find any document on their website nor anywhere in forums.

Does anyone have an idea how to proceed or some documents addressing us to the solution?

Regards
Fabio

Before to buy this shield, we had only the microphone MAX4466 giving output directly in the sketch, but this way was judged not trustable as the Arduino YUN can’t elaborate sound up to 44 kHz (it is up to 10 kHz).

That is a very odd statement. Why can you not trust the amplitude of the sound samples at a sample rate of 10KHz. This will allow any sample frequency up to 5KHz.

The YUN is a hybrid board consisting of a traditional Arduino and a Linux box.

What we will be trying to do is to have a microphone giving input to this board and have the output measured in dB.

dBs in relationship to what? A decibel is a ratio so you will get the output of the microphone as a ratio to what?

What we will be trying to do is to have a microphone giving input to this board and have the output measured in dB.

You’ll need to calibrate it* using a known-good SPL meter and a test-tone or pink or white noise.

Now that you have a reference, you can calculate dB relative to that reference: dB = 20log(ADCx/ADCRef)[/b].
If 92dB was 500 and the new reading is 250, we would calculate -6dB. So, we have 92 - 6 = 89dB SPL.
Note that SPL measurements are normally averaged and [u]weighted[/u]. That’s difficult to do with a homemade SPL meter so your readings may differ from a real SLP meter, even after calibration.
* If you have the sensitivity specs for the microphone you can calculate the voltage (including the gain from the preamp) and make the dB SPL calculation from that, but you may not find the specs, and there is a tolerance and your device should be calibrated.
** Since you’re reading a sound wave, you’ll have to decide if you want to read the peak, average, or RMS.
*** Of course, once you have a corresponding SPL and ADC reading, you can calculate a new reference level to use in your software. For example, you might want to use a reference of 0dB, or 100dB, or whatever is convenient. Or, you might want to use an ADC reading of 1000 as your reference, etc.

Hi,

thanks for your replies. Maybe I explained the whole thing in the wrong way.

We had a working Arduino Yun with Microphone MAX4466, and we got the dB SPL through several lines of code of sketch.

As DVDdoug pointed out we went through voltage to dB calculation (taking sensitivity, RMS, etc, into account) and this part was written by a sound engineer so, I would say we are ok with that.

However, a real SPL meter showed us that the values were ok with stable and not changing sound levels but, when in real situations, with continuously changing sound levels, values coming from Arduino were totally different and no more trustable.

The sound engineer told us it was Arduino's fault as it just throws away too many measurements being not able to go over 10 kHz. This made sense to us (even if we are not expert at all of this stuff).
He suggested to buy the Arduino Codec Shield, which can read the audio at a better frequency.

The problem is that this shield comes with no how-to or starting guides at all. What we guess, is that the MAX4466 can be the input of this shield. Supposing this, we can't figure how to take the dB back from the audio shield output with Arduino.

Thanks
Fabio

However, a real SPL meter showed us that the values were ok with stable and not changing sound levels but, when in real situations, with continuously changing sound levels, values coming from Arduino were totally different and no more trustable.

I'm guess your weighting & averaging doesn't match the SPL meter.

The sound engineer told us it was Arduino's fault as it just throws away too many measurements being not able to go over 10 kHz.

Not Likely... With normal sound there's not much energy above 10kHz.

Try this experiment -
1. Play some regular music on a stereo system with an [u]equalizer[/u] or use computer audio player with an equalizer, such as [u]Windows media player[/u].

2. Set the equalizer to flat (or "off"' or "bypass") and watch the SPL meter.

3. Turn down the frequencies above 10kHz as much as possible and notice how the SPL readings don't change.

4. Return the frequencies above 10kHz to normal and reduce everything below 10kHz as much as possible. Notice how much quieter the sound is and notice how much the SPL readings drop.

Not Likely... With normal sound there's not much energy above 10kHz.

I quite agree, it looks like your sound engineer knows little about a digitised signal.

If you are only interested in the peak amplitude why not put a peak detector, sometimes called an envelope follower, in front of the A/D?

I wouldn't be so quick to call this engineer incompetent. He might be, and I'll agree the notion that the low sample rate is the blame seems suspicious. But then again, from only the very limited info in this thread, we know almost nothing about what's really been tried so far.

We haven't even seen those few lines of code that were running on Yun. There's all sorts of ways this could be done wrong, apart from a low sample rate.

Regarding the original question:

Does anyone have an idea how to proceed or some documents addressing us to the solution?

There's really 2 ways to understand and answer this question.

#1: Regarding use of the codec shield, you're almost certainly going to have to read the example code Open Music Labs publishes. It's not terribly complicated. I know, because I've read it. You can too. You're not going to find the detailed answers spelled out in web documentation. The knowledge you seek, about how to specifically get the data from this shield, is found in the code.

#2: The words "how to proceed" could also be read as inviting a discussion about what is the proper algorithm or even appropriate hardware to accomplish this task.

With that in mind, I'd like to ask you what specific algorithm you're going to use on those samples arriving at 44100 per second rate? Presumably you're doing something pretty simple right now, if it's just a few lines of code, right?

I'll also point out the very limited speed of 8 bit AVR-based Arduino and the huge overhead the codec shield takes, because those Arduino boards lack a proper I2S communication port. If you look at the codec shield library code, you'll see there is a very limited amount of time to execute instructions before work must begin again to receive the next incoming sample.

I'm going to refrain from suggesting anything better, at least until I know much more about what you're really doing.

Hi,

sure I am going to paste my code, begging your pardon if my English is not of the best…

So, basically, every 10 seconds I am calculating the dB SPL in this way, commenting the most important lines.

``````const long interval = 10000; // this is the interval where the Microphone MAX4466 is doing a new measurement
const int sampleWindow = 1000 ; // Sample window width in mS (50 mS = 20Hz), this is the window in milliseconds where the measurement is done

uint32_t timer = millis();

void misuraEinvio() {

unsigned long startMillis= millis();  // Start of sample window

unsigned int peakToPeak = 0;   // peak-to-peak level

unsigned int signalMax = 0;
unsigned int signalMin = 1024;

while (millis() - startMillis < sampleWindow)
{

if (sample < 1024)  // toss out spurious readings
{
if (sample > signalMax)
{
signalMax = sample;  // save just the max levels
}
else if (sample < signalMin)
{
signalMin = sample;  // save just the min levels
}
}
//SerialUSB.print(sample);
}
peakToPeak = signalMax - signalMin;  // max - min = peak-peak amplitude
double volts = ((peakToPeak * 3.3) / 1024) * 0.707;  // convert to RMS voltage
// as the mic sensitivity is -44 +-2 dB converted to V RMS / PA is 0.000631
double first = log10(volts/0.00631)*20;
// gain is 25, 94 is a PA expressed as dB Spl
double second = first + 94 - 44 - 25;
``````

Basically the engineer is stating that even if I take those 10 seconds down to 1 second let’s say (or even less) there would be no trustable measurement at all due to the 10 kHz sampling rate of Arduino.
Is he right?
Another question: is it really not possible to tweak Arduino Yun to make it able to go at a greater frequency than 10 kHz without burning its processor?
I repeat once more that for stable sounds the sketch works like a charm

Any help is greatly appreciated.
Regards

Fabio

Is he right?

No.

Another question: is it really not possible to tweak Arduino Yun to make it able to go at a greater frequency than 10 kHz without burning its processor?

I told you before the Yun is two boards, the input board is just like an Ardunio Uno. It is not a matter of processor speed it is a matter of the A/D settling time.
Yes you can speed things up by altering the prescaler rate in the A/D chain. BUT that is not your problem. Your problem is:-

1. A audio engineer who it seems from your reports not to know much about digitising sound.
2. The limited resolution of your A/D in the Arduino
3. The method you are extracting the peak amplitude from the samples
4. Your lack of filtering on the output producing .....

I repeat once more that for stable sounds the sketch works like a charm

Hi Grumpy_Mike,

1. I could agree, but as far as I know, the sampling of 10 kHz is not enough to produce results so precise as with 44.000 kHz sampling. So, how is he wrong about it?

2. Ok, could we tweak the code this to increase the prescaler rate, I suppose?

3. I am quite sure the methods are right. As proof I can mention this forum thread on Adafruit (Adafruit customer service forums • View topic - How to get Decibel sound level from MAX4466) where almost at the end of it, an admin member of Adafruit says the code is ok

4. I am aware of this. What do you suggest in order to solve this? Could you indicate some hardware you are aware of?

Fabio

Maybe we should back-up a bit...

You really can't expect the kind of results you'd get with a laboratory-calibrated SPL meter. And, I wouldn't be surprised if a "cheap" SPL meter is off by 6dB or more, depending on the nature of the sound you're measuring.

You should be able to build something that gives you an idea of relative loudness, but you can't expect something homemade to be "accurate".

What's the nature of the sound you're measuring? What's the purpose and how much accuracy do you need?

I haven't studied your code in detail but looks like you are taking the peak over a 10 second period. Is that what you want? Do you want the peak loudness? Of course, that's NOT what a normal SPL meter does...

And, you are not measuring/calculating RMS. The 0.707 factor is only true for a constant sine wave. You're calculating the approximate RMS value of the cycle with the highest peak. With normal audio, that could easily be 20dB greater than the true RMS (over a longer period of time). I assume your readings are generally higher than the SPL meters ?

A true [u]Root Mean Square[/u] calculation may not be practical on the Arduino, but you can do averaging or take a moving average.

However, a real SPL meter showed us that the values were ok with stable and not changing sound levels but, when in real situations, with continuously changing sound levels, values coming from Arduino were totally different and no more trustable.

What are you using for your "non-changing" signal? A sine wave? If so what frequency? Pink noise or white noise?

Is your real SPL meter A-Weighted?

1. I am aware of this. What do you suggest in order to solve this? Could you indicate some hardware you are aware of?

You don't need hardware to do this, you just take a running average of the last n results. That is what your "professional" system does and that this why the output indication is "steady" when you have changing noise.

1. I could agree, but as far as I know, the sampling of 10 kHz is not enough to produce results so precise as with 44.000 kHz sampling. So, how is he wrong about it?

Because the measurement you want to take is not affected by the sample rate. With the right envelope detector on the front end you could get a very accurate result with a sample rate of 10 per second, let alone 10K.

1. I am quite sure the methods are right.

See what Doug says, he is quite right the 0.707 is just silly. What you want to do if you want to do it properly is to take the square of each sample, add them all up, and take the square root of the result. That gives you the RMS value of the actual waveform you have not a sin wave, which you haven't.

Hi and again thank you for your kind replies!

yes, the fact of the interval of 10 seconds could be a problem. I can take it down to 1 second and see what happens.
This interval was chosen as we collect 360 mesurements in an array and then calculate the hourly LAEQ sending it to the server afterwards. We make the array then empty and start again collecting measurements. This is the logic.

Now, the professional tool used by the engineer revealed that with stable sounds (both white and pink noise) this is working.

BTW, with changing sounds we have a higher levels than the SPL meter says, that's true, however, no more than 6-7 dB to speak the truth.

All considered, do you think that by taking the interval to 1 could improve results? About RMS, this goes beyond my knowledge actually and I thought it was a constant at least for that measurement (1 second every 10 seconds).

The peak-to-peak is taken from the Adafruit sample and all the calculation was actually approved by their admins. So, forgive me, but i really thought we were ok like that.

How could I get better results with software only?

Last but not least, our purposes is to collect 24 LAEQs a day, send them to the server and calculate the night, daily and 24h LAEQ and finally compare these values with WHO and European Union recommended limits.

Thanks
Fabio

The peak-to-peak is taken from the Adafruit sample and all the calculation was actually approved by their admins

What do you mean by "approved by their admins"? Did these admins know what you were going to use the calculations for? You can have calculations in one context that will be fine, but totally rubbish in another context.

I once did some consultancy for a night club owner who had commissioned a sound system, specified the output power but thought it was not loud enough. His problem was that he did not understand what he was specifying.

There are many ways to express sound level and if you are going to " finally compare these values with WHO and European Union recommended limits", then you better do some research and find out what these values are expressed in, and how they are measured.

Last but not least, our purposes is to collect 24 LAEQs a day, send them to the server and calculate the night, daily and 24h LAEQ and finally compare these values with WHO and European Union recommended limits.

Anything related to regulatory requirements has to be periodically calibrated/validated by an independent lab.

A calibration lab probably won't calibrate anything "homemade".

And as you've discovered, if you calibrate it for pink noise it won't be properly calibrated for a constant tone, and vice-versa.

Grumpy_Mike:
See what Doug says, he is quite right the 0.707 is just silly.

I agree 100%. Multiplying peak-to-peak by 0.707 is only valid if the signals are always absolutely pure sine waves. For natural sounds, or anything that's not a pure sine wave, this is incorrect. The less the sound resembles a constant, unchanging, spectrally pure sine wave, the greater the error. Or ordinary real-world sound, the error will be large, and will fluctuate as the sound changes.

DVDdoug:
A true [u]Root Mean Square[/u] calculation may not be practical on the Arduino,

It's probably possible, but difficult, on 8 bit AVR. If one interrupt is serviced per sample, the amount of CPU overhead for merely acquiring the data without efficient DMA is probably a bigger limitation.

I can tell you true RMS on 16 bit, 44.1 kHz data on Teensy 3.2 running at 96 MHz (leveraging the Cortex-M4 DSP extensions) consumes approx 1% of the available CPU time. Here's the source code, if anyone's interested.