131 lines
4.1 KiB
C++
131 lines
4.1 KiB
C++
#pragma once
|
|
#include "lasp_biquadbank.h"
|
|
#include "lasp_filter.h"
|
|
#include <memory>
|
|
#include <optional>
|
|
|
|
/**
|
|
* @brief Sound Level Meter implementation that gives a result for each
|
|
* channel. A channel is the result of a filtered signal
|
|
*/
|
|
class SLM {
|
|
/**
|
|
* @brief A, C or Z weighting, depending on the pre-filter installed.
|
|
*/
|
|
std::unique_ptr<Filter> _pre_filter;
|
|
|
|
/**
|
|
* @brief Bandpass filters for each channel
|
|
*/
|
|
std::vector<std::unique_ptr<Filter>> _bandpass;
|
|
/**
|
|
* @brief Storage for the single-pole low-pass filter coefficient based on
|
|
* the Fast / Slow time constant. < 0 means the filter is disabled.
|
|
*/
|
|
d _alpha = -1;
|
|
vd _sp_storage;
|
|
|
|
d Lref; /// Reference value for computing decibels
|
|
us downsampling_fac; /// Every x'th sample is returned.
|
|
us cur_offset = 0; /// Storage for offset point in input arrays
|
|
///
|
|
public:
|
|
/**
|
|
* @brief Public storage for the mean of the square of the signal.
|
|
*/
|
|
vd Pm;
|
|
/**
|
|
* @brief Public storage for the maximum signal power, after single pole
|
|
* low-pass filter.
|
|
*/
|
|
vd Pmax; /// Storage for maximum computed signal power so far.
|
|
/**
|
|
* @brief Public storage for the peak signal power, before single pole
|
|
* low-pass filter.
|
|
*/
|
|
vd Ppeak;
|
|
|
|
us N = 0; /// Counter for the number of time samples counted that came
|
|
/// in;
|
|
|
|
/**
|
|
* @brief Initialize a Sound Level Meter
|
|
*
|
|
* @param fs Sampling frequency [Hz]
|
|
* @param Lref Level reference, used to scale to proper decibel units (dB
|
|
* SPL / dBV, etc)
|
|
* @param downsampling_fac Every 1/downsampling_fac value is returned from
|
|
* compute()
|
|
* @param tau Time consant of level meter
|
|
* @param pre_filter The pre-filter (Typically an A/C frequency weighting
|
|
* filter)
|
|
* @param bandpass The parallel set of bandpass filters.
|
|
*/
|
|
SLM(const d fs, const d Lref, const us downsampling_fac, const d tau,
|
|
std::unique_ptr<Filter> pre_filter,
|
|
std::vector<std::unique_ptr<Filter>> bandpass);
|
|
|
|
/**
|
|
* @brief Convenience function to create a Sound Level meter from Biquad
|
|
* filters only.
|
|
*
|
|
* @param fs Sampling frequency [Hz]
|
|
* @param Lref Level reference, used to scale to proper decibel units (dB
|
|
* SPL / dBV, etc)
|
|
* @param downsampling_fac Every 1/downsampling_fac value is returned from
|
|
* compute()
|
|
* @param tau Time consant of level meter
|
|
* @param pre_filter_coefs Biquad filter coefficients for pre-filter
|
|
* @param bandpass_coefs Biquad filter coeffiecients for bandpass filter
|
|
*
|
|
* @return Sound Level Meter object
|
|
*/
|
|
static SLM fromBiquads(const d fs, const d Lref, const us downsampling_fac,
|
|
const d tau, const vd &pre_filter_coefs,
|
|
const dmat &bandpass_coefs);
|
|
/**
|
|
* @brief Convenience function to create a Sound Level meter from Biquad
|
|
* filters only. No pre-filter, only bandpass.
|
|
*
|
|
* @param fs Sampling frequency [Hz]
|
|
* @param Lref Level reference, used to scale to proper decibel units (dB
|
|
* SPL / dBV, etc)
|
|
* @param downsampling_fac Every 1/downsampling_fac value is returned from
|
|
* compute()
|
|
* @param tau Time consant of level meter
|
|
* @param bandpass_coefs Biquad filter coeffiecients for bandpass filter
|
|
*
|
|
* @return Sound Level Meter object
|
|
*/
|
|
static SLM fromBiquads(const d fs, const d Lref, const us downsampling_fac,
|
|
const d tau, const dmat &bandpass_coefs);
|
|
|
|
~SLM();
|
|
|
|
/**
|
|
* @brief Reset state related to samples acquired. All filters reset to zero.
|
|
* Start again from no history.
|
|
*/
|
|
void reset();
|
|
|
|
SLM(const SLM &o) = delete;
|
|
SLM &operator=(const SLM &o) = delete;
|
|
SLM(SLM &&o) = default;
|
|
|
|
/**
|
|
* @brief Run the sound level meter on given input data. Return downsampled
|
|
* level data for each filterbank channel.
|
|
*
|
|
* @param input Raw input data
|
|
*
|
|
* @return Filtered level data.
|
|
*/
|
|
dmat run(const vd &input);
|
|
vd Lpeak() const { return 10*arma::log10(Ppeak/Lref);};
|
|
vd Leq() const { return 10*arma::log10(Pm/Lref);};
|
|
vd Lmax() const { return 10*arma::log10(Pmax/Lref);};
|
|
|
|
private:
|
|
vd run_single(const us i,d* inout,const us size);
|
|
};
|