Memory/CPU performance improvement and Audio/Mixer source restructuring

Converted to use float primitives and to keep samples in buffer format until the sample rate is decimated to 48kHz.  
Added new non-recursive, CIC decimation filter -- untested

Updated sound card/mixer input source management.  Now testing for mono/stereo support for each card and limiting channel choices accordingly.  Separated the mixersource into a ComplexMixer and and SimplexMixerSource.  The ComplexMixer is used for sound card based tuners like the funcube.  The SimplexMixerSource is used for demodulated sound card inputs.

Interfaces for sample handling - standardized on using 'Complex' to indicate I/Q samples and 'Simplex' to indicate demodulated float samples.  The processing chain now accepts either a decimated (48k) list of complex samples from a tuner channel source, or a 48k simplex buffer (array of demodulated float samples).

Resolved issue with HackRF tuner not applying tuner configuration information.
This commit is contained in:
dennis.sheirer
2014-10-26 10:11:30 +00:00
parent 0ad710fea2
commit e61c3a891c
71 changed files with 1754 additions and 619 deletions

View File

@@ -17,6 +17,8 @@ import javax.swing.SwingUtilities;
import net.miginfocom.swing.MigLayout;
import sample.Listener;
import sample.complex.ComplexBuffer;
import sample.simplex.SimplexSampleListener;
import settings.ColorSetting.ColorSettingName;
import settings.ColorSettingMenuItem;
import settings.Setting;
@@ -43,7 +45,7 @@ import dsp.filter.Window.WindowType;
public class ChannelSpectrumPanel extends JPanel
implements ChannelEventListener,
Listener<Float>,
SimplexSampleListener,
SettingChangeListener,
SpectralDisplayAdjuster
{
@@ -62,7 +64,7 @@ public class ChannelSpectrumPanel extends JPanel
private int mSpectrumAveragingSize;
private int mSampleBufferSize = 2400;
private Float[] mSamples = new Float[ mSampleBufferSize ];
private float[] mSamples = new float[ mSampleBufferSize ];
private int mSamplePointer = 0;
private DecimatingSampleAssembler mDecimatingSampleAssembler;
@@ -204,7 +206,7 @@ public class ChannelSpectrumPanel extends JPanel
{
if( mEnabled.get() && mCurrentChannel != null && mCurrentChannel.isProcessing() )
{
mCurrentChannel.getProcessingChain().addFloatListener( this );
mCurrentChannel.getProcessingChain().addSimplexListener( (SimplexSampleListener)this );
mDFTProcessor.start();
}
}
@@ -214,7 +216,7 @@ public class ChannelSpectrumPanel extends JPanel
if( mCurrentChannel != null && mCurrentChannel.isProcessing() )
{
mCurrentChannel.getProcessingChain().removeFloatListener( this );
mCurrentChannel.getProcessingChain().removeSimplexListener( (SimplexSampleListener)this );
}
mDFTProcessor.stop();
@@ -250,7 +252,7 @@ public class ChannelSpectrumPanel extends JPanel
}
@Override
public void receive( Float sample )
public void receive( float sample )
{
mDecimatingSampleAssembler.receive( sample );
}
@@ -470,37 +472,36 @@ public class ChannelSpectrumPanel extends JPanel
mSpectrumPanel.setBaseline( baseline );
}
public class DecimatingSampleAssembler implements Listener<Float>
public class DecimatingSampleAssembler
{
private FloatHalfBandFilter mDecimationFilter = new FloatHalfBandFilter(
Filters.FIR_HALF_BAND_31T_ONE_EIGHTH_FCO, 1.0002 );
private SampleAssembler mSampleAssembler;
public DecimatingSampleAssembler( Listener<Float[]> listener )
public DecimatingSampleAssembler( Listener<ComplexBuffer> listener )
{
mSampleAssembler = new SampleAssembler( listener );
mDecimationFilter.setListener( mSampleAssembler );
}
@Override
public void receive( Float sample )
public void receive( float sample )
{
mDecimationFilter.receive( sample );
}
}
public class SampleAssembler implements Listener<Float>
public class SampleAssembler implements SimplexSampleListener
{
private Listener<Float[]> mListener;
private Listener<ComplexBuffer> mListener;
public SampleAssembler( Listener<Float[]> listener )
public SampleAssembler( Listener<ComplexBuffer> listener )
{
mListener = listener;
}
@Override
public void receive( Float sample )
public void receive( float sample )
{
mSamples[ mSamplePointer++ ] = sample;
@@ -508,15 +509,16 @@ public class ChannelSpectrumPanel extends JPanel
{
if( mEnabled.get() )
{
mListener.receive( Arrays.copyOf( mSamples,
mSamples.length ) );
float[] copy = Arrays.copyOf( mSamples, mSamples.length );
mListener.receive( new ComplexBuffer( copy ) );
}
mSamplePointer = 0;
if( mSamples.length != mSampleBufferSize )
{
mSamples = new Float[ mSampleBufferSize ];
mSamples = new float[ mSampleBufferSize ];
}
}
}

View File

@@ -31,6 +31,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sample.Listener;
import sample.complex.ComplexBuffer;
import source.Source;
import source.Source.SampleType;
import source.tuner.FrequencyChangeEvent;
@@ -43,7 +44,7 @@ import dsp.filter.Window.WindowType;
* Processes both complex samples or float samples and dispatches a float array
* of DFT results, using configurable fft size and output dispatch timelines.
*/
public class DFTProcessor implements Listener<Float[]>,
public class DFTProcessor implements Listener<ComplexBuffer>,
FrequencyChangeListener
{
private final static Logger mLog =
@@ -52,8 +53,8 @@ public class DFTProcessor implements Listener<Float[]>,
private CopyOnWriteArrayList<DFTResultsConverter> mListeners =
new CopyOnWriteArrayList<DFTResultsConverter>();
private ArrayBlockingQueue<Float[]> mQueue =
new ArrayBlockingQueue<Float[]>( 200 );
private ArrayBlockingQueue<ComplexBuffer> mQueue =
new ArrayBlockingQueue<ComplexBuffer>( 200 );
private ScheduledExecutorService mScheduler =
Executors.newScheduledThreadPool(1);
@@ -74,7 +75,7 @@ public class DFTProcessor implements Listener<Float[]>,
private float mNewFloatResidual;
private float[] mPreviousFrame = new float[ 8192 ];
private Float[] mCurrentBuffer;
private float[] mCurrentBuffer;
private int mCurrentBufferPointer = 0;
private SampleType mSampleType;
@@ -222,16 +223,16 @@ public class DFTProcessor implements Listener<Float[]>,
* Places the sample into a transfer queue for future processing.
*/
@Override
public void receive( Float[] samples )
public void receive( ComplexBuffer sampleBuffer )
{
if( !mQueue.offer( samples ) )
if( !mQueue.offer( sampleBuffer ) )
{
mLog.error( "DFTProcessor - [" + mSampleType.toString()
+ "]queue is full, purging queue, "
+ "samples[" + samples + "]" );
+ "samples[" + sampleBuffer + "]" );
mQueue.clear();
mQueue.offer( samples );
mQueue.offer( sampleBuffer );
}
}
@@ -241,7 +242,8 @@ public class DFTProcessor implements Listener<Float[]>,
try
{
mCurrentBuffer = mQueue.take();
ComplexBuffer buffer = mQueue.take();
mCurrentBuffer = buffer.getSamples();
}
catch ( InterruptedException e )
{

View File

@@ -47,6 +47,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sample.Listener;
import sample.complex.ComplexBuffer;
import settings.ColorSetting;
import settings.ColorSetting.ColorSettingName;
import settings.ColorSettingMenuItem;
@@ -89,7 +90,7 @@ import dsp.filter.Window.WindowType;
*/
public class SpectralDisplayPanel extends JPanel
implements ChannelEventListener,
Listener<Float[]>,
Listener<ComplexBuffer>,
FrequencyChangeListener,
SettingChangeListener,
TunerSelectionListener
@@ -359,9 +360,9 @@ public class SpectralDisplayPanel extends JPanel
}
@Override
public void receive( Float[] samples )
public void receive( ComplexBuffer sampleBuffer )
{
mDFTProcessor.receive( samples );
mDFTProcessor.receive( sampleBuffer );
}
/**
@@ -382,7 +383,7 @@ public class SpectralDisplayPanel extends JPanel
mTuner.addListener( (FrequencyChangeListener)this );
//Register the dft processor to receive samples from the tuner
mTuner.addListener( (Listener<Float[]>)mDFTProcessor );
mTuner.addListener( (Listener<ComplexBuffer>)mDFTProcessor );
//Fire frequency and sample rate change events so that everyone
//can init
@@ -413,7 +414,7 @@ public class SpectralDisplayPanel extends JPanel
mTuner.removeListener( (FrequencyChangeListener)this );
//Deregister the dft processor from receiving samples
mTuner.removeListener( (Listener<Float[]>)mDFTProcessor );
mTuner.removeListener( (Listener<ComplexBuffer>)mDFTProcessor );
mTuner = null;
}
}