Negative time constant for single pole lowpass filter means no time-weighting at all.
This commit is contained in:
parent
29dc70fad3
commit
bd88882f25
@ -20,10 +20,7 @@ Slm *Slm_create(Sosfilterbank *prefilter, Sosfilterbank *bandpass, const d fs,
|
|||||||
assertvalidptr(downsampling_fac);
|
assertvalidptr(downsampling_fac);
|
||||||
|
|
||||||
Slm *slm = NULL;
|
Slm *slm = NULL;
|
||||||
if (tau <= 0) {
|
if (ref_level <= 0) {
|
||||||
WARN("Invalid time constant");
|
|
||||||
return NULL;
|
|
||||||
} else if (ref_level <= 0) {
|
|
||||||
WARN("Invalid reference level");
|
WARN("Invalid reference level");
|
||||||
return NULL;
|
return NULL;
|
||||||
} else if (fs <= 0) {
|
} else if (fs <= 0) {
|
||||||
@ -41,10 +38,15 @@ Slm *Slm_create(Sosfilterbank *prefilter, Sosfilterbank *bandpass, const d fs,
|
|||||||
/// documentation for the computation of its minus 20 dB point. We set the
|
/// documentation for the computation of its minus 20 dB point. We set the
|
||||||
/// reduction in its 'sampling frequency' such that its noise is at a level
|
/// reduction in its 'sampling frequency' such that its noise is at a level
|
||||||
/// of 20 dB less than its 'signal'.
|
/// of 20 dB less than its 'signal'.
|
||||||
|
if (tau > 0) {
|
||||||
const d fs_slm = 1 / (2 * number_pi * tau) * (1 - 0.01) / 0.01;
|
const d fs_slm = 1 / (2 * number_pi * tau) * (1 - 0.01) / 0.01;
|
||||||
slm->downsampling_fac = (us)(fs / fs_slm);
|
slm->downsampling_fac = (us)(fs / fs_slm);
|
||||||
slm->cur_offset = 0;
|
slm->cur_offset = 0;
|
||||||
*downsampling_fac = slm->downsampling_fac;
|
*downsampling_fac = slm->downsampling_fac;
|
||||||
|
} else {
|
||||||
|
*downsampling_fac = 1;
|
||||||
|
slm->downsampling_fac = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/// Create the single pole lowpass
|
/// Create the single pole lowpass
|
||||||
us filterbank_size;
|
us filterbank_size;
|
||||||
@ -54,6 +56,8 @@ Slm *Slm_create(Sosfilterbank *prefilter, Sosfilterbank *bandpass, const d fs,
|
|||||||
filterbank_size = 1;
|
filterbank_size = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tau > 0) {
|
||||||
|
|
||||||
vd lowpass_sos = vd_alloc(6);
|
vd lowpass_sos = vd_alloc(6);
|
||||||
d b0 = 1.0 / (1 + 2 * tau * fs);
|
d b0 = 1.0 / (1 + 2 * tau * fs);
|
||||||
*getvdval(&lowpass_sos, 0) = b0;
|
*getvdval(&lowpass_sos, 0) = b0;
|
||||||
@ -70,6 +74,10 @@ Slm *Slm_create(Sosfilterbank *prefilter, Sosfilterbank *bandpass, const d fs,
|
|||||||
Sosfilterbank_setFilter(slm->splowpass[ch], 0, lowpass_sos);
|
Sosfilterbank_setFilter(slm->splowpass[ch], 0, lowpass_sos);
|
||||||
}
|
}
|
||||||
vd_free(&lowpass_sos);
|
vd_free(&lowpass_sos);
|
||||||
|
} else {
|
||||||
|
/// No low-pass filtering. Tau set to zero
|
||||||
|
slm->splowpass = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
feTRACE(15);
|
feTRACE(15);
|
||||||
return slm;
|
return slm;
|
||||||
@ -106,19 +114,26 @@ dmat Slm_run(Slm *slm, vd *input_data) {
|
|||||||
iVARTRACE(15, samples_bandpassed);
|
iVARTRACE(15, samples_bandpassed);
|
||||||
us cur_offset = slm->cur_offset;
|
us cur_offset = slm->cur_offset;
|
||||||
|
|
||||||
|
/// Compute the number of samples output
|
||||||
int nsamples_output = (samples_bandpassed - cur_offset) / downsampling_fac;
|
int nsamples_output = (samples_bandpassed - cur_offset) / downsampling_fac;
|
||||||
while (nsamples_output * downsampling_fac + cur_offset < samples_bandpassed)
|
while (nsamples_output * downsampling_fac + cur_offset < samples_bandpassed)
|
||||||
nsamples_output++;
|
nsamples_output++;
|
||||||
if(nsamples_output < 0) nsamples_output = 0;
|
if (nsamples_output < 0)
|
||||||
|
nsamples_output = 0;
|
||||||
|
|
||||||
iVARTRACE(15, nsamples_output);
|
iVARTRACE(15, nsamples_output);
|
||||||
iVARTRACE(15, cur_offset);
|
iVARTRACE(15, cur_offset);
|
||||||
|
|
||||||
dmat levels = dmat_alloc(nsamples_output, filterbank_size);
|
dmat levels;
|
||||||
|
if (slm->splowpass) {
|
||||||
|
levels = dmat_alloc(nsamples_output, filterbank_size);
|
||||||
|
} else {
|
||||||
|
levels = dmat_alloc(samples_bandpassed, filterbank_size);
|
||||||
|
}
|
||||||
|
|
||||||
for (us ch = 0; ch < bandpassed.n_cols; ch++) {
|
for (us ch = 0; ch < bandpassed.n_cols; ch++) {
|
||||||
iVARTRACE(15, ch);
|
iVARTRACE(15, ch);
|
||||||
cur_offset = slm->cur_offset;
|
vd chan = dmat_column(&bandpassed, ch);
|
||||||
/// Inplace squaring of the signal
|
/// Inplace squaring of the signal
|
||||||
for (us sample = 0; sample < bandpassed.n_rows; sample++) {
|
for (us sample = 0; sample < bandpassed.n_rows; sample++) {
|
||||||
tmp = getdmatval(&bandpassed, sample, ch);
|
tmp = getdmatval(&bandpassed, sample, ch);
|
||||||
@ -127,7 +142,8 @@ dmat Slm_run(Slm *slm, vd *input_data) {
|
|||||||
|
|
||||||
// Now that all data for the channel is squared, we can run it through
|
// Now that all data for the channel is squared, we can run it through
|
||||||
// the low-pass filter
|
// the low-pass filter
|
||||||
vd chan = dmat_column(&bandpassed, ch);
|
if (slm->splowpass) {
|
||||||
|
cur_offset = slm->cur_offset;
|
||||||
|
|
||||||
/// Apply single-pole lowpass filter for current filterbank channel
|
/// Apply single-pole lowpass filter for current filterbank channel
|
||||||
vd power_filtered = Sosfilterbank_filter(slm->splowpass[ch], &chan);
|
vd power_filtered = Sosfilterbank_filter(slm->splowpass[ch], &chan);
|
||||||
@ -135,25 +151,32 @@ dmat Slm_run(Slm *slm, vd *input_data) {
|
|||||||
|
|
||||||
/// Output resulting levels at a lower interval
|
/// Output resulting levels at a lower interval
|
||||||
us i = 0;
|
us i = 0;
|
||||||
d level;
|
|
||||||
while (cur_offset < samples_bandpassed) {
|
while (cur_offset < samples_bandpassed) {
|
||||||
iVARTRACE(10, i);
|
iVARTRACE(10, i);
|
||||||
iVARTRACE(10, cur_offset);
|
iVARTRACE(10, cur_offset);
|
||||||
level = 10 * d_log10(*getvdval(&power_filtered, cur_offset) / ref_level /
|
/// Compute level
|
||||||
ref_level);
|
d level = 10 * d_log10(*getvdval(&power_filtered, cur_offset) /
|
||||||
|
ref_level / ref_level);
|
||||||
|
|
||||||
*getdmatval(&levels, i++, ch) = level;
|
*getdmatval(&levels, i++, ch) = level;
|
||||||
cur_offset = cur_offset + downsampling_fac;
|
cur_offset = cur_offset + downsampling_fac;
|
||||||
}
|
}
|
||||||
iVARTRACE(15, cur_offset);
|
iVARTRACE(15, cur_offset);
|
||||||
iVARTRACE(15, i);
|
iVARTRACE(15, i);
|
||||||
dbgassert(i == nsamples_output, "BUG");
|
dbgassert(i == (int) nsamples_output, "BUG");
|
||||||
|
|
||||||
vd_free(&chan);
|
vd_free(&chan);
|
||||||
vd_free(&power_filtered);
|
vd_free(&power_filtered);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
slm->cur_offset = cur_offset - samples_bandpassed;
|
slm->cur_offset = cur_offset - samples_bandpassed;
|
||||||
|
|
||||||
|
if (!slm->splowpass) {
|
||||||
|
/// Raw copy of to levels. Happens only when the low-pass filter does not
|
||||||
|
/// have to come into action.
|
||||||
|
dmat_copy(&levels, &bandpassed);
|
||||||
|
}
|
||||||
|
|
||||||
vd_free(&prefiltered);
|
vd_free(&prefiltered);
|
||||||
dmat_free(&bandpassed);
|
dmat_free(&bandpassed);
|
||||||
feTRACE(15);
|
feTRACE(15);
|
||||||
@ -166,7 +189,6 @@ void Slm_free(Slm *slm) {
|
|||||||
if (slm->prefilter) {
|
if (slm->prefilter) {
|
||||||
Sosfilterbank_free(slm->prefilter);
|
Sosfilterbank_free(slm->prefilter);
|
||||||
}
|
}
|
||||||
assertvalidptr(slm->splowpass);
|
|
||||||
|
|
||||||
us filterbank_size;
|
us filterbank_size;
|
||||||
if (slm->bandpass) {
|
if (slm->bandpass) {
|
||||||
@ -175,11 +197,12 @@ void Slm_free(Slm *slm) {
|
|||||||
} else {
|
} else {
|
||||||
filterbank_size = 1;
|
filterbank_size = 1;
|
||||||
}
|
}
|
||||||
|
if (slm->splowpass) {
|
||||||
for (us ch = 0; ch < filterbank_size; ch++) {
|
for (us ch = 0; ch < filterbank_size; ch++) {
|
||||||
Sosfilterbank_free(slm->splowpass[ch]);
|
Sosfilterbank_free(slm->splowpass[ch]);
|
||||||
}
|
}
|
||||||
a_free(slm->splowpass);
|
a_free(slm->splowpass);
|
||||||
|
}
|
||||||
a_free(slm);
|
a_free(slm);
|
||||||
|
|
||||||
feTRACE(15);
|
feTRACE(15);
|
||||||
|
Loading…
Reference in New Issue
Block a user