Skip to content

Commit

Permalink
member cleanup and replace defines with constexpr
Browse files Browse the repository at this point in the history
  • Loading branch information
tcsullivan committed Apr 13, 2024
1 parent b6c80b0 commit 4d93d30
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 55 deletions.
70 changes: 30 additions & 40 deletions noisemeter-device/spl-meter.cpp
Original file line number Diff line number Diff line change
@@ -1,66 +1,56 @@
#include "board.h"
#include "sos-iir-filter.h"
#include "spl-meter.h"

#include <cmath>
#include <cstdint>
#include <ctime>
#include <driver/i2s.h> // ESP32 core

#include "board.h"
#include "sos-iir-filter.h"
static constexpr auto LEQ_PERIOD = 1.f; // second(s)
static constexpr auto SAMPLES_LEQ = SPLMeter::SAMPLE_RATE * LEQ_PERIOD;

static constexpr auto& WEIGHTING = A_weighting; // Also avaliable: 'C_weighting' or 'None' (Z_weighting)
static constexpr auto& MIC_EQUALIZER = SPH0645LM4H_B_RB; // See below for defined IIR filters or set to 'None' to disable

//
// Constants & Config
//
#define LEQ_PERIOD 1 // second(s)
#define WEIGHTING A_weighting // Also avaliable: 'C_weighting' or 'None' (Z_weighting)

// NOTE: Some microphones require at least DC-Blocker filter
#define MIC_EQUALIZER SPH0645LM4H_B_RB // See below for defined IIR filters or set to 'None' to disable
#define MIC_OFFSET_DB 0 // Default offset (sine-wave RMS vs. dBFS). Modify this value for linear calibration

// Customize these values from microphone datasheet
#define MIC_SENSITIVITY -26.f // dBFS value expected at MIC_REF_DB (Sensitivity value from datasheet)
#define MIC_REF_DB 94.f // Value at which point sensitivity is specified in datasheet (dB)
#define MIC_BITS 24 // valid number of bits in I2S data
#define MIC_CONVERT(s) (s >> (SAMPLE_BITS - MIC_BITS))

//
// Sampling
//
#define SAMPLES_LEQ (SAMPLE_RATE * LEQ_PERIOD)
#define DMA_BANK_SIZE (SAMPLES_SHORT / 16)
#define DMA_BANKS 32
static constexpr auto MIC_BITS = 24u; // valid number of bits in I2S data
static constexpr auto MIC_SENSITIVITY = -26.f; // dBFS value expected at MIC_REF_DB (Sensitivity value from datasheet)
static constexpr auto MIC_REF_DB = 94.f; // Value at which point sensitivity is specified in datasheet (dB)
static constexpr auto MIC_OVERLOAD_DB = 120.f; // dB - Acoustic overload point
static constexpr auto MIC_NOISE_DB = 29.f; // dB - Noise floor
static constexpr auto MIC_OFFSET_DB = 0.f; // Default offset (sine-wave RMS vs. dBFS). Modify this value for linear calibration

// Calculate reference amplitude value at compile time
constexpr auto MIC_REF_AMPL = std::pow(10.f, MIC_SENSITIVITY / 20.f) * ((1 << (MIC_BITS - 1)) - 1);
static constexpr auto MIC_REF_AMPL = std::pow(10.f, MIC_SENSITIVITY / 20.f) * ((1 << (MIC_BITS - 1)) - 1);

void SPLMeter::initMicrophone() noexcept
{
const i2s_config_t i2s_config = {
const i2s_config_t SPLMeter::i2s_config = {
mode: i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX),
sample_rate: SAMPLE_RATE,
bits_per_sample: i2s_bits_per_sample_t(SAMPLE_BITS),
bits_per_sample: i2s_bits_per_sample_t(SPLMeter::SAMPLE_BITS),
channel_format: I2S_FORMAT,
communication_format: i2s_comm_format_t(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB),
intr_alloc_flags: ESP_INTR_FLAG_LEVEL1,
dma_buf_count: DMA_BANKS,
dma_buf_len: DMA_BANK_SIZE,
dma_buf_count: 32,
dma_buf_len: SPLMeter::SAMPLES_SHORT / 16u,
use_apll: true,
tx_desc_auto_clear: false,
fixed_mclk: 0,
mclk_multiple: I2S_MCLK_MULTIPLE_DEFAULT,
bits_per_chan: I2S_BITS_PER_CHAN_DEFAULT,
};
};

// I2S pin mapping
const i2s_pin_config_t pin_config = {
const i2s_pin_config_t SPLMeter::pin_config = {
mck_io_num: -1, // not used
bck_io_num: I2S_SCK,
ws_io_num: I2S_WS,
data_out_num: -1, // not used
data_in_num: I2S_SD
};
};

constexpr std::int32_t SPLMeter::micConvert(std::int32_t s)
{
return s >> (SAMPLE_BITS - MIC_BITS);
}

void SPLMeter::initMicrophone() noexcept
{
i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL);
i2s_set_pin(I2S_PORT, &pin_config);

Expand All @@ -76,7 +66,7 @@ std::optional<float> SPLMeter::readMicrophoneData() noexcept
// using the same buffer (assumed sample size is same as size of float),
// to save a bit of memory
for (auto& s : samples)
s.f = MIC_CONVERT(s.i);
s.f = micConvert(s.i);

// Apply equalization and calculate Z-weighted sum of squares,
// writes filtered samples back to the same buffer.
Expand Down Expand Up @@ -113,7 +103,7 @@ std::optional<float> SPLMeter::readMicrophoneData() noexcept
}
}

void SPLMeter::i2sRead()
void SPLMeter::i2sRead() noexcept
{
// Block and wait for microphone values from I2S
//
Expand Down
32 changes: 17 additions & 15 deletions noisemeter-device/spl-meter.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,42 @@

#include <array>
#include <cstdint>
#include <driver/i2s.h>
#include <optional>

#define SAMPLE_RATE 48000 // Hz, fixed to design of IIR filters
#define SAMPLE_BITS 32 // bits
#define SAMPLES_SHORT (SAMPLE_RATE / 8) // ~125ms

#define MIC_OVERLOAD_DB 120.f // dB - Acoustic overload point
#define MIC_NOISE_DB 29.f // dB - Noise floor

class SPLMeter
{
static_assert(sizeof(float) == sizeof(std::int32_t));
union sample_t {
std::int32_t i;
float f;
};

public:
static constexpr auto SAMPLE_RATE = 48000u;

// Prepares I2S Driver and mic config.
void initMicrophone() noexcept;

// Reads data to Microphones buffer
std::optional<float> readMicrophoneData() noexcept;

private:
// Buffer for block of samples
union sample_t {
std::int32_t i;
float f;
};
static_assert(sizeof(float) == sizeof(std::int32_t));

static constexpr auto SAMPLE_BITS = sizeof(sample_t) * 8u;
static constexpr auto SAMPLES_SHORT = SAMPLE_RATE / 8u;
static const i2s_config_t i2s_config;
static const i2s_pin_config_t pin_config;

alignas(4)
std::array<sample_t, SAMPLES_SHORT> samples;

// Sampling accumulators
unsigned Leq_samples = 0;
float Leq_sum_sqr = 0;

void i2sRead();
void i2sRead() noexcept;

static constexpr std::int32_t micConvert(std::int32_t s);
};

#endif // SPL_METER_H
Expand Down

0 comments on commit 4d93d30

Please sign in to comment.