From 50bc3088b713cda0f719ed7326dd038ed5910c6f Mon Sep 17 00:00:00 2001 From: Denny Date: Wed, 5 Sep 2018 06:31:39 -0400 Subject: [PATCH] Removes unused legacy code. --- .../dsheirer/dsp/filter/FilterFactory.java | 10 - .../filter/cic/ComplexPrimeCICDecimate.java | 415 ------------------ .../tuner/channel/CICTunerChannelSource.java | 215 --------- 3 files changed, 640 deletions(-) delete mode 100644 src/main/java/io/github/dsheirer/dsp/filter/cic/ComplexPrimeCICDecimate.java delete mode 100644 src/main/java/io/github/dsheirer/source/tuner/channel/CICTunerChannelSource.java 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