-
Notifications
You must be signed in to change notification settings - Fork 72
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
FIR Bandpass Resampling becomes unstable after a long duration #59
Comments
Just a small update, it turns out the signal quality degrades constantly over time. Even before 36 hours, the signal is starting to look more 'square' compared to at the beginning. Is this an error accumulating and eventually overflowing perhaps? |
The fix for me at the moment is to reset the filter after short sections of data with lpFilter.Reset(); but it does cause some aliasing at each boundary. Do you know if you'll have a chance to take a look at this @ar1st0crat ? |
Hi! Hence, there are two options: // 1) solution similar to yours:
// the filter will be essentially LP (although, technically it's BP):
var lowCutoff = 0.5 / newSr; // high pass to remove baseline wander
var highCutoff = 0.5 / 3; // 3 because greatest_common_divisor(128, 192) = 3
var filterOrder = 11;
var resampler = new Resampler();
var lpFilter = new FirFilter(DesignFilter.FirWinBp(filterOrder, lowCutoff, highCutoff));
var resampled = resampler.Resample(new NWaves.Signals.DiscreteSignal(oldSr, data), newSr, lpFilter);
return resampled.Samples;
// 2) slighly-less efficient, but more readable
var cutoff = 0.5 / newSr; // high pass to remove baseline wander
var filterOrder = 11;
// filter to remove baseline wander, first:
var hpFilter = new FirFilter(DesignFilter.FirWinHp(filterOrder, cutoff));
var filtered = hpFilter.ApplyTo(new NWaves.Signals.DiscreteSignal(oldSr, data));
var resampler = new Resampler();
// resampling antialiasing LP filter will be constructed automatically inside Resample() function:
var resampled = resampler.Resample(filtered, newSr);
return resampled.Samples; PS. Btw, is filter order=11 OK? Perhaps, it's too small. You can try bigger values. Like 101 for example. Filtering will be automatically be carried out via block convolution, so it's going to be quite fast. |
I just noticed, if you pass in a filter it doesn't actually get used at all which is probably why I was getting such bad aliasing NWaves/NWaves/Operations/Resampler.cs Line 115 in 726d8dd
The if's need to be split up into something like:
otherwise the low pass filter you pass in won't be used. |
No, AFAIR, filtering is not needed for band-limited upsampling, so my code is correct. // 1)
var lowCutoff = 0.5 / newSr; // high pass to remove baseline wander
var highCutoff = 0.5 / 3; // 3 because greatest_common_divisor(128, 192) = 3
var filterOrder = 99;
var filter = new FirFilter(DesignFilter.FirWinBp(filterOrder, lowCutoff, highCutoff));
var resampler = new Resampler();
var resampled = resampler.ResampleUpDown(new NWaves.Signals.DiscreteSignal(oldSr, data), 3, 2, filter);
return resampled.Samples;
// 2) this is the most correct version (but it will create intermediate HP-filtered signal):
var cutoff = 0.5 / newSr; // high pass to remove baseline wander
var filterOrder = 11;
// filter to remove baseline wander, first:
var hpFilter = new FirFilter(DesignFilter.FirWinHp(filterOrder, cutoff));
var filtered = hpFilter.ApplyTo(new NWaves.Signals.DiscreteSignal(oldSr, data));
var resampler = new Resampler();
// resampling antialiasing LP filter will be constructed automatically inside ResampleUpDown() function:
var resampled = resampler.ResampleUpDown(filtered, 3, 2);
return resampled.Samples; |
This is just one example, my input data sample rate varies and often the resample ratio is not a nice integer, like 200=>192, 250=>192 etc. The code for Resample() is still not working correctly if downsampling though right? If you pass in a filter yourself, it won't be used even in the case of downsampling, because it checks if the filter is null to do the filtering step. |
@ar1st0crat NWaves/NWaves/Operations/Resampler.cs Lines 115 to 121 in 0728ca6
There is no else condition to use a provided filter if it is not null. |
Yes, you're right. I remember about this issue and I keep it open. I wanted to revise the entire resampling part of NWaves, but unfortunately at the moment I have no time for it. |
I've figured out the source of the noise, its actually caused by poor floating point precision at large values here: NWaves/NWaves/Operations/Resampler.cs Line 126 in c1a6a4a
It's especially bad in my case because signal values are small, so the lack of precision is relatively quite large. // eliminate any floating point quantization errors for very large sample counts
decimal step = 1 / (decimal)g;
for (var n = 0; n < output.Length; n++)
{
var x = n * step;
for (var i = -order; i < order; i++)
{
var j = (int)Math.Floor(x) - i;
if (j < 0 || j >= input.Length)
{
continue;
}
var t = (double)(x - j); // at this point we are back to a small scale, safe to return to double type |
First of all, thanks for the great library.
I'm having an issue with resampling using a bandpass FIR filter, here is my Resample configuration:
The original sample rate is 128 Hz
The new sample rate is 192 Hz
After about 36 hours, I see a sudden change in the resample output:
Then at 72 hours, I see another abrupt degradation in signal quality
Is this a bug in the code, or something I can expect from resampling for a long duration?
The text was updated successfully, but these errors were encountered: