mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 08:37:25 -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.Window.WindowType;
|
||||
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.real.IOverflowListener;
|
||||
import org.jtransforms.fft.FloatFFT_1D;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -42,6 +44,7 @@ public class ComplexPolyphaseChannelizerM2 extends AbstractComplexPolyphaseChann
|
||||
private PolyphaseChannelResultsBuffer mChannelResultsBuffer;
|
||||
private int mChannelResultsBufferSize = 2500;
|
||||
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
|
||||
@@ -95,6 +98,16 @@ public class ComplexPolyphaseChannelizerM2 extends AbstractComplexPolyphaseChann
|
||||
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
|
||||
* each channel has a minimum bandwidth of the default channel bandwidth (12.5 kHz).
|
||||
@@ -144,6 +157,8 @@ public class ComplexPolyphaseChannelizerM2 extends AbstractComplexPolyphaseChann
|
||||
@Override
|
||||
public void receive(ReusableComplexBuffer reusableComplexBuffer)
|
||||
{
|
||||
long start = System.nanoTime();
|
||||
|
||||
//Use the buffer's reference timestamp to update our timestamp manager (for timestamping output buffers)
|
||||
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
|
||||
reusableComplexBuffer.decrementUserCount();
|
||||
|
||||
mLog.debug("Duration: " + (System.nanoTime() - start));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -216,7 +233,6 @@ public class ComplexPolyphaseChannelizerM2 extends AbstractComplexPolyphaseChann
|
||||
|
||||
int half = getChannelCount() / 2;
|
||||
|
||||
// int outputOffset = getChannelCount() - half - 1;
|
||||
int outputOffset = getChannelCount() - 1;
|
||||
int outputIndex;
|
||||
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
|
||||
sampleIndexMap = mSampleIndexMap[(mColumnPointer == (mSamples.length - 1) ? 0 : mColumnPointer + 1)];
|
||||
// outputOffset = getChannelCount() + half - 1;
|
||||
outputOffset = getChannelCount() - 1;
|
||||
|
||||
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
|
||||
mFFT.complexInverse(processed, true);
|
||||
|
||||
processChannelResults(processed);
|
||||
mIFFTProcessor.receive(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)
|
||||
{
|
||||
mReusableBufferProvider.addBufferListener(mBufferProcessor);
|
||||
mPolyphaseChannelizer.start();
|
||||
mBufferProcessor.start();
|
||||
}
|
||||
}
|
||||
@@ -254,6 +255,7 @@ public class PolyphaseChannelManager implements ISourceEventProcessor
|
||||
{
|
||||
mReusableBufferProvider.removeBufferListener(mBufferProcessor);
|
||||
mBufferProcessor.stop();
|
||||
mPolyphaseChannelizer.stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -78,10 +78,7 @@ public abstract class AbstractReusableBufferQueue<T extends ReusableBuffer> impl
|
||||
mBufferCount++;
|
||||
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
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user