mirror of
https://github.com/SDRSharpR/SDRSharper.git
synced 2025-12-06 04:12:02 +01:00
125 lines
3.2 KiB
C#
125 lines
3.2 KiB
C#
namespace SDRSharp.Radio
|
|
{
|
|
public sealed class FloatDecimator
|
|
{
|
|
private readonly int _stageCount;
|
|
|
|
private readonly int _threadCount;
|
|
|
|
private readonly int _cicCount;
|
|
|
|
private readonly UnsafeBuffer _cicDecimatorsBuffer;
|
|
|
|
private unsafe readonly CicDecimator* _cicDecimators;
|
|
|
|
private readonly FirFilter[] _firFilters;
|
|
|
|
private static readonly double _minimumCICSampleRate = Utils.GetDoubleSetting("minimumCICSampleRate", 1500000.0);
|
|
|
|
public int StageCount => this._stageCount;
|
|
|
|
public FloatDecimator(int stageCount)
|
|
: this(stageCount, 0.0, DecimationFilterType.Audio, 1)
|
|
{
|
|
}
|
|
|
|
public FloatDecimator(int stageCount, double samplerate, DecimationFilterType filterType)
|
|
: this(stageCount, samplerate, filterType, 1)
|
|
{
|
|
}
|
|
|
|
public unsafe FloatDecimator(int stageCount, double samplerate, DecimationFilterType filterType, int threadCount)
|
|
{
|
|
this._stageCount = stageCount;
|
|
this._threadCount = threadCount;
|
|
this._cicCount = 0;
|
|
int num = 0;
|
|
switch (filterType)
|
|
{
|
|
case DecimationFilterType.Fast:
|
|
this._cicCount = stageCount;
|
|
break;
|
|
case DecimationFilterType.Audio:
|
|
num = stageCount;
|
|
break;
|
|
case DecimationFilterType.Baseband:
|
|
while (this._cicCount < stageCount && samplerate >= FloatDecimator._minimumCICSampleRate)
|
|
{
|
|
this._cicCount++;
|
|
samplerate /= 2.0;
|
|
}
|
|
num = stageCount - this._cicCount;
|
|
break;
|
|
}
|
|
this._cicDecimatorsBuffer = UnsafeBuffer.Create(this._threadCount * this._cicCount, sizeof(CicDecimator));
|
|
this._cicDecimators = (CicDecimator*)(void*)this._cicDecimatorsBuffer;
|
|
for (int i = 0; i < this._threadCount; i++)
|
|
{
|
|
for (int j = 0; j < this._cicCount; j++)
|
|
{
|
|
this._cicDecimators[i * this._cicCount + j] = default(CicDecimator);
|
|
}
|
|
}
|
|
this._firFilters = new FirFilter[num];
|
|
for (int k = 0; k < num; k++)
|
|
{
|
|
this._firFilters[k] = new FirFilter(DecimationKernels.Kernel51, 2);
|
|
}
|
|
}
|
|
|
|
public unsafe void Process(float* buffer, int length)
|
|
{
|
|
this.DecimateStage1(buffer, length);
|
|
length >>= this._cicCount;
|
|
this.DecimateStage2(buffer, length);
|
|
}
|
|
|
|
public unsafe void ProcessInterleaved(float* buffer, int length)
|
|
{
|
|
this.DecimateStage1Interleaved(buffer, length);
|
|
length >>= this._cicCount;
|
|
this.DecimateStage2Interleaved(buffer, length);
|
|
}
|
|
|
|
private unsafe void DecimateStage1(float* buffer, int sampleCount)
|
|
{
|
|
for (int i = 0; i < this._cicCount; i++)
|
|
{
|
|
int num = 0;
|
|
int length = sampleCount;
|
|
this._cicDecimators[num * this._cicCount + i].Process(buffer, length);
|
|
sampleCount /= 2;
|
|
}
|
|
}
|
|
|
|
private unsafe void DecimateStage2(float* buffer, int length)
|
|
{
|
|
for (int i = 0; i < this._firFilters.Length; i++)
|
|
{
|
|
this._firFilters[i].Process(buffer, length);
|
|
length /= 2;
|
|
}
|
|
}
|
|
|
|
private unsafe void DecimateStage1Interleaved(float* buffer, int sampleCount)
|
|
{
|
|
for (int i = 0; i < this._cicCount; i++)
|
|
{
|
|
int num = 0;
|
|
int length = sampleCount;
|
|
this._cicDecimators[num * this._cicCount + i].ProcessInterleaved(buffer, length);
|
|
sampleCount /= 2;
|
|
}
|
|
}
|
|
|
|
private unsafe void DecimateStage2Interleaved(float* buffer, int length)
|
|
{
|
|
for (int i = 0; i < this._firFilters.Length; i++)
|
|
{
|
|
this._firFilters[i].ProcessInterleaved(buffer, length);
|
|
length /= 2;
|
|
}
|
|
}
|
|
}
|
|
}
|