Changed FrequencyChangeListener interface to an event so that I could describe what event was causing the frequency change and to broadcast frequency and sample rate error values.

R820T - added a couple more sample rate settings to the enum and modified the periodic sample rate info logger.
This commit is contained in:
dennis.sheirer
2014-09-27 09:46:18 +00:00
parent e441ebf0c9
commit 550aed79d4
28 changed files with 600 additions and 500 deletions

View File

@@ -46,6 +46,7 @@ import source.FloatSource;
import source.Source;
import source.SourceException;
import source.config.SourceConfigMixer;
import source.tuner.FrequencyChangeListener;
import source.tuner.Tuner;
import source.tuner.TunerChannelSource;
import alias.AliasList;
@@ -61,7 +62,6 @@ import controller.state.ChannelState.State;
import decode.Decoder;
import decode.DecoderFactory;
import dsp.afc.AutomaticFrequencyControl;
import dsp.afc.FrequencyErrorListener;
import eventlog.EventLogType;
import eventlog.EventLogger;
@@ -403,16 +403,15 @@ public class ProcessingChain implements Listener<Message>
mAFC = null;
}
if( mSource instanceof FrequencyErrorListener &&
if( mSource instanceof TunerChannelSource &&
mChannel.getDecodeConfiguration().isAFCEnabled() )
{
FrequencyErrorListener listener =
(FrequencyErrorListener)mSource;
TunerChannelSource tcs = (TunerChannelSource)mSource;
mAFC = new AutomaticFrequencyControl( listener );
mAFC = new AutomaticFrequencyControl( tcs );
/* Register AFC to receive frequency change events */
listener.addListener( mAFC );
tcs.addListener( mAFC );
/* Add AFC as listener to the decoder */
mDecoder.addUnfilteredFloatListener( mAFC );

View File

@@ -1,7 +1,9 @@
package dsp.afc;
import sample.Listener;
import source.tuner.FrequencyChangeEvent;
import source.tuner.FrequencyChangeListener;
import source.tuner.FrequencyChangeEvent.Attribute;
import buffer.FloatAveragingBuffer;
public class AutomaticFrequencyControl implements Listener<Float>,
@@ -22,15 +24,14 @@ public class AutomaticFrequencyControl implements Listener<Float>,
private int mSkipThreshold = 4;
private int mErrorCorrection = 0;
private long mCurrentFrequency;
private int mCurrentSampleRate;
private FrequencyErrorListener mListener;
private FrequencyChangeListener mListener;
public enum Mode
{
NORMAL,FAST;
}
public AutomaticFrequencyControl( FrequencyErrorListener listener )
public AutomaticFrequencyControl( FrequencyChangeListener listener )
{
mListener = listener;
}
@@ -57,7 +58,9 @@ public class AutomaticFrequencyControl implements Listener<Float>,
{
if( mListener != null )
{
mListener.setError( mErrorCorrection );
mListener.frequencyChanged(
new FrequencyChangeEvent( Attribute.FREQUENCY_ERROR,
mErrorCorrection ) );
}
}
@@ -156,14 +159,23 @@ public class AutomaticFrequencyControl implements Listener<Float>,
}
@Override
public void frequencyChanged( long frequency, int bandwidth )
public void frequencyChanged( FrequencyChangeEvent event )
{
if( mCurrentFrequency != frequency || mCurrentSampleRate != bandwidth )
switch( event.getAttribute() )
{
mCurrentFrequency = frequency;
mCurrentSampleRate = bandwidth;
reset();
case FREQUENCY:
int frequency = (int)event.getValue();
if( mCurrentFrequency != frequency )
{
mCurrentFrequency = frequency;
reset();
}
case SAMPLE_RATE_ERROR:
break;
default:
break;
}
}
}

View File

@@ -1,10 +0,0 @@
package dsp.afc;
import source.tuner.FrequencyChangeListener;
public interface FrequencyErrorListener
{
public void setError( int error );
public void addListener( FrequencyChangeListener listener );
}

View File

@@ -406,7 +406,15 @@ public class FilterFactory
int decimate = (int)( sampleRate / decimatedRate );
filters[ 0 ] = new ComplexCICDecimate( decimate, 2, decimatedRate );
// if( decimate < 25 )
// {
filters[ 0 ] = new ComplexCICDecimate( decimate, 1, decimatedRate );
// }
// else
// {
// filters[ 0 ] = new ComplexCICDecimate( decimate, 3, decimatedRate );
// }
// int finalStopFrequency = decimatedRate - passFrequency;
//

View File

