Compare commits

...

7 Commits

Author SHA1 Message Date
Denny
cf0018e6ba Incrementing build to 0.3.0-beta4 2017-02-11 07:22:54 -05:00
Denny Sheirer
e8055dcab0 Merge pull request #187 from DSheirer/186-p25-c4fm-decoder-no-worky
Resolves #186 - p25 C4FM decoder wasn't working (at all).
2017-02-11 12:17:58 +00:00
Denny
fce3d5c4f3 Resolves #186 - p25 C4FM decoder wasn't working (at all). 2017-02-11 07:17:23 -05:00
Denny Sheirer
9cc0d367a8 Merge pull request #185 from DSheirer/183-alias-list-throws-npe-on-empty-name
Resolves #183 - alias list throws NPE when created with a null or emp…
2017-02-11 00:35:16 +00:00
Denny
2ca9e5d5ce Resolves #183 - alias list throws NPE when created with a null or empty name and receives alias updates. 2017-02-10 19:34:50 -05:00
Denny Sheirer
861203c3a0 Merge pull request #184 from DSheirer/181-patch-group-audio-priority
Resolves #181 - patch group audio priority will assume the highest (l…
2017-02-11 00:31:42 +00:00
Denny
7c930deefe Resolves #181 - patch group audio priority will assume the highest (listenable) audio priority and override a 'Do Not Monitor' setting if any of the other aliases have an audio priority defined. 2017-02-10 19:31:09 -05:00
7 changed files with 158 additions and 138 deletions

View File

@@ -7,7 +7,7 @@
<property name="major" value="0"/> <property name="major" value="0"/>
<property name="minor" value="3"/> <property name="minor" value="3"/>
<property name="patch" value="0"/> <property name="patch" value="0"/>
<property name="release" value="-beta3"/> <property name="release" value="-beta4"/>
<property name="filename" value="sdrtrunk_${major}.${minor}.${patch}${release}"/> <property name="filename" value="sdrtrunk_${major}.${minor}.${patch}${release}"/>
<!-- Build properties --> <!-- Build properties -->

View File

@@ -631,11 +631,21 @@ public class AliasList implements Listener<AliasEvent>
return mName; return mName;
} }
/**
* Indicates if this alias list has a non-null, non-empty name
*/
private boolean hasName()
{
return mName != null && !mName.isEmpty();
}
/** /**
* Receive alias change event notifications and modify this list accordingly * Receive alias change event notifications and modify this list accordingly
*/ */
@Override @Override
public void receive(AliasEvent event) public void receive(AliasEvent event)
{
if(hasName())
{ {
Alias alias = event.getAlias(); Alias alias = event.getAlias();
@@ -664,3 +674,4 @@ public class AliasList implements Listener<AliasEvent>
} }
} }
} }
}

View File

@@ -197,23 +197,45 @@ public class PatchGroupAlias extends Alias
return hasPatchGroupAlias() && getPatchGroupAlias().hasActions(); return hasPatchGroupAlias() && getPatchGroupAlias().hasActions();
} }
/**
* Returns the highest listenable audio priority defined among the aliases in the group, or returns 'Do Not Monitor'
* if that is the only priority defined. Otherwise, returns default (100) priority.
*/
@Override @Override
public int getCallPriority() public int getCallPriority()
{ {
int highestPriority = (hasPatchGroupAlias() ? getPatchGroupAlias().getCallPriority() : Priority.DEFAULT_PRIORITY); boolean hasDoNotMonitor = false;
int highestPriority = (hasPatchGroupAlias() ? getPatchGroupAlias().getCallPriority() : Priority.DEFAULT_PRIORITY + 1);
for(Alias alias: mPatchedAliases) for(Alias alias: mPatchedAliases)
{ {
if(!(alias instanceof PatchGroupAlias) && if(!(alias instanceof PatchGroupAlias) && alias.hasCallPriority() && alias.getCallPriority() < highestPriority)
alias.hasCallPriority() && {
alias.getCallPriority() < highestPriority) if(alias.getCallPriority() == Priority.DO_NOT_MONITOR)
{
hasDoNotMonitor = true;
}
else
{ {
highestPriority = alias.getCallPriority(); highestPriority = alias.getCallPriority();
} }
} }
}
if(highestPriority <= Priority.DEFAULT_PRIORITY)
{
return highestPriority; return highestPriority;
} }
else if(hasDoNotMonitor)
{
return Priority.DO_NOT_MONITOR;
}
else
{
return Priority.DEFAULT_PRIORITY;
}
}
@Override @Override
public boolean hasCallPriority() public boolean hasCallPriority()

