3#include "debugtrace.hpp"
8using rte = std::runtime_error;
16 : nfft(window.size()), _fft(nfft), _window(window) {
18 d win_pow = arma::sum(window % window) / window.size();
21 _scale_fac = 2.0 / (win_pow * (d)
nfft * (d)
nfft);
23 DEBUGTRACE_PRINT(
nfft);
24 DEBUGTRACE_PRINT(win_pow);
32 dmat input_tmp = input;
35 input_tmp.each_col() %= _window;
37 cmat rfft = _fft.
fft(input_tmp);
39 ccube output(rfft.n_rows, input.n_cols, input.n_cols);
40 for (
us i = 0; i < input.n_cols; i++) {
43#pragma omp parallel for
44 for (
us j = 0; j < input.n_cols; j++) {
45 output.slice(j).col(i) =
46 _scale_fac * (rfft.col(i) % arma::conj(rfft.col(j)));
48 output.slice(j).col(i)(0) /= 2;
49 output.slice(j).col(i)(
nfft / 2) /= 2;
56 const d overlap_percentage,
57 const d time_constant_times_fs)
61 if (overlap_percentage >= 100 || overlap_percentage < 0) {
62 throw rte(
"Overlap percentage should be >= 0 and < 100");
65 _overlap_keep = (nfft * overlap_percentage) / 100;
66 DEBUGTRACE_PRINT(_overlap_keep);
67 if (_overlap_keep >= nfft) {
68 throw rte(
"Overlap is too high. Results in no jump. Please "
69 "choose a smaller overlap percentage or a higher nfft");
71 if (time_constant_times_fs < 0) {
72 _mode = Mode::Averaging;
73 }
else if (time_constant_times_fs == 0) {
74 _mode = Mode::Spectrogram;
76 _mode = Mode::Leaking;
77 _alpha =
d_exp(-
static_cast<d
>((nfft - _overlap_keep)/time_constant_times_fs));
78 DEBUGTRACE_PRINT(_alpha);
91 DEBUGTRACE_PRINT(timedata.n_rows);
92 DEBUGTRACE_PRINT(_ps.
nfft);
94 _timeBuf.
push(timedata);
96 bool run_once =
false;
97 while (_timeBuf.
size() >= _ps.
nfft) {
99 DEBUGTRACE_PRINT((
int)_mode);
101 dmat samples = _timeBuf.
pop(_ps.
nfft, _overlap_keep);
104 case (Mode::Spectrogram):
105 DEBUGTRACE_PRINT(
"Spectrogram mode");
108 case (Mode::Averaging):
109 DEBUGTRACE_PRINT(
"Averaging mode");
111 if (n_averages == 1) {
114 _est = (
static_cast<d
>(n_averages - 1) / n_averages) * _est +
115 _ps.
compute(samples) / n_averages;
118 case (Mode::Leaking):
119 DEBUGTRACE_PRINT(
"Leaking mode");
120 if (arma::size(_est) == arma::size(0, 0, 0)) {
123 _est = _alpha * _est + (1 - _alpha) * _ps.
compute(samples);
132 return run_once ? _est :
ccube();
ccube get_est() const
Returns the latest estimate of cps (cross-power spectra.
ccube compute(const dmat &timedata)
Compute an update of the power spectra based on given time data. Note that the number of channels is ...
AvPowerSpectra(const us nfft=2048, const Window::WindowType w=Window::WindowType::Hann, const d overlap_percentage=50., const d fs_tau=-1)
Initalize averaged power spectra computer. If a time constant is given > 0, it is used in a kind of e...
void reset()
Reset to empty state. Clears the time buffer and sets estimator to empty.
vc fft(const vd &timedata)
Computes single-sided cross-power spectra for a group of channels. Only a single block of length fft,...
ccube compute(const dmat &input)
Computes the spectra. Data is normalized by the (spectral) power of the window, to compensate for the...
PowerSpectra(const us nfft, const Window::WindowType w)
Initalize power spectra computer.
dmat pop(const us nframes, const us keep=0)
Pop frames from the buffer. Throws a runtime error if more frames are requested than actually stored.
us size() const
Returns current size of stored amount of frames.
void reset()
Reset (empties) the time buffer.
void push(const dmat &mat)
Put samples in the buffer. Number of channels should match other frames, otherwise things go wrong.
Window (aka taper) functions of a certain type.
size_t us
We often use boolean values.