@@ -43,7 +43,9 @@ import net.miginfocom.swing.MigLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import source.tuner.FrequencyChangeEvent;
import source.tuner.FrequencyChangeListener;
import source.tuner.FrequencyChangeEvent.Attribute;
public class JFrequencyControl extends JPanel implements FrequencyChangeListener
{
@@ -132,9 +134,12 @@ public class JFrequencyControl extends JPanel implements FrequencyChangeListener
* rebroadcast this event, just set the control to indicate the new frequency.
*/
@Override
public void frequencyChanged( long frequency, int bandwidth )
public void frequencyChanged( FrequencyChangeEvent event )
{
setFrequency( frequency, false );
if( event.getAttribute() == Attribute.FREQUENCY )
{
setFrequency( (int)event.getValue(), false );
}
}
/**
@@ -174,9 +179,12 @@ public class JFrequencyControl extends JPanel implements FrequencyChangeListener
Iterator<FrequencyChangeListener> it = mListeners.iterator();
FrequencyChangeEvent event =
new FrequencyChangeEvent( Attribute.FREQUENCY, mFrequency );
while( it.hasNext() )
{
it.next().frequencyChanged( mFrequency, -1 );
it.next().frequencyChanged( event );
}
}

View File

@@ -1,114 +0,0 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014 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 sample.complex;
import gui.SDRTrunk;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sample.Listener;
import source.tuner.FrequencyChangeListener;
import buffer.FloatAveragingBuffer;
public class ComplexSampleRateCounter implements Listener<ComplexSample>,
ComplexSampleListListener,
FrequencyChangeListener
{
private final static Logger mLog =
LoggerFactory.getLogger( ComplexSampleRateCounter.class );
private int mCounter;
private int mAverageCounter;
private int mExpectedSampleRate;
private long mLastRun = 0;
private int mBufferSize = 100;
private FloatAveragingBuffer mAveragingBuffer;
public ComplexSampleRateCounter( int expectedSampleRate, int bufferSize )
{
mExpectedSampleRate = expectedSampleRate;
mBufferSize = bufferSize;
mAveragingBuffer = new FloatAveragingBuffer( mBufferSize );
mLastRun = System.currentTimeMillis();
mLog.info( "Complex Sample Rate Counter started ...." );
}
@Override
public void receive( ComplexSample sample )
{
mCounter++;
if( mCounter >= mExpectedSampleRate )
{
mCounter = 0;
long now = System.currentTimeMillis();
long elapsed = now - mLastRun;
mLastRun = now;
float average = (float)mExpectedSampleRate * 1000.0f / (float)elapsed;
float runningAverage = mAveragingBuffer.get( average );
mAverageCounter++;
mLog.info( "Complex Sample Rate Avg " + mAverageCounter +
" current [" + elapsed + " ms/" + average +
" hz] average [" + runningAverage + " hz] expected [" +
mExpectedSampleRate + " hz] over [" +
mBufferSize + "] buffer length" );
}
}
@Override
public void receive( List<ComplexSample> samples )
{
mCounter += samples.size();
if( mCounter >= mExpectedSampleRate )
{
mCounter -= mExpectedSampleRate;
long now = System.currentTimeMillis();
long elapsed = now - mLastRun;
mLastRun = now;
float average = (float)mExpectedSampleRate * 1000.0f / (float)elapsed;
float runningAverage = mAveragingBuffer.get( average );
mAverageCounter++;
mLog.info( "Complex Sample Rate Avg " + mAverageCounter +
" current [" + elapsed + " ms/" + average +
" hz] average [" + runningAverage + " hz] expected [" +
mExpectedSampleRate + " hz] over [" +
mBufferSize + "] buffer length" );
}
}
@Override
public void frequencyChanged( long frequency, int bandwidth )
{
mExpectedSampleRate = bandwidth;
}
}

View File

@@ -5,10 +5,12 @@ import java.util.ArrayList;
import java.util.concurrent.RejectedExecutionException;
import source.SourceException;
import source.tuner.FrequencyChangeEvent;
import source.tuner.FrequencyChangeListener;
import source.tuner.TunerChannel;
import source.tuner.TunerChannelProvider;
import source.tuner.TunerChannelSource;
import source.tuner.FrequencyChangeEvent.Attribute;
import controller.ResourceManager;
import controller.ThreadPoolManager;
@@ -86,16 +88,22 @@ public class Recording implements Comparable<Recording>,
}
@Override
public void frequencyChanged( long frequency, int bandwidth )
public void frequencyChanged( FrequencyChangeEvent event )
{
mConfiguration.setCenterFrequency( frequency );
mResourceManager.getSettingsManager().save();
mCenterFrequency = frequency;
for( TunerChannelSource channel: mTunerChannels )
if( event.getAttribute() == Attribute.FREQUENCY )
{
channel.frequencyChanged( frequency, bandwidth );
int frequency = (int)event.getValue();
mConfiguration.setCenterFrequency( frequency );
mResourceManager.getSettingsManager().save();
mCenterFrequency = frequency;
for( TunerChannelSource channel: mTunerChannels )
{
channel.frequencyChanged( event );
}
}
}

View File

@@ -0,0 +1,34 @@
package source.tuner;
public class FrequencyChangeEvent
{
public enum Attribute
{
SAMPLE_RATE_ERROR,
BANDWIDTH,
FREQUENCY,
FREQUENCY_ERROR,
SAMPLE_RATE;
}
private Attribute mAttribute;
private long mValue;
public FrequencyChangeEvent( Attribute attribute, long value )
{
mAttribute = attribute;
mValue = value;
}
public Attribute getAttribute()
{
return mAttribute;
}
public long getValue()
{
return mValue;
}
}

View File

@@ -18,8 +18,8 @@
package source.tuner;
/**
* Interface for broadcasting changes to frequency and/or bandwidth/sample rate
* to all registered listeners.
* Interface for broadcasting changes to frequency, bandwidth, sample rate,
* and actual sample rate values to all registered listeners.
*
* Note: broadcasted frequency should be the uncorrected, or displayable
* frequency value. All frequency correction aspects should be handled within
@@ -27,12 +27,5 @@ package source.tuner;
*/
public interface FrequencyChangeListener
{
/**
* Broadcasts a change to the (uncorrected) frequency and/or bandwidth
* or sample rate.
*
* @param frequency - uncorrected frequency in hertz
* @param bandwidth - bandwidth in hertz
*/
public void frequencyChanged( long frequency, int bandwidth );
public void frequencyChanged( FrequencyChangeEvent event );
}

View File

@@ -20,6 +20,7 @@ package source.tuner;
import java.util.ArrayList;
import source.SourceException;
import source.tuner.FrequencyChangeEvent.Attribute;
public class FrequencyController
{
@@ -29,7 +30,7 @@ public class FrequencyController
private long mMinimumFrequency;
private long mMaximumFrequency;
private double mFrequencyCorrection = 0d;
private int mBandwidth = 0;
private int mSampleRate = 0;
private ArrayList<FrequencyChangeListener> mListeners =
new ArrayList<FrequencyChangeListener>();
@@ -50,17 +51,17 @@ public class FrequencyController
*/
public int getBandwidth()
{
return mBandwidth;
return mSampleRate;
}
/**
* Set bandwidth/sample rate in hertz
* Set sample rate in hertz
*/
public void setBandwidth( int bandwidth )
public void setSampleRate( int sampleRate )
{
mBandwidth = bandwidth;
mSampleRate = sampleRate;
broadcastFrequencyChange();
broadcastSampleRateChange();
}
/**
@@ -193,12 +194,28 @@ public class FrequencyController
* bandwidth/sample rate value.
*/
protected void broadcastFrequencyChange()
{
broadcastFrequencyChangeEvent(
new FrequencyChangeEvent( Attribute.FREQUENCY, mFrequency ) );
}
/**
* Broadcasts a sample rate change
*/
protected void broadcastSampleRateChange()
{
broadcastFrequencyChangeEvent(
new FrequencyChangeEvent( Attribute.SAMPLE_RATE, mSampleRate ) );
}
public void broadcastFrequencyChangeEvent( FrequencyChangeEvent event )
{
for( FrequencyChangeListener listener: mListeners )
{
listener.frequencyChanged( mFrequency, mBandwidth );
listener.frequencyChanged( event );
}
}
public interface Tunable
{

View File

@@ -1,127 +0,0 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014 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 source.tuner;
import sample.Listener;
import sample.complex.ComplexSample;
import sample.complex.ComplexSampleUtils;
import util.Oscillator;
public class NumericallyControlledOscillator implements Listener<ComplexSample>,
FrequencyChangeListener
{
private long mFrequency;
private int mSampleRate;
private Oscillator mSineWaveGenerator;
private Listener<ComplexSample> mListener;
/**
* Translates (shifts) frequency spectrum up or down, depending on the sign
* of the frequency argument, by mixing received complex samples with a
* generated sine wave of the frequency argument. Positive frequency shifts
* the received spectrum higher in frequency. Negative frequency shifts the
* received spectrum lower in frequency. In both cases, spectrum that is
* shifted outside of the sampling bandwidth will wrap around, due to the
* nature of quadrature sampling.
*/
public NumericallyControlledOscillator( long frequencyShift, int sampleRate )
{
mFrequency = frequencyShift;
mSampleRate = sampleRate;
int defaultMixingSignalGain = 10;
mSineWaveGenerator = new Oscillator( mFrequency, mSampleRate );
}
/**
* Listener method for this class to receive samples from a Complex Sample
* Provider. This method multiplies the incoming sample by the generated
* mixing frequency to translate (ie shift +/-) the incoming signal, and
* then send the translated signal on to all registered listeners
*/
@Override
public void receive( ComplexSample sample )
{
if( mListener != null )
{
mListener.receive( ComplexSampleUtils.multiply( sample,
mSineWaveGenerator.nextComplex() ) );
}
}
@Override
public void frequencyChanged( long frequency, int bandwidth )
{
if( frequency != mFrequency )
{
setFrequency( frequency );
}
if( bandwidth != mSampleRate )
{
setSampleRate( bandwidth );
}
}
/**
* Changes the frequency value and resets the sine wave generator, so that
* all subsequent samples will be output at the new translated frequency
* @param frequency - hertz
*/
public void setFrequency( long frequency )
{
mFrequency = frequency;
mSineWaveGenerator.setFrequency( frequency );
}
/**
* Current frequency shift setting
* @return - frequency - hertz
*/
public long getFrequency()
{
return mFrequency;
}
/**
* Changes the sample rate, so that all new input/output values will be
* translated at the new sample rate
* @param sampleRate - hertz
*/
public void setSampleRate( int sampleRate )
{
mSampleRate = sampleRate;
mSineWaveGenerator.setSampleRate( sampleRate );
}
/**
* Add listener to receive frequency translated complex samples
*/
public void setListener( Listener<ComplexSample> listener )
{
mListener = listener;
}
/**
* Remove listener from receiving frequency translated complex samples.
*/
public void clearListener()
{
mListener = null;
}
}

View File

@@ -24,6 +24,7 @@ import javax.swing.JPanel;
import sample.Listener;
import source.SourceException;
import source.tuner.FrequencyChangeEvent.Attribute;
import controller.ResourceManager;
import controller.ThreadPoolManager;
@@ -172,11 +173,38 @@ public abstract class Tuner implements FrequencyChangeBroadcaster,
/**
* Broadcasts a frequency change event to all registered listeners
*/
public void broadcastFrequencyChange( long frequency, int bandwidth )
public void broadcastFrequencyChange( long frequency )
{
broadcastFrequencyChangeEvent(
new FrequencyChangeEvent( Attribute.FREQUENCY, frequency ) );
}
/**
* Broadcasts a sample rate change event to all registered listeners
*/
public void broadcastSampleRateChange( int sampleRate )
{
broadcastFrequencyChangeEvent(
new FrequencyChangeEvent( Attribute.SAMPLE_RATE, sampleRate ) );
}
/**
* Broadcasts actual sample rate change event to all registered listeners
*/
public void broadcastActualSampleRateChange( int actualSampleRate )
{
broadcastFrequencyChangeEvent(
new FrequencyChangeEvent( Attribute.SAMPLE_RATE, actualSampleRate ) );
}
/**
* Broadcasts a frequency change event to all registered listeners
*/
public void broadcastFrequencyChangeEvent( FrequencyChangeEvent event )
{
for( FrequencyChangeListener listener: mFrequencyChangeListeners )
{
listener.frequencyChanged( frequency, bandwidth );
listener.frequencyChanged( event );
}
}
@@ -184,8 +212,19 @@ public abstract class Tuner implements FrequencyChangeBroadcaster,
* Frequency change listener method. We receive change events from the
* controller and rebroadcast them to all registered listeners.
*/
public void frequencyChanged( long frequency, int bandwidth )
public void frequencyChanged( FrequencyChangeEvent event )
{
broadcastFrequencyChange( frequency, bandwidth );
broadcastFrequencyChangeEvent( event );
}
// /**
// * Broadcasts a frequency change event to all registered listeners
// */
// public void broadcastBandwidthChange( int bandwidth )
// {
// broadcastFrequencyChangeEvent(
// new FrequencyChangeEvent( Attribute.BANDWIDTH, bandwidth ) );
// }
//
}

View File

@@ -29,17 +29,16 @@ import sample.complex.ComplexSample;
import sample.complex.ComplexSampleAssembler;
import source.ComplexSource;
import source.SourceException;
import source.tuner.FrequencyChangeEvent.Attribute;
import util.Oscillator;
import controller.ThreadPoolManager;
import controller.ThreadPoolManager.ThreadType;
import dsp.afc.FrequencyErrorListener;
import dsp.filter.ComplexFilter;
import dsp.filter.FilterFactory;
import dsp.filter.Window.WindowType;
public class TunerChannelSource extends ComplexSource
implements FrequencyChangeListener,
FrequencyErrorListener,
Listener<Float[]>
{
private static int sCHANNEL_RATE = 48000;
@@ -64,32 +63,34 @@ public class TunerChannelSource extends ComplexSource
public TunerChannelSource( ThreadPoolManager threadPoolManager,
Tuner tuner,
TunerChannel tunerChannel )
throws RejectedExecutionException
throws RejectedExecutionException, SourceException
{
super( "Tuner Channel Source" );
mThreadPoolManager = threadPoolManager;
/* Schedule the decimation task to run 20 times a second */
mTaskHandle = mThreadPoolManager.schedule( ThreadType.DECIMATION,
new DecimationProcessor(), 50, TimeUnit.MILLISECONDS );
mTuner = tuner;
mTuner.addListener( (FrequencyChangeListener)this );
mTunerChannel = tunerChannel;
mTunerFrequency = mTuner.getFrequency();
/* Setup the frequency translator to the current source frequency */
try
{
frequencyChanged( mTuner.getFrequency(), mTuner.getSampleRate() );
}
catch ( SourceException e )
{
e.printStackTrace();
}
long frequencyOffset = mTunerFrequency - mTunerChannel.getFrequency();
mSineWaveGenerator = new Oscillator( frequencyOffset, mTuner.getSampleRate() );
/* Finally, register to receive samples from the tuner */
/* Fire a sample rate change event to get the decimation chain setup */
frequencyChanged( new FrequencyChangeEvent(
Attribute.SAMPLE_RATE, mTuner.getSampleRate() ) );
/* Schedule the decimation task to run 20 times a second */
mTaskHandle = mThreadPoolManager.schedule( ThreadType.DECIMATION,
new DecimationProcessor(), 50, TimeUnit.MILLISECONDS );
/* Finally, register to receive samples from the tuner */
mTuner.addListener( (Listener<Float[]>)this );
}
@@ -156,60 +157,73 @@ public class TunerChannelSource extends ComplexSource
}
@Override
public void frequencyChanged( long frequency, int bandwidth )
public void frequencyChanged( FrequencyChangeEvent event )
{
/* Send change to Automatic Frequency Control */
/* Send change to Automatic Frequency Control if it exists */
if( mFrequencyChangeListener != null )
{
mFrequencyChangeListener.frequencyChanged( frequency, bandwidth );
mFrequencyChangeListener.frequencyChanged( event );
}
long frequencyOffset = frequency -
mTunerChannel.getFrequency() -
mTunerFrequencyError;
if( mSineWaveGenerator == null )
switch( event.getAttribute() )
{
mSineWaveGenerator = new Oscillator( frequencyOffset, bandwidth );
}
else
{
mSineWaveGenerator.setFrequency( frequencyOffset );
}
/* Clear the buffer for the frequency to take immediate effect */
// mBuffer.clear();
mTunerFrequency = frequency;
/* Bandwidth/Sample rate change */
if( bandwidth != mTunerSampleRate )
{
/* Get the original decimation filter output listener */
// Listener<ComplexSample> listener = null;
/* Get new decimation filters */
mDecimationFilters = FilterFactory
.getDecimationFilters( bandwidth,
case SAMPLE_RATE_ERROR:
break;
case SAMPLE_RATE:
int sampleRate = (int)event.getValue();
if( mTunerSampleRate != sampleRate )
{
/* Set the oscillator to the new frequency */
mSineWaveGenerator.setSampleRate( sampleRate );
/* Get new decimation filters */
mDecimationFilters = FilterFactory
.getDecimationFilters( sampleRate,
sCHANNEL_RATE,
sCHANNEL_PASS_FREQUENCY,
48, //dB attenuation
WindowType.HAMMING );
/* wire the filters together */
if( mDecimationFilters.length > 1 )
{
for( int x = 1; x < mDecimationFilters.length; x++ )
{
mDecimationFilters[ x - 1 ].setListener( mDecimationFilters[ x ] );
}
}
/* re-add the original output listener */
mDecimationFilters[ mDecimationFilters.length - 1 ]
.setListener( mBufferAssembler );
/* wire the filters together */
if( mDecimationFilters.length > 1 )
{
for( int x = 1; x < mDecimationFilters.length; x++ )
{
mDecimationFilters[ x - 1 ]
.setListener( mDecimationFilters[ x ] );
}
}
/* re-add the original output listener */
mDecimationFilters[ mDecimationFilters.length - 1 ]
.setListener( mBufferAssembler );
mTunerSampleRate = bandwidth;
mTunerSampleRate = sampleRate;
}
break;
case FREQUENCY_ERROR:
mTunerFrequencyError = (int)event.getValue();
long frequencyErrorOffset = mTunerFrequency -
mTunerChannel.getFrequency() -
mTunerFrequencyError;
mSineWaveGenerator.setFrequency( frequencyErrorOffset );
break;
case FREQUENCY:
int frequency = (int)event.getValue();
/* If the frequency is updated, the AFC will also get reset, so
* we don't include the frequency error value here */
long frequencyOffset = frequency - mTunerChannel.getFrequency();
mSineWaveGenerator.setFrequency( frequencyOffset );
mTunerFrequency = frequency;
break;
default:
break;
}
}
@@ -264,20 +278,6 @@ public class TunerChannelSource extends ComplexSource
}
}
/**
* Automatic Frequency Control
*/
@Override
public void setError( int error )
{
if( mTunerFrequencyError != error )
{
mTunerFrequencyError = error;
frequencyChanged( mTunerFrequency, mTunerSampleRate );
}
}
@Override
public void addListener( FrequencyChangeListener listener )
{
mFrequencyChangeListener = listener;

View File

@@ -167,7 +167,8 @@ public abstract class TunerController implements Tunable
updateLOFrequency();
source = new TunerChannelSource( threadPoolManager, tuner, tunerChannel );
source = new TunerChannelSource( threadPoolManager,
tuner, tunerChannel );
}
return source;

View File

@@ -42,7 +42,7 @@ public class TunerNode extends BaseNode implements FrequencyChangeListener
private static DecimalFormat SAMPLE_RATE_FORMAT = new DecimalFormat( "0.000" );
private long mFrequency;
private int mBandwidth;
private int mSampleRate;
public TunerNode( Tuner tuner )
{
@@ -53,7 +53,7 @@ public class TunerNode extends BaseNode implements FrequencyChangeListener
try
{
mFrequency = tuner.getFrequency();
mBandwidth = tuner.getSampleRate();
mSampleRate = tuner.getSampleRate();
}
catch ( SourceException e )
{
@@ -82,7 +82,7 @@ public class TunerNode extends BaseNode implements FrequencyChangeListener
sb.append( " " );
sb.append( FREQUENCY_FORMAT.format( (double)mFrequency / 1E6d ) );
sb.append( " [" );
sb.append( SAMPLE_RATE_FORMAT.format( (double)mBandwidth / 1E6d ) );
sb.append( SAMPLE_RATE_FORMAT.format( (double)mSampleRate / 1E6d ) );
sb.append( "] MHz" );
return sb.toString();
@@ -122,11 +122,29 @@ public class TunerNode extends BaseNode implements FrequencyChangeListener
}
@Override
public void frequencyChanged( long frequency, int bandwidth )
public void frequencyChanged( FrequencyChangeEvent event )
{
mFrequency = frequency;
mBandwidth = bandwidth;
getModel().nodeChanged( TunerNode.this );
switch( event.getAttribute() )
{
case FREQUENCY:
int frequency = (int)event.getValue();
if( mFrequency != frequency )
{
mFrequency = frequency;
getModel().nodeChanged( TunerNode.this );
}
case SAMPLE_RATE:
int sampleRate = (int)event.getValue();
if( mSampleRate != sampleRate )
{
mSampleRate = sampleRate;
getModel().nodeChanged( TunerNode.this );
}
break;
default:
break;
}
}
}

View File

@@ -60,7 +60,7 @@ public class FCD1TunerController extends FCDTunerController
sMINIMUM_TUNABLE_FREQUENCY,
sMAXIMUM_TUNABLE_FREQUENCY );
mFrequencyController.setBandwidth( sSAMPLE_RATE );
mFrequencyController.setSampleRate( sSAMPLE_RATE );
try
{

View File

@@ -30,6 +30,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import source.SourceException;
import source.tuner.FrequencyChangeEvent;
import source.tuner.FrequencyChangeEvent.Attribute;
import source.tuner.FrequencyChangeListener;
import source.tuner.fcd.FCDTuner;
import source.tuner.fcd.FCDTunerDetailsPanel;
@@ -91,17 +93,19 @@ public class FCD1TunerEditorPanel extends JPanel implements FrequencyChangeListe
}
@Override
public void frequencyChanged( long frequency, int bandwidth )
public void frequencyChanged( FrequencyChangeEvent event )
{
//Disregard the bandwidth value, which shouldn't be changing
try
{
mController.setFrequency( frequency );
}
catch ( SourceException e )
{
mLog.error( "FCTProController - error setting frequency [" +
frequency + "]", e );
}
if( event.getAttribute() == Attribute.FREQUENCY )
{
try
{
mController.setFrequency( event.getValue() );
}
catch ( SourceException e )
{
mLog.error( "FCTProController - error setting frequency [" +
event.getValue() + "]", e );
}
}
}
}