View File

@@ -1,13 +1,12 @@
package dsp.filter.design; package dsp.filter.design;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import dsp.filter.fir.FIRFilterSpecification; import dsp.filter.fir.FIRFilterSpecification;
import dsp.filter.fir.remez.RemezFIRFilterDesigner; import dsp.filter.fir.remez.RemezFIRFilterDesigner;
import javafx.application.Application; import javafx.application.Application;
import javafx.scene.Scene; import javafx.scene.Scene;
import javafx.stage.Stage; import javafx.stage.Stage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class FilterViewer extends Application public class FilterViewer extends Application
{ {
@@ -40,27 +39,27 @@ public class FilterViewer extends Application
*/ */
private float[] getFilter() private float[] getFilter()
{ {
// FIRFilterSpecification specification = FIRFilterSpecification.lowPassBuilder() FIRFilterSpecification specification = FIRFilterSpecification.lowPassBuilder()
// .sampleRate( 48000 ) .sampleRate(48000)
// .gridDensity( 16 ) .gridDensity(16)
// .passBandCutoff( 3200 ) .passBandCutoff(2500)
// .passBandAmplitude( 1.0 ) .passBandAmplitude(1.0)
// .passBandRipple( 0.02 ) .passBandRipple(0.01)
// .stopBandStart( 4000 ) .stopBandStart(4000)
.stopBandAmplitude(0.0)
.stopBandRipple(0.008)
.build();
// FIRFilterSpecification specification = FIRFilterSpecification.highPassBuilder()
// .sampleRate(24000)
// .stopBandCutoff(800)
// .stopBandAmplitude(0.0) // .stopBandAmplitude(0.0)
// .stopBandRipple(0.03) // .stopBandRipple(0.03)
// .passBandStart(1000)
// .passBandAmplitude(1.0)
// .passBandRipple(0.08)
// .build(); // .build();
FIRFilterSpecification specification = FIRFilterSpecification.highPassBuilder()
.sampleRate( 24000 )
.stopBandCutoff( 800 )
.stopBandAmplitude( 0.0 )
.stopBandRipple( 0.03 )
.passBandStart( 1000 )
.passBandAmplitude( 1.0 )
.passBandRipple( 0.08 )
.build();
// FIRFilterSpecification specification = FIRFilterSpecification.bandPassBuilder() // FIRFilterSpecification specification = FIRFilterSpecification.bandPassBuilder()
// .sampleRate( 48000 ) // .sampleRate( 48000 )
// .stopFrequency1( 200 ) // .stopFrequency1( 200 )
@@ -73,7 +72,8 @@ public class FilterViewer extends Application
float[] taps = null; float[] taps = null;
// taps = FilterFactory.getLowPass( 16000, 2400, 73, WindowType.HANNING ); // taps = FilterFactory.getLowPass(48000, 6750, 7500, 60,
// Window.WindowType.HAMMING, true);
try try
{ {

View File

@@ -103,35 +103,35 @@ public class DecoderFactory
//Low-pass filter with ~60 dB attenuation and 89 taps //Low-pass filter with ~60 dB attenuation and 89 taps
private static final FIRFilterSpecification MPT1327_FILTER_SPECIFICATION = FIRFilterSpecification.lowPassBuilder() private static final FIRFilterSpecification MPT1327_FILTER_SPECIFICATION = FIRFilterSpecification.lowPassBuilder()
.sampleRate( 48000 ) .sampleRate( 48000 ).gridDensity( 16 ).passBandCutoff( 3200 ).passBandAmplitude( 1.0 ).passBandRipple( 0.02 )
.gridDensity( 16 ) .stopBandStart( 4000 ).stopBandAmplitude( 0.0 ).stopBandRipple( 0.03 ).build();
.passBandCutoff( 3200 )
.passBandAmplitude( 1.0 ) private static final FIRFilterSpecification P25_C4FM_IQ_SPECIFICATION = FIRFilterSpecification.lowPassBuilder()
.passBandRipple( 0.02 ) .sampleRate(48000).gridDensity(16).passBandCutoff(6750).passBandAmplitude(1.0).passBandRipple(0.01)
.stopBandStart( 4000 ) .stopBandStart(7000).stopBandAmplitude(0.0).stopBandRipple(0.008).build();
.stopBandAmplitude( 0.0 )
.stopBandRipple( 0.03 ) private static final FIRFilterSpecification P25_C4FM_DEMOD_SPECIFICATION = FIRFilterSpecification.lowPassBuilder()
.build(); .sampleRate(48000).gridDensity(16).passBandCutoff(2500).passBandAmplitude(1.0).passBandRipple(0.01)
.stopBandStart(4000).stopBandAmplitude(0.0).stopBandRipple(0.008).build();
private static float[] MPT1327_LOWPASS_FILTER; private static float[] MPT1327_LOWPASS_FILTER;
private static float[] P25_C4FM_IQ_FILTER;
private static float[] P25_C4FM_DEMOD_FILTER;
static static
{ {
try try
{ {
MPT1327_LOWPASS_FILTER = FilterFactory.getTaps(MPT1327_FILTER_SPECIFICATION); MPT1327_LOWPASS_FILTER = FilterFactory.getTaps(MPT1327_FILTER_SPECIFICATION);
P25_C4FM_IQ_FILTER = FilterFactory.getTaps(P25_C4FM_IQ_SPECIFICATION);
P25_C4FM_DEMOD_FILTER = FilterFactory.getTaps(P25_C4FM_DEMOD_SPECIFICATION);
} }
catch(Exception e) catch(Exception e)
{ {
mLog.error("Couldn't design MPT1327 bandpass filter"); mLog.error("Couldn't design startup filter(s)");
} }
} }
public static final boolean NO_REMOVE_DC = false;
public static final boolean REMOVE_DC = true;
public static final int NO_FREQUENCY_CORRECTION = 0;
/** /**
* Returns a list of one primary decoder and any auxiliary decoders, as * Returns a list of one primary decoder and any auxiliary decoders, as
* specified in the configurations. * specified in the configurations.
@@ -228,7 +228,7 @@ public class DecoderFactory
} }
modules.add(new FMDemodulatorModule(iqPass, iqStop)); modules.add(new FMDemodulatorModule(iqPass, iqStop));
modules.add(new DemodulatedAudioFilterModule(MPT1327_LOWPASS_FILTER, 1.0f)); modules.add(new DemodulatedAudioFilterModule(P25_C4FM_DEMOD_FILTER, 1.0f));
modules.add(new AudioModule(metadata)); modules.add(new AudioModule(metadata));
break; break;
case PASSPORT: case PASSPORT:
@@ -247,7 +247,8 @@ public class DecoderFactory
switch(modulation) switch(modulation)
{ {
case C4FM: case C4FM:
modules.add(new FMDemodulatorModule(6750, 7500)); modules.add(new FMDemodulatorModule(P25_C4FM_IQ_FILTER));
modules.add(new DemodulatedAudioFilterModule(P25_C4FM_DEMOD_FILTER, 1.0f));
modules.add(new P25_C4FMDecoder(aliasList, decodeConfig.getAFCMaximumCorrection())); modules.add(new P25_C4FMDecoder(aliasList, decodeConfig.getAFCMaximumCorrection()));
modules.add(new P25DecoderState(aliasList, channelType, Modulation.C4FM, modules.add(new P25DecoderState(aliasList, channelType, Modulation.C4FM,
p25Config.getIgnoreDataCalls())); p25Config.getIgnoreDataCalls()));

View File

@@ -47,12 +47,10 @@ public class P25_C4FMDecoder extends P25Decoder
private final static Logger mLog = LoggerFactory.getLogger( P25_C4FMDecoder.class ); private final static Logger mLog = LoggerFactory.getLogger( P25_C4FMDecoder.class );
/* Instrumentation Taps */ /* Instrumentation Taps */
private static final String INSTRUMENT_FILTER_OUTPUT = "Tap Point: Pre-Filter Output";
private static final String INSTRUMENT_C4FM_SYMBOL_FILTER_OUTPUT = "Tap Point: Symbol Filter Output"; private static final String INSTRUMENT_C4FM_SYMBOL_FILTER_OUTPUT = "Tap Point: Symbol Filter Output";
private static final String INSTRUMENT_C4FM_SLICER_OUTPUT = "Tap Point: C4FM Slicer Output"; private static final String INSTRUMENT_C4FM_SLICER_OUTPUT = "Tap Point: C4FM Slicer Output";
private List<TapGroup> mAvailableTaps; private List<TapGroup> mAvailableTaps;
private RealFIRFilter_RB_RB mC4FMPreFilter;
private C4FMSymbolFilter mSymbolFilter; private C4FMSymbolFilter mSymbolFilter;
private C4FMSlicer mC4FMSlicer; private C4FMSlicer mC4FMSlicer;
private P25MessageFramer mMessageFramer; private P25MessageFramer mMessageFramer;
@@ -74,14 +72,8 @@ public class P25_C4FMDecoder extends P25Decoder
{ {
super( aliasList ); super( aliasList );
/* Filter demodulated sample buffers */
float[] filter = FilterFactory.getLowPass( 48000, 2500, 4000, 80, WindowType.HANNING, true );
mC4FMPreFilter = new RealFIRFilter_RB_RB( filter, 1.0f );
/* Shape gain and frequency offsets to optimize sample stream */ /* Shape gain and frequency offsets to optimize sample stream */
mSymbolFilter = new C4FMSymbolFilter( frequencyCorrectionMaximum ); mSymbolFilter = new C4FMSymbolFilter( frequencyCorrectionMaximum );
mC4FMPreFilter.setListener( mSymbolFilter );
/* Convert samples to symbols */ /* Convert samples to symbols */
mC4FMSlicer = new C4FMSlicer(); mC4FMSlicer = new C4FMSlicer();
@@ -100,9 +92,6 @@ public class P25_C4FMDecoder extends P25Decoder
{ {
super.dispose(); super.dispose();
mC4FMPreFilter.dispose();
mC4FMPreFilter = null;
mSymbolFilter.dispose(); mSymbolFilter.dispose();
mSymbolFilter = null; mSymbolFilter = null;
@@ -121,7 +110,7 @@ public class P25_C4FMDecoder extends P25Decoder
@Override @Override
public Listener<RealBuffer> getFilteredRealBufferListener() public Listener<RealBuffer> getFilteredRealBufferListener()
{ {
return mC4FMPreFilter; return mSymbolFilter;
} }
/** /**
@@ -136,8 +125,6 @@ public class P25_C4FMDecoder extends P25Decoder
TapGroup group = new TapGroup( "P25 C4FM Decoder" ); TapGroup group = new TapGroup( "P25 C4FM Decoder" );
group.add( new FloatBufferTap( INSTRUMENT_FILTER_OUTPUT, 0, 1.0f ) );
group.add( new FloatTap( INSTRUMENT_C4FM_SYMBOL_FILTER_OUTPUT, 0, 0.1f ) ); group.add( new FloatTap( INSTRUMENT_C4FM_SYMBOL_FILTER_OUTPUT, 0, 0.1f ) );
group.add( new DibitTap( INSTRUMENT_C4FM_SLICER_OUTPUT, 0, 0.1f ) ); group.add( new DibitTap( INSTRUMENT_C4FM_SLICER_OUTPUT, 0, 0.1f ) );
@@ -165,11 +152,6 @@ public class P25_C4FMDecoder extends P25Decoder
switch( tap.getName() ) switch( tap.getName() )
{ {
case INSTRUMENT_FILTER_OUTPUT:
FloatBufferTap filterOutput = (FloatBufferTap)tap;
mC4FMPreFilter.setListener( filterOutput );
filterOutput.setListener( mSymbolFilter );
break;
case INSTRUMENT_C4FM_SYMBOL_FILTER_OUTPUT: case INSTRUMENT_C4FM_SYMBOL_FILTER_OUTPUT:
FloatTap symbolTap = (FloatTap)tap; FloatTap symbolTap = (FloatTap)tap;
mSymbolFilter.setListener( symbolTap ); mSymbolFilter.setListener( symbolTap );
@@ -201,9 +183,6 @@ public class P25_C4FMDecoder extends P25Decoder
switch( tap.getName() ) switch( tap.getName() )
{ {
case INSTRUMENT_FILTER_OUTPUT:
mC4FMPreFilter.setListener( mSymbolFilter );
break;
case INSTRUMENT_C4FM_SYMBOL_FILTER_OUTPUT: case INSTRUMENT_C4FM_SYMBOL_FILTER_OUTPUT:
mSymbolFilter.setListener( mC4FMSlicer ); mSymbolFilter.setListener( mC4FMSlicer );
break; break;

View File

@@ -62,6 +62,13 @@ public class FMDemodulatorModule extends Module implements IComplexBufferListene
mIQFilter.setListener(mDemodulator); mIQFilter.setListener(mDemodulator);
} }
public FMDemodulatorModule(float[] filter)
{
mIQFilter = new ComplexFIRFilter_CB_CB(filter, 1.0f);
mDemodulator = new FMDemodulator_CB(1.0f);
mIQFilter.setListener(mDemodulator);
}
@Override @Override
public Listener<ComplexBuffer> getComplexBufferListener() public Listener<ComplexBuffer> getComplexBufferListener()
{ {