Merge pull request #136 from DSheirer/130-mpt1327-decoder-filtering

#130 MPT-1327 Decoder Filter issue resolved.
This commit is contained in:
Denny Sheirer
2017-01-24 20:27:56 -05:00
committed by GitHub
3 changed files with 83 additions and 53 deletions

View File

@@ -43,33 +43,33 @@ public class FilterViewer extends Application
// FIRFilterSpecification specification = FIRFilterSpecification.lowPassBuilder() // FIRFilterSpecification specification = FIRFilterSpecification.lowPassBuilder()
// .sampleRate( 48000 ) // .sampleRate( 48000 )
// .gridDensity( 16 ) // .gridDensity( 16 )
// .passBandCutoff( 3000 ) // .passBandCutoff( 3200 )
// .passBandAmplitude( 1.0 ) // .passBandAmplitude( 1.0 )
// .passBandRipple( 0.01 ) // .passBandRipple( 0.02 )
// .stopBandStart( 4000 ) // .stopBandStart( 4000 )
// .stopBandAmplitude( 0.0 ) // .stopBandAmplitude( 0.0 )
// .stopBandRipple( 0.027 ) // .stopBandRipple( 0.03 )
// .build(); // .build();
// FIRFilterSpecification specification = FIRFilterSpecification.highPassBuilder() FIRFilterSpecification specification = FIRFilterSpecification.highPassBuilder()
// .sampleRate( 8000 ) .sampleRate( 24000 )
// .stopBandCutoff( 250 ) .stopBandCutoff( 800 )
// .stopBandAmplitude( 0.0 ) .stopBandAmplitude( 0.0 )
// .stopBandRipple( 0.01 ) .stopBandRipple( 0.03 )
// .passBandStart( 300 ) .passBandStart( 1000 )
// .passBandAmplitude( 1.0 ) .passBandAmplitude( 1.0 )
// .passBandRipple( 0.01 ) .passBandRipple( 0.08 )
// .build(); .build();
FIRFilterSpecification specification = FIRFilterSpecification.bandPassBuilder() // FIRFilterSpecification specification = FIRFilterSpecification.bandPassBuilder()
.sampleRate( 48000 ) // .sampleRate( 48000 )
.stopFrequency1( 200 ) // .stopFrequency1( 200 )
.passFrequencyBegin( 400 ) // .passFrequencyBegin( 400 )
.passFrequencyEnd( 3200 ) // .passFrequencyEnd( 3200 )
.stopFrequency2( 3400 ) // .stopFrequency2( 3400 )
.stopRipple( 0.0003 ) // .stopRipple( 0.0003 )
.passRipple( 0.008) // .passRipple( 0.008)
.build(); // .build();
float[] taps = null; float[] taps = null;

View File