View File

@@ -53,7 +53,7 @@ public class FCD2TunerController extends FCDTunerController
sMINIMUM_TUNABLE_FREQUENCY,
sMAXIMUM_TUNABLE_FREQUENCY );
mFrequencyController.setBandwidth( sSAMPLE_RATE );
mFrequencyController.setSampleRate( sSAMPLE_RATE );
try
{

View File

@@ -30,6 +30,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import source.SourceException;
import source.tuner.FrequencyChangeEvent;
import source.tuner.FrequencyChangeEvent.Attribute;
import source.tuner.FrequencyChangeListener;
import source.tuner.fcd.FCDTuner;
import source.tuner.fcd.FCDTunerDetailsPanel;
@@ -90,17 +92,20 @@ public class FCD2TunerEditorPanel extends JPanel implements FrequencyChangeListe
}
@Override
public void frequencyChanged( long frequency, int bandwidth )
public void frequencyChanged( FrequencyChangeEvent event )
{
//Disregard the bandwidth, which shouldn't be changing
try
{
mController.setFrequency( frequency );
}
catch ( SourceException e )
{
mLog.error( "FCTProController - error setting frequency [" +
frequency + "]", e );
}
if( event.getAttribute() == Attribute.FREQUENCY )
{
//Disregard the bandwidth, which shouldn't be changing
try
{
mController.setFrequency( event.getValue() );
}
catch ( SourceException e )
{
mLog.error( "FCDProController - error setting frequency [" +
event.getValue() + "]", e );
}
}
}
}

