private void AnalyzeCustomLpFilter() { var order = 23; var freq = 0.22; if (filterParamsDataGrid.RowCount > 0) { order = Convert.ToInt32(filterParamsDataGrid.Rows[0].Cells[1].Value); freq = Convert.ToDouble(filterParamsDataGrid.Rows[1].Cells[1].Value); } orderNumeratorTextBox.Text = (order - 1).ToString(); orderDenominatorTextBox.Text = (order - 1).ToString(); _filter = new FirFilter(DesignFilter.FirWinLp(order, freq)); // for double precision and FDA: //var tf = new TransferFunction(DesignFilter.FirWinLp(order, freq)); //_filter = new FirFilter(tf); filterParamsDataGrid.RowCount = 2; filterParamsDataGrid.Rows[0].Cells[0].Value = "order"; filterParamsDataGrid.Rows[0].Cells[1].Value = order; filterParamsDataGrid.Rows[1].Cells[0].Value = "freq"; filterParamsDataGrid.Rows[1].Cells[1].Value = freq; }
/// <summary> /// Does interpolation of <paramref name="signal"/> followed by lowpass filtering. /// </summary> /// <param name="signal">Signal</param> /// <param name="factor">Interpolation factor (e.g. factor=2 if 8000 Hz -> 16000 Hz)</param> /// <param name="filter">Lowpass anti-aliasing filter</param> public DiscreteSignal Interpolate(DiscreteSignal signal, int factor, FirFilter filter = null) { if (factor == 1) { return(signal.Copy()); } var output = new float[signal.Length * factor]; var pos = 0; for (var i = 0; i < signal.Length; i++) { output[pos] = factor * signal[i]; pos += factor; } var lpFilter = filter; if (filter is null) { var filterSize = factor > MinResamplingFilterOrder / 2 ? 2 * factor + 1 : MinResamplingFilterOrder; lpFilter = new FirFilter(DesignFilter.FirWinLp(filterSize, 0.5f / factor)); } return(lpFilter.ApplyTo(new DiscreteSignal(signal.SamplingRate * factor, output))); }
/// <summary> /// Decimation preceded by low-pass filtering /// </summary> /// <param name="signal"></param> /// <param name="factor"></param> /// <param name="filter"></param> /// <returns></returns> public DiscreteSignal Decimate(DiscreteSignal signal, int factor, FirFilter filter = null) { if (factor == 1) { return(signal.Copy()); } var filterSize = factor > MinResamplingFilterOrder / 2 ? 2 * factor + 1 : MinResamplingFilterOrder; var lpFilter = filter; if (filter == null) { lpFilter = new FirFilter(DesignFilter.FirWinLp(filterSize, 0.5f / factor)); signal = lpFilter.ApplyTo(signal); } var output = new float[signal.Length / factor]; var pos = 0; for (var i = 0; i < output.Length; i++) { output[i] = signal[pos]; pos += factor; } return(new DiscreteSignal(signal.SamplingRate / factor, output)); }
public FirFiltersVersion2Vs5VsZi() { _signal = new WhiteNoiseBuilder().OfLength(N).Build(); _filterV5Kernel5 = new FirFilter(DesignFilter.FirWinLp(5, 0.1)); _filterV2Kernel5 = new FirFilterV2(DesignFilter.FirWinLp(5, 0.1)); _filterZiKernel5 = new ZiFilter(DesignFilter.FirWinLp(5, 0.1), new[] { 1.0 }); _filterV5Kernel35 = new FirFilter(DesignFilter.FirWinLp(35, 0.1)); _filterV2Kernel35 = new FirFilterV2(DesignFilter.FirWinLp(35, 0.1)); _filterZiKernel35 = new ZiFilter(DesignFilter.FirWinLp(35, 0.1), new[] { 1.0 }); }
/// <summary> /// Simple resampling as the combination of interpolation and decimation. /// </summary> /// <param name="signal"></param> /// <param name="up"></param> /// <param name="down"></param> /// <param name="filter"></param> /// <returns></returns> public DiscreteSignal ResampleUpDown(DiscreteSignal signal, int up, int down, FirFilter filter = null) { if (up == down) { return(signal.Copy()); } var newSamplingRate = signal.SamplingRate * up / down; if (up > 20 && down > 20) { return(Resample(signal, newSamplingRate, filter)); } var output = new float[signal.Length * up]; var pos = 0; for (var i = 0; i < signal.Length; i++) { output[pos] = up * signal[i]; pos += up; } var lpFilter = filter; if (filter == null) { var factor = Math.Max(up, down); var filterSize = factor > MinResamplingFilterOrder / 2 ? 8 * factor + 1 : MinResamplingFilterOrder; lpFilter = new FirFilter(DesignFilter.FirWinLp(filterSize, 0.5f / factor)); } var upsampled = lpFilter.ApplyTo(new DiscreteSignal(signal.SamplingRate * up, output)); output = new float[upsampled.Length / down]; pos = 0; for (var i = 0; i < output.Length; i++) { output[i] = upsampled[pos]; pos += down; } return(new DiscreteSignal(newSamplingRate, output)); }
private void ApplySettings() { _fftSize = int.Parse(fftSizeTextBox.Text); chunkTimer.Interval = int.Parse(intervalTextBox.Text); var kernel = DesignFilter.FirWinLp(int.Parse(kernelSizeTextBox.Text), 0.2); _blockConvolver = new OlaBlockConvolver(kernel, _fftSize); // or equivalently: //_blockConvolver = OlaBlockConvolver.FromFilter(new FirFilter(kernel), _fftSize); _output = new float[_blockConvolver.HopSize * 5]; }
/// <summary> /// Band-limited resampling /// </summary> /// <param name="signal"></param> /// <param name="newSamplingRate"></param> /// <param name="filter"></param> /// <param name="order"></param> /// <returns></returns> public DiscreteSignal Resample(DiscreteSignal signal, int newSamplingRate, FirFilter filter = null, int order = 15) { if (signal.SamplingRate == newSamplingRate) { return(signal.Copy()); } var g = (float)newSamplingRate / signal.SamplingRate; var input = signal.Samples; var output = new float[(int)(input.Length * g)]; if (g < 1 && filter == null) { filter = new FirFilter(DesignFilter.FirWinLp(MinResamplingFilterOrder, g / 2)); input = filter.ApplyTo(signal).Samples; } var step = 1 / 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 = x - j; float w = (float)(0.5 * (1.0 + Math.Cos(t / order * Math.PI))); // Hann window float sinc = (float)MathUtils.Sinc(t); // Sinc function output[n] += w * sinc * input[j]; } } return(new DiscreteSignal(newSamplingRate, output)); }
public FirFiltersVsBlockConvolvers() { _signal = new WhiteNoiseBuilder().OfLength(N).Build(); var kernel21 = DesignFilter.FirWinLp(21, 0.1); _filter21 = new FirFilter(kernel21); _ola21 = new OlaBlockConvolver(kernel21, 128); _ols21 = new OlsBlockConvolver(kernel21, 128); var kernel101 = DesignFilter.FirWinLp(101, 0.1); _filter101 = new FirFilter(kernel101); _filter101.KernelSizeForBlockConvolution = 2048; _ola101 = new OlaBlockConvolver(kernel101, 512); _ols101 = new OlsBlockConvolver(kernel101, 512); var kernel315 = DesignFilter.FirWinLp(315, 0.1); _filter315 = new FirFilter(kernel315); _filter315.KernelSizeForBlockConvolution = 2048; _ola315 = new OlaBlockConvolver(kernel315, 2048); _ols315 = new OlsBlockConvolver(kernel315, 2048); }
public void Run() { var output2 = new float[_signal.Length]; var output4 = new float[_signal.Length]; var output5 = new float[_signal.Length]; var outputZi = new float[_signal.Length]; var samples = _signal.Samples; for (var i = 0; i < samples.Length; i++) { output4[i] = _filterV4BiQuad.Process(samples[i]); output5[i] = _filterV5BiQuad.Process(samples[i]); outputZi[i] = _filterZiBiQuad.Process(samples[i]); } var diffAverageV4 = output5.Zip(output4, (o5, o4) => Math.Abs(o5 - o4)).Average(); var diffAverageZi = output5.Zip(outputZi, (o5, zi) => Math.Abs(o5 - zi)).Average(); Console.WriteLine($"Average difference Ver.0.9.5 vs. Ver.0.9.4 : {diffAverageV4}"); Console.WriteLine($"Average difference IirFilter vs. ZiFilter : {diffAverageZi}"); for (var i = 0; i < samples.Length; i++) { output4[i] = _filterV4Butterworth6.Process(samples[i]); output5[i] = _filterV5Butterworth6.Process(samples[i]); outputZi[i] = _filterZiButterworth6.Process(samples[i]); } diffAverageV4 = output5.Zip(output4, (o5, o4) => Math.Abs(o5 - o4)).Average(); diffAverageZi = output5.Zip(outputZi, (o5, zi) => Math.Abs(o5 - zi)).Average(); Console.WriteLine($"Average difference Ver.0.9.5 vs. Ver.0.9.4 : {diffAverageV4}"); Console.WriteLine($"Average difference IirFilter vs. ZiFilter : {diffAverageZi}"); // === MISC ==== var med = new MedianFilter(); var med2 = new MedianFilter2(); var medOut = med.ApplyTo(_signal).Samples; var medOut2 = med2.ApplyTo(_signal).Samples; var diffAverageMed = medOut.Zip(medOut, (m1, m2) => Math.Abs(m1 - m2)).Average(); Console.WriteLine($"Average difference MedianFilter vs. MedianFilter2 : {diffAverageMed}"); var ma = new MovingAverageFilter(); var maRec = new MovingAverageRecursiveFilter(); var maOut = ma.ApplyTo(_signal).Samples; var maRecOut = maRec.ApplyTo(_signal).Samples; var diffAverageMa = maOut.Zip(maRecOut, (m1, m2) => Math.Abs(m1 - m2)).Average(); Console.WriteLine($"Average difference MovingAverageFilter vs. MovingAverageRecursiveFilter : {diffAverageMa}"); // 32bit vs. 64bit var fir32 = new FirFilter(DesignFilter.FirWinLp(7, 0.1)); var fir64 = new FirFilter64(DesignFilter.FirWinLp(7, 0.1)); var fir32Out = fir32.ApplyTo(_signal).Samples; var fir64Out = fir64.ApplyTo(_signal.Samples.ToDoubles()); var diffAverageFir = fir64Out.Zip(fir32Out, (m1, m2) => Math.Abs(m1 - m2)).Average(); Console.WriteLine($"Average difference FirFilter vs. FirFilter64 : {diffAverageFir}"); var iir32 = new IirFilter(_filterV5Butterworth6.Tf); var iir64 = new IirFilter64(_filterV5Butterworth6.Tf); var iir32Out = iir32.ApplyTo(_signal).Samples; var iir64Out = iir64.ApplyTo(_signal.Samples.ToDoubles()); var diffAverageIir = iir64Out.Zip(iir32Out, (m1, m2) => Math.Abs(m1 - m2)).Average(); Console.WriteLine($"Average difference IirFilter vs. IirFilter64 : {diffAverageIir}"); var zi32 = new ZiFilter(_filterV5Butterworth6.Tf); var zi64 = new ZiFilter64(_filterV5Butterworth6.Tf); var zi32Out = zi32.ApplyTo(_signal).Samples; var zi64Out = zi64.ApplyTo(_signal.Samples.ToDoubles()); var diffAverageZis = zi64Out.Zip(zi32Out, (m1, m2) => Math.Abs(m1 - m2)).Average(); Console.WriteLine($"Average difference ZiFilter vs. ZiFilter64 : {diffAverageZis}"); zi32Out = zi32.ZeroPhase(_signal).Samples; zi64Out = zi64.ZeroPhase(_signal.Samples.ToDoubles()); var diffAverageZiZeroPhase = zi64Out.Zip(zi32Out, (m1, m2) => Math.Abs(m1 - m2)).Average(); Console.WriteLine($"Average difference ZiFilter vs. ZiFilter64 (zero-phase): {diffAverageZiZeroPhase}"); }