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

@@ -20,11 +20,12 @@ package decode;
import java.util.ArrayList;
import java.util.List;
import dsp.afc.AutomaticFrequencyControl;
import message.Message;
import sample.Broadcaster;
import sample.Listener;
import sample.complex.ComplexSample;
import sample.simplex.SimplexSampleBroadcaster;
import sample.simplex.SimplexSampleListener;
import source.Source.SampleType;
import eventlog.MessageEventLogger;
@@ -32,25 +33,36 @@ public abstract class Decoder implements Listener<Message>
{
private MessageEventLogger mEventLogger;
private Broadcaster<Message> mMessageBroadcaster = new Broadcaster<Message>();
private Broadcaster<Float> mFloatBroadcaster = new Broadcaster<Float>();
private SimplexSampleBroadcaster mSimplexBroadcaster = new SimplexSampleBroadcaster();
private Broadcaster<ComplexSample> mComplexBroadcaster =
new Broadcaster<ComplexSample>();
protected SampleType mSourceSampleType;
protected ArrayList<Decoder> mAuxiliaryDecoders = new ArrayList<Decoder>();
/**
* Abstract decoder class.
*
* @param sampleType - complex (I/Q) or simplex (demodulated) sample type.
* Each decoder instance will be configured to receive either complex or
* simplex samples. When configured to receive complex samples, the
* decoder will implement a demodulator component and feed the output from
* that demodulator back onto itself via the simplex sample interface, so
* that any added auxiliary decoders will then receive the demodulated
* output stream.
*/
public Decoder( SampleType sampleType )
{
mSourceSampleType = sampleType;
}
/**
* Returns a float listener interface for connecting this decoder to a
* float stream provider
* Returns a simplex (ie demodulated) sample listener interface for
* connecting this decoder to a simplex sample stream provider
*/
public Listener<Float> getFloatReceiver()
public SimplexSampleListener getSimplexReceiver()
{
return (Listener<Float>)mFloatBroadcaster;
return mSimplexBroadcaster;
}
/**
@@ -61,16 +73,12 @@ public abstract class Decoder implements Listener<Message>
{
return (Listener<ComplexSample>)mComplexBroadcaster;
}
/**
* Returns the primary decoder type for this decoder
*/
public abstract DecoderType getType();
public void addAuxiliaryDecoder( Decoder decoder )
{
mAuxiliaryDecoders.add( decoder );
mFloatBroadcaster.addListener( decoder.getFloatReceiver() );
decoder.addMessageListener( this );
}
/**
* Cleanup method. Invoke this method after stop and before delete.
*/
@@ -85,30 +93,66 @@ public abstract class Decoder implements Listener<Message>
mMessageBroadcaster.clear();
mComplexBroadcaster.clear();
mFloatBroadcaster.clear();
mSimplexBroadcaster.clear();
}
/**
* Adds the auxiliary decoder (piggyback) to this decoder.
*
* Note: we assume that the auxiliary decoder is designed to receive
* demodulated samples, thus we automatically register the aux decoder to
* receive the demodulated sample stream.
*
* Registers this decoder to receive the message output stream from the
* auxiliary decoder, so that those messages can be echoed and included in
* the consolidated message stream to all message listeners registered on
* the primary decoder.
*/
public void addAuxiliaryDecoder( Decoder decoder )
{
mAuxiliaryDecoders.add( decoder );
mSimplexBroadcaster.addListener( decoder.getSimplexReceiver() );
decoder.addMessageListener( this );
}
/**
* Returns a list of all auxiliary decoders that have been added to this
* processing chain
*/
public List<Decoder> getAuxiliaryDecoders()
{
return mAuxiliaryDecoders;
}
/**
* Sets the MessageEventLogger for this processing chain
*/
public void setEventLogger( MessageEventLogger eventLogger )
{
mEventLogger = eventLogger;
}
/**
* Returns the MessageEventLogger for this processing chain
*/
public MessageEventLogger getEventLogger()
{
return mEventLogger;
}
/**
* Main receiver method for all demodulators to send their decoded messages
* so that they will be broadcast to all registered listeners
*/
@Override
public void receive( Message message )
{
send( message );
}
/**
* Broadcasts the message to all registered listeners
*/
public void send( Message message )
{
if( mMessageBroadcaster != null )
@@ -116,34 +160,57 @@ public abstract class Decoder implements Listener<Message>
mMessageBroadcaster.receive( message );
}
}
/**
* Adds a listener to receiving decoded messages from all attached decoders
*/
public void addMessageListener( Listener<Message> listener )
{
mMessageBroadcaster.addListener( listener );
}
/**
* Removes the listener from receiving decoded messages from all attached
* decoders
*/
public void removeMessageListener( Listener<Message> listener )
{
mMessageBroadcaster.removeListener( listener );
}
public void addFloatListener( Listener<Float> listener )
{
mFloatBroadcaster.addListener( listener );
}
public abstract void addUnfilteredFloatListener( Listener<Float> listener );
/**
* Adds a simplex sample listener to receive unfiltered demodulated samples
*/
public abstract void addUnfilteredSimplexSampleListener( SimplexSampleListener listener );
public void removeFloatListener( Listener<Float> listener )
/**
* Adds a simplex sample listener to receive demodulated samples
*/
public void addSimplexSampleListener( SimplexSampleListener listener )
{
mFloatBroadcaster.removeListener( listener );
mSimplexBroadcaster.addListener( listener );
}
/**
* Remove the simplex sample listener from receiving demodulated samples
*/
public void removeSimplexListener( SimplexSampleListener listener )
{
mSimplexBroadcaster.removeListener( listener );
}
/**
* Adds a complex (I/Q) sample listener to receive copy of the inbound
* complex sample stream
*/
public void addComplexListener( Listener<ComplexSample> listener )
{
mComplexBroadcaster.addListener( listener );
}
/**
* Removes the complex (I/Q) sample listener from receiving samples
*/
public void removeComplexListener( Listener<ComplexSample> listener )
{
mComplexBroadcaster.removeListener( listener );

View File

@@ -1,6 +1,6 @@
package decode.am;
import sample.Listener;
import sample.simplex.SimplexSampleListener;
import source.Source.SampleType;
import decode.Decoder;
import decode.DecoderType;
@@ -61,7 +61,7 @@ public class AMDecoder extends Decoder
mDCRemovalFilter.setListener( mLowPassFilter );
mLowPassFilter.setListener( this.getFloatReceiver() );
mLowPassFilter.setListener( this.getSimplexReceiver() );
}
}
@@ -72,7 +72,7 @@ public class AMDecoder extends Decoder
}
@Override
public void addUnfilteredFloatListener( Listener<Float> listener )
public void addUnfilteredSimplexSampleListener( SimplexSampleListener listener )
{
mDemodulator.addListener( listener );
}

