SDRSharper/SDRSharper.Radio/SDRSharp.Radio/FftProcessor.cs
SDRSharpR c07e6e6034 SDRSharper (SDRSharp Remake) Full Source (VS2017)
SDRSharper (SDRSharp Remake) Full Source (VS2017)
2018-03-26 14:02:05 -07:00

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);
}
}