mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 08:37:25 -05:00
Removes unused legacy code.
This commit is contained in:
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user