Made power correction in smoothing algorithm optional. Window decreases in size symmetrically around the edged of the frequency spectrum
Some checks failed
Building, testing and releasing LASP if it has a tag / Release-Ubuntu (push) Blocked by required conditions
Building, testing and releasing LASP if it has a tag / Build-Test-Ubuntu (push) Has been cancelled

This commit is contained in:
Anne de Jong 2024-03-12 11:19:52 +01:00
parent 6799ee9287
commit ab080910fc
2 changed files with 46 additions and 18 deletions

View File

@ -1,11 +1,14 @@
// #define DEBUGTRACE_ENABLED // #define DEBUGTRACE_ENABLED
#include "lasp_freqsmooth.h" #include "lasp_freqsmooth.h"
#include <cassert>
#include "debugtrace.hpp" #include "debugtrace.hpp"
using rte = std::runtime_error; using rte = std::runtime_error;
vd freqSmooth(const vd& freq, const vd& X, const unsigned w) { vd freqSmooth(const vd& freq, const vd& X, const unsigned w,
bool power_correct) {
DEBUGTRACE_ENTER; DEBUGTRACE_ENTER;
if (freq.size() < 2) { if (freq.size() < 2) {
throw rte("Invalid frequency size. Should be > 2"); throw rte("Invalid frequency size. Should be > 2");
@ -34,11 +37,15 @@ vd freqSmooth(const vd& freq, const vd& X, const unsigned w) {
d ac_pwr; d ac_pwr;
if (firstFreqEqZero) { if (firstFreqEqZero) {
freq_min = freq(1); freq_min = freq(1);
if (power_correct) {
ac_pwr = arma::sum(X.subvec(1, Nfreq - 1)); ac_pwr = arma::sum(X.subvec(1, Nfreq - 1));
}
} else { } else {
freq_min = freq(0); freq_min = freq(0);
if (power_correct) {
ac_pwr = arma::sum(X); ac_pwr = arma::sum(X);
} }
}
DEBUGTRACE_PRINT(freq_min); DEBUGTRACE_PRINT(freq_min);
DEBUGTRACE_PRINT(freq_max); DEBUGTRACE_PRINT(freq_max);
const vd freq_log = const vd freq_log =
@ -72,10 +79,20 @@ vd freqSmooth(const vd& freq, const vd& X, const unsigned w) {
// Long is at least 32 bits. So +/- 2M points length // Long is at least 32 bits. So +/- 2M points length
for (long k = 0; k < Nfreq_sm; k++) { for (long k = 0; k < Nfreq_sm; k++) {
// const d fcur = freq_log(k); // const d fcur = freq_log(k);
const us idx_start = std::max(k - mu, 0l); long idx_start = std::max(k - mu, 0l);
const us idx_stop = std::min(k + mu, Nfreq_sm - 1); long idx_stop = std::min(k + mu, Nfreq_sm - 1);
// DEBUGTRACE_PRINT(idx_start)
// DEBUGTRACE_PRINT(idx_stop); // Make window smaller at the sides (close to the end of the array)
if (idx_start == 0 || idx_stop == Nfreq_sm - 1) {
const long mu_edge = std::min(k - idx_start, idx_stop - k);
idx_start = k - mu_edge;
idx_stop = k + mu_edge;
}
assert(idx_stop < Nfreq_sm);
assert(idx_start < Nfreq_sm);
DEBUGTRACE_PRINT(idx_start)
DEBUGTRACE_PRINT(idx_stop);
Xsm_log(k) = arma::mean(X_log.subvec(idx_start, idx_stop)); Xsm_log(k) = arma::mean(X_log.subvec(idx_start, idx_stop));
} }
@ -95,8 +112,10 @@ vd freqSmooth(const vd& freq, const vd& X, const unsigned w) {
Xsm(Nfreq - 1) = Xsm_log(Nfreq_sm - 1); Xsm(Nfreq - 1) = Xsm_log(Nfreq_sm - 1);
// Final step: power-correct smoothed spectrum // Final step: power-correct smoothed spectrum
if (power_correct) {
d new_acpwr = arma::sum(Xsm.subvec(1, Nfreq - 1)); d new_acpwr = arma::sum(Xsm.subvec(1, Nfreq - 1));
Xsm.subvec(1, Nfreq - 1) *= ac_pwr / new_acpwr; Xsm.subvec(1, Nfreq - 1) *= ac_pwr / new_acpwr;
}
} else { } else {
arma::interp1(freq_log, Xsm_log, freq, Xsm, "*linear"); arma::interp1(freq_log, Xsm_log, freq, Xsm, "*linear");
@ -104,9 +123,11 @@ vd freqSmooth(const vd& freq, const vd& X, const unsigned w) {
Xsm(Nfreq - 1) = Xsm_log(Nfreq_sm - 1); Xsm(Nfreq - 1) = Xsm_log(Nfreq_sm - 1);
// Final step: power-correct smoothed spectrum // Final step: power-correct smoothed spectrum
if (power_correct) {
d new_acpwr = arma::sum(Xsm); d new_acpwr = arma::sum(Xsm);
Xsm *= ac_pwr / new_acpwr; Xsm *= ac_pwr / new_acpwr;
} }
}
return Xsm; return Xsm;
} }

View File

@ -1,21 +1,28 @@
#pragma once #pragma once
#include <vector>
#include <memory> #include <memory>
#include "lasp_types.h" #include <vector>
#include "lasp_mathtypes.h"
#include "lasp_mathtypes.h"
#include "lasp_types.h"
/** /**
* \addtogroup dsp * \addtogroup dsp
* @{ * @{
*/ */
/** /**
* @brief Frequency domain smoothing. Returns a smoothed variant of the power * @brief Apply frequency domain smoothing to a Frequency domain (single
* spectrum given as input. * sided)signal power spectrum
* *
* @param freq Frequency range
* @param X Signal pwr
* @param w Parameter determining the smoothing with. 1 = 1/1 octave, 3 = 1/3th
* octave and so on
* @param power_correct Apply a correction to the whole spectrum to make the
* signal power equal to the unsmoothed signal power.
* @return vd Smoothed spectrum
*/ */
vd freqSmooth(const vd& freq,const vd& X,const unsigned w); vd freqSmooth(const vd& freq, const vd& X, const unsigned w,
bool power_correct = false);
/** @} */ /** @} */