@@ -101,17 +101,25 @@ public class DecoderFactory
{ {
private final static Logger mLog = LoggerFactory.getLogger(DecoderFactory.class); private final static Logger mLog = LoggerFactory.getLogger(DecoderFactory.class);
private static final FIRFilterSpecification MPT1327_FILTER_SPECIFICATION = FIRFilterSpecification.bandPassBuilder() //Low-pass filter with ~60 dB attenuation and 89 taps
.sampleRate(48000).stopFrequency1(200).passFrequencyBegin(400).passFrequencyEnd(3200) private static final FIRFilterSpecification MPT1327_FILTER_SPECIFICATION = FIRFilterSpecification.lowPassBuilder()
.stopFrequency2(3400).stopRipple(0.0003).passRipple(0.008).build(); .sampleRate( 48000 )
.gridDensity( 16 )
.passBandCutoff( 3200 )
.passBandAmplitude( 1.0 )
.passBandRipple( 0.02 )
.stopBandStart( 4000 )
.stopBandAmplitude( 0.0 )
.stopBandRipple( 0.03 )
.build();
private static float[] MPT1327_BANDPASS_FILTER; private static float[] MPT1327_LOWPASS_FILTER;
static static
{ {
try try
{ {
MPT1327_BANDPASS_FILTER = FilterFactory.getTaps(MPT1327_FILTER_SPECIFICATION); MPT1327_LOWPASS_FILTER = FilterFactory.getTaps(MPT1327_FILTER_SPECIFICATION);
} }
catch(Exception e) catch(Exception e)
{ {
@@ -221,7 +229,7 @@ public class DecoderFactory
} }
modules.add(new FMDemodulatorModule(iqPass, iqStop)); modules.add(new FMDemodulatorModule(iqPass, iqStop));
modules.add(new DemodulatedAudioFilterModule(MPT1327_BANDPASS_FILTER, 2.0f)); modules.add(new DemodulatedAudioFilterModule(MPT1327_LOWPASS_FILTER, 1.0f));
modules.add(new AudioModule(metadata)); modules.add(new AudioModule(metadata));
break; break;
case PASSPORT: case PASSPORT:

View File

@@ -21,8 +21,9 @@ package module.decode.mpt1327;
import alias.AliasList; import alias.AliasList;
import bits.MessageFramer; import bits.MessageFramer;
import bits.SyncPattern; import bits.SyncPattern;
import dsp.filter.FilterFactory;
import dsp.filter.Filters; import dsp.filter.Filters;
import dsp.filter.dc.DCRemovalFilterLyons; import dsp.filter.fir.FIRFilterSpecification;
import dsp.filter.fir.real.RealFIRFilter_RB_RB; import dsp.filter.fir.real.RealFIRFilter_RB_RB;
import dsp.filter.halfband.real.HalfBandFilter_RB_RB; import dsp.filter.halfband.real.HalfBandFilter_RB_RB;
import dsp.fsk.FSK2Decoder; import dsp.fsk.FSK2Decoder;
@@ -55,6 +56,30 @@ public class MPT1327Decoder extends Decoder implements IFilteredRealBufferListen
{ {
private final static Logger mLog = LoggerFactory.getLogger(MPT1327Decoder.class); private final static Logger mLog = LoggerFactory.getLogger(MPT1327Decoder.class);
private static final FIRFilterSpecification HIGH_PASS_SPECIFICATION = FIRFilterSpecification.highPassBuilder()
.sampleRate( 24000 )
.stopBandCutoff( 800 )
.stopBandAmplitude( 0.0 )
.stopBandRipple( 0.03 )
.passBandStart( 1000 )
.passBandAmplitude( 1.0 )
.passBandRipple( 0.08 )
.build();
private static float[] HIGHPASS_FILTER;
static
{
try
{
HIGHPASS_FILTER = FilterFactory.getTaps(HIGH_PASS_SPECIFICATION);
}
catch(Exception e)
{
mLog.error("Couldn't design MPT1327 highpass filter");
}
}
/* Decimated sample rate ( 48,000 / 2 = 24,000 ) feeding the decoder */ /* Decimated sample rate ( 48,000 / 2 = 24,000 ) feeding the decoder */
private static final int sDECIMATED_SAMPLE_RATE = 24000; private static final int sDECIMATED_SAMPLE_RATE = 24000;
@@ -66,17 +91,16 @@ public class MPT1327Decoder extends Decoder implements IFilteredRealBufferListen
private static final int sMESSAGE_LENGTH = 350; private static final int sMESSAGE_LENGTH = 350;
/* Instrumentation Taps */ /* Instrumentation Taps */
private static final String INSTRUMENT_HB1_FILTER_TO_LOW_PASS = private static final String INSTRUMENT_HB1_FILTER_TO_HIGH_PASS =
"Tap Point: Half-band Decimation Filter > < Low Pass Filter"; "Tap Point: Half-band Decimation Filter > < Low Pass Filter";
private static final String INSTRUMENT_LOW_PASS_TO_DECODER = private static final String INSTRUMENT_HIGH_PASS_TO_DECODER =
"Tap Point: Low Pass Filter > < Decoder"; "Tap Point: Low Pass Filter > < Decoder";
private static final String INSTRUMENT_DECODER_TO_FRAMER = private static final String INSTRUMENT_DECODER_TO_FRAMER =
"Tap Point: Decoder > < Sync Detect/Message Framer"; "Tap Point: Decoder > < Sync Detect/Message Framer";
private List<TapGroup> mAvailableTaps; private List<TapGroup> mAvailableTaps;
private HalfBandFilter_RB_RB mDecimationFilter; private HalfBandFilter_RB_RB mDecimationFilter;
private RealFIRFilter_RB_RB mLowPassFilter; private RealFIRFilter_RB_RB mHighPassFilter;
private DCRemovalFilterLyons mDCRemovalFilter;
private FSK2Decoder mFSKDecoder; private FSK2Decoder mFSKDecoder;
private Broadcaster<Boolean> mSymbolBroadcaster; private Broadcaster<Boolean> mSymbolBroadcaster;
private MessageFramer mControlMessageFramer; private MessageFramer mControlMessageFramer;
@@ -85,9 +109,6 @@ public class MPT1327Decoder extends Decoder implements IFilteredRealBufferListen
public MPT1327Decoder(AliasList aliasList, Sync sync) public MPT1327Decoder(AliasList aliasList, Sync sync)
{ {
/* Decimation filter - 48000 / 2 = 24000 output */
mDecimationFilter = new HalfBandFilter_RB_RB(Filters.FIR_HALF_BAND_31T_ONE_EIGHTH_FCO.getCoefficients(), 1.0002f, true);
/** /**
* Normal: 2FSK Decoder with inverted output * Normal: 2FSK Decoder with inverted output
* French: 2FSK Decoder with normal output * French: 2FSK Decoder with normal output
@@ -105,7 +126,15 @@ public class MPT1327Decoder extends Decoder implements IFilteredRealBufferListen
throw new IllegalArgumentException("MPT1327 Decoder - unrecognized Sync type"); throw new IllegalArgumentException("MPT1327 Decoder - unrecognized Sync type");
} }
mDecimationFilter.setListener(mFSKDecoder); /* Decimation filter - 48000 / 2 = 24000 output */
mDecimationFilter = new HalfBandFilter_RB_RB(Filters.FIR_HALF_BAND_31T_ONE_EIGHTH_FCO.getCoefficients(), 1.0002f, true);
//High-pass filter the audio to remove any DC component or CTCSS tones. The audio has already been low-pass
//filtered by the AudioDemodulation filter cutoff of 3400 Hz.
mHighPassFilter = new RealFIRFilter_RB_RB(HIGHPASS_FILTER, 1.0f);
mDecimationFilter.setListener(mHighPassFilter);
mHighPassFilter.setListener(mFSKDecoder);
mSymbolBroadcaster = new Broadcaster<Boolean>(); mSymbolBroadcaster = new Broadcaster<Boolean>();
mFSKDecoder.setListener(mSymbolBroadcaster); mFSKDecoder.setListener(mSymbolBroadcaster);
@@ -148,17 +177,10 @@ public class MPT1327Decoder extends Decoder implements IFilteredRealBufferListen
mControlMessageFramer.dispose(); mControlMessageFramer.dispose();
if(mDCRemovalFilter != null)
{
mDCRemovalFilter.dispose();
}
mFSKDecoder.dispose(); mFSKDecoder.dispose();
mDecimationFilter.dispose(); mDecimationFilter.dispose();
mLowPassFilter.dispose();
mMessageProcessor.dispose(); mMessageProcessor.dispose();
mTrafficMessageFramer.dispose(); mTrafficMessageFramer.dispose();
@@ -174,8 +196,8 @@ public class MPT1327Decoder extends Decoder implements IFilteredRealBufferListen
TapGroup group = new TapGroup("MPT-1327 Decoder"); TapGroup group = new TapGroup("MPT-1327 Decoder");
group.add(new FloatTap(INSTRUMENT_HB1_FILTER_TO_LOW_PASS, 0, 0.5f)); group.add(new FloatTap(INSTRUMENT_HB1_FILTER_TO_HIGH_PASS, 0, 0.5f));
group.add(new FloatTap(INSTRUMENT_LOW_PASS_TO_DECODER, 0, 0.5f)); group.add(new FloatTap(INSTRUMENT_HIGH_PASS_TO_DECODER, 0, 0.5f));
group.add(new BinaryTap(INSTRUMENT_DECODER_TO_FRAMER, 0, 0.025f)); group.add(new BinaryTap(INSTRUMENT_DECODER_TO_FRAMER, 0, 0.025f));
mAvailableTaps.add(group); mAvailableTaps.add(group);
@@ -195,14 +217,14 @@ public class MPT1327Decoder extends Decoder implements IFilteredRealBufferListen
switch(tap.getName()) switch(tap.getName())
{ {
case INSTRUMENT_HB1_FILTER_TO_LOW_PASS: case INSTRUMENT_HB1_FILTER_TO_HIGH_PASS:
FloatBufferTap hb1Tap = (FloatBufferTap) tap; FloatBufferTap hb1Tap = (FloatBufferTap) tap;
mDecimationFilter.setListener(hb1Tap); mDecimationFilter.setListener(hb1Tap);
hb1Tap.setListener(mLowPassFilter); hb1Tap.setListener(mHighPassFilter);
break; break;
case INSTRUMENT_LOW_PASS_TO_DECODER: case INSTRUMENT_HIGH_PASS_TO_DECODER:
FloatBufferTap lowTap = (FloatBufferTap) tap; FloatBufferTap lowTap = (FloatBufferTap) tap;
mLowPassFilter.setListener(lowTap); mHighPassFilter.setListener(lowTap);
lowTap.setListener(mFSKDecoder); lowTap.setListener(mFSKDecoder);
break; break;
case INSTRUMENT_DECODER_TO_FRAMER: case INSTRUMENT_DECODER_TO_FRAMER:
@@ -220,11 +242,11 @@ public class MPT1327Decoder extends Decoder implements IFilteredRealBufferListen
switch(tap.getName()) switch(tap.getName())
{ {
case INSTRUMENT_HB1_FILTER_TO_LOW_PASS: case INSTRUMENT_HB1_FILTER_TO_HIGH_PASS:
mDecimationFilter.setListener(mLowPassFilter); mDecimationFilter.setListener(mHighPassFilter);
break; break;
case INSTRUMENT_LOW_PASS_TO_DECODER: case INSTRUMENT_HIGH_PASS_TO_DECODER:
mLowPassFilter.setListener(mFSKDecoder); mHighPassFilter.setListener(mFSKDecoder);
break; break;
case INSTRUMENT_DECODER_TO_FRAMER: case INSTRUMENT_DECODER_TO_FRAMER:
mFSKDecoder.setListener(mSymbolBroadcaster); mFSKDecoder.setListener(mSymbolBroadcaster);