mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-15 01:57:39 -05:00
39 [WIP] experiments to reduce processing time for high sample rate tuners (e.g airspy)
This commit is contained in:
@@ -21,7 +21,9 @@ package io.github.dsheirer.dsp.filter.channelizer;
|
|||||||
import io.github.dsheirer.dsp.filter.FilterFactory;
|
import io.github.dsheirer.dsp.filter.FilterFactory;
|
||||||
import io.github.dsheirer.dsp.filter.Window.WindowType;
|
import io.github.dsheirer.dsp.filter.Window.WindowType;
|
||||||
import io.github.dsheirer.dsp.filter.design.FilterDesignException;
|
import io.github.dsheirer.dsp.filter.design.FilterDesignException;
|
||||||
|
import io.github.dsheirer.sample.Listener;
|
||||||
import io.github.dsheirer.sample.buffer.ReusableComplexBuffer;
|
import io.github.dsheirer.sample.buffer.ReusableComplexBuffer;
|
||||||
|
import io.github.dsheirer.sample.real.IOverflowListener;
|
||||||
import org.jtransforms.fft.FloatFFT_1D;
|
import org.jtransforms.fft.FloatFFT_1D;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -42,6 +44,7 @@ public class ComplexPolyphaseChannelizerM2 extends AbstractComplexPolyphaseChann
|
|||||||
private PolyphaseChannelResultsBuffer mChannelResultsBuffer;
|
private PolyphaseChannelResultsBuffer mChannelResultsBuffer;
|
||||||
private int mChannelResultsBufferSize = 2500;
|
private int mChannelResultsBufferSize = 2500;
|
||||||
private SampleTimestampManager mTimestampManager;
|
private SampleTimestampManager mTimestampManager;
|
||||||
|
private IFFTProcessor mIFFTProcessor = new IFFTProcessor(300, 50);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Non-Maximally Decimated Polyphase Filter Bank (NMDPFB) channelizer that divides the input frequency band into
|
* Non-Maximally Decimated Polyphase Filter Bank (NMDPFB) channelizer that divides the input frequency band into
|
||||||
@@ -95,6 +98,16 @@ public class ComplexPolyphaseChannelizerM2 extends AbstractComplexPolyphaseChann
|
|||||||
init(filterTaps);
|
init(filterTaps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void start()
|
||||||
|
{
|
||||||
|
mIFFTProcessor.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop()
|
||||||
|
{
|
||||||
|
mIFFTProcessor.stop();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the multiple of two number of channels that can be channelized from the specified sample rate so that
|
* Calculates the multiple of two number of channels that can be channelized from the specified sample rate so that
|
||||||
* each channel has a minimum bandwidth of the default channel bandwidth (12.5 kHz).
|
* each channel has a minimum bandwidth of the default channel bandwidth (12.5 kHz).
|
||||||
@@ -144,6 +157,8 @@ public class ComplexPolyphaseChannelizerM2 extends AbstractComplexPolyphaseChann
|
|||||||
@Override
|
@Override
|
||||||
public void receive(ReusableComplexBuffer reusableComplexBuffer)
|
public void receive(ReusableComplexBuffer reusableComplexBuffer)
|
||||||
{
|
{
|
||||||
|
long start = System.nanoTime();
|
||||||
|
|
||||||
//Use the buffer's reference timestamp to update our timestamp manager (for timestamping output buffers)
|
//Use the buffer's reference timestamp to update our timestamp manager (for timestamping output buffers)
|
||||||
mTimestampManager.setReferenceTimestamp(reusableComplexBuffer.getTimestamp());
|
mTimestampManager.setReferenceTimestamp(reusableComplexBuffer.getTimestamp());
|
||||||
|
|
||||||
@@ -172,6 +187,8 @@ public class ComplexPolyphaseChannelizerM2 extends AbstractComplexPolyphaseChann
|
|||||||
|
|
||||||
//Decrement the user count to let the originator know we're done with their buffer
|
//Decrement the user count to let the originator know we're done with their buffer
|
||||||
reusableComplexBuffer.decrementUserCount();
|
reusableComplexBuffer.decrementUserCount();
|
||||||
|
|
||||||
|
mLog.debug("Duration: " + (System.nanoTime() - start));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -216,7 +233,6 @@ public class ComplexPolyphaseChannelizerM2 extends AbstractComplexPolyphaseChann
|
|||||||
|
|
||||||
int half = getChannelCount() / 2;
|
int half = getChannelCount() / 2;
|
||||||
|
|
||||||
// int outputOffset = getChannelCount() - half - 1;
|
|
||||||
int outputOffset = getChannelCount() - 1;
|
int outputOffset = getChannelCount() - 1;
|
||||||
int outputIndex;
|
int outputIndex;
|
||||||
int sampleIndex;
|
int sampleIndex;
|
||||||
@@ -234,7 +250,6 @@ public class ComplexPolyphaseChannelizerM2 extends AbstractComplexPolyphaseChann
|
|||||||
|
|
||||||
//The second half of the sample buffer was loaded using the previous column pointer - adjust for that now
|
//The second half of the sample buffer was loaded using the previous column pointer - adjust for that now
|
||||||
sampleIndexMap = mSampleIndexMap[(mColumnPointer == (mSamples.length - 1) ? 0 : mColumnPointer + 1)];
|
sampleIndexMap = mSampleIndexMap[(mColumnPointer == (mSamples.length - 1) ? 0 : mColumnPointer + 1)];
|
||||||
// outputOffset = getChannelCount() + half - 1;
|
|
||||||
outputOffset = getChannelCount() - 1;
|
outputOffset = getChannelCount() - 1;
|
||||||
|
|
||||||
for(int channel = half; channel < getChannelCount(); channel++)
|
for(int channel = half; channel < getChannelCount(); channel++)
|
||||||
@@ -248,10 +263,7 @@ public class ComplexPolyphaseChannelizerM2 extends AbstractComplexPolyphaseChann
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Rotate each of the channels to the correct phase using the IFFT
|
mIFFTProcessor.receive(processed);
|
||||||
mFFT.complexInverse(processed, true);
|
|
||||||
|
|
||||||
processChannelResults(processed);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -397,4 +409,35 @@ public class ComplexPolyphaseChannelizerM2 extends AbstractComplexPolyphaseChann
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processor to enqueue filtered channels, perform IFFT and dispatch the results
|
||||||
|
*/
|
||||||
|
public class IFFTProcessor extends ContinuousBufferProcessor<float[]>
|
||||||
|
{
|
||||||
|
public IFFTProcessor(int maximumSize, int resetThreshold)
|
||||||
|
{
|
||||||
|
super(maximumSize, resetThreshold);
|
||||||
|
|
||||||
|
setListener(new Listener<float[]>()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void receive(float[] floatsToProcess)
|
||||||
|
{
|
||||||
|
//Rotate each of the channels to the correct phase using the IFFT
|
||||||
|
mFFT.complexInverse(floatsToProcess, true);
|
||||||
|
processChannelResults(floatsToProcess);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
setOverflowListener(new IOverflowListener()
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public void sourceOverflow(boolean overflow)
|
||||||
|
{
|
||||||
|
mLog.debug("IFFTProcessor overflow changed - overflow:" + overflow);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -232,6 +232,7 @@ public class PolyphaseChannelManager implements ISourceEventProcessor
|
|||||||
if(mPolyphaseChannelizer.getRegisteredChannelCount() == 1)
|
if(mPolyphaseChannelizer.getRegisteredChannelCount() == 1)
|
||||||
{
|
{
|
||||||
mReusableBufferProvider.addBufferListener(mBufferProcessor);
|
mReusableBufferProvider.addBufferListener(mBufferProcessor);
|
||||||
|
mPolyphaseChannelizer.start();
|
||||||
mBufferProcessor.start();
|
mBufferProcessor.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -254,6 +255,7 @@ public class PolyphaseChannelManager implements ISourceEventProcessor
|
|||||||
{
|
{
|
||||||
mReusableBufferProvider.removeBufferListener(mBufferProcessor);
|
mReusableBufferProvider.removeBufferListener(mBufferProcessor);
|
||||||
mBufferProcessor.stop();
|
mBufferProcessor.stop();
|
||||||
|
mPolyphaseChannelizer.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -78,10 +78,7 @@ public abstract class AbstractReusableBufferQueue<T extends ReusableBuffer> impl
|
|||||||
mBufferCount++;
|
mBufferCount++;
|
||||||
buffer.setDebugName("Owner:" + mDebugName + " Number:" + mBufferUserCounter++ + " NEW BUFFER");
|
buffer.setDebugName("Owner:" + mDebugName + " Number:" + mBufferUserCounter++ + " NEW BUFFER");
|
||||||
|
|
||||||
// if(mDebugName != null && mDebugName.contentEquals("NativeBufferConverter"))
|
mLog.debug("Buffer Created - Count:" + mBufferCount + (mDebugName != null ? " [" + mDebugName + "]" : ""));
|
||||||
// {
|
|
||||||
// mLog.debug("Buffer Created - Count:" + mBufferCount + (mDebugName != null ? " [" + mDebugName + "]" : ""));
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user