View File

@@ -26,6 +26,7 @@ import java.util.ArrayList;
import java.util.List;
import sample.Listener;
import sample.simplex.SimplexSampleListener;
import source.Source.SampleType;
import alias.AliasList;
import bits.MessageFramer;
@@ -75,7 +76,7 @@ public class Fleetsync2Decoder extends Decoder implements Instrumentable
mDecimationFilter = new FloatHalfBandFilter(
Filters.FIR_HALF_BAND_31T_ONE_EIGHTH_FCO, 1.0002 );
addFloatListener( mDecimationFilter );
addSimplexSampleListener( mDecimationFilter );
mBandPassFilter = new FloatFIRFilter(
Filters.FIRBP_1200FSK_24000FS.getCoefficients(), 1.02 );
@@ -115,9 +116,9 @@ public class Fleetsync2Decoder extends Decoder implements Instrumentable
* Returns a float listener interface for connecting this decoder to a
* float stream provider
*/
public Listener<Float> getFloatReceiver()
public SimplexSampleListener getSimplexReceiver()
{
return (Listener<Float>)mDecimationFilter;
return (SimplexSampleListener)mDecimationFilter;
}
@Override
@@ -147,7 +148,7 @@ public class Fleetsync2Decoder extends Decoder implements Instrumentable
{
case INSTRUMENT_INPUT:
FloatTap inputTap = (FloatTap)tap;
addFloatListener( inputTap );
addSimplexSampleListener( inputTap );
break;
case INSTRUMENT_BANDPASS_FILTER_TO_FSK2_DEMOD:
FloatTap bpTap = (FloatTap)tap;
@@ -171,7 +172,7 @@ public class Fleetsync2Decoder extends Decoder implements Instrumentable
{
case INSTRUMENT_INPUT:
FloatTap inputTap = (FloatTap)tap;
removeFloatListener( inputTap );
removeSimplexListener( inputTap );
break;
case INSTRUMENT_BANDPASS_FILTER_TO_FSK2_DEMOD:
mBandPassFilter.setListener( mFSKDecoder );
@@ -183,7 +184,7 @@ public class Fleetsync2Decoder extends Decoder implements Instrumentable
}
@Override
public void addUnfilteredFloatListener( Listener<Float> listener )
public void addUnfilteredSimplexSampleListener( SimplexSampleListener listener )
{
//Not implemented
}

View File

@@ -24,7 +24,7 @@ import java.util.ArrayList;
import java.util.List;
import message.MessageDirection;
import sample.Listener;
import sample.simplex.SimplexSampleListener;
import source.Source.SampleType;
import alias.AliasList;
import bits.MessageFramer;
@@ -81,7 +81,7 @@ public class LTRNetDecoder extends Decoder implements Instrumentable
mDCRemovalFilter = new DCRemovalFilter2( sDC_REMOVAL_RATIO );
mDemodulator.addListener( mDCRemovalFilter );
mDCRemovalFilter.setListener( this.getFloatReceiver() );
mDCRemovalFilter.setListener( this.getSimplexReceiver() );
}
mLTRFSKDecoder = new LTRFSKDecoder();
@@ -96,7 +96,7 @@ public class LTRNetDecoder extends Decoder implements Instrumentable
}
else
{
this.addFloatListener( mLTRFSKDecoder );
this.addSimplexSampleListener( mLTRFSKDecoder );
}
if( direction == MessageDirection.OSW )
@@ -151,7 +151,7 @@ public class LTRNetDecoder extends Decoder implements Instrumentable
}
@Override
public void addUnfilteredFloatListener( Listener<Float> listener )
public void addUnfilteredSimplexSampleListener( SimplexSampleListener listener )
{
if( mDemodulator != null )
{

View File

@@ -18,7 +18,7 @@
package decode.ltrstandard;
import message.MessageDirection;
import sample.Listener;
import sample.simplex.SimplexSampleListener;
import source.Source.SampleType;
import alias.AliasList;
import bits.MessageFramer;
@@ -73,7 +73,7 @@ public class LTRStandardDecoder extends Decoder
mDCRemovalFilter = new DCRemovalFilter2( sDC_REMOVAL_RATIO );
mDemodulator.addListener( mDCRemovalFilter );
mDCRemovalFilter.setListener( this.getFloatReceiver() );
mDCRemovalFilter.setListener( this.getSimplexReceiver() );
}
mLTRFSKDecoder = new LTRFSKDecoder();
@@ -88,7 +88,7 @@ public class LTRStandardDecoder extends Decoder
}
else
{
this.addFloatListener( mLTRFSKDecoder );
this.addSimplexSampleListener( mLTRFSKDecoder );
}
if( direction == MessageDirection.OSW )
@@ -118,7 +118,7 @@ public class LTRStandardDecoder extends Decoder
}
@Override
public void addUnfilteredFloatListener( Listener<Float> listener )
public void addUnfilteredSimplexSampleListener( SimplexSampleListener listener )
{
if( mDemodulator != null )
{

View File

@@ -25,7 +25,7 @@ import instrument.tap.stream.FloatTap;
import java.util.ArrayList;
import java.util.List;
import sample.Listener;
import sample.simplex.SimplexSampleListener;
import source.Source.SampleType;
import alias.AliasList;
import bits.MessageFramer;
@@ -79,7 +79,7 @@ public class MDCDecoder extends Decoder implements Instrumentable
/* Decimation filter: 48000 / 2 = 24000 */
mDecimationFilter = new FloatHalfBandFilter(
Filters.FIR_HALF_BAND_31T_ONE_EIGHTH_FCO, 1.0002 );
addFloatListener( mDecimationFilter );
addSimplexSampleListener( mDecimationFilter );
/* Bandpass filter - predefined */
mBandPassFilter = new FloatFIRFilter(
@@ -154,7 +154,7 @@ public class MDCDecoder extends Decoder implements Instrumentable
switch( tap.getName() )
{
case INSTRUMENT_INPUT:
addFloatListener( (FloatTap)tap );
addSimplexSampleListener( (FloatTap)tap );
break;
case INSTRUMENT_BANDPASS_FILTER_TO_FSK2_DEMOD:
/* wire the tap between the bandpass filter and the demod */
@@ -186,7 +186,7 @@ public class MDCDecoder extends Decoder implements Instrumentable
switch( tap.getName() )
{
case INSTRUMENT_INPUT:
removeFloatListener( (FloatTap)tap );
removeSimplexListener( (FloatTap)tap );
break;
case INSTRUMENT_BANDPASS_FILTER_TO_FSK2_DEMOD:
mBandPassFilter.setListener( mFSKDecoder );
@@ -202,7 +202,7 @@ public class MDCDecoder extends Decoder implements Instrumentable
}
@Override
public void addUnfilteredFloatListener( Listener<Float> listener )
public void addUnfilteredSimplexSampleListener( SimplexSampleListener listener )
{
//Not implemented
}

View File

@@ -26,7 +26,7 @@ import java.util.ArrayList;
import java.util.List;
import sample.Broadcaster;
import sample.Listener;
import sample.simplex.SimplexSampleListener;
import source.Source.SampleType;
import alias.AliasList;
import bits.MessageFramer;
@@ -106,7 +106,7 @@ public class MPT1327Decoder extends Decoder implements Instrumentable
if( mNBFMDemodulator != null )
{
mNBFMDemodulator.addListener( mDCRemovalFilter );
mDCRemovalFilter.setListener( this.getFloatReceiver() );
mDCRemovalFilter.setListener( this.getSimplexReceiver() );
}
}
@@ -115,7 +115,7 @@ public class MPT1327Decoder extends Decoder implements Instrumentable
/* Decimation filter - 48000 / 2 = 24000 output */
mDecimationFilter = new FloatHalfBandFilter(
Filters.FIR_HALF_BAND_31T_ONE_EIGHTH_FCO, 1.0002 );
addFloatListener( mDecimationFilter );
addSimplexSampleListener( mDecimationFilter );
/* Low pass filter: 2kHz to pass the 1200 & 1800 Hz FSK */
mLowPassFilter = new FloatFIRFilter(
@@ -169,7 +169,7 @@ public class MPT1327Decoder extends Decoder implements Instrumentable
}
@Override
public void addUnfilteredFloatListener( Listener<Float> listener )
public void addUnfilteredSimplexSampleListener( SimplexSampleListener listener )
{
if( mNBFMDemodulator != null )
{
@@ -256,7 +256,7 @@ public class MPT1327Decoder extends Decoder implements Instrumentable
}
else
{
addFloatListener( inputTap );
addSimplexSampleListener( inputTap );
}
break;
case INSTRUMENT_HB1_FILTER_TO_LOW_PASS:
@@ -292,7 +292,7 @@ public class MPT1327Decoder extends Decoder implements Instrumentable
}
else
{
removeFloatListener( inputTap );
removeSimplexListener( inputTap );
}
break;
case INSTRUMENT_HB1_FILTER_TO_LOW_PASS:

View File

@@ -17,11 +17,10 @@
******************************************************************************/
package decode.nbfm;
import sample.Listener;
import sample.simplex.SimplexSampleListener;
import source.Source.SampleType;
import decode.Decoder;
import decode.DecoderType;
import dsp.afc.AutomaticFrequencyControl;
import dsp.filter.DCRemovalFilter2;
import dsp.nbfm.FilteringNBFMDemodulator;
@@ -67,7 +66,7 @@ public class NBFMConventionalDecoder extends Decoder
* Route the demodulated, filtered samples back to this class to send
* to all registered listeners
*/
mDCRemovalFilter.setListener( this.getFloatReceiver() );
mDCRemovalFilter.setListener( this.getSimplexReceiver() );
}
}
@@ -78,7 +77,7 @@ public class NBFMConventionalDecoder extends Decoder
}
@Override
public void addUnfilteredFloatListener( Listener<Float> listener )
public void addUnfilteredSimplexSampleListener( SimplexSampleListener listener )
{
if( mDemodulator != null )
{

View File

@@ -24,12 +24,11 @@ import instrument.tap.stream.FloatTap;
import java.util.ArrayList;
import java.util.List;
import sample.Listener;
import sample.simplex.SimplexSampleListener;
import source.Source.SampleType;
import alias.AliasList;
import decode.Decoder;
import decode.DecoderType;
import dsp.afc.AutomaticFrequencyControl;
import dsp.filter.DCRemovalFilter2;
import dsp.fsk.C4FMDecoder;
import dsp.nbfm.FilteringNBFMDemodulator;
@@ -84,12 +83,12 @@ public class P25Decoder extends Decoder implements Instrumentable
* Route the demodulated, filtered samples back to this class to send
* to all registered listeners
*/
mDCRemovalFilter.setListener( this.getFloatReceiver() );
mDCRemovalFilter.setListener( this.getSimplexReceiver() );
}
mC4FMDecoder = new C4FMDecoder();
addFloatListener( mC4FMDecoder );
addSimplexSampleListener( mC4FMDecoder );
}
@Override
@@ -121,8 +120,8 @@ public class P25Decoder extends Decoder implements Instrumentable
{
case TAP_DEMOD_TO_DECODER:
FloatTap demodTap = (FloatTap)tap;
removeFloatListener( mC4FMDecoder );
addFloatListener( demodTap );
removeSimplexListener( mC4FMDecoder );
addSimplexSampleListener( demodTap );
demodTap.setListener( mC4FMDecoder );
break;
}
@@ -137,17 +136,16 @@ public class P25Decoder extends Decoder implements Instrumentable
{
case TAP_DEMOD_TO_DECODER:
FloatTap demodTap = (FloatTap)tap;
removeFloatListener( demodTap );
removeSimplexListener( demodTap );
demodTap.removeListener( mC4FMDecoder );
addFloatListener( mC4FMDecoder );
addSimplexSampleListener( mC4FMDecoder );
break;
}
}
@Override
public void addUnfilteredFloatListener( Listener<Float> listener )
public void addUnfilteredSimplexSampleListener( SimplexSampleListener listener )
{
// TODO Auto-generated method stub
}
}

