diff --git a/src/main/java/io/github/dsheirer/dsp/filter/FilterFactory.java b/src/main/java/io/github/dsheirer/dsp/filter/FilterFactory.java
index 53ae57f3..cab8d1b7 100644
--- a/src/main/java/io/github/dsheirer/dsp/filter/FilterFactory.java
+++ b/src/main/java/io/github/dsheirer/dsp/filter/FilterFactory.java
@@ -22,7 +22,6 @@
******************************************************************************/
package io.github.dsheirer.dsp.filter;
-import io.github.dsheirer.dsp.filter.cic.ComplexPrimeCICDecimate;
import io.github.dsheirer.dsp.filter.design.FilterDesignException;
import io.github.dsheirer.dsp.filter.fir.FIRFilterSpecification;
import io.github.dsheirer.dsp.filter.fir.remez.RemezFIRFilterDesigner;
@@ -358,15 +357,6 @@ public class FilterFactory
return (int)(Math.round((double)attenuation / (22.0d * frequency)));
}
- public static ComplexPrimeCICDecimate getDecimationFilter(int sampleRate, int decimatedRate, int order,
- int passFrequency, int attenuation, Window.WindowType windowType)
- {
- int decimationRate = (int)(sampleRate / decimatedRate);
-
- return new ComplexPrimeCICDecimate(decimationRate, order,
- passFrequency, attenuation, windowType);
- }
-
/**
* Determines decimation rate(s) for a polyphase decimation filter.
*
diff --git a/src/main/java/io/github/dsheirer/dsp/filter/cic/ComplexPrimeCICDecimate.java b/src/main/java/io/github/dsheirer/dsp/filter/cic/ComplexPrimeCICDecimate.java
deleted file mode 100644
index 54c2db59..00000000
--- a/src/main/java/io/github/dsheirer/dsp/filter/cic/ComplexPrimeCICDecimate.java
+++ /dev/null
@@ -1,415 +0,0 @@
-/*******************************************************************************
- * sdr-trunk
- * Copyright (C) 2014-2018 Dennis Sheirer
- *
- * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program.
- * If not, see
- *
- ******************************************************************************/
-package io.github.dsheirer.dsp.filter.cic;
-
-import io.github.dsheirer.dsp.filter.FilterFactory;
-import io.github.dsheirer.dsp.filter.Filters;
-import io.github.dsheirer.dsp.filter.Window;
-import io.github.dsheirer.dsp.filter.fir.complex.ComplexFIRFilter2;
-import io.github.dsheirer.dsp.filter.halfband.complex.ComplexHalfBandFilter;
-import io.github.dsheirer.sample.Listener;
-import io.github.dsheirer.sample.buffer.ReusableComplexBuffer;
-import io.github.dsheirer.sample.buffer.ReusableComplexBufferAssembler;
-import io.github.dsheirer.sample.complex.ComplexSampleListener;
-import io.github.dsheirer.sample.decimator.ComplexDecimator;
-import org.apache.commons.lang3.Validate;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class ComplexPrimeCICDecimate implements Listener
-{
- public static int[] PRIMES = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53,
- 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151,
- 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251,
- 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359,
- 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
- 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593,
- 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691};
-
- private ArrayList mDecimatingStages =
- new ArrayList();
-
- private DecimatingStage mFirstDecimatingStage;
-
- private Output mOutput;
-
- /**
- * Non-Recursive Prime-Factor CIC Filter with float sample array inputs and
- * decimated, single paired i/q float sample output.
- *
- * Implements the CIC filter described in Understanding Digital Signal
- * Processing, 3e, Lyons, on page 769. This filter is comprised of multiple
- * decimating stages each with a prime factor decimation rate. Multiple
- * stages are cascaded to achieve the overall decimation rate.
- *
- * This filter supports a maximum decimation rate of 700. This filter can
- * be adapted to higher decimation rates by adding additional prime factors
- * to the PRIMES array.
- *
- * @param decimation - overall decimation rate
- * @param order - filter order
- */
- public ComplexPrimeCICDecimate(int decimation, int order,
- int passFrequency, int attenuation, Window.WindowType windowType)
- {
- Validate.isTrue(decimation <= 700);
-
-
- List stageSizes = getPrimeFactors(decimation);
-
- for(int x = 0; x < stageSizes.size(); x++)
- {
- DecimatingStage stage = new DecimatingStage(stageSizes.get(x), order);
-
- mDecimatingStages.add(stage);
-
- if(x == 0)
- {
- /* Reference to first stage -- will receive all samples */
- mFirstDecimatingStage = stage;
- }
- else
- {
- /* Wire the current stage to the previous stage */
- mDecimatingStages.get(x - 1).setListener(stage);
- }
- }
-
- mOutput = new Output(48000, passFrequency, attenuation, windowType);
-
- mDecimatingStages.get(mDecimatingStages.size() - 1)
- .setListener(mOutput);
- }
-
- public void dispose()
- {
- for(DecimatingStage stage : mDecimatingStages)
- {
- stage.dispose();
- }
-
- mDecimatingStages.clear();
- mDecimatingStages = null;
- mFirstDecimatingStage = null;
-
- mOutput.dispose();
- mOutput = null;
- }
-
- /**
- * Adds a listener to receive the output of this CIC decimation filter
- */
- public void setListener(Listener listener)
- {
- mOutput.setListener(listener);
- }
-
- /**
- * Removes listener from output of this CIC decimation filter
- */
- public void removeListener()
- {
- mOutput.removeListener();
- }
-
- /**
- * Calculates the prime factors of the decimation rate up to a maximum
- * decimation rate of 700. If you wish to have decimation rates higher
- * than 700, then add additional prime factors to the PRIMES array.
- *
- * @param decimation - integral decimation rate
- * @return - ordered list (smallest to largest) of prime factors
- */
- public static List getPrimeFactors(int decimation)
- {
- ArrayList stages = new ArrayList();
-
- int pointer = 0;
-
- while(decimation > 0 && pointer < PRIMES.length)
- {
- int prime = PRIMES[pointer];
-
- if(decimation % prime == 0)
- {
- stages.add(prime);
-
- decimation /= prime;
- }
- else
- {
- pointer++;
- }
- }
-
- return stages;
- }
-
- /**
- * Primary input method for receiving sample arrays composed as I,Q,I,Q, etc.
- */
- @Override
- public void receive(ReusableComplexBuffer buffer)
- {
- if(mFirstDecimatingStage != null)
- {
- float[] samples = buffer.getSamples();
-
- for(int x = 0; x < samples.length; x += 2)
- {
- mFirstDecimatingStage.receive(samples[x], samples[x + 1]);
- }
- }
-
- buffer.decrementUserCount();
- }
-
- /**
- * Decimating stage combines multiple CIC stages with a decimator. The
- * number of stages is indicated by the order value and the size indicates
- * the decimation rate of this stage.
- */
- public class DecimatingStage implements ComplexSampleListener
- {
- private ArrayList mStages = new ArrayList();
- private Stage mFirstStage;
- private ComplexDecimator mDecimator;
-
- public DecimatingStage(int size, int order)
- {
- for(int x = 0; x < order; x++)
- {
- Stage stage;
-
- if(size == 2)
- {
- stage = new TwoStage();
- }
- else
- {
- stage = new Stage(size);
- }
-
- mStages.add(stage);
-
- if(x == 0)
- {
- mFirstStage = stage;
- }
- else
- {
- mStages.get(x - 1).setListener(stage);
- }
- }
-
- mDecimator = new ComplexDecimator(size);
-
- mStages.get(mStages.size() - 1).setListener(mDecimator);
- }
-
- public void dispose()
- {
- for(Stage stage : mStages)
- {
- stage.dispose();
- }
-
- mStages.clear();
- mDecimator.dispose();
- mDecimator = null;
- mFirstStage = null;
- mStages = null;
- }
-
- @Override
- public void receive(float i, float q)
- {
- mFirstStage.receive(i, q);
- }
-
- public void setListener(ComplexSampleListener listener)
- {
- mDecimator.setListener(listener);
- }
- }
-
- /**
- * Single non-decimating CIC stage component. Uses a circular buffer and a
- * running average internally to implement the stage so that stage size has
- * essentially no impact on the computational requirements of the stage
- */
- public class Stage implements ComplexSampleListener
- {
- protected ComplexSampleListener mListener;
-
- private float[] mISamples;
- private float[] mQSamples;
-
- protected float mISum;
- protected float mQSum;
-
- private int mSamplePointer = 0;
- private int mSize;
-
- protected float mGain;
-
- public Stage()
- {
- }
-
- public Stage(int size)
- {
- mSize = size - 1;
-
- mISamples = new float[mSize];
- mQSamples = new float[mSize];
-
- mGain = 1.0f / (float)size;
- }
-
- public void dispose()
- {
- mListener = null;
- }
-
- public void receive(float i, float q)
- {
- /* Subtract the oldest sample and add back in the newest */
- mISum = mISum - mISamples[mSamplePointer] + i;
- mQSum = mQSum - mQSamples[mSamplePointer] + q;
-
- /* Overwrite the oldest sample with the newest */
- mISamples[mSamplePointer] = i;
- mQSamples[mSamplePointer] = q;
-
- mSamplePointer++;
-
- if(mSamplePointer >= mSize)
- {
- mSamplePointer = 0;
- }
-
- if(mListener != null)
- {
- mListener.receive((mISum * mGain), (mQSum * mGain));
- }
- }
-
- public void setListener(ComplexSampleListener listener)
- {
- mListener = listener;
- }
- }
-
- /**
- * Size 2 stage that removes the unnecessary circular buffer management for
- * a two-stage.
- */
- public class TwoStage extends Stage
- {
- public TwoStage()
- {
- super();
-
- mGain = 0.5f;
- }
-
- public void receive(float i, float q)
- {
- float iSum = mISum + i;
- float qSum = mQSum + q;
-
- mISum = i;
- mQSum = q;
-
- if(mListener != null)
- {
- mListener.receive((iSum * mGain), (qSum * mGain));
- }
- }
- }
-
-
- /**
- * Output adapter - applies gain correction and cleanup filter and broadcast
- * to registered listener.
- */
- public class Output implements ComplexSampleListener
- {
- /* Decimated output buffers will contain 1024 samples */
- private ReusableComplexBufferAssembler mAssembler = new ReusableComplexBufferAssembler(2048, 48000.0);
-
- private ComplexFIRFilter2 mCleanupFilter;
- private ComplexHalfBandFilter mHalfBandFilter = new ComplexHalfBandFilter(
- Filters.FIR_HALF_BAND_31T_ONE_EIGHTH_FCO.getCoefficients(), 0.4f, false);
- private Listener mReusableComplexBufferListener;
-
- public Output(int outputSampleRate, int passFrequency, int attenuation,
- Window.WindowType windowType)
- {
- mCleanupFilter = new ComplexFIRFilter2(FilterFactory
- .getCICCleanupFilter(outputSampleRate, passFrequency, attenuation, windowType), 0.4f);
-
- //Bypassing the CIC cleanup filter for now
- mAssembler.setListener(new Listener()
- {
- @Override
- public void receive(ReusableComplexBuffer reusableComplexBuffer)
- {
- if(mReusableComplexBufferListener != null)
- {
- ReusableComplexBuffer cleanupFiltered = mCleanupFilter.filter(reusableComplexBuffer);
- ReusableComplexBuffer halfBandFiltered = mHalfBandFilter.filter(cleanupFiltered);
- mReusableComplexBufferListener.receive(halfBandFiltered);
- }
- else
- {
- reusableComplexBuffer.decrementUserCount();
- }
- }
- });
- }
-
- public void dispose()
- {
- mAssembler.dispose();
- mCleanupFilter.dispose();
- mHalfBandFilter.dispose();
- }
-
- /**
- * Receiver method for the output adapter to receive a filtered,
- * decimated sample, apply gain correction, apply cleanup filtering
- * and output the sample values as a complex sample.
- */
- @Override
- public void receive(float inphase, float quadrature)
- {
- mAssembler.receive(new float[]{inphase, quadrature});
- }
-
- public void setListener(Listener listener)
- {
- mReusableComplexBufferListener = listener;
- }
-
- public void removeListener()
- {
- mReusableComplexBufferListener = null;
- }
- }
-}
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
deleted file mode 100644
index 0ea4fdf8..00000000
--- a/src/main/java/io/github/dsheirer/source/tuner/channel/CICTunerChannelSource.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/*******************************************************************************
- * sdr-trunk
- * Copyright (C) 2014-2018 Dennis Sheirer
- *
- * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with this program.
- * If not, see
- *
- ******************************************************************************/
-package io.github.dsheirer.source.tuner.channel;
-
-import io.github.dsheirer.dsp.filter.FilterFactory;
-import io.github.dsheirer.dsp.filter.Window;
-import io.github.dsheirer.dsp.filter.cic.ComplexPrimeCICDecimate;
-import io.github.dsheirer.dsp.mixer.IOscillator;
-import io.github.dsheirer.dsp.mixer.Oscillator;
-import io.github.dsheirer.sample.Listener;
-import io.github.dsheirer.sample.buffer.OverflowableReusableBufferTransferQueue;
-import io.github.dsheirer.sample.buffer.ReusableComplexBuffer;
-import io.github.dsheirer.sample.buffer.ReusableComplexBufferQueue;
-import io.github.dsheirer.sample.complex.Complex;
-import io.github.dsheirer.source.tuner.Tuner;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class CICTunerChannelSource
-{
- private final static Logger mLog = LoggerFactory.getLogger(CICTunerChannelSource.class);
-
- //Maximum number of filled buffers for the blocking queue
- private static final int BUFFER_MAX_CAPACITY = 300;
-
- //Threshold for resetting buffer overflow condition
- private static final int BUFFER_OVERFLOW_RESET_THRESHOLD = 100;
-
- private static double CHANNEL_RATE = 48000.0;
- private static int CHANNEL_PASS_FREQUENCY = 12000;
-
- private OverflowableReusableBufferTransferQueue mBuffer;
- private ReusableComplexBufferQueue mReusableComplexBufferQueue = new ReusableComplexBufferQueue("CICTunerChannelSource");
- private IOscillator mFrequencyCorrectionMixer;
- private ComplexPrimeCICDecimate mDecimationFilter;
- private Listener mListener;
- private List mSampleBuffers = new ArrayList<>();
- private long mTunerFrequency = 0;
- private double mTunerSampleRate;
- private long mChannelFrequencyCorrection = 0;
-
- /**
- * Implements a heterodyne/decimate Digital Drop Channel (DDC) to decimate the IQ output from a tuner down to a
- * fixed 48 kHz IQ channel rate.
- *
- * Note: this class can only be used once (started and stopped) and a new tuner channel source must be requested
- * from the tuner once this object has been stopped. This is because channels are managed dynamically and center
- * tuned frequency may have changed since this source was obtained and thus the tuner might no longer be able to
- * source this channel once it has been stopped.
- *
- * @param tunerChannel specifying the center frequency for the DDC
- */
- public CICTunerChannelSource(Tuner tuner, TunerChannel tunerChannel)
- {
- mBuffer = new OverflowableReusableBufferTransferQueue<>(BUFFER_MAX_CAPACITY, BUFFER_OVERFLOW_RESET_THRESHOLD);
-// mBuffer.setSourceOverflowListener(this);
-
- //Setup the frequency translator to the current source frequency
- mTunerFrequency = tuner.getTunerController().getFrequency();
- long frequencyOffset = mTunerFrequency - tunerChannel.getFrequency();
- mFrequencyCorrectionMixer = new Oscillator(frequencyOffset, tuner.getTunerController().getSampleRate());
-
- //Setup the decimation filter chain
- setSampleRate(tuner.getTunerController().getSampleRate());
- }
-
- /**
- * Sets the center frequency for the incoming sample buffers
- * @param frequency in hertz
- */
- protected void setFrequency(long frequency)
- {
- mTunerFrequency = frequency;
-
- //Reset frequency correction so that consumer components can adjust
- setFrequencyCorrection(0);
-
- updateMixerFrequencyOffset();
- }
-
- /**
- * Current frequency correction being applied to the channel sample stream
- * @return correction in hertz
- */
- public long getFrequencyCorrection()
- {
- return mChannelFrequencyCorrection;
- }
-
- /**
- * Changes the frequency correction value and broadcasts the change to the registered downstream listener.
- * @param correction current frequency correction value.
- */
- protected void setFrequencyCorrection(long correction)
- {
- mChannelFrequencyCorrection = correction;
-
- updateMixerFrequencyOffset();
-
-// broadcastConsumerSourceEvent(SourceEvent.frequencyCorrectionChange(mChannelFrequencyCorrection));
- }
-
- /**
- * Primary input method for receiving complex sample buffers from the wideband source (ie tuner)
- * @param buffer to receive and eventually process
- */
- public void receive(ReusableComplexBuffer buffer)
- {
- mBuffer.offer(buffer);
- }
-
- public void setListener(Listener listener)
- {
- /* Save a pointer to the listener so that if we have to change the
- * decimation filter, we can re-add the listener */
- mListener = listener;
-
- mDecimationFilter.setListener(listener);
- }
-
- public void removeListener(Listener listener)
- {
- mDecimationFilter.removeListener();
- }
-
- /**
- * Updates the sample rate to the requested value and notifies any downstream components of the change
- * @param sampleRate to set
- */
- protected void setSampleRate(double sampleRate)
- {
- if(mTunerSampleRate != sampleRate)
- {
- mFrequencyCorrectionMixer.setSampleRate(sampleRate);
-
- /* Get new decimation filter */
- mDecimationFilter = FilterFactory.getDecimationFilter((int)sampleRate, (int)CHANNEL_RATE, 1,
- CHANNEL_PASS_FREQUENCY, 60, Window.WindowType.HAMMING);
-
- /* re-add the original output listener */
- mDecimationFilter.setListener(mListener);
-
- mTunerSampleRate = sampleRate;
-
-// broadcastConsumerSourceEvent(SourceEvent.channelSampleRateChange(getSampleRate()));
- }
- }
-
- /**
- * Calculates the local mixer frequency offset from the tuned frequency,
- * channel's requested frequency, and channel frequency correction.
- */
- private void updateMixerFrequencyOffset()
- {
-// long offset = mTunerFrequency - getTunerChannel().getFrequency() - mChannelFrequencyCorrection;
-// mFrequencyCorrectionMixer.setFrequency(offset);
- }
-
- public double getSampleRate()
- {
- return CHANNEL_RATE;
- }
-
- protected void processSamples()
- {
- mBuffer.drainTo(mSampleBuffers, 20);
-
- for(ReusableComplexBuffer buffer : mSampleBuffers)
- {
- float[] samples = buffer.getSamples();
-
- ReusableComplexBuffer reusableComplexBuffer = mReusableComplexBufferQueue.getBuffer(samples.length);
- float[] translated = reusableComplexBuffer.getSamples();
-
- /* Perform frequency translation */
- for(int x = 0; x < samples.length; x += 2)
- {
- mFrequencyCorrectionMixer.rotate();
-
- translated[x] = Complex.multiplyInphase(
- samples[x], samples[x + 1], mFrequencyCorrectionMixer.inphase(), mFrequencyCorrectionMixer.quadrature());
-
- translated[x + 1] = Complex.multiplyQuadrature(
- samples[x], samples[x + 1], mFrequencyCorrectionMixer.inphase(), mFrequencyCorrectionMixer.quadrature());
- }
-
- final ComplexPrimeCICDecimate filter = mDecimationFilter;
-
- if(filter != null)
- {
- filter.receive(reusableComplexBuffer);
- }
-
- buffer.decrementUserCount();
- }
-
- mSampleBuffers.clear();
- }
-}
\ No newline at end of file