1
$\begingroup$

I'm trying to write a program that takes values from a MEMS microphone and calculates the dB of the incoming audio data.

The microphone i'm using is this: https://www.mouser.es/datasheet/2/218/ph0645lm4h-b-datasheet-rev-c-1525723.pdf using the I2S protocol, 24 bits signed integers.

The problem i have is that my dB SPL calculations are reading at 80 dB SPL at silence whereas my sound level meter reads around 30/40 dB(A).

Here is how i'm calculating the db SPL of the microphone input:

#define DC_OFFSET 419430

// this int32_t contains a 24 bit signed integer
int32_t sample = GetSample();

// Remove the DC offset.
sample = sample + DC_OFFSET;

sample = sqrt(pow(sample, 2));
double sampleNormalized = ((double)(sample) / 8388607);

// Convert the normalized samples to dB FS
double dbFS = 20.0 * log10(sampleNormalized);
double dbSPL = dbFS + 120.0;

Why do my readings read from 80 dB SPL whereas my sound level meter reads from 30/40 dB(A)?

UPDATE

Now my GetSample() function returns a signed 18 bit values, a few test samples results in these values, before DB offset adjustment:

  1. 78528
  2. 77376
  3. 73472
  4. 80384
  5. 79872
  6. 83648

DC offset defined as (+-100 5%), max value of 18 bits is 131071, therefore DC offset is (131071 * 0.05) = 6553.0.

When i pass it through this algorithm to convert it to dBSPL, the values now come out even higher than before, but the value responds how it should.

double ref = 131071.0;
double dc_offset = ref * 0.05;

// read 18 bit signed value
int32_t sample = GetSample(); // 18 bits wide.

// remove the dc offset.
double adjustedSample = sample - dc_offset;
adjustedSample = fabs(adjustedSample);

// normalize. the sample to the range 0.0 to 1.0.
double sampleNormalized = ((double)(adjustedSample) / ref);

// map the range from 0.0->1.0 to -1.0->1.0.
sampleNormalized -= 0.5;

sampleNormalized = abs(sampleNormalized);

// convert the normalized samples to dB FS
double dbFS = 20.0 * log10(sampleNormalized);
double dbSPL = dbFS + 120.0;

I'm still calculating db SPL values that are 88 dB SPL at quiet background, but the value actually responds correctly, i will apply the A filter as @Max posted and return the results afterwards.

$\endgroup$
  • 1
    $\begingroup$ What kind of values the GetSample returns? Why is it only a 24-bit integer? The I2S protocol uses 32 bits per sample, and microphone will only send highest 18 bits and set the LSBs to zero. $\endgroup$ – Justme Mar 20 at 9:15
  • $\begingroup$ "sample = sample + DC_OFFSET" you are adding or removing DC_OFFSET?. Also, "sample = sqrt(pow(sample, 2));" you are just raising to power of 2 and taking its square-root. Shouldn't you divide by 2 before taking sqrt? $\endgroup$ – jithin Mar 20 at 9:28
  • $\begingroup$ The equation for SPL is 10*log10(p^2), which translates to 20*log10(p). In your case you are doing both: 20*log10(p^2). So I guess this explains why you get double the value. $\endgroup$ – jojek Mar 20 at 9:41
  • $\begingroup$ No, he is not doing both. He is doing sqrt(pow())which translates to abs(), so 20*log10() is correct. $\endgroup$ – Max Mar 20 at 9:48
  • $\begingroup$ @justme you are absolutely correct, i thougt the numbers were 24 bits wide. $\endgroup$ – Richard Bamford Mar 20 at 11:34
2
$\begingroup$

Your calculations are correct, although you should do some kind of sliding average over a few hundred samples or so. The problem seems to be that the sound level meter employs an A-weighting, while your code does not. If there is low frequency noise in your measurement environment, the readings at "silence" can easily differ by 40-50dB. Try measuring a test tone at 1kHz, results should be closer together. Also, have a look at

https://en.wikipedia.org/wiki/A-weighting

You can see the huge low frequency differences there.

| improve this answer | |
$\endgroup$
  • $\begingroup$ Yes you are correct, my minimum value is around 88 dB SPL, i need to apply the A-weighting in order to re-adjust the values. Thank you. $\endgroup$ – Richard Bamford Mar 20 at 16:32
  • $\begingroup$ Another quesiton here, if i do a sliding average over samples, wouldn't that change the sample rate? $\endgroup$ – Richard Bamford Mar 24 at 13:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.