mirror of
https://github.com/SDRSharpR/SDRSharper.git
synced 2025-12-06 04:12:02 +01:00
212 lines
6.3 KiB
C#
212 lines
6.3 KiB
C#
using System;
|
|
|
|
namespace SDRSharp.Radio
|
|
{
|
|
public abstract class FftProcessor
|
|
{
|
|
private readonly int _fftSize;
|
|
|
|
private readonly int _halfSize;
|
|
|
|
private readonly int _overlapSize;
|
|
|
|
private readonly float _blendFactor;
|
|
|
|
private int _fftBufferPos;
|
|
|
|
private int _sampleBufferHead;
|
|
|
|
private int _sampleBufferTail;
|
|
|
|
private UnsafeBuffer _fftBuffer;
|
|
|
|
private unsafe Complex* _fftBufferPtr;
|
|
|
|
private UnsafeBuffer _overlapBuffer;
|
|
|
|
private unsafe Complex* _overlapBufferPtr;
|
|
|
|
private UnsafeBuffer _outOverlapBuffer;
|
|
|
|
private unsafe Complex* _outOverlapPtr;
|
|
|
|
private UnsafeBuffer _sampleBuffer;
|
|
|
|
private unsafe Complex* _sampleBufferPtr;
|
|
|
|
private Complex _tmp = default(Complex);
|
|
|
|
public unsafe FftProcessor(int fftSize, float overlapRatio = 0f)
|
|
{
|
|
this._fftSize = fftSize;
|
|
this._halfSize = fftSize / 2;
|
|
this._overlapSize = (int)Math.Ceiling((double)((float)this._fftSize * overlapRatio));
|
|
this._fftBufferPos = this._halfSize;
|
|
this._blendFactor = 1f / (float)this._overlapSize;
|
|
this._fftBuffer = UnsafeBuffer.Create(fftSize, sizeof(Complex));
|
|
this._fftBufferPtr = (Complex*)(void*)this._fftBuffer;
|
|
this._outOverlapBuffer = UnsafeBuffer.Create(this._overlapSize, sizeof(Complex));
|
|
this._outOverlapPtr = (Complex*)(void*)this._outOverlapBuffer;
|
|
this._overlapBuffer = UnsafeBuffer.Create(fftSize / 2, sizeof(Complex));
|
|
this._overlapBufferPtr = (Complex*)(void*)this._overlapBuffer;
|
|
this._sampleBuffer = UnsafeBuffer.Create(fftSize, sizeof(Complex));
|
|
this._sampleBufferPtr = (Complex*)(void*)this._sampleBuffer;
|
|
this._sampleBufferHead = this._halfSize;
|
|
}
|
|
|
|
public unsafe void Process(Complex* buffer, int length)
|
|
{
|
|
int i = 0;
|
|
int j = 0;
|
|
for (; i < length; i++)
|
|
{
|
|
this._fftBufferPtr[this._fftBufferPos++] = buffer[i];
|
|
if (this._fftBufferPos == this._fftSize)
|
|
{
|
|
int num = this._halfSize;
|
|
int num2 = 0;
|
|
while (num < this._fftSize)
|
|
{
|
|
this._overlapBufferPtr[num2] = this._fftBufferPtr[num];
|
|
num++;
|
|
num2++;
|
|
}
|
|
for (; j < length; j++)
|
|
{
|
|
if (this._sampleBufferHead == this._sampleBufferTail)
|
|
{
|
|
break;
|
|
}
|
|
buffer[j] = this._sampleBufferPtr[this._sampleBufferTail];
|
|
this._sampleBufferTail = (this._sampleBufferTail + 1 & this._fftSize - 1);
|
|
}
|
|
Fourier.ForwardTransform(this._fftBufferPtr, this._fftSize, false);
|
|
this.ProcessFft(this._fftBufferPtr, this._fftSize);
|
|
Fourier.BackwardTransform(this._fftBufferPtr, this._fftSize);
|
|
int num3 = 0;
|
|
int num4 = this._halfSize - this._overlapSize;
|
|
while (num3 < this._halfSize)
|
|
{
|
|
if (num3 < this._overlapSize)
|
|
{
|
|
float num5 = (float)num3 * this._blendFactor;
|
|
Complex.Mul(ref this._sampleBufferPtr[this._sampleBufferHead], this._fftBufferPtr[num4], num5);
|
|
Complex.Mul(ref this._tmp, this._outOverlapPtr[num3], 1f - num5);
|
|
Complex.Add(ref this._sampleBufferPtr[this._sampleBufferHead], this._tmp);
|
|
}
|
|
else
|
|
{
|
|
this._sampleBufferPtr[this._sampleBufferHead] = this._fftBufferPtr[num4];
|
|
}
|
|
this._sampleBufferHead = (this._sampleBufferHead + 1 & this._fftSize - 1);
|
|
num3++;
|
|
num4++;
|
|
}
|
|
int num6 = 0;
|
|
int num7 = this._fftSize - this._overlapSize;
|
|
while (num6 < this._overlapSize)
|
|
{
|
|
this._outOverlapPtr[num6] = this._fftBufferPtr[num7];
|
|
num6++;
|
|
num7++;
|
|
}
|
|
for (int k = 0; k < this._halfSize; k++)
|
|
{
|
|
this._fftBufferPtr[k] = this._overlapBufferPtr[k];
|
|
}
|
|
this._fftBufferPos = this._halfSize;
|
|
}
|
|
}
|
|
for (; j < length; j++)
|
|
{
|
|
if (this._sampleBufferHead == this._sampleBufferTail)
|
|
{
|
|
break;
|
|
}
|
|
buffer[j] = this._sampleBufferPtr[this._sampleBufferTail];
|
|
this._sampleBufferTail = (this._sampleBufferTail + 1 & this._fftSize - 1);
|
|
}
|
|
}
|
|
|
|
public unsafe void Process(float* buffer, int length, int step = 1)
|
|
{
|
|
int i = 0;
|
|
int j = 0;
|
|
for (; i < length; i += step)
|
|
{
|
|
this._fftBufferPtr[this._fftBufferPos].Real = buffer[i];
|
|
this._fftBufferPtr[this._fftBufferPos++].Imag = 0f;
|
|
if (this._fftBufferPos == this._fftSize)
|
|
{
|
|
int num = this._halfSize;
|
|
int num2 = 0;
|
|
while (num < this._fftSize)
|
|
{
|
|
this._overlapBufferPtr[num2].Real = this._fftBufferPtr[num].Real;
|
|
this._overlapBufferPtr[num2].Imag = 0f;
|
|
num++;
|
|
num2++;
|
|
}
|
|
for (; j < length; j += step)
|
|
{
|
|
if (this._sampleBufferHead == this._sampleBufferTail)
|
|
{
|
|
break;
|
|
}
|
|
buffer[j] = this._sampleBufferPtr[this._sampleBufferTail].Real;
|
|
this._sampleBufferTail = (this._sampleBufferTail + 1 & this._fftSize - 1);
|
|
}
|
|
Fourier.ForwardTransform(this._fftBufferPtr, this._fftSize, false);
|
|
this.ProcessFft(this._fftBufferPtr, this._fftSize);
|
|
Fourier.BackwardTransform(this._fftBufferPtr, this._fftSize);
|
|
int num3 = 0;
|
|
int num4 = this._halfSize - this._overlapSize;
|
|
while (num3 < this._halfSize)
|
|
{
|
|
if (num3 < this._overlapSize)
|
|
{
|
|
float num5 = (float)num3 * this._blendFactor;
|
|
Complex.Mul(ref this._sampleBufferPtr[this._sampleBufferHead], this._fftBufferPtr[num4], num5);
|
|
Complex.Mul(ref this._tmp, this._outOverlapPtr[num3], 1f - num5);
|
|
Complex.Add(ref this._sampleBufferPtr[this._sampleBufferHead], this._tmp);
|
|
}
|
|
else
|
|
{
|
|
this._sampleBufferPtr[this._sampleBufferHead].Real = this._fftBufferPtr[num4].Real;
|
|
this._sampleBufferPtr[this._sampleBufferHead].Imag = 0f;
|
|
}
|
|
this._sampleBufferHead = (this._sampleBufferHead + 1 & this._fftSize - 1);
|
|
num3++;
|
|
num4++;
|
|
}
|
|
int num6 = 0;
|
|
int num7 = this._fftSize - this._overlapSize;
|
|
while (num6 < this._overlapSize)
|
|
{
|
|
this._outOverlapPtr[num6].Real = this._fftBufferPtr[num7].Real;
|
|
this._outOverlapPtr[num6].Imag = 0f;
|
|
num6++;
|
|
num7++;
|
|
}
|
|
for (int k = 0; k < this._halfSize; k++)
|
|
{
|
|
this._fftBufferPtr[k] = this._overlapBufferPtr[k];
|
|
}
|
|
this._fftBufferPos = this._halfSize;
|
|
}
|
|
}
|
|
for (; j < length; j += step)
|
|
{
|
|
if (this._sampleBufferHead == this._sampleBufferTail)
|
|
{
|
|
break;
|
|
}
|
|
buffer[j] = this._sampleBufferPtr[this._sampleBufferTail].Real;
|
|
this._sampleBufferTail = (this._sampleBufferTail + 1 & this._fftSize - 1);
|
|
}
|
|
}
|
|
|
|
protected unsafe abstract void ProcessFft(Complex* buffer, int length);
|
|
}
|
|
}
|