lasp/src/lasp/dsp/lasp_slm.h

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);
};