mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-14 09:37:36 -05:00
Adds airspy USB tuner support and updates the spectral display
component. -Airspy supported with 10 and 2.5 MSps sample rates. Additional decimation may be added later. -Spectral display updated to include smoothing and filtering options. Note: the decimated output of a tuner channel from the airspy is 48,076.9 samples per second, versus the normal 48 kHz decimated rate. This is 1.0015 times the normal rate and doesn't appear to impact the decoders or audio processing. Therefore, no fractional resampling has been added.
This commit is contained in:
@@ -1,3 +1,20 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2015 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 spectrum.converter;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@@ -6,52 +23,60 @@ import org.slf4j.LoggerFactory;
|
||||
public class ComplexDecibelConverter extends DFTResultsConverter
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( DFTResultsConverter.class );
|
||||
LoggerFactory.getLogger( ComplexDecibelConverter.class );
|
||||
|
||||
private float mDynamicRangeReference = (float)Math.pow( 2.0, 16.0 );
|
||||
|
||||
/**
|
||||
* Converts the output of the JTransforms FloatFFT_1D.complexForward()
|
||||
* calculation into a normalized power spectrum in decibels, per description
|
||||
* in Lyons, Understanding Digital Signal Processing, 3e, page 141.
|
||||
* calculation into the power spectrum in decibels, normalized to the
|
||||
* sample bit depth.
|
||||
*/
|
||||
public ComplexDecibelConverter()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the bit depth to establish the maximum dynamic range. All
|
||||
* FFT bin values will be scaled according to this value.
|
||||
*/
|
||||
@Override
|
||||
public void setSampleSize( double size )
|
||||
{
|
||||
assert( 2.0 <= size && size <= 32.0 );
|
||||
|
||||
mDynamicRangeReference = (float)Math.pow( 2.0d, size );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( float[] results )
|
||||
{
|
||||
float[] processed = new float[ results.length / 2 ];
|
||||
|
||||
/* Output from JTransforms 3.0 has the lower and upper halves of the
|
||||
* spectrum swapped. */
|
||||
int half = processed.length / 2;
|
||||
|
||||
|
||||
for( int x = 0; x < results.length; x += 2 )
|
||||
{
|
||||
float magnitude = (float)Math.sqrt( results[ x ] *
|
||||
results[ x ] + results[ x + 1 ] * results[ x + 1 ] );
|
||||
|
||||
/* Place upper half of magnitudes in lower half of results, vice-versa */
|
||||
//Calculate the magnitude squared value from each bin's real and
|
||||
//imaginary value, scale it to the available dynamic range and
|
||||
//convert to dB.
|
||||
float normalizedMagnitude = 10.0f * (float)Math.log10(
|
||||
( ( results[ x ] * results[ x ] ) +
|
||||
( results[ x + 1 ] * results[ x + 1 ] ) ) /
|
||||
mDynamicRangeReference );
|
||||
|
||||
// We have to swap the upper and lower halves of the JTransforms
|
||||
// DFT results for correct display
|
||||
if( x / 2 >= half )
|
||||
{
|
||||
processed[ x / 2 - half ] = magnitude;
|
||||
processed[ x / 2 - half ] = normalizedMagnitude;
|
||||
}
|
||||
else
|
||||
{
|
||||
processed[ x / 2 + half ] = magnitude;
|
||||
processed[ x / 2 + half ] = normalizedMagnitude;
|
||||
}
|
||||
}
|
||||
|
||||
/* Use the DC component as the largest magnitude value to keep the
|
||||
* display from jumping when a strong bursting signal exists */
|
||||
float largestMagnitude = processed[ half ];
|
||||
|
||||
if( largestMagnitude > 0 )
|
||||
{
|
||||
/* Convert magnitudes to normized power spectrum dBm */
|
||||
for( int i = 0; i < processed.length; i++ )
|
||||
{
|
||||
processed[ i ] = 20.0f *
|
||||
(float)Math.log10( processed[ i ] / largestMagnitude );
|
||||
}
|
||||
|
||||
dispatch( processed );
|
||||
}
|
||||
dispatch( processed );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,12 @@ public abstract class DFTResultsConverter
|
||||
public DFTResultsConverter()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the sample size in bits to establish the maximum dynamic range.
|
||||
* All FFT bin values will be scaled according to this value.
|
||||
*/
|
||||
public abstract void setSampleSize( double size );
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
|
||||
@@ -1,7 +1,31 @@
|
||||
package spectrum.converter;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class RealDecibelConverter extends DFTResultsConverter
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger( RealDecibelConverter.class );
|
||||
|
||||
private float mDynamicRangeReference;
|
||||
|
||||
public RealDecibelConverter()
|
||||
{
|
||||
setSampleSize( 24.0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the bit depth to establish the maximum dynamic range. All
|
||||
* FFT bin values will be scaled according to this value.
|
||||
*/
|
||||
@Override
|
||||
public void setSampleSize( double size )
|
||||
{
|
||||
assert( 2.0 <= size && size <= 32.0 );
|
||||
|
||||
mDynamicRangeReference = (float)Math.pow( 2.0d, size );
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the output of the JTransforms FloatFFT_1D.realForward()
|
||||
* calculation into a normalized power spectrum in decibels, per description
|
||||
@@ -10,29 +34,22 @@ public class RealDecibelConverter extends DFTResultsConverter
|
||||
@Override
|
||||
public void receive( float[] results )
|
||||
{
|
||||
float dc = Math.abs( results[ 0 ] );
|
||||
float[] processed = new float[ results.length / 4 ];
|
||||
|
||||
/* Ensure we have power in the DC power bin (bin 0), otherwise don't
|
||||
* dispatch the results */
|
||||
if( dc != 0 )
|
||||
int index = 0;
|
||||
|
||||
for( int x = 0; x < processed.length; x ++ )
|
||||
{
|
||||
/* Note: we're only processing 1/4 of the output samples */
|
||||
float[] processed = new float[ results.length / 4 + 1 ];
|
||||
index = x * 2;
|
||||
|
||||
for( int x = 0; x < processed.length - 2; x ++ )
|
||||
{
|
||||
int index = ( x + 1 ) * 2;
|
||||
float normalizedMagnitude = 10.0f * (float)Math.log10(
|
||||
( ( results[ index ] * results[ index ] ) +
|
||||
( results[ index + 1 ] * results[ index + 1 ] ) ) /
|
||||
mDynamicRangeReference );
|
||||
|
||||
double magnitude = ( ( results[ index ] * results[ index ] ) +
|
||||
( results[ index + 1 ] * results[ index + 1 ] ) );
|
||||
|
||||
processed[ x ] = 10.0f *
|
||||
(float)( Math.log10( magnitude / dc ) );
|
||||
}
|
||||
|
||||
processed[ processed.length - 1 ] = processed[ 0 ];
|
||||
|
||||
dispatch( processed );
|
||||
processed[ x ] = normalizedMagnitude;
|
||||
}
|
||||
|
||||
dispatch( processed );
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user