0
$\begingroup$

For a first approach on audio-sampling I'm currently working with the raspberry pi's pcm pins and MEMS-microphones, using the ALSA library.

A problem arises when I want to calculate dBFS from a buffer's rms-value because i have to assume that a sample can be as big as (2^32)/2. In order to obtain rms, I would have to square every single sample, some of which might not be computable due to their size.

What would be a good way of obataining the dBFS of a finite array of discrete values without causing overflows?

$\endgroup$

1 Answer 1

1
$\begingroup$

There are a few different ways:

  1. Use a fractional multiply or data types. Unfortunately that's not a standard "C" or "C++" instruction but most embedded processors do support it and have some sort of non-standard way to call it.
  2. Use a "long int" 64-bit integer data type, do a double precision multiply.
  3. Convert everything to floating point (float or double) before multiplying.
  4. Scale the numbers by $2^{-16}$ (arithmetic right shift by 16-bits) before squaring.

Option 1 is typically the "best" if your processor supports it as a native instruction. Option 4 is often "good enough" if you have half-way decent signal to noise ratio but that may depend on the specifics or you application and data.

Note on "fractional" data types: This is a fixed point type that is scaled so that the data range is assumed to be from -1 to +1, hence a multiply can never overflow. That's actually the most "natural" type for fixed point signal processing. Multiplying two 32-bit numbers yields a 64 bit result. The difference between an integer and fractional multiply is that the integer multiply keeps the lower 32 bit and the fractional keeps the higher 32 bit of the result.

Both integer and fractional format are subsets of the "Q" number format. See https://en.wikipedia.org/wiki/Q_(number_format). Loosely speaking integers are Q0 and fractionals are Q31(signed).

$\endgroup$
2
  • $\begingroup$ Question about method 3: Do you mean to simply convert or to actually scale every sample by 1/MAX_VALUE? Because doing so decreases the value of a sqaured sample, which occurs since the square of values between 1 and -1 is less than than the value itself $\endgroup$ Commented Mar 20, 2022 at 7:42
  • $\begingroup$ If you do this on floating point it doesn't matter. You can scale by any number that's convenient (for instance you can do this all directly in sound pressure units, i.e. Pascal). The key here is that floating point won't overflow regardless of how you scale it (within reason) $\endgroup$
    – Hilmar
    Commented Mar 21, 2022 at 11:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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