2022-08-16 19:22:35 +00:00
|
|
|
#pragma once
|
|
|
|
#include "lasp_biquadbank.h"
|
|
|
|
#include "lasp_filter.h"
|
2023-06-10 13:47:52 +00:00
|
|
|
#include "lasp_thread.h"
|
2022-08-16 19:22:35 +00:00
|
|
|
#include <memory>
|
|
|
|
#include <optional>
|
|
|
|
|
2022-09-22 08:18:38 +00:00
|
|
|
/**
|
|
|
|
* \ingroup dsp
|
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
|
2022-08-16 19:22:35 +00:00
|
|
|
/**
|
|
|
|
* @brief Sound Level Meter implementation that gives a result for each
|
|
|
|
* channel. A channel is the result of a filtered signal
|
|
|
|
*/
|
|
|
|
class SLM {
|
2023-06-12 07:11:08 +00:00
|
|
|
GlobalThreadPool _pool;
|
2022-08-16 19:22:35 +00:00
|
|
|
/**
|
|
|
|
* @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;
|
|
|
|
|
2022-09-22 08:18:38 +00:00
|
|
|
d Lrefsq; /// Square of reference value for computing decibels
|
2022-08-16 19:22:35 +00:00
|
|
|
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.
|
|
|
|
*/
|
2022-09-22 08:18:38 +00:00
|
|
|
vd Pmax; /// Storage for maximum computed signal power so far.
|
2022-08-16 19:22:35 +00:00
|
|
|
/**
|
|
|
|
* @brief Public storage for the peak signal power, before single pole
|
|
|
|
* low-pass filter.
|
|
|
|
*/
|
|
|
|
vd Ppeak;
|
|
|
|
|
2022-09-22 08:18:38 +00:00
|
|
|
us N = 0; /// Counter for the number of time samples counted that came
|
|
|
|
/// in;
|
2022-08-16 19:22:35 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @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
|
2022-10-01 17:59:35 +00:00
|
|
|
* @param bandpass_coefs Biquad filter coefficients for bandpass filter. First axis isis the coefficient index, second axis is the filter index.
|
|
|
|
|
2022-08-16 19:22:35 +00:00
|
|
|
*
|
|
|
|
* @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
|
|
|
|
*
|
2022-09-22 08:18:38 +00:00
|
|
|
* @return Filtered level data for each filtered channel.
|
2022-08-16 19:22:35 +00:00
|
|
|
*/
|
|
|
|
dmat run(const vd &input);
|
2022-09-22 08:18:38 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Calculates peak levels measured for each filter channel. The peak
|
|
|
|
* level is just the highest instantaneous measured power value.
|
|
|
|
*
|
|
|
|
* @return vector of peak level values
|
|
|
|
*/
|
|
|
|
vd Lpeak() const { return 10 * arma::log10(Ppeak / Lrefsq); };
|
|
|
|
/**
|
|
|
|
* @brief Calculates equivalent (time-averaged) levels measured for each
|
|
|
|
* filter channel
|
|
|
|
*
|
|
|
|
* @return vector of equivalent level values
|
|
|
|
*/
|
|
|
|
vd Leq() const { return 10 * arma::log10(Pm / Lrefsq); };
|
|
|
|
/**
|
|
|
|
* @brief Calculates max levels measured for each filter channel. The max
|
|
|
|
* value is the maximum time-filtered (Fast / Slow) power level.
|
|
|
|
*
|
|
|
|
* @return vector of max level values
|
|
|
|
*/
|
|
|
|
vd Lmax() const { return 10 * arma::log10(Pmax / Lrefsq); };
|
2022-08-16 19:22:35 +00:00
|
|
|
|
2022-10-01 17:59:35 +00:00
|
|
|
/**
|
|
|
|
* @brief Comput a 'suggested' downsampling factor, i.e. a lower frame rate
|
|
|
|
* at which sound level meter values are returned from the computation. This
|
|
|
|
* is possible since the signal power is low-pas filtered with a single pole
|
|
|
|
* low pass filter. It can remove computational burden, especially for
|
|
|
|
* plotting, to have a value > 10.
|
|
|
|
*
|
|
|
|
* @param fs Sampling frequency of signal [Hz]
|
|
|
|
* @param tw Time weighting of SLM low pass filter
|
|
|
|
*
|
|
|
|
* @return Suggested downsampling factor, no unit. [-]
|
|
|
|
*/
|
|
|
|
static us suggestedDownSamplingFac(const d fs,const d tw);
|
|
|
|
|
2022-08-16 19:22:35 +00:00
|
|
|
private:
|
2022-09-03 18:59:14 +00:00
|
|
|
vd run_single(vd input, const us filter_no);
|
2022-08-16 19:22:35 +00:00
|
|
|
};
|
2022-09-22 08:18:38 +00:00
|
|
|
/** @} */
|