#pragma once #include "lasp_biquadbank.h" #include "lasp_filter.h" #include "lasp_thread.h" #include #include /** * \ingroup dsp * @{ */ /** * @brief Sound Level Meter implementation that gives a result for each * channel. A channel is the result of a filtered signal */ class SLM { GlobalThreadPool _pool; /** * @brief A, C or Z weighting, depending on the pre-filter installed. */ std::unique_ptr _pre_filter; /** * @brief Bandpass filters for each channel */ std::vector> _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 Lrefsq; /// Square of 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 pre_filter, std::vector> 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 coefficients for bandpass filter. First axis isis the coefficient index, second axis is the filter index. * * @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 for each filtered channel. */ dmat run(const vd &input); /** * @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); }; /** * @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); private: vd run_single(vd input, const us filter_no); }; /** @} */