View File

@@ -60,10 +60,13 @@ import org.usb4java.LibUsb;
import sample.Listener;
import source.SourceException;
import source.tuner.FrequencyChangeEvent;
import source.tuner.FrequencyChangeEvent.Attribute;
import source.tuner.TunerController;
import source.tuner.TunerType;
import source.tuner.usb.USBTunerDevice;
import util.TimeStamp;
import buffer.FloatAveragingBuffer;
import controller.ResourceManager;
public abstract class RTL2832TunerController extends TunerController
@@ -85,7 +88,6 @@ public abstract class RTL2832TunerController extends TunerController
(byte)( LibUsb.ENDPOINT_OUT | LibUsb.REQUEST_TYPE_VENDOR );
public final static byte sREQUEST_ZERO = (byte)0;
public final static int sUSB_IRP_DATA_SIZE = 65536;
public final static int sUSB_IRP_POOL_SIZE = 10;
public final static byte EEPROM_ADDRESS = (byte)0xA0;
@@ -135,7 +137,9 @@ public abstract class RTL2832TunerController extends TunerController
};
private static final DecimalFormat mDecimalFormatter =
new DecimalFormat( "###,###,###.#" );
new DecimalFormat( "###,###,###.0" );
private static final DecimalFormat mPercentFormatter =
new DecimalFormat( "###.00" );
private USBTunerDevice mUSBTunerDevice;
protected UsbDevice mUSBDevice;
@@ -163,6 +167,9 @@ public abstract class RTL2832TunerController extends TunerController
private int mSampleRateAverageCount;
protected int mOscillatorFrequency = 28800000; //28.8 MHz
private SampleRateMonitor mSampleRateMonitor;
public int mBufferSize = 16384;
/**
* Abstract tuner controller device. Use the static getTunerClass() method
* to determine the tuner type, and construct the corresponding child
@@ -1163,7 +1170,17 @@ public abstract class RTL2832TunerController extends TunerController
mSampleRate = sampleRate;
mFrequencyController.setBandwidth( sampleRate.getRate() );
/**
* Adjust the size of the byte array buffers sent over the USB bus
*/
mBufferSize = mSampleRate.getBufferSize();
mFrequencyController.setSampleRate( sampleRate.getRate() );
if( mSampleRateMonitor != null )
{
mSampleRateMonitor.setSampleRate( mSampleRate.getRate() );
}
}
public void setSampleRateFrequencyCorrection( int ppm )
@@ -1392,34 +1409,37 @@ public abstract class RTL2832TunerController extends TunerController
public enum SampleRate
{
/* Note: sample rates below 1.0MHz are subject to aliasing */
RATE_0_240MHZ( 0x0DFC, 0x0000, 240000, "0.240 MHz" ),
RATE_0_288MHZ( 0x08FC, 0x0000, 288000, "0.288 MHz" ),
RATE_0_912MHZ( 0x07E6, 0x0000, 912000, "0.912 MHz" ),
RATE_0_960MHZ( 0x077A, 0x0000, 960000, "0.960 MHz" ),
RATE_1_200MHZ( 0x05F4, 0x0000, 1200000, "1.200 MHz" ),
RATE_1_440MHZ( 0x0500, 0x0000, 1440000, "1.440 MHz" ),
RATE_1_680MHZ( 0x044A, 0x0000, 1680000, "1.680 MHz" ),
RATE_1_824MHZ( 0x03F3, 0x0000, 1824000, "1.824 MHz" ),
RATE_2_016MHZ( 0x038F, 0x0000, 2016000, "2.016 MHz" );
/* Note: usb4java library buffer processing scheme doesn't seem capable
* of supporting these rates */
//RATE_2_400MHZ( 0x0300, 0x0000, 2400000, "2.400 MHz" ),
//RATE_2_880MHZ( 0x0280, 0x0000, 2880000, "2.880 MHz" ),
//RATE_3_072MHZ( 0x0258, 0x0000, 3072000, "3.072 MHz" ),
//RATE_3_216MHZ( 0x023D, 0x0000, 3216000, "3.216 MHz" );
RATE_0_240MHZ( 0x0DFC, 0x0000, 240000, "0.240 MHz", 16384 ),
RATE_0_288MHZ( 0x08FC, 0x0000, 288000, "0.288 MHz", 16384 ),
RATE_0_912MHZ( 0x07E4, 0x0000, 912000, "0.912 MHz", 32768 ),
RATE_0_960MHZ( 0x0778, 0x0000, 960000, "0.960 MHz", 32768 ),
RATE_1_200MHZ( 0x05F4, 0x0000, 1200000, "1.200 MHz", 65536 ),
RATE_1_440MHZ( 0x04FC, 0x0000, 1440000, "1.440 MHz", 65536 ),
RATE_1_680MHZ( 0x0448, 0x0000, 1680000, "1.680 MHz", 65536 ),
RATE_1_824MHZ( 0x03F0, 0x0000, 1824000, "1.824 MHz", 65536 ),
RATE_2_016MHZ( 0x038C, 0x0000, 2016000, "2.016 MHz", 131072 ),
RATE_2_208MHZ( 0x0340, 0x0000, 2208000, "2.208 MHz", 131072 ),
RATE_2_400MHZ( 0x02FC, 0x0000, 2400000, "2.400 MHz", 131072 ),
RATE_2_640MHZ( 0x02B4, 0x8000, 2640000, "2.640 MHz", 262144 ),
RATE_2_880MHZ( 0x027C, 0x0000, 2880000, "2.880 MHz", 262144 );
private int mRatioHigh;
private int mRatioLow;
private int mRate;
private String mLabel;
private int mBufferSize;
private SampleRate( int ratioHigh, int ratioLow, int rate, String label )
private SampleRate( int ratioHigh,
int ratioLow,
int rate,
String label,
int bufferSize )
{
mRatioHigh = ratioHigh;
mRatioLow = ratioLow;
mRate = rate;
mLabel = label;
mBufferSize = bufferSize;
}
public int getRatioHighBits()
@@ -1447,6 +1467,11 @@ public abstract class RTL2832TunerController extends TunerController
return mLabel;
}
public int getBufferSize()
{
return mBufferSize;
}
/**
* Returns the sample rate that is equal to the argument or the next
* higher sample rate
@@ -1545,7 +1570,7 @@ public abstract class RTL2832TunerController extends TunerController
for( int x = 0; x < sUSB_IRP_POOL_SIZE; x++ )
{
UsbIrp irp = mUSBPipe.createUsbIrp();
irp.setData( new byte[ sUSB_IRP_DATA_SIZE ] );
irp.setData( new byte[ mBufferSize ] );
irps.add( irp );
}
@@ -1566,12 +1591,15 @@ public abstract class RTL2832TunerController extends TunerController
if( mUSBPipe.isOpen() )
{
mSampleDispatcherTask = mExecutor
.scheduleAtFixedRate( new BufferDispatcher(),
0, 20, TimeUnit.MILLISECONDS );
.scheduleAtFixedRate( new BufferDispatcher(),
0, 20, TimeUnit.MILLISECONDS );
mSampleRateMonitor =
new SampleRateMonitor( mSampleRate.getRate() );
mSampleRateCounterTask = mExecutor
.scheduleAtFixedRate( new SampleRateMonitor(),
60, 60, TimeUnit.SECONDS );
.scheduleAtFixedRate( mSampleRateMonitor,
10, 10, TimeUnit.SECONDS );
mUSBPipe.asyncSubmit( irps );
}
@@ -1645,7 +1673,7 @@ public abstract class RTL2832TunerController extends TunerController
{
try
{
mUSBPipe.asyncSubmit( new byte[ sUSB_IRP_DATA_SIZE ] );
mUSBPipe.asyncSubmit( new byte[ mBufferSize ] );
}
catch ( UsbNotActiveException | UsbNotOpenException
| IllegalArgumentException | UsbDisconnectedException
@@ -1707,37 +1735,103 @@ public abstract class RTL2832TunerController extends TunerController
*/
public class SampleRateMonitor implements Runnable
{
private static final int BUFFER_SIZE = 5;
private int mTargetSampleRate;
private int mSampleRateMinimum;
private int mSampleRateMaximum;
private int mNewTargetSampleRate;
private FloatAveragingBuffer mRateErrorBuffer =
new FloatAveragingBuffer( BUFFER_SIZE );
private AtomicBoolean mRateChanged = new AtomicBoolean();
public SampleRateMonitor( int sampleRate )
{
setTargetRate( sampleRate );
}
public void setSampleRate( int sampleRate )
{
mNewTargetSampleRate = sampleRate;
mRateChanged.set( true );
}
private void setTargetRate( int rate )
{
mTargetSampleRate = rate;
mSampleRateMinimum = (int)( (float)mTargetSampleRate * 0.95f );
mSampleRateMaximum = (int)( (float)mTargetSampleRate * 1.05f );
for( int x = 0; x < BUFFER_SIZE; x++ )
{
mRateErrorBuffer.get( 0 );
}
}
@Override
public void run()
{
int count = mSampleCounter.getAndSet( 0 );
double rate = (double)count / 120.0d;
mSampleRateAverageSum += rate;
mSampleRateAverageCount++;
double average = mSampleRateAverageSum / (double)mSampleRateAverageCount;
StringBuilder sb = new StringBuilder();
sb.append( TimeStamp.getTimeStamp( " " ) );
sb.append( " RTL-2832 [" );
if( mDescriptor != null )
if( mRateChanged.compareAndSet( true, false ) )
{
sb.append( mDescriptor.getSerial() );
setTargetRate( mNewTargetSampleRate );
/* Reset the sample counter */
mSampleCounter.set( 0 );
mLog.info( "monitor reset for new sample rate [" + mTargetSampleRate + "]" );
System.out.println( "monitor reset for new sample rate [" + mTargetSampleRate + "]" );
}
else
{
sb.append( "DESCRIPTOR IS NULL" );
int count = mSampleCounter.getAndSet( 0 );
float current = (float)count / 20.0f;
/**
* Only accept values +/- 5% of target rate
*/
float average;
if( mSampleRateMinimum < current && current < mSampleRateMaximum )
{
average = mRateErrorBuffer.get( (float)mTargetSampleRate - current );
/* broadcast an actual sample rate update */
if( mFrequencyController != null )
{
mFrequencyController.broadcastFrequencyChangeEvent(
new FrequencyChangeEvent(
Attribute.SAMPLE_RATE_ERROR, (int)average ) );
}
}
else
{
average = mTargetSampleRate;
}
StringBuilder sb = new StringBuilder();
sb.append( TimeStamp.getTimeStamp( " " ) );
sb.append( " RTL-2832 [" );
if( mDescriptor != null )
{
sb.append( mDescriptor.getSerial() );
}
else
{
sb.append( "DESCRIPTOR IS NULL" );
}
sb.append( "] sample rate current [" );
sb.append( mDecimalFormatter.format( current ) );
sb.append( " Hz " );
sb.append( mPercentFormatter.format( 100.0f * ( current / (float)mTargetSampleRate ) ) );
sb.append( "% ] average error [" );
sb.append( average );
sb.append( " Hz ] target " );
sb.append( mTargetSampleRate );
System.out.println( sb.toString() );
mLog.info( sb.toString() );
}
sb.append( "] Sample Rate - current: " );
sb.append( mDecimalFormatter.format( rate ) );
sb.append( "\taverage: " );
sb.append( mDecimalFormatter.format( average ) );
sb.append( " count:" );
sb.append( mSampleRateAverageCount );
mLog.info( sb.toString() );
}
}

