public object Clone() { FirFilter f = new FirFilter(this.a); for (int i = 0; i < this.buf.Count; ++i) { f.GetValue(this.buf[i]); } return f; }
/// <summary> /// Construct BlockConvolver from a specific FIR filter /// </summary> /// <param name="filter"></param> /// <param name="fftSize"></param> /// <returns></returns> public static OlsBlockConvolver FromFilter(FirFilter filter, int fftSize) { fftSize = MathUtils.NextPowerOfTwo(fftSize); return(new OlsBlockConvolver(filter.Kernel, fftSize)); }
/// <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)); }
public unsafe void ProcessBuffer( Burst burst, Complex *iqBuffer, double iqSamplerate, int iqBufferLength, float *digitalBuffer) { burst.Type = BurstType.WaitBurst; burst.Length = 0; if (this._buffer == null || iqSamplerate != this._samplerateIn) { this._samplerateIn = iqSamplerate; this._samplerate = this._samplerateIn; this._interpolation = 1; while (this._samplerateIn * (double)this._interpolation < 90000.0) { ++this._interpolation; } this._samplerate = this._samplerateIn * (double)this._interpolation; this._length = iqBufferLength * this._interpolation; this._symbolLength = this._samplerate / 18000.0; this._windowLength = (int)Math.Round(this._symbolLength * (double)byte.MaxValue); this._writeAddress = 0; this._tailBufferLength = (int)Math.Round(this._symbolLength); this._syncCounter = 0; this._buffer = UnsafeBuffer.Create(this._length + this._tailBufferLength, sizeof(Complex)); this._bufferPtr = (Complex *)(void *)this._buffer; this._tempBuffer = UnsafeBuffer.Create((int)this._samplerate, 4); this._tempBufferPtr = (float *)(void *)this._tempBuffer; this._filterLength = Math.Max((int)(this._samplerate / 18000.0) | 1, 5); float[] coefficients = FilterBuilder.MakeSinc(this._samplerate, 13500.0, this._filterLength); this._matchedFilter = new IQFirFilter(coefficients); this._fsFilter = new FirFilter(coefficients); this.CreateFrameSynchronization(); } if (this._interpolation > 1) { int num = 0; Complex complex = new Complex(0.0f, 0.0f); for (int index = 0; index < this._length; ++index) { this._bufferPtr[index + this._tailBufferLength] = index % this._interpolation == 0 ? iqBuffer[num++] : complex; } } else { Radio.Utils.Memcpy((void *)(this._bufferPtr + this._tailBufferLength), (void *)iqBuffer, this._length * sizeof(Complex)); } this._matchedFilter.Process(this._bufferPtr + this._tailBufferLength, this._length); if (this._writeAddress + this._length < this._tempBuffer.Length) { for (int index = 0; index < this._length; ++index) { this._tempBufferPtr[this._writeAddress] = (this._bufferPtr[index + this._tailBufferLength] * this._bufferPtr[index].Conjugate()).ArgumentFast(); ++this._writeAddress; } } for (int index = 0; index < this._tailBufferLength; ++index) { this._bufferPtr[index] = this._bufferPtr[this._length + index]; } if (this._writeAddress < this._windowLength * 2) { return; } this._ntsOffset = burst.Mode == Mode.TMO ? (int)Math.Round(122.0 * this._symbolLength) : (int)Math.Round(115.0 * this._symbolLength); this._stsOffset = (int)Math.Round(107.0 * this._symbolLength); this._ndb1minSum = float.MaxValue; this._ndb1Index = 0; this._ndb2minSum = float.MaxValue; this._ndb2Index = 0; this._stsMinSum = float.MaxValue; this._stsIndex = 0; this._trainingWindow = this._syncCounter > 0 ? 6 * this._tailBufferLength : this._windowLength; if (this._syncCounter > 0) { --this._syncCounter; } for (int index1 = 0; index1 < this._trainingWindow; ++index1) { this._ndb1sum = 0.0f; this._ndb2sum = 0.0f; this._stsSum = 0.0f; for (int index2 = 0; index2 < this._nts1Buffer.Length; ++index2) { this._sample = this._tempBufferPtr[index1 + index2 + this._ntsOffset]; this._training = this._nts1BufferPtr[index2]; this._ndb1sum += (float)(((double)this._training - (double)this._sample) * ((double)this._training - (double)this._sample)); } if ((double)this._ndb1sum < (double)this._ndb1minSum) { this._ndb1minSum = this._ndb1sum; this._ndb1Index = index1; } for (int index2 = 0; index2 < this._nts2Buffer.Length; ++index2) { this._sample = this._tempBufferPtr[index1 + index2 + this._ntsOffset]; this._training = this._nts2BufferPtr[index2]; this._ndb2sum += (float)(((double)this._training - (double)this._sample) * ((double)this._training - (double)this._sample)); } if ((double)this._ndb2sum < (double)this._ndb2minSum) { this._ndb2minSum = this._ndb2sum; this._ndb2Index = index1; } for (int index2 = 0; index2 < this._stsBuffer.Length; ++index2) { this._sample = this._tempBufferPtr[index1 + index2 + this._stsOffset]; this._training = this._stsBufferPtr[index2]; this._stsSum += (float)(((double)this._training - (double)this._sample) * ((double)this._training - (double)this._sample)); } if ((double)this._stsSum < (double)this._stsMinSum) { this._stsMinSum = this._stsSum; this._stsIndex = index1; } } this._ndb1minSum /= (float)this._nts1Buffer.Length; this._ndb2minSum /= (float)this._nts2Buffer.Length; this._stsMinSum /= (float)this._stsBuffer.Length; if ((double)this._ndb1minSum < 1.0 || (double)this._ndb2minSum < 1.0 || (double)this._stsMinSum < 1.0) { if ((double)this._ndb1minSum < (double)this._ndb2minSum && (double)this._ndb1minSum < (double)this._stsMinSum) { this._offset = this._ndb1Index; burst.Type = BurstType.NDB1; } else if ((double)this._ndb2minSum < (double)this._ndb1minSum && (double)this._ndb2minSum < (double)this._stsMinSum) { this._offset = this._ndb2Index; burst.Type = BurstType.NDB2; } else { this._offset = this._stsIndex; burst.Type = BurstType.SYNC; } this._syncCounter = 8; } else { burst.Type = BurstType.None; this._offset = this._tailBufferLength * 2; } int index3 = 0; int num1 = 0; for (; index3 < 256; ++index3) { num1 = (int)Math.Round((double)index3 * this._symbolLength); digitalBuffer[index3] = this._tempBufferPtr[this._offset + num1]; } this._offset += num1; this._offset -= this._tailBufferLength * 2; if (this._offset < 0) { this._offset = 0; } this._writeAddress -= this._offset; if (this._writeAddress < 0) { this._writeAddress = 0; } Radio.Utils.Memcpy((void *)this._tempBufferPtr, (void *)(this._tempBufferPtr + this._offset), this._writeAddress * 4); this.AngleToSymbol(burst.Ptr, digitalBuffer, (int)byte.MaxValue); burst.Length = 510; }
/// <summary> /// Construct BlockConvolver from a specific FIR filter /// </summary> /// <param name="filter"></param> /// <param name="fftSize"></param> /// <returns></returns> public static OlaBlockConvolver FromFilter(FirFilter filter, int fftSize) { fftSize = MathUtils.NextPowerOfTwo(fftSize); return(new OlaBlockConvolver(filter.ImpulseResponse().ToFloats(), fftSize)); }
/// <summary> /// Method for making LP filter from the linear-phase HP filter /// (no different from LpToHp method) /// </summary> /// <param name="filter"></param> /// <returns></returns> public static FirFilter HpToLp(FirFilter filter) { return(LpToHp(filter)); }
/// <summary> /// Simple resampling (as the combination of interpolation and decimation). /// </summary> /// <param name="signal"></param> /// <param name="newSamplingRate"></param> /// <param name="filter"></param> /// <returns></returns> public static DiscreteSignal Resample(DiscreteSignal signal, int newSamplingRate, FirFilter filter = null) { return(new Resampler().Resample(signal, newSamplingRate, filter)); }
/// <summary> /// Decimation preceded by low-pass filtering /// </summary> /// <param name="signal"></param> /// <param name="factor"></param> /// <param name="filter"></param> /// <returns></returns> public static DiscreteSignal Decimate(DiscreteSignal signal, int factor, FirFilter filter = null) { return(new Resampler().Decimate(signal, factor, filter)); }
public void Should_return_the_name_fir_filter() { target = new FirFilter(); Assert.AreEqual("FIR Filter", target.Name); }
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}"); }
/// <summary> /// Does simple resampling of <paramref name="signal"/> (as the combination of interpolation and decimation). /// </summary> /// <param name="signal">Input signal</param> /// <param name="up">Interpolation factor</param> /// <param name="down">Decimation factor</param> /// <param name="filter">Lowpass anti-aliasing filter</param> public static DiscreteSignal ResampleUpDown(DiscreteSignal signal, int up, int down, FirFilter filter = null) { return(new Resampler().ResampleUpDown(signal, up, down, filter)); }