dB SPL readings differ from external sound level meter? 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:


78528
77376
73472
80384
79872
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-&gt;1.0 to -1.0-&gt;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.
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.