View File

@@ -31,7 +31,9 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import source.SourceException;
import source.tuner.FrequencyChangeEvent;
import source.tuner.FrequencyChangeListener;
import source.tuner.FrequencyChangeEvent.Attribute;
import source.tuner.rtl.RTL2832InfoPanel;
import com.jidesoft.swing.JideTabbedPane;
@@ -94,23 +96,28 @@ public class E4KTunerEditorPanel extends JPanel implements FrequencyChangeListen
* apply end-user requested frequency changes against the tuner
*/
@Override
public void frequencyChanged( final long frequency, int bandwidth )
public void frequencyChanged( FrequencyChangeEvent event )
{
EventQueue.invokeLater( new Runnable()
if( event.getAttribute() == Attribute.FREQUENCY )
{
@Override
public void run()
{
try
{
mController.setFrequency( frequency );
}
catch ( SourceException e )
{
mLog.error( "E4KTunerController - error setting frequency [" +
frequency + "]", e );
}
}
} );
final int frequency = (int)event.getValue();
EventQueue.invokeLater( new Runnable()
{
@Override
public void run()
{
try
{
mController.setFrequency( frequency );
}
catch ( SourceException e )
{
mLog.error( "E4KTunerController - error setting frequency [" +
frequency + "]", e );
}
}
} );
}
}
}