View File

@@ -23,14 +23,13 @@ import instrument.tap.Tap;
import java.util.ArrayList;
import java.util.List;
import sample.Listener;
import sample.simplex.SimplexSampleListener;
import source.Source.SampleType;
import alias.AliasList;
import bits.MessageFramer;
import bits.SyncPattern;
import decode.Decoder;
import decode.DecoderType;
import dsp.afc.AutomaticFrequencyControl;
import dsp.filter.DCRemovalFilter2;
import dsp.fsk.LTRFSKDecoder;
import dsp.nbfm.FilteringNBFMDemodulator;
@@ -79,7 +78,7 @@ public class PassportDecoder extends Decoder implements Instrumentable
*/
mDCRemovalFilter = new DCRemovalFilter2( sDC_REMOVAL_RATIO );
mNBFMDemodulator.addListener( mDCRemovalFilter );
mDCRemovalFilter.setListener( this.getFloatReceiver() );
mDCRemovalFilter.setListener( this.getSimplexReceiver() );
}
mPassportFSKDecoder =
@@ -95,7 +94,7 @@ public class PassportDecoder extends Decoder implements Instrumentable
}
else
{
addFloatListener( mPassportFSKDecoder );
addSimplexSampleListener( mPassportFSKDecoder );
}
@@ -142,7 +141,7 @@ public class PassportDecoder extends Decoder implements Instrumentable
}
@Override
public void addUnfilteredFloatListener( Listener<Float> listener )
public void addUnfilteredSimplexSampleListener( SimplexSampleListener listener )
{
if( mNBFMDemodulator != null )
{