diff --git a/src/main/java/io/github/dsheirer/dsp/filter/channelizer/ComplexPolyphaseChannelizerM2.java b/src/main/java/io/github/dsheirer/dsp/filter/channelizer/ComplexPolyphaseChannelizerM2.java index a8d794d1..faf941cd 100644 --- a/src/main/java/io/github/dsheirer/dsp/filter/channelizer/ComplexPolyphaseChannelizerM2.java +++ b/src/main/java/io/github/dsheirer/dsp/filter/channelizer/ComplexPolyphaseChannelizerM2.java @@ -63,7 +63,7 @@ public class ComplexPolyphaseChannelizerM2 extends AbstractComplexPolyphaseChann { private final static Logger mLog = LoggerFactory.getLogger(ComplexPolyphaseChannelizerM2.class); - private static final int DEFAULT_MINIMUM_CHANNEL_BANDWIDTH = 12500; + private static final int DEFAULT_MINIMUM_CHANNEL_BANDWIDTH = 25000; //Sized at 152 buffers a second where max = 5 seconds and reset = 2 seconds worth of buffers private IFFTProcessor mIFFTProcessor = new IFFTProcessor((5 * 152), (2 * 152)); diff --git a/src/main/java/io/github/dsheirer/dsp/filter/channelizer/PolyphaseChannelManager.java b/src/main/java/io/github/dsheirer/dsp/filter/channelizer/PolyphaseChannelManager.java index daeade11..dd57205a 100644 --- a/src/main/java/io/github/dsheirer/dsp/filter/channelizer/PolyphaseChannelManager.java +++ b/src/main/java/io/github/dsheirer/dsp/filter/channelizer/PolyphaseChannelManager.java @@ -29,6 +29,7 @@ import io.github.dsheirer.source.Source; import io.github.dsheirer.source.SourceEvent; import io.github.dsheirer.source.SourceException; import io.github.dsheirer.source.tuner.TunerController; +import io.github.dsheirer.source.tuner.channel.ChannelSpecification; import io.github.dsheirer.source.tuner.channel.TunerChannel; import io.github.dsheirer.source.tuner.channel.TunerChannelSource; import org.slf4j.Logger; @@ -62,7 +63,7 @@ import java.util.concurrent.CopyOnWriteArrayList; public class PolyphaseChannelManager implements ISourceEventProcessor { private final static Logger mLog = LoggerFactory.getLogger(PolyphaseChannelManager.class); - private static final double MINIMUM_CHANNEL_BANDWIDTH = 12500.0; + private static final double MINIMUM_CHANNEL_BANDWIDTH = 25000.0; private static final double CHANNEL_OVERSAMPLING = 2.0; private static final int POLYPHASE_CHANNELIZER_TAPS_PER_CHANNEL = 9; private static final int POLYPHASE_SYNTHESIZER_TAPS_PER_CHANNEL = 9; @@ -141,7 +142,7 @@ public class PolyphaseChannelManager implements ISourceEventProcessor * @param tunerChannel specifying center frequency and bandwidth. * @return source or null. */ - public TunerChannelSource getChannel(TunerChannel tunerChannel) + public TunerChannelSource getChannel(TunerChannel tunerChannel, ChannelSpecification channelSpecification) { PolyphaseChannelSource channelSource = null; @@ -155,10 +156,17 @@ public class PolyphaseChannelManager implements ISourceEventProcessor { long centerFrequency = mChannelCalculator.getCenterFrequencyForIndexes(polyphaseIndexes); - channelSource = new PolyphaseChannelSource(tunerChannel, outputProcessor, mChannelSourceEventListener, - mChannelCalculator.getChannelSampleRate(), centerFrequency); + try + { + channelSource = new PolyphaseChannelSource(tunerChannel, outputProcessor, mChannelSourceEventListener, + mChannelCalculator.getChannelSampleRate(), centerFrequency, channelSpecification); - mChannelSources.add(channelSource); + mChannelSources.add(channelSource); + } + catch(FilterDesignException fde) + { + mLog.debug("Couldn't design final output low pass filter for polyphase channel source"); + } } } catch(IllegalArgumentException iae) diff --git a/src/main/java/io/github/dsheirer/dsp/filter/channelizer/PolyphaseChannelSource.java b/src/main/java/io/github/dsheirer/dsp/filter/channelizer/PolyphaseChannelSource.java index 7b33b9aa..a21a244e 100644 --- a/src/main/java/io/github/dsheirer/dsp/filter/channelizer/PolyphaseChannelSource.java +++ b/src/main/java/io/github/dsheirer/dsp/filter/channelizer/PolyphaseChannelSource.java @@ -16,22 +16,35 @@ package io.github.dsheirer.dsp.filter.channelizer; import io.github.dsheirer.dsp.filter.channelizer.output.IPolyphaseChannelOutputProcessor; +import io.github.dsheirer.dsp.filter.design.FilterDesignException; +import io.github.dsheirer.dsp.filter.fir.FIRFilterSpecification; +import io.github.dsheirer.dsp.filter.fir.complex.ComplexFIRFilter2; +import io.github.dsheirer.dsp.filter.fir.remez.RemezFIRFilterDesigner; import io.github.dsheirer.sample.Listener; import io.github.dsheirer.sample.buffer.ReusableChannelResultsBuffer; import io.github.dsheirer.sample.buffer.ReusableComplexBuffer; import io.github.dsheirer.sample.buffer.ReusableComplexBufferAssembler; import io.github.dsheirer.source.SourceEvent; +import io.github.dsheirer.source.tuner.channel.ChannelSpecification; import io.github.dsheirer.source.tuner.channel.TunerChannel; import io.github.dsheirer.source.tuner.channel.TunerChannelSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.HashMap; +import java.util.Map; + public class PolyphaseChannelSource extends TunerChannelSource { private final static Logger mLog = LoggerFactory.getLogger(PolyphaseChannelSource.class); private ReusableComplexBufferAssembler mReusableComplexBufferAssembler; private IPolyphaseChannelOutputProcessor mPolyphaseChannelOutputProcessor; + private IPolyphaseChannelOutputProcessor mReplacementPolyphaseChannelOutputProcessor; + private long mReplacementFrequency; + private ComplexFIRFilter2 mLowPassFilter; + private static Map sLowPassFilters = new HashMap(); + private double mChannelSampleRate; private long mIndexCenterFrequency; private long mChannelFrequencyCorrection; @@ -46,15 +59,22 @@ public class PolyphaseChannelSource extends TunerChannelSource * @param producerSourceEventListener to receive source event requests (e.g. start/stop sample stream) * @param channelSampleRate for the downstream sample output * @param centerFrequency of the incoming polyphase channel(s) + * @throws FilterDesignException if a channel low pass filter can't be designed to the channel specification */ public PolyphaseChannelSource(TunerChannel tunerChannel, IPolyphaseChannelOutputProcessor outputProcessor, Listener producerSourceEventListener, double channelSampleRate, - long centerFrequency) + long centerFrequency, ChannelSpecification channelSpecification) + throws FilterDesignException { super(producerSourceEventListener, tunerChannel); mPolyphaseChannelOutputProcessor = outputProcessor; mChannelSampleRate = channelSampleRate; mReusableComplexBufferAssembler = new ReusableComplexBufferAssembler(2500, mChannelSampleRate); + + float[] filterCoefficients = getLowPassFilter(channelSampleRate, channelSpecification.getPassFrequency(), + channelSpecification.getStopFrequency()); + mLowPassFilter = new ComplexFIRFilter2(filterCoefficients, 1.0f); + setFrequency(centerFrequency); } @@ -93,14 +113,33 @@ public class PolyphaseChannelSource extends TunerChannelSource */ public void setPolyphaseChannelOutputProcessor(IPolyphaseChannelOutputProcessor outputProcessor, long frequency) { - //Lock on the channel output processor to block the channel results processor thread from servicing the - //channel output processor's buffer while we change out the processors. - synchronized(mPolyphaseChannelOutputProcessor) + //If this is the first time, simply assign the output processor + if(mPolyphaseChannelOutputProcessor == null) + { + mPolyphaseChannelOutputProcessor = outputProcessor; + } + //Otherwise, we have to swap out the processor on the sample processing thread + else + { + mReplacementPolyphaseChannelOutputProcessor = outputProcessor; + mReplacementFrequency = frequency; + } + } + + /** + * Updates the output processor to use the new output processor provided by the external + * polyphase channel manager. This method should only be executed on the sample processing + * thread, within the processChannelResults() method. + */ + private void swapOutputProcessor() + { + if(mReplacementPolyphaseChannelOutputProcessor != null) { IPolyphaseChannelOutputProcessor existingProcessor = mPolyphaseChannelOutputProcessor; //Swap out the processor so that incoming samples can accumulate in the new channel output processor - mPolyphaseChannelOutputProcessor = outputProcessor; + mPolyphaseChannelOutputProcessor = mReplacementPolyphaseChannelOutputProcessor; + mReplacementPolyphaseChannelOutputProcessor = null; //Remove the buffer overflow listener and clear any previous buffer overflow state existingProcessor.setSourceOverflowListener(null); @@ -109,18 +148,9 @@ public class PolyphaseChannelSource extends TunerChannelSource //Register to receive buffer overflow notifications so we can push them up through the source chain mPolyphaseChannelOutputProcessor.setSourceOverflowListener(this); - //Fully process the residual channel results buffer of the previous channel output processor - if(existingProcessor != null) - { - existingProcessor.processChannelResults(mReusableComplexBufferAssembler); - } - - //Finally, setup the frequency offset for the output processor and reset the frequency correction value - //to allow consumers to adjust and calculate a new frequency correction value, if needed. - mIndexCenterFrequency = frequency; - mChannelFrequencyCorrection = 0; + //Finally, setup the frequency offset for the output processor. + mIndexCenterFrequency = mReplacementFrequency; mPolyphaseChannelOutputProcessor.setFrequencyOffset(getFrequencyOffset()); - broadcastConsumerSourceEvent(SourceEvent.frequencyCorrectionChange(mChannelFrequencyCorrection)); } } @@ -133,12 +163,13 @@ public class PolyphaseChannelSource extends TunerChannelSource */ public void receiveChannelResults(ReusableChannelResultsBuffer channelResultsBuffer) { - mReusableComplexBufferAssembler.updateTimestamp(channelResultsBuffer.getTimestamp()); - - if(mPolyphaseChannelOutputProcessor != null) + if(mReplacementPolyphaseChannelOutputProcessor != null) { - mPolyphaseChannelOutputProcessor.receiveChannelResults(channelResultsBuffer); + swapOutputProcessor(); } + + mReusableComplexBufferAssembler.updateTimestamp(channelResultsBuffer.getTimestamp()); + mPolyphaseChannelOutputProcessor.receiveChannelResults(channelResultsBuffer); } /** @@ -173,7 +204,6 @@ public class PolyphaseChannelSource extends TunerChannelSource if(mPolyphaseChannelOutputProcessor != null) { mPolyphaseChannelOutputProcessor.dispose(); - mPolyphaseChannelOutputProcessor = null; } } @@ -213,11 +243,7 @@ public class PolyphaseChannelSource extends TunerChannelSource @Override protected void processSamples() { - //Lock on the output processor so that it can't be changed in the middle of processing - synchronized(mPolyphaseChannelOutputProcessor) - { - mPolyphaseChannelOutputProcessor.processChannelResults(mReusableComplexBufferAssembler); - } + mPolyphaseChannelOutputProcessor.processChannelResults(mReusableComplexBufferAssembler); } /** @@ -236,10 +262,7 @@ public class PolyphaseChannelSource extends TunerChannelSource */ private void updateFrequencyOffset() { - synchronized(mPolyphaseChannelOutputProcessor) - { - mPolyphaseChannelOutputProcessor.setFrequencyOffset(getFrequencyOffset()); - } + mPolyphaseChannelOutputProcessor.setFrequencyOffset(getFrequencyOffset()); } @Override @@ -248,4 +271,42 @@ public class PolyphaseChannelSource extends TunerChannelSource return "POLYPHASE [" + mPolyphaseChannelOutputProcessor.getInputChannelCount() + "] " + getTunerChannel().getFrequency(); } + + /** + * Creates a low-pass filter to use as the final cleanup filter for the decimated output stream + * + * @param sampleRate for the final output channel rate + * @param passFrequency for half of the desired channel rate + * @param stopFrequency for the attenuated band + * @return a newly designed filter or a previously designed (cached) filter + * @throws FilterDesignException + */ + private float[] getLowPassFilter(double sampleRate, double passFrequency, double stopFrequency) throws FilterDesignException + { + //Use existing filter if we've already designed one + if(sLowPassFilters.containsKey((int)sampleRate)) + { + return sLowPassFilters.get((int)sampleRate); + } + + FIRFilterSpecification specification = FIRFilterSpecification.lowPassBuilder() + .sampleRate(sampleRate) + .gridDensity(16) + .passBandCutoff(passFrequency) + .passBandAmplitude(1.0) + .passBandRipple(0.01) + .stopBandStart(stopFrequency) + .stopBandAmplitude(0.0) + .stopBandRipple(0.01) + .build(); + + RemezFIRFilterDesigner designer = new RemezFIRFilterDesigner(specification); + + //This will throw an exception if the filter cannot be designed + float[] taps = designer.getImpulseResponse(); + + sLowPassFilters.put((int)sampleRate, taps); + + return taps; + } } diff --git a/src/main/java/io/github/dsheirer/dsp/filter/channelizer/output/TwoChannelOutputProcessor.java b/src/main/java/io/github/dsheirer/dsp/filter/channelizer/output/TwoChannelOutputProcessor.java index 6a8090f0..780d136e 100644 --- a/src/main/java/io/github/dsheirer/dsp/filter/channelizer/output/TwoChannelOutputProcessor.java +++ b/src/main/java/io/github/dsheirer/dsp/filter/channelizer/output/TwoChannelOutputProcessor.java @@ -16,29 +16,18 @@ package io.github.dsheirer.dsp.filter.channelizer.output; import io.github.dsheirer.dsp.filter.channelizer.TwoChannelSynthesizerM2; -import io.github.dsheirer.dsp.filter.design.FilterDesignException; -import io.github.dsheirer.dsp.filter.fir.FIRFilterSpecification; -import io.github.dsheirer.dsp.filter.fir.complex.ComplexFIRFilter2; -import io.github.dsheirer.dsp.filter.fir.remez.RemezFIRFilterDesigner; import io.github.dsheirer.dsp.mixer.FS4DownConverter; import io.github.dsheirer.sample.buffer.ReusableChannelResultsBuffer; import io.github.dsheirer.sample.buffer.ReusableComplexBuffer; import io.github.dsheirer.sample.buffer.ReusableComplexBufferAssembler; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import java.util.HashMap; import java.util.List; -import java.util.Map; public class TwoChannelOutputProcessor extends ChannelOutputProcessor { - private final static Logger mLog = LoggerFactory.getLogger(TwoChannelOutputProcessor.class); - - private static Map sLowPassFilterKernelMap = new HashMap<>(); +// private final static Logger mLog = LoggerFactory.getLogger(TwoChannelOutputProcessor.class); private TwoChannelSynthesizerM2 mSynthesizer; private FS4DownConverter mFS4DownConverter = new FS4DownConverter(); - private ComplexFIRFilter2 mLowPassFilter; private int mChannelOffset1; private int mChannelOffset2; @@ -58,28 +47,11 @@ public class TwoChannelOutputProcessor extends ChannelOutputProcessor super(2, sampleRate, gain); setPolyphaseChannelIndices(channelIndexes); setSynthesisFilter(filter); - - float[] lowPassFilter = sLowPassFilterKernelMap.get((int)sampleRate); - - if(lowPassFilter == null) - { - try - { - lowPassFilter = getLowPassFilter(sampleRate); - sLowPassFilterKernelMap.put((int)sampleRate, lowPassFilter); - } - catch(FilterDesignException fde) - { - mLog.error("Couldn't design a low-pass filter for 2-channel synthesizer", fde); - throw new IllegalStateException("Cannot design low-pass filter for 2 channel synthesizer", fde); - } - } - - mLowPassFilter = new ComplexFIRFilter2(lowPassFilter, 1.0f); } /** * Sets the frequency offset to apply to the incoming samples to mix the desired signal to baseband. + * * @param frequencyOffset in hertz */ @Override @@ -126,7 +98,7 @@ public class TwoChannelOutputProcessor extends ChannelOutputProcessor public void process(List channelResultsBuffers, ReusableComplexBufferAssembler reusableComplexBufferAssembler) { - for(ReusableChannelResultsBuffer buffer: channelResultsBuffers) + for(ReusableChannelResultsBuffer buffer : channelResultsBuffers) { ReusableComplexBuffer channel1 = buffer.getChannel(mChannelOffset1); ReusableComplexBuffer channel2 = buffer.getChannel(mChannelOffset2); @@ -140,48 +112,11 @@ public class TwoChannelOutputProcessor extends ChannelOutputProcessor //Apply offset and frequency correction to center the signal of interest within the synthesized channel getFrequencyCorrectionMixer().mixComplex(synthesized.getSamples()); - ReusableComplexBuffer lowPassFiltered = mLowPassFilter.filter(synthesized); + synthesized.applyGain(getGain()); - lowPassFiltered.applyGain(getGain()); - - reusableComplexBufferAssembler.receive(lowPassFiltered); + reusableComplexBufferAssembler.receive(synthesized); buffer.decrementUserCount(); } } - - /** - * Creates a low-pass filter kernel for the specified sample rate. - * @param sampleRate for the channel - * @return filter - * @throws FilterDesignException if the filter cannot be designed - */ - private static float[] getLowPassFilter(double sampleRate) throws FilterDesignException - { - double cutoff = sampleRate / 4.0; - int passBandCutoff = (int)(cutoff * 0.92); - int stopBandStart = (int)(cutoff * 1.08); - - FIRFilterSpecification specification = FIRFilterSpecification.lowPassBuilder() - .sampleRate(sampleRate) - .gridDensity(16) - .oddLength(true) - .passBandCutoff((int)passBandCutoff) - .passBandAmplitude(1.0) - .passBandRipple(0.01) - .stopBandStart((int)stopBandStart) - .stopBandAmplitude(0.0) - .stopBandRipple(0.005) //Approximately 94 dB attenuation - .build(); - - RemezFIRFilterDesigner designer = new RemezFIRFilterDesigner(specification); - - if(designer.isValid()) - { - return designer.getImpulseResponse(); - } - - throw new FilterDesignException("Couldn't design low-pass filter for sample rate: " + sampleRate + - " Pass End:" + passBandCutoff + " Stop Begin:" + stopBandStart); - } } diff --git a/src/main/java/io/github/dsheirer/dsp/psk/pll/PLLGain.java b/src/main/java/io/github/dsheirer/dsp/psk/pll/PLLGain.java index dd813578..2e0a52a6 100644 --- a/src/main/java/io/github/dsheirer/dsp/psk/pll/PLLGain.java +++ b/src/main/java/io/github/dsheirer/dsp/psk/pll/PLLGain.java @@ -23,8 +23,8 @@ public enum PLLGain //NOTE: static gain level of 200 produced the best results for releases prior to 0.3.4b2 LEVEL_1(150.0, 0, 1), - LEVEL_2(175.0, 2, 4), - LEVEL_3(200.0, 5, 6), + LEVEL_2(170.0, 2, 4), + LEVEL_3(190.0, 5, 6), LEVEL_4(200.0, 7, 8), LEVEL_5(200.0, 9, 10); diff --git a/src/main/java/io/github/dsheirer/gui/channelizer/ChannelizerViewer2.java b/src/main/java/io/github/dsheirer/gui/channelizer/ChannelizerViewer2.java index 2f50df16..4a7bc457 100644 --- a/src/main/java/io/github/dsheirer/gui/channelizer/ChannelizerViewer2.java +++ b/src/main/java/io/github/dsheirer/gui/channelizer/ChannelizerViewer2.java @@ -23,6 +23,7 @@ import io.github.dsheirer.source.ISourceEventProcessor; import io.github.dsheirer.source.SourceEvent; import io.github.dsheirer.source.SourceException; import io.github.dsheirer.source.tuner.Tuner; +import io.github.dsheirer.source.tuner.channel.ChannelSpecification; import io.github.dsheirer.source.tuner.channel.TunerChannel; import io.github.dsheirer.source.tuner.channel.TunerChannelSource; import io.github.dsheirer.source.tuner.configuration.TunerConfigurationModel; @@ -376,10 +377,11 @@ public class ChannelizerViewer2 extends JFrame mComplexDecibelConverter.addListener(mSpectrumPanel); TunerChannel tunerChannel = new TunerChannel(frequency, bandwidth); - mSource = mTestTuner.getChannelSourceManager().getSource(tunerChannel, null); + mSource = mTestTuner.getChannelSourceManager().getSource(tunerChannel, new ChannelSpecification(50000, 12500, 6000, 7000)); if(mSource != null) { + mLog.debug("Channel: " + mSource.getTunerChannel() + " Rate:" + mSource.getSampleRate()); mSource.setListener(new Listener() { @Override diff --git a/src/main/java/io/github/dsheirer/module/decode/p25/DecodeConfigP25Phase1.java b/src/main/java/io/github/dsheirer/module/decode/p25/DecodeConfigP25Phase1.java index e76b3267..d9300630 100644 --- a/src/main/java/io/github/dsheirer/module/decode/p25/DecodeConfigP25Phase1.java +++ b/src/main/java/io/github/dsheirer/module/decode/p25/DecodeConfigP25Phase1.java @@ -113,7 +113,6 @@ public class DecodeConfigP25Phase1 extends DecodeConfiguration @Override public ChannelSpecification getChannelSpecification() { - return new ChannelSpecification(50000.0, - 12500, 6000.0, 7000.0); + return new ChannelSpecification(50000.0, 12500, 5750.0, 6500.0); } } diff --git a/src/main/java/io/github/dsheirer/source/tuner/Tuner.java b/src/main/java/io/github/dsheirer/source/tuner/Tuner.java index cfe6eae3..da355c87 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/Tuner.java +++ b/src/main/java/io/github/dsheirer/source/tuner/Tuner.java @@ -21,7 +21,7 @@ import io.github.dsheirer.source.ISourceEventProcessor; import io.github.dsheirer.source.SourceEvent; import io.github.dsheirer.source.tuner.TunerEvent.Event; import io.github.dsheirer.source.tuner.manager.ChannelSourceManager; -import io.github.dsheirer.source.tuner.manager.HeterodyneChannelSourceManager; +import io.github.dsheirer.source.tuner.manager.PolyphaseChannelSourceManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -51,8 +51,8 @@ public abstract class Tuner implements ISourceEventProcessor //Register to receive frequency and sample rate change notifications mTunerController.addListener(this::process); -// mChannelSourceManager = new PolyphaseChannelSourceManager(mTunerController); - mChannelSourceManager = new HeterodyneChannelSourceManager(mTunerController); + mChannelSourceManager = new PolyphaseChannelSourceManager(mTunerController); +// mChannelSourceManager = new HeterodyneChannelSourceManager(mTunerController); //Register to receive channel count change notifications mChannelSourceManager.addSourceEventListener(this::process); diff --git a/src/main/java/io/github/dsheirer/source/tuner/channel/CICTunerChannelSource.java b/src/main/java/io/github/dsheirer/source/tuner/channel/CICTunerChannelSource.java index e15cdfbc..9253200b 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/channel/CICTunerChannelSource.java +++ b/src/main/java/io/github/dsheirer/source/tuner/channel/CICTunerChannelSource.java @@ -18,7 +18,7 @@ package io.github.dsheirer.source.tuner.channel; import io.github.dsheirer.dsp.filter.cic.ComplexPrimeCICDecimate; import io.github.dsheirer.dsp.filter.design.FilterDesignException; import io.github.dsheirer.dsp.mixer.IOscillator; -import io.github.dsheirer.dsp.mixer.Oscillator; +import io.github.dsheirer.dsp.mixer.LowPhaseNoiseOscillator; import io.github.dsheirer.sample.IOverflowListener; import io.github.dsheirer.sample.Listener; import io.github.dsheirer.sample.buffer.OverflowableReusableBufferTransferQueue; @@ -81,7 +81,7 @@ public class CICTunerChannelSource extends TunerChannelSource implements Listene mTunerFrequency = tunerChannel.getFrequency(); long frequencyOffset = mTunerFrequency - getTunerChannel().getFrequency(); - mFrequencyCorrectionMixer = new Oscillator(frequencyOffset, sampleRate); + mFrequencyCorrectionMixer = new LowPhaseNoiseOscillator(frequencyOffset, sampleRate); } /** diff --git a/src/main/java/io/github/dsheirer/source/tuner/channel/TunerChannelSource.java b/src/main/java/io/github/dsheirer/source/tuner/channel/TunerChannelSource.java index 8a8efac4..0f429aed 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/channel/TunerChannelSource.java +++ b/src/main/java/io/github/dsheirer/source/tuner/channel/TunerChannelSource.java @@ -294,6 +294,10 @@ public abstract class TunerChannelSource extends ComplexSource implements ISourc { mLog.error("Error while sending heartbeat", t); } + } + + if(!mStopped) + { try { processSamples(); diff --git a/src/main/java/io/github/dsheirer/source/tuner/manager/PolyphaseChannelSourceManager.java b/src/main/java/io/github/dsheirer/source/tuner/manager/PolyphaseChannelSourceManager.java index 24db62a1..4da3e143 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/manager/PolyphaseChannelSourceManager.java +++ b/src/main/java/io/github/dsheirer/source/tuner/manager/PolyphaseChannelSourceManager.java @@ -393,11 +393,6 @@ public class PolyphaseChannelSourceManager extends ChannelSourceManager @Override public TunerChannelSource getSource(TunerChannel tunerChannel, ChannelSpecification channelSpecification) { - if(channelSpecification != null) - { - throw new IllegalArgumentException("Update polyphase source manager to support channel specifications"); - } - if(isTunable(tunerChannel)) { //Get a new set of currently tuned channels @@ -422,7 +417,7 @@ public class PolyphaseChannelSourceManager extends ChannelSourceManager } //If we're successful to here, allocate the channel - return mPolyphaseChannelManager.getChannel(tunerChannel); + return mPolyphaseChannelManager.getChannel(tunerChannel, channelSpecification); } catch(SourceException se) { diff --git a/src/main/java/io/github/dsheirer/source/tuner/test/TestTunerController.java b/src/main/java/io/github/dsheirer/source/tuner/test/TestTunerController.java index 27a7e08f..00876662 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/test/TestTunerController.java +++ b/src/main/java/io/github/dsheirer/source/tuner/test/TestTunerController.java @@ -32,7 +32,7 @@ public class TestTunerController extends TunerController public static final long MINIMUM_FREQUENCY = 1l; public static final long MAXIMUM_FREQUENCY = 1000000000l; - public static final int SAMPLE_RATE = 50000; + public static final int SAMPLE_RATE = 10000000; public static final int DC_NOISE_BANDWIDTH = 0; public static final double USABLE_BANDWIDTH_PERCENTAGE = 1.00;