View File

@@ -77,6 +77,7 @@ public class R820TTunerConfigurationPanel extends JPanel
private JTextField mName;
private JSpinner mFrequencyCorrection;
private JSpinner mSampleRateCorrection;
private JComboBox<R820TGain> mComboMasterGain;
private JComboBox<R820TMixerGain> mComboMixerGain;
private JComboBox<R820TLNAGain> mComboLNAGain;
@@ -268,6 +269,65 @@ public class R820TTunerConfigurationPanel extends JPanel
add( new JLabel( "Sample Rate:" ) );
add( mComboSampleRate, "growx,push" );
/**
* Sample Rate Correction
*/
SpinnerModel sampleRateCorrectionModel =
new SpinnerNumberModel( 0, //initial value
-32768, //min
32767, //max
1 ); //step
mSampleRateCorrection = new JSpinner( sampleRateCorrectionModel );
JSpinner.NumberEditor sampleRateCorrectionEditor =
(JSpinner.NumberEditor)mSampleRateCorrection.getEditor();
DecimalFormat sampleRateCorrectionFormat =
sampleRateCorrectionEditor.getFormat();
sampleRateCorrectionFormat.setMinimumFractionDigits( 0 );
sampleRateCorrectionEditor.getTextField()
.setHorizontalAlignment( SwingConstants.CENTER );
mSampleRateCorrection.addChangeListener( new ChangeListener()
{
@Override
public void stateChanged( ChangeEvent e )
{
final int value = ((SpinnerNumberModel)mSampleRateCorrection
.getModel()).getNumber().intValue();
EventQueue.invokeLater( new Runnable()
{
@Override
public void run()
{
try
{
mController.setSampleRateFrequencyCorrection( value );
}
catch ( SourceException | UsbException e1 )
{
JOptionPane.showMessageDialog(
R820TTunerConfigurationPanel.this,
"E4K Tuner Controller - couldn't apply "
+ "sample rate correction value: " + value +
e1.getLocalizedMessage() );
mLog.error( "E4K Tuner Controller - couldn't apply "
+ "sample rate correction value: " + value +
e1.getLocalizedMessage() );
}
}
} );
}
} );
add( mSampleRateCorrection );
add( new JLabel( "Sample Rate Correction (ppm)" ), "grow,push" );
/**
* Gain Controls
*/

