/// <summary> /// Interpolation followed by low-pass filtering /// </summary> /// <param name="signal"></param> /// <param name="factor"></param> /// <param name="filter"></param> /// <returns></returns> 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 == null) { var filterSize = factor > MinResamplingFilterOrder / 2 ? 2 * factor + 1 : MinResamplingFilterOrder; lpFilter = DesignFilter.FirLp(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 = DesignFilter.FirLp(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)); }
private void ApplySettings() { _fftSize = int.Parse(fftSizeTextBox.Text); chunkTimer.Interval = int.Parse(intervalTextBox.Text); var filter = DesignFilter.FirLp(int.Parse(kernelSizeTextBox.Text), 0.2); _blockConvolver = OlaBlockConvolver.FromFilter(filter, _fftSize); _output = new float[_blockConvolver.HopSize * 5]; }
/// <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 = DesignFilter.FirLp(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)); }
/// <summary> /// Simple resampling (as the combination of interpolation and decimation). /// </summary> /// <param name="signal"></param> /// <param name="newSamplingRate"></param> /// <returns></returns> public static DiscreteSignal Resample(DiscreteSignal signal, int newSamplingRate) { if (newSamplingRate == signal.SamplingRate) { return(signal.Copy()); } var gcd = MathUtils.Gcd(signal.SamplingRate, newSamplingRate); var up = newSamplingRate / gcd; var down = signal.SamplingRate / gcd; if (up > 20 && down > 20) { return(ResampleUpDown(signal, up, down)); } 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 factor = Math.Max(up, down); var filterSize = factor > MinResamplingFilterOrder / 2 ? 8 * factor + 1 : MinResamplingFilterOrder; var lpFilter = DesignFilter.FirLp(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)); }
/// <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 = DesignFilter.FirLp(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)); }
/// <summary> /// Resampling based on simple interpolation /// </summary> /// <param name="signal"></param> /// <param name="up"></param> /// <param name="down"></param> /// <returns></returns> private static DiscreteSignal ResampleUpDown(DiscreteSignal signal, int up, int down) { var ratio = (float)up / down; var freq = ratio > 1 ? 0.5f / ratio : 0.5f * ratio; var lpFilter = DesignFilter.FirLp(MinResamplingFilterOrder, freq); var input = signal.Samples; var output = MathUtils.InterpolateLinear( Enumerable.Range(0, input.Length) .Select(s => s * ratio) .ToArray(), input, Enumerable.Range(0, (int)(signal.Length * ratio) + 1) .Select(s => (float)s) .ToArray()); return(lpFilter.ApplyTo(new DiscreteSignal(signal.SamplingRate * up / down, output))); }
private void AnalyzeCustomLpFilter() { var order = 15; var freq = 0.1; 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 = DesignFilter.FirLp(order, freq); 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; }