mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 16:47:31 -05:00
39 [WIP] cleans up the reusable buffers and creates both real and
complex variants.
This commit is contained in:
@@ -20,7 +20,7 @@ package io.github.dsheirer.dsp.filter.channelizer;
|
||||
|
||||
import io.github.dsheirer.sample.Broadcaster;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.sample.complex.reusable.ReusableComplexBuffer;
|
||||
import io.github.dsheirer.sample.buffer.ReusableComplexBuffer;
|
||||
import io.github.dsheirer.source.ISourceEventListener;
|
||||
import io.github.dsheirer.source.SourceEvent;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
@@ -18,7 +18,7 @@ package io.github.dsheirer.dsp.filter.channelizer;
|
||||
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.sample.SampleType;
|
||||
import io.github.dsheirer.sample.complex.reusable.ReusableComplexBuffer;
|
||||
import io.github.dsheirer.sample.buffer.ReusableComplexBuffer;
|
||||
import io.github.dsheirer.settings.SettingsManager;
|
||||
import io.github.dsheirer.source.ISourceEventProcessor;
|
||||
import io.github.dsheirer.source.SourceEvent;
|
||||
@@ -258,7 +258,7 @@ public class ChannelizerViewer extends JFrame
|
||||
|
||||
for(int x = 0; x < mChannelCount; x++)
|
||||
{
|
||||
TunerChannelSource source = mTestTuner.getChannelSourceManager().getSpecialSource(x);
|
||||
TunerChannelSource source = mTestTuner.getChannelSourceManager().getTestingSource(x);
|
||||
DiscreteChannelPanel channelPanel = new DiscreteChannelPanel(mSettingsManager, source, x);
|
||||
channelPanel.setDFTSize(mChannelPanelDFTSize);
|
||||
|
||||
@@ -327,8 +327,7 @@ public class ChannelizerViewer extends JFrame
|
||||
@Override
|
||||
public void receive(ReusableComplexBuffer reusableComplexBuffer)
|
||||
{
|
||||
mDFTProcessor.receive(reusableComplexBuffer.incrementUserCount());
|
||||
reusableComplexBuffer.decrementUserCount();
|
||||
mDFTProcessor.receive(reusableComplexBuffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -373,7 +372,8 @@ public class ChannelizerViewer extends JFrame
|
||||
mLog.debug("Samples:" + Arrays.toString(complexBuffer.getSamples()));
|
||||
}
|
||||
|
||||
mDFTProcessor.receive(complexBuffer.incrementUserCount());
|
||||
complexBuffer.incrementUserCount();
|
||||
mDFTProcessor.receive(complexBuffer);
|
||||
complexBuffer.decrementUserCount();
|
||||
}
|
||||
});
|
||||
@@ -420,7 +420,8 @@ public class ChannelizerViewer extends JFrame
|
||||
@Override
|
||||
public void receive(ReusableComplexBuffer reusableComplexBuffer)
|
||||
{
|
||||
mDFTProcessor.receive(reusableComplexBuffer.incrementUserCount());
|
||||
reusableComplexBuffer.incrementUserCount();
|
||||
mDFTProcessor.receive(reusableComplexBuffer);
|
||||
reusableComplexBuffer.decrementUserCount();
|
||||
}
|
||||
|
||||
@@ -476,7 +477,8 @@ public class ChannelizerViewer extends JFrame
|
||||
mLog.debug("Samples:" + Arrays.toString(complexBuffer.getSamples()));
|
||||
}
|
||||
|
||||
mDFTProcessor.receive(complexBuffer.incrementUserCount());
|
||||
complexBuffer.incrementUserCount();
|
||||
mDFTProcessor.receive(complexBuffer);
|
||||
complexBuffer.decrementUserCount();
|
||||
}
|
||||
});
|
||||
@@ -502,7 +504,8 @@ public class ChannelizerViewer extends JFrame
|
||||
@Override
|
||||
public void receive(ReusableComplexBuffer reusableComplexBuffer)
|
||||
{
|
||||
mDFTProcessor.receive(reusableComplexBuffer.incrementUserCount());
|
||||
reusableComplexBuffer.incrementUserCount();
|
||||
mDFTProcessor.receive(reusableComplexBuffer);
|
||||
reusableComplexBuffer.decrementUserCount();
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ 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.complex.reusable.ReusableComplexBuffer;
|
||||
import io.github.dsheirer.sample.buffer.ReusableComplexBuffer;
|
||||
import org.jtransforms.fft.FloatFFT_1D;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -28,15 +28,13 @@ import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class ScheduledBufferProcessor<E> implements Listener<E>
|
||||
public class ContinuousBufferProcessor<E> implements Listener<E>
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(ScheduledBufferProcessor.class);
|
||||
private final static Logger mLog = LoggerFactory.getLogger(ContinuousBufferProcessor.class);
|
||||
|
||||
private OverflowableTransferQueue<E> mQueue;
|
||||
private Listener<E> mListener;
|
||||
private ScheduledFuture<?> mScheduledFuture;
|
||||
private long mDistributionInterval;
|
||||
private int mMaxBuffersPerInterval;
|
||||
private AtomicBoolean mRunning = new AtomicBoolean();
|
||||
|
||||
/**
|
||||
@@ -52,14 +50,10 @@ public class ScheduledBufferProcessor<E> implements Listener<E>
|
||||
*
|
||||
* @param maximumSize of the internal queue (overflow happens when this is exceeded)
|
||||
* @param resetThreshold of the internal queue (overflow reset happens once queue size falls below this threshold
|
||||
* @param distributionInterval in milliseconds specifying how often the internal scheduled thread pool buffer
|
||||
* distributor should run
|
||||
* @param maxBuffersPerInterval maximum number of buffers to pull from the internal queue during each distribution
|
||||
* interval
|
||||
*/
|
||||
public ScheduledBufferProcessor(int maximumSize, int resetThreshold, long distributionInterval, int maxBuffersPerInterval)
|
||||
public ContinuousBufferProcessor(int maximumSize, int resetThreshold)
|
||||
{
|
||||
this(new OverflowableTransferQueue<>(maximumSize, resetThreshold), distributionInterval, maxBuffersPerInterval);
|
||||
this(new OverflowableTransferQueue<>(maximumSize, resetThreshold));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,16 +68,10 @@ public class ScheduledBufferProcessor<E> implements Listener<E>
|
||||
* notifications of overflow and reset state. Queue sizing parameters are specified in the constructor.
|
||||
*
|
||||
* @param queue implmentation of an overflowable transfer queue
|
||||
* @param distributionInterval in milliseconds specifying how often the internal scheduled thread pool buffer
|
||||
* distributor should run
|
||||
* @param maxBuffersPerInterval maximum number of buffers to pull from the internal queue during each distribution
|
||||
* interval
|
||||
*/
|
||||
public ScheduledBufferProcessor(OverflowableTransferQueue<E> queue, long distributionInterval, int maxBuffersPerInterval)
|
||||
public ContinuousBufferProcessor(OverflowableTransferQueue<E> queue)
|
||||
{
|
||||
mQueue = queue;
|
||||
mDistributionInterval = distributionInterval;
|
||||
mMaxBuffersPerInterval = maxBuffersPerInterval;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,6 +104,7 @@ public class ScheduledBufferProcessor<E> implements Listener<E>
|
||||
@Override
|
||||
public void receive(E e)
|
||||
{
|
||||
// mLog.debug(" Queuing: " + e.toString());
|
||||
mQueue.offer(e);
|
||||
}
|
||||
|
||||
@@ -126,7 +115,7 @@ public class ScheduledBufferProcessor<E> implements Listener<E>
|
||||
{
|
||||
if(mRunning.compareAndSet(false, true))
|
||||
{
|
||||
mScheduledFuture = ThreadPool.SCHEDULED.scheduleAtFixedRate(new Processor(), 0, mDistributionInterval, TimeUnit.MILLISECONDS);
|
||||
mScheduledFuture = ThreadPool.SCHEDULED.scheduleAtFixedRate(new Processor(), 0, 5, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,17 +164,22 @@ public class ScheduledBufferProcessor<E> implements Listener<E>
|
||||
{
|
||||
try
|
||||
{
|
||||
mQueue.drainTo(mBuffers, mMaxBuffersPerInterval);
|
||||
mQueue.drainTo(mBuffers, 10);
|
||||
|
||||
if(mListener != null)
|
||||
{
|
||||
for(E buffer: mBuffers)
|
||||
while(!mBuffers.isEmpty())
|
||||
{
|
||||
mListener.receive(buffer);
|
||||
for(E buffer: mBuffers)
|
||||
{
|
||||
// mLog.debug("Dispatching: " + buffer.toString() + " Count:" + mBuffers.size());
|
||||
mListener.receive(buffer);
|
||||
}
|
||||
|
||||
mBuffers.clear();
|
||||
mQueue.drainTo(mBuffers, 10);
|
||||
}
|
||||
}
|
||||
|
||||
mBuffers.clear();
|
||||
}
|
||||
catch(Throwable throwable)
|
||||
{
|
||||
@@ -15,10 +15,10 @@
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.dsp.filter.channelizer;
|
||||
|
||||
import io.github.dsheirer.sample.complex.reusable.OverflowableReusableBufferTransferQueue;
|
||||
import io.github.dsheirer.sample.complex.reusable.ReusableComplexBuffer;
|
||||
import io.github.dsheirer.sample.buffer.OverflowableReusableBufferTransferQueue;
|
||||
import io.github.dsheirer.sample.buffer.ReusableBuffer;
|
||||
|
||||
public class ScheduledReusableBufferProcessor extends ScheduledBufferProcessor<ReusableComplexBuffer>
|
||||
public class ContinuousReusableBufferProcessor<T extends ReusableBuffer> extends ContinuousBufferProcessor<T>
|
||||
{
|
||||
/**
|
||||
* Scheduled Reusable Buffer Processor combines an internal overflowable buffer with a scheduled runnable processing
|
||||
@@ -33,13 +33,9 @@ public class ScheduledReusableBufferProcessor extends ScheduledBufferProcessor<R
|
||||
*
|
||||
* @param maximumSize of the internal queue (overflow happens when this is exceeded)
|
||||
* @param resetThreshold of the internal queue (overflow reset happens once queue size falls below this threshold
|
||||
* @param distributionInterval in milliseconds specifying how often the internal scheduled thread pool buffer
|
||||
* distributor should run
|
||||
* @param maxBuffersPerInterval maximum number of buffers to pull from the internal queue during each distribution
|
||||
*/
|
||||
public ScheduledReusableBufferProcessor(int maximumSize, int resetThreshold, long distributionInterval, int maxBuffersPerInterval)
|
||||
public ContinuousReusableBufferProcessor(int maximumSize, int resetThreshold)
|
||||
{
|
||||
super(new OverflowableReusableBufferTransferQueue(maximumSize, resetThreshold),
|
||||
distributionInterval, maxBuffersPerInterval);
|
||||
super(new OverflowableReusableBufferTransferQueue<T>(maximumSize, resetThreshold));
|
||||
}
|
||||
}
|
||||
@@ -23,8 +23,8 @@ import io.github.dsheirer.dsp.filter.channelizer.output.TwoChannelOutputProcesso
|
||||
import io.github.dsheirer.dsp.filter.design.FilterDesignException;
|
||||
import io.github.dsheirer.sample.Broadcaster;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.sample.complex.reusable.IReusableComplexBufferProvider;
|
||||
import io.github.dsheirer.sample.complex.reusable.ReusableComplexBuffer;
|
||||
import io.github.dsheirer.sample.buffer.IReusableBufferProvider;
|
||||
import io.github.dsheirer.sample.buffer.ReusableComplexBuffer;
|
||||
import io.github.dsheirer.source.ISourceEventProcessor;
|
||||
import io.github.dsheirer.source.SourceEvent;
|
||||
import io.github.dsheirer.source.SourceException;
|
||||
@@ -52,13 +52,13 @@ public class PolyphaseChannelManager implements ISourceEventProcessor
|
||||
private static final int POLYPHASE_FILTER_TAPS_PER_CHANNEL = 17;
|
||||
|
||||
private Broadcaster<SourceEvent> mSourceEventBroadcaster = new Broadcaster<>();
|
||||
private IReusableComplexBufferProvider mReusableBufferProvider;
|
||||
private IReusableBufferProvider<ReusableComplexBuffer> mReusableBufferProvider;
|
||||
private List<PolyphaseChannelSource> mChannelSources = new CopyOnWriteArrayList<>();
|
||||
private ChannelCalculator mChannelCalculator;
|
||||
private ComplexPolyphaseChannelizerM2 mPolyphaseChannelizer;
|
||||
private ChannelSourceEventListener mChannelSourceEventListener = new ChannelSourceEventListener();
|
||||
private BufferSourceEventMonitor mBufferSourceEventMonitor = new BufferSourceEventMonitor();
|
||||
private ScheduledBufferProcessor mBufferProcessor;
|
||||
private ContinuousBufferProcessor<ReusableComplexBuffer> mBufferProcessor;
|
||||
private Map<Integer,float[]> mOutputProcessorFilters = new HashMap<>();
|
||||
|
||||
/**
|
||||
@@ -76,7 +76,8 @@ public class PolyphaseChannelManager implements ISourceEventProcessor
|
||||
* @param frequency of the provided complex buffer samples
|
||||
* @param sampleRate of the provided complex buffer samples
|
||||
*/
|
||||
public PolyphaseChannelManager(IReusableComplexBufferProvider reusableBufferProvider, long frequency, double sampleRate)
|
||||
public PolyphaseChannelManager(IReusableBufferProvider<ReusableComplexBuffer> reusableBufferProvider,
|
||||
long frequency, double sampleRate)
|
||||
{
|
||||
if(reusableBufferProvider == null)
|
||||
{
|
||||
@@ -95,7 +96,7 @@ public class PolyphaseChannelManager implements ISourceEventProcessor
|
||||
|
||||
mChannelCalculator = new ChannelCalculator(sampleRate, channelCount, frequency, CHANNEL_OVERSAMPLING);
|
||||
|
||||
mBufferProcessor = new ScheduledBufferProcessor(500, 100, 50, 50);
|
||||
mBufferProcessor = new ContinuousBufferProcessor(200, 50);
|
||||
mBufferProcessor.setListener(mBufferSourceEventMonitor);
|
||||
|
||||
updateChannelizerSampleRate(sampleRate);
|
||||
@@ -160,7 +161,7 @@ public class PolyphaseChannelManager implements ISourceEventProcessor
|
||||
return channelSource;
|
||||
}
|
||||
|
||||
public TunerChannelSource getSpecialChannel(int index)
|
||||
public TunerChannelSource getTestChannel(int index)
|
||||
{
|
||||
PolyphaseChannelSource channelSource = null;
|
||||
|
||||
@@ -181,6 +182,7 @@ public class PolyphaseChannelManager implements ISourceEventProcessor
|
||||
}
|
||||
catch(IllegalArgumentException iae)
|
||||
{
|
||||
mLog.error("Error", iae);
|
||||
}
|
||||
|
||||
return channelSource;
|
||||
@@ -582,15 +584,19 @@ public class PolyphaseChannelManager implements ISourceEventProcessor
|
||||
|
||||
if(mPolyphaseChannelizer != null)
|
||||
{
|
||||
mPolyphaseChannelizer.receive(reusableComplexBuffer.incrementUserCount());
|
||||
//User count management is handled by the channelizer
|
||||
mPolyphaseChannelizer.receive(reusableComplexBuffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
reusableComplexBuffer.decrementUserCount();
|
||||
}
|
||||
}
|
||||
catch(Throwable throwable)
|
||||
{
|
||||
mLog.error("Error", throwable);
|
||||
reusableComplexBuffer.decrementUserCount();
|
||||
}
|
||||
|
||||
reusableComplexBuffer.decrementUserCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,8 +17,8 @@ package io.github.dsheirer.dsp.filter.channelizer;
|
||||
|
||||
import io.github.dsheirer.dsp.filter.channelizer.output.IPolyphaseChannelOutputProcessor;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.sample.complex.reusable.ReusableBufferAssembler;
|
||||
import io.github.dsheirer.sample.complex.reusable.ReusableComplexBuffer;
|
||||
import io.github.dsheirer.sample.buffer.ReusableBufferAssembler;
|
||||
import io.github.dsheirer.sample.buffer.ReusableComplexBuffer;
|
||||
import io.github.dsheirer.source.SourceEvent;
|
||||
import io.github.dsheirer.source.tuner.channel.TunerChannel;
|
||||
import io.github.dsheirer.source.tuner.channel.TunerChannelSource;
|
||||
|
||||
@@ -23,8 +23,8 @@ import io.github.dsheirer.dsp.mixer.IOscillator;
|
||||
import io.github.dsheirer.dsp.mixer.LowPhaseNoiseOscillator;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.sample.SampleType;
|
||||
import io.github.dsheirer.sample.complex.reusable.ReusableBufferQueue;
|
||||
import io.github.dsheirer.sample.complex.reusable.ReusableComplexBuffer;
|
||||
import io.github.dsheirer.sample.buffer.ReusableComplexBuffer;
|
||||
import io.github.dsheirer.sample.buffer.ReusableComplexBufferQueue;
|
||||
import io.github.dsheirer.sample.real.IOverflowListener;
|
||||
import io.github.dsheirer.settings.SettingsManager;
|
||||
import io.github.dsheirer.source.SourceEvent;
|
||||
@@ -177,8 +177,7 @@ public class SynthesizerViewer extends JFrame
|
||||
@Override
|
||||
public void receive(ReusableComplexBuffer reusableComplexBuffer)
|
||||
{
|
||||
mDFTProcessor.receive(reusableComplexBuffer.incrementUserCount());
|
||||
reusableComplexBuffer.decrementUserCount();
|
||||
mDFTProcessor.receive(reusableComplexBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,8 +211,7 @@ public class SynthesizerViewer extends JFrame
|
||||
@Override
|
||||
public void receive(ReusableComplexBuffer reusableComplexBuffer)
|
||||
{
|
||||
mDFTProcessor.receive(reusableComplexBuffer.incrementUserCount());
|
||||
reusableComplexBuffer.decrementUserCount();
|
||||
mDFTProcessor.receive(reusableComplexBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,7 +275,7 @@ public class SynthesizerViewer extends JFrame
|
||||
private TwoChannelSynthesizerM2 mSynthesizer;
|
||||
private FS4DownConverter mFS4DownConverter = new FS4DownConverter();
|
||||
private int mSamplesPerCycle = CHANNEL_SAMPLE_RATE / DATA_GENERATOR_FRAME_RATE;
|
||||
private ReusableBufferQueue mReusableBufferQueue = new ReusableBufferQueue();
|
||||
private ReusableComplexBufferQueue mReusableComplexBufferQueue = new ReusableComplexBufferQueue("SynthesizerViewer");
|
||||
|
||||
public DataGenerationManager()
|
||||
{
|
||||
@@ -296,19 +294,22 @@ public class SynthesizerViewer extends JFrame
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
ReusableComplexBuffer channel1Buffer = mReusableBufferQueue.getBuffer(mSamplesPerCycle);
|
||||
ReusableComplexBuffer channel1Buffer = mReusableComplexBufferQueue.getBuffer(mSamplesPerCycle);
|
||||
getChannel1ControlPanel().getOscillator().generateComplex(channel1Buffer);
|
||||
|
||||
ReusableComplexBuffer channel2Buffer = mReusableBufferQueue.getBuffer(mSamplesPerCycle);
|
||||
ReusableComplexBuffer channel2Buffer = mReusableComplexBufferQueue.getBuffer(mSamplesPerCycle);
|
||||
getChannel2ControlPanel().getOscillator().generateComplex(channel2Buffer);
|
||||
|
||||
float[] synthesized = mSynthesizer.process(channel1Buffer.getSamples(), channel2Buffer.getSamples());
|
||||
mFS4DownConverter.mixComplex(synthesized);
|
||||
ReusableComplexBuffer synthesizedBuffer = mReusableBufferQueue.getBuffer(synthesized.length);
|
||||
ReusableComplexBuffer synthesizedBuffer = mReusableComplexBufferQueue.getBuffer(synthesized.length);
|
||||
|
||||
getChannel1Panel().receive(channel1Buffer.incrementUserCount());
|
||||
getChannel2Panel().receive(channel2Buffer.incrementUserCount());
|
||||
getSpectrumPanel().receive(synthesizedBuffer.incrementUserCount());
|
||||
channel1Buffer.incrementUserCount();
|
||||
getChannel1Panel().receive(channel1Buffer);
|
||||
channel2Buffer.incrementUserCount();
|
||||
getChannel2Panel().receive(channel2Buffer);
|
||||
synthesizedBuffer.incrementUserCount();
|
||||
getSpectrumPanel().receive(synthesizedBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ import io.github.dsheirer.dsp.filter.channelizer.PolyphaseChannelResultsBuffer;
|
||||
import io.github.dsheirer.dsp.mixer.IOscillator;
|
||||
import io.github.dsheirer.dsp.mixer.Oscillator;
|
||||
import io.github.dsheirer.sample.OverflowableTransferQueue;
|
||||
import io.github.dsheirer.sample.complex.reusable.ReusableBufferAssembler;
|
||||
import io.github.dsheirer.sample.buffer.ReusableBufferAssembler;
|
||||
import io.github.dsheirer.sample.real.IOverflowListener;
|
||||
import io.github.dsheirer.source.Source;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
package io.github.dsheirer.dsp.filter.channelizer.output;
|
||||
|
||||
import io.github.dsheirer.dsp.filter.channelizer.PolyphaseChannelResultsBuffer;
|
||||
import io.github.dsheirer.sample.complex.reusable.ReusableBufferAssembler;
|
||||
import io.github.dsheirer.sample.buffer.ReusableBufferAssembler;
|
||||
import io.github.dsheirer.source.Source;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
package io.github.dsheirer.dsp.filter.channelizer.output;
|
||||
|
||||
import io.github.dsheirer.dsp.filter.channelizer.PolyphaseChannelResultsBuffer;
|
||||
import io.github.dsheirer.sample.complex.reusable.ReusableBufferAssembler;
|
||||
import io.github.dsheirer.sample.buffer.ReusableBufferAssembler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ package io.github.dsheirer.dsp.filter.channelizer.output;
|
||||
import io.github.dsheirer.dsp.filter.channelizer.PolyphaseChannelResultsBuffer;
|
||||
import io.github.dsheirer.dsp.filter.channelizer.TwoChannelSynthesizerM2;
|
||||
import io.github.dsheirer.dsp.mixer.FS4DownConverter;
|
||||
import io.github.dsheirer.sample.complex.reusable.ReusableBufferAssembler;
|
||||
import io.github.dsheirer.sample.buffer.ReusableBufferAssembler;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
@@ -17,13 +17,13 @@ package io.github.dsheirer.dsp.filter.fir.complex;
|
||||
|
||||
import io.github.dsheirer.dsp.filter.fir.FIRFilter;
|
||||
import io.github.dsheirer.dsp.filter.fir.real.RealFIRFilter;
|
||||
import io.github.dsheirer.sample.buffer.ReusableComplexBuffer;
|
||||
import io.github.dsheirer.sample.buffer.ReusableComplexBufferQueue;
|
||||
import io.github.dsheirer.sample.complex.Complex;
|
||||
import io.github.dsheirer.sample.complex.reusable.ReusableBufferQueue;
|
||||
import io.github.dsheirer.sample.complex.reusable.ReusableComplexBuffer;
|
||||
|
||||
public class ComplexFIRFilter extends FIRFilter
|
||||
{
|
||||
private ReusableBufferQueue mReusableBufferQueue = new ReusableBufferQueue("Complex FIR Filter");
|
||||
private ReusableComplexBufferQueue mReusableComplexBufferQueue = new ReusableComplexBufferQueue("Complex FIR Filter");
|
||||
private RealFIRFilter mIFilter;
|
||||
private RealFIRFilter mQFilter;
|
||||
|
||||
@@ -84,7 +84,7 @@ public class ComplexFIRFilter extends FIRFilter
|
||||
*/
|
||||
public ReusableComplexBuffer filter(ReusableComplexBuffer originalBuffer)
|
||||
{
|
||||
ReusableComplexBuffer filteredBuffer = mReusableBufferQueue.getBuffer(originalBuffer.getSamples().length);
|
||||
ReusableComplexBuffer filteredBuffer = mReusableComplexBufferQueue.getBuffer(originalBuffer.getSamples().length);
|
||||
filteredBuffer.setTimestamp(originalBuffer.getTimestamp());
|
||||
|
||||
float[] samples = originalBuffer.getSamples();
|
||||
@@ -107,6 +107,6 @@ public class ComplexFIRFilter extends FIRFilter
|
||||
{
|
||||
mIFilter.dispose();
|
||||
mQFilter.dispose();
|
||||
mReusableBufferQueue.dispose();
|
||||
mReusableComplexBufferQueue.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* sdr-trunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program.
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.dsp.filter.resample;
|
||||
|
||||
import com.laszlosystems.libresample4j.Resampler;
|
||||
import io.github.dsheirer.module.Module;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.source.ISourceEventListener;
|
||||
import io.github.dsheirer.source.SourceEvent;
|
||||
|
||||
public class AudioResampler extends Module implements ISourceEventListener
|
||||
{
|
||||
private Resampler mResampler;
|
||||
|
||||
public AudioResampler(double inputRate, double outputRate)
|
||||
{
|
||||
double resampleRate = outputRate / inputRate;
|
||||
|
||||
mResampler = new Resampler(true, resampleRate, resampleRate);
|
||||
}
|
||||
|
||||
public float[] resample(float[] samples)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Listener<SourceEvent> getSourceEventListener()
|
||||
{
|
||||
//TODO: we should get the channel sample rate and setup the resampler to output 8 kHz audio
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
/*******************************************************************************
|
||||
* sdr-trunk
|
||||
* Copyright (C) 2014-2018 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program.
|
||||
* If not, see <http://www.gnu.org/licenses/>
|
||||
*
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.dsp.filter.resample;
|
||||
|
||||
import com.laszlosystems.libresample4j.Resampler;
|
||||
import com.laszlosystems.libresample4j.SampleBuffers;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.sample.buffer.ReusableBuffer;
|
||||
import io.github.dsheirer.sample.buffer.ReusableBufferQueue;
|
||||
import io.github.dsheirer.sample.real.RealBuffer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
public class RealResampler implements Listener<RealBuffer>
|
||||
{
|
||||
protected static final Logger mLog = LoggerFactory.getLogger(RealResampler.class);
|
||||
|
||||
private Resampler mResampler;
|
||||
private Listener<ReusableBuffer> mResampledListener;
|
||||
private BufferManager mBufferManager = new BufferManager();
|
||||
private ReusableBufferQueue mReusableBufferQueue = new ReusableBufferQueue("RealResampler");
|
||||
private double mResampleFactor;
|
||||
|
||||
/**
|
||||
* Resampler for real sample buffers.
|
||||
* @param inputRate
|
||||
* @param outputRate
|
||||
*/
|
||||
public RealResampler(double inputRate, double outputRate)
|
||||
{
|
||||
mResampleFactor = outputRate / inputRate;
|
||||
mResampler = new Resampler(true, mResampleFactor, mResampleFactor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Primary input method to the resampler
|
||||
* @param realBuffer to resample
|
||||
*/
|
||||
@Override
|
||||
public void receive(RealBuffer realBuffer)
|
||||
{
|
||||
mBufferManager.load(realBuffer);
|
||||
mResampler.process(mResampleFactor, mBufferManager, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the listener to receive the resampled buffer output
|
||||
* @param resampledBufferListener to receive buffers
|
||||
*/
|
||||
public void setListener(Listener<ReusableBuffer> resampledBufferListener)
|
||||
{
|
||||
mResampledListener = resampledBufferListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Buffer manager for input and output buffers used during the resampling process. The manager will
|
||||
* auto-resize the input and output buffers to meet the size of the incoming sample buffers.
|
||||
*/
|
||||
public class BufferManager implements SampleBuffers
|
||||
{
|
||||
private int mBufferLength = 1000;
|
||||
private FloatBuffer mInputBuffer = ByteBuffer.allocate(mBufferLength).asFloatBuffer();
|
||||
private FloatBuffer mOutputBuffer = ByteBuffer.allocate(mBufferLength).asFloatBuffer();
|
||||
|
||||
public void resize(int bufferLength)
|
||||
{
|
||||
int floatBufferLength = bufferLength * 4;
|
||||
|
||||
FloatBuffer inputBuffer = ByteBuffer.allocate(floatBufferLength).asFloatBuffer();
|
||||
inputBuffer.put(mInputBuffer);
|
||||
mInputBuffer = inputBuffer;
|
||||
|
||||
FloatBuffer outputBuffer = ByteBuffer.allocate(floatBufferLength).asFloatBuffer();
|
||||
outputBuffer.put(mOutputBuffer);
|
||||
mOutputBuffer = outputBuffer;
|
||||
|
||||
mBufferLength = bufferLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Current length of the input and output buffers
|
||||
*/
|
||||
public int getBufferLength()
|
||||
{
|
||||
return mBufferLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Queues the buffer sample for resampling
|
||||
*/
|
||||
public void load(RealBuffer realBuffer)
|
||||
{
|
||||
int remaining = mInputBuffer.remaining();
|
||||
|
||||
if(mInputBuffer.remaining() < realBuffer.getSamples().length)
|
||||
{
|
||||
resize(mInputBuffer.capacity() + (realBuffer.getSamples().length - mInputBuffer.remaining()));
|
||||
}
|
||||
|
||||
mInputBuffer.put(realBuffer.getSamples());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInputBufferLength()
|
||||
{
|
||||
return mInputBuffer.position();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOutputBufferLength()
|
||||
{
|
||||
return mOutputBuffer.remaining();
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides input to the resampler
|
||||
*/
|
||||
@Override
|
||||
public void produceInput(float[] samples, int offset, int length)
|
||||
{
|
||||
mInputBuffer.flip();
|
||||
mInputBuffer.get(samples, offset, length);
|
||||
mInputBuffer.compact();
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives output from the resampler and dispatches output buffers periodically.
|
||||
*/
|
||||
@Override
|
||||
public void consumeOutput(float[] samples, int offset, int length)
|
||||
{
|
||||
mOutputBuffer.put(samples, offset, length);
|
||||
|
||||
while(mOutputBuffer.position() > 200)
|
||||
{
|
||||
ReusableBuffer outputBuffer = mReusableBufferQueue.getBuffer(200);
|
||||
|
||||
mOutputBuffer.flip();
|
||||
mOutputBuffer.get(outputBuffer.getSamples());
|
||||
mOutputBuffer.compact();
|
||||
|
||||
if(mResampledListener != null)
|
||||
{
|
||||
outputBuffer.incrementUserCount();
|
||||
mResampledListener.receive(outputBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,11 +16,11 @@
|
||||
package io.github.dsheirer.dsp.gain;
|
||||
|
||||
import io.github.dsheirer.buffer.FloatCircularBuffer;
|
||||
import io.github.dsheirer.sample.buffer.ReusableComplexBuffer;
|
||||
import io.github.dsheirer.sample.buffer.ReusableComplexBufferQueue;
|
||||
import io.github.dsheirer.sample.complex.Complex;
|
||||
import io.github.dsheirer.sample.complex.ComplexBuffer;
|
||||
import io.github.dsheirer.sample.complex.ComplexSampleListener;
|
||||
import io.github.dsheirer.sample.complex.reusable.ReusableBufferQueue;
|
||||
import io.github.dsheirer.sample.complex.reusable.ReusableComplexBuffer;
|
||||
|
||||
public class ComplexFeedForwardGainControl implements ComplexSampleListener
|
||||
{
|
||||
@@ -29,7 +29,7 @@ public class ComplexFeedForwardGainControl implements ComplexSampleListener
|
||||
|
||||
private ComplexSampleListener mListener;
|
||||
private FloatCircularBuffer mEnvelopeHistory;
|
||||
private ReusableBufferQueue mReusableBufferQueue = new ReusableBufferQueue("ComplexFeedForwardGainControl");
|
||||
private ReusableComplexBufferQueue mReusableComplexBufferQueue = new ReusableComplexBufferQueue("ComplexFeedForwardGainControl");
|
||||
|
||||
private float mMaxEnvelope = 0.0f;
|
||||
private float mGain = 1.0f;
|
||||
@@ -157,7 +157,7 @@ public class ComplexFeedForwardGainControl implements ComplexSampleListener
|
||||
{
|
||||
float[] samples = buffer.getSamples();
|
||||
|
||||
ReusableComplexBuffer filteredBuffer = mReusableBufferQueue.getBuffer(samples.length);
|
||||
ReusableComplexBuffer filteredBuffer = mReusableComplexBufferQueue.getBuffer(samples.length);
|
||||
filteredBuffer.setTimestamp(buffer.getTimestamp());
|
||||
|
||||
float[] filtered = filteredBuffer.getSamples();
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.dsp.mixer;
|
||||
|
||||
import io.github.dsheirer.sample.buffer.ReusableComplexBuffer;
|
||||
import io.github.dsheirer.sample.complex.Complex;
|
||||
import io.github.dsheirer.sample.complex.reusable.ReusableComplexBuffer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -160,7 +160,7 @@ public abstract class AbstractOscillator implements IOscillator
|
||||
@Override
|
||||
public void generateComplex(ReusableComplexBuffer reusableComplexBuffer)
|
||||
{
|
||||
int sampleCount = reusableComplexBuffer.getSampleLength();
|
||||
int sampleCount = reusableComplexBuffer.getSampleCount();
|
||||
|
||||
if(mSampleBuffer == null || mSampleBuffer.capacity() != sampleCount * 2)
|
||||
{
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
******************************************************************************/
|
||||
package io.github.dsheirer.dsp.mixer;
|
||||
|
||||
import io.github.dsheirer.sample.complex.reusable.ReusableComplexBuffer;
|
||||
import io.github.dsheirer.sample.buffer.ReusableComplexBuffer;
|
||||
|
||||
/**
|
||||
* Oscillator interface.
|
||||
|
||||
@@ -17,9 +17,9 @@ package io.github.dsheirer.dsp.psk;
|
||||
|
||||
import io.github.dsheirer.dsp.psk.pll.IPhaseLockedLoop;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.sample.buffer.ReusableComplexBuffer;
|
||||
import io.github.dsheirer.sample.complex.Complex;
|
||||
import io.github.dsheirer.sample.complex.ComplexSampleListener;
|
||||
import io.github.dsheirer.sample.complex.reusable.ReusableComplexBuffer;
|
||||
|
||||
public abstract class PSKDemodulator<T> implements ComplexSampleListener
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user