View File

@@ -31,7 +31,9 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import source.SourceException;
import source.tuner.FrequencyChangeEvent;
import source.tuner.FrequencyChangeListener;
import source.tuner.FrequencyChangeEvent.Attribute;
import source.tuner.rtl.RTL2832InfoPanel;
import com.jidesoft.swing.JideTabbedPane;
@@ -93,23 +95,28 @@ public class R820TTunerEditorPanel extends JPanel implements FrequencyChangeList
* apply end-user requested frequency changes against the tuner
*/
@Override
public void frequencyChanged( final long frequency, int bandwidth )
public void frequencyChanged( FrequencyChangeEvent event )
{
EventQueue.invokeLater( new Runnable()
if( event.getAttribute() == Attribute.FREQUENCY )
{
@Override
public void run()
{
try
{
mController.setFrequency( frequency );
}
catch ( SourceException e )
{
mLog.error( "R820T Tuner Controller - error setting frequency [" +
frequency + "]", e );
}
}
} );
final int frequency = (int)event.getValue();
EventQueue.invokeLater( new Runnable()
{
@Override
public void run()
{
try
{
mController.setFrequency( frequency );
}
catch ( SourceException e )
{
mLog.error( "R820T Tuner Controller - error setting frequency [" +
frequency + "]", e );
}
}
} );
}
}
}

View File

@@ -23,6 +23,8 @@ import settings.Setting;
import settings.SettingChangeListener;
import settings.SettingsManager;
import source.Source.SampleType;
import source.tuner.FrequencyChangeEvent;
import source.tuner.FrequencyChangeEvent.Attribute;
import spectrum.converter.DFTResultsConverter;
import spectrum.converter.RealDecibelConverter;
import spectrum.menu.AmplificationItem;
@@ -86,7 +88,8 @@ public class ChannelSpectrumPanel extends JPanel
mDecimatingSampleAssembler = new DecimatingSampleAssembler( mDFTProcessor );
/* Set the DFTProcessor to the decimated 24kHz sample rate */
mDFTProcessor.frequencyChanged( 0, 24000 );
mDFTProcessor.frequencyChanged(
new FrequencyChangeEvent( Attribute.SAMPLE_RATE, 24000 ) );
initGui();
}

View File

@@ -33,6 +33,7 @@ import org.slf4j.LoggerFactory;
import sample.Listener;
import source.Source;
import source.Source.SampleType;
import source.tuner.FrequencyChangeEvent;
import source.tuner.FrequencyChangeListener;
import spectrum.converter.DFTResultsConverter;
import dsp.filter.Window;
@@ -443,11 +444,19 @@ public class DFTProcessor implements Listener<Float[]>,
}
@Override
public void frequencyChanged( long frequency, int bandwidth )
public void frequencyChanged( FrequencyChangeEvent event )
{
mSampleRate = bandwidth;
calculateConsumptionRate();
switch( event.getAttribute() )
{
case SAMPLE_RATE_ERROR:
break;
case SAMPLE_RATE:
mSampleRate = (int)event.getValue();
calculateConsumptionRate();
break;
default:
break;
}
}
/**

View File

@@ -36,6 +36,7 @@ import settings.ColorSetting;
import settings.ColorSetting.ColorSettingName;
import settings.Setting;
import settings.SettingChangeListener;
import source.tuner.FrequencyChangeEvent;
import source.tuner.FrequencyChangeListener;
import source.tuner.TunerChannel;
import controller.ResourceManager;
@@ -523,10 +524,22 @@ public class OverlayPanel extends JPanel
* Frequency change event handler
*/
@Override
public void frequencyChanged( long frequency, int bandwidth )
public void frequencyChanged( FrequencyChangeEvent event )
{
mBandwidth = bandwidth;
mFrequency = frequency;
switch( event.getAttribute() )
{
case SAMPLE_RATE_ERROR:
// System.out.println( "OVerlay panel got a sample rate error update" );
break;
case SAMPLE_RATE:
mBandwidth = (int)event.getValue();
break;
case FREQUENCY:
mFrequency = (int)event.getValue();
break;
default:
break;
}
/**
* Reset the visible channel configs list

View File

@@ -55,9 +55,11 @@ import settings.SettingChangeListener;
import settings.SettingsManager;
import source.Source.SampleType;
import source.SourceException;
import source.tuner.FrequencyChangeEvent;
import source.tuner.FrequencyChangeListener;
import source.tuner.Tuner;
import source.tuner.TunerSelectionListener;
import source.tuner.FrequencyChangeEvent.Attribute;
import spectrum.converter.ComplexDecibelConverter;
import spectrum.converter.DFTResultsConverter;
import spectrum.menu.AmplificationItem;
@@ -340,10 +342,10 @@ public class SpectralDisplayPanel extends JPanel
* Receives frequency change events -- primarily from tuner components.
*/
@Override
public void frequencyChanged( long frequency, int bandwidth )
public void frequencyChanged( FrequencyChangeEvent event )
{
mOverlayPanel.frequencyChanged( frequency, bandwidth );
mDFTProcessor.frequencyChanged( frequency, bandwidth );
mOverlayPanel.frequencyChanged( event );
mDFTProcessor.frequencyChanged( event );
}
/**
@@ -381,11 +383,15 @@ public class SpectralDisplayPanel extends JPanel
//Register the dft processor to receive samples from the tuner
mTuner.addListener( (Listener<Float[]>)mDFTProcessor );
//Fire a frequency change event so that everyone can init
//Fire frequency and sample rate change events so that everyone
//can init
try
{
frequencyChanged( mTuner.getFrequency(),
mTuner.getSampleRate() );
frequencyChanged( new FrequencyChangeEvent(
Attribute.FREQUENCY, mTuner.getFrequency() ) );
frequencyChanged( new FrequencyChangeEvent(
Attribute.SAMPLE_RATE, mTuner.getSampleRate() ) );
}
catch ( SourceException e )
{

View File

@@ -42,6 +42,11 @@ public class Oscillator
update();
}
public ComplexSample getCurrentAngle()
{
return mCurrentAngle;
}
private void update()
{
float anglePerSample =
@@ -64,6 +69,7 @@ public class Oscillator
*/
public void setSampleRate( int sampleRate )
{
System.out.println( "Oscillator - setting sampleRate to:" + sampleRate );
mSampleRate = (double)sampleRate;
update();
}