Removes unused legacy code.

This commit is contained in:
Denny
2018-09-05 06:31:39 -04:00
parent 09356848eb
commit 50bc3088b7
3 changed files with 0 additions and 640 deletions

View File

@@ -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.
*

View File

@@ -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 <http://www.gnu.org/licenses/>
*
******************************************************************************/
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<ReusableComplexBuffer>
{
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<DecimatingStage> mDecimatingStages =
new ArrayList<DecimatingStage>();
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<Integer> 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<ReusableComplexBuffer> 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<Integer> getPrimeFactors(int decimation)
{
ArrayList<Integer> stages = new ArrayList<Integer>();
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<Stage> mStages = new ArrayList<Stage>();
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<ReusableComplexBuffer> 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<ReusableComplexBuffer>()
{
@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<ReusableComplexBuffer> listener)
{
mReusableComplexBufferListener = listener;
}
public void removeListener()
{
mReusableComplexBufferListener = null;
}
}
}

View File

@@ -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 <http://www.gnu.org/licenses/>
*
******************************************************************************/
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<ReusableComplexBuffer> mBuffer;
private ReusableComplexBufferQueue mReusableComplexBufferQueue = new ReusableComplexBufferQueue("CICTunerChannelSource");
private IOscillator mFrequencyCorrectionMixer;
private ComplexPrimeCICDecimate mDecimationFilter;
private Listener<ReusableComplexBuffer> mListener;
private List<ReusableComplexBuffer> 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<ReusableComplexBuffer> 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<ReusableComplexBuffer> 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();
}
}