// I2S MEMS microphone level maths (RMS -> dBFS) — PURE LOGIC. // // ESP-IDF-free by design: no I2S, no esp_err_t, no logging. Only // / and in the .c, so it compiles and is // testable on a host with plain gcc (see ../test/). `mems_mic.c` does the // I2S read and calls in here for the arithmetic. // // The INMP441 family outputs 24-bit signed PCM, MSB-first, left-justified // in a 32-bit I2S slot (Philips/standard I2S timing). The right-shift-by-8 // used below to recover the 24-bit sample from the 32-bit slot, and the // dBFS reference level (2^23, a 24-bit signed sample's full-scale // magnitude), are the commonly-documented values for this exact mic family // — but "commonly documented" is not "verified against this specific // board." Host tests prove the arithmetic (full scale reads ~0 dBFS, // silence reads the floor and never -inf/NaN); they cannot prove the shift // amount matches this module revision's real bit alignment. #pragma once #include #include #ifdef __cplusplus extern "C" { #endif // dBFS reference: full-scale magnitude of a 24-bit signed sample. #define MEMS_FULL_SCALE_24BIT (8388608.0) // 2^23 // Level reported for a true-silent (or sub-LSB) input, and the clamp // applied to anything quieter. #define MEMS_DBFS_FLOOR (-120.0) // RMS over a block of raw 32-bit I2S slots. The mic's 24-bit sample is // left-justified in the 32-bit slot -- shift right 8 to recover it before // squaring, so the magnitude lines up with MEMS_FULL_SCALE_24BIT. // Returns 0.0 for an empty block. double mems_level_rms(const int32_t *samples, size_t n_samples); // dBFS: 20*log10(rms / full_scale). A true-silent input gives rms=0, // which is -inf in dB -- clamp to a floor rather than emit a value the // JSON encoder/backend can't handle. double mems_level_dbfs(double rms); #ifdef __cplusplus } #endif