/*******************************************************************************
* 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;
/**
* Converts complex DFT output to scaled dB values with a maximum amplitude of
* 0 dB and all values scaled to the minimum dB value which is:
*
* Max: 0dB
* Min: 20 * log10( 1.0 / ( 2.0 ^ ( bit depth - 1) ) = scaling factor
*
* Notes:
*
* The magnitude of each DFT output bin must be scaled by the number of DFT
* points to normalize the output to a range of ( 0 to 1.0 ). DFT bin magnitude
* can be calculated as:
*
* 1) sqrt( bin[ x ] * bin[ x ] + bin[ x + 1 ] * bin[ x + 1] ) / DFTSize or,
* 2) ( bin[ x ] * bin[ x ] + bin[ x + 1 ] * bin[ x + 1] ) / ( DFTSize * DFTSize )
*
* Convert each scaled DFT bin magnitude to decibels using this formula:
*
* 20 * log10( scaledBinValue )
*
* Max Value: 20 * log10( 1.0 ) = 0 dB
*
* When plotting, these dB bin values should be scaled according to the maximum
* dynamic range supported by the source. Maximum dynamic range for bit depth
* is calculated as:
*
* 20 * log10( 1 / ( 2 ^ ( bit depth - 1 ) )
*
* A source that provides 12-bit samples can produce values in the range of
* ( 0 to 4096 ) or -2048 to 2047. The smallest observable value would then
* be 1 / 2048.
*
* So, the smallest decibel value of a source producing 12 bit samples is:
*
* 20 * log10( 1 / 2048 ) = -66.23 dB
*
* and the dynamic range is: (-66.23 to 0.0 dB)
*
*/
public class ComplexDecibelConverter extends DFTResultsConverter
{
/**
* Converts the output of the JTransforms FloatFFT_1D.complexForward()
* calculation into the power spectrum in decibels, normalized to the
* sample bit depth.
*/
public ComplexDecibelConverter()
{
}
@Override
public void receive( float[] results )
{
int halfResults = results.length / 2;
// float dftBinSizeScalor = 1.0f / (float)Math.pow( halfResults, 2.0 );
float dftBinSizeScalor = 1.0f / (float)halfResults;
float[] processed = new float[ halfResults ];
int middle = processed.length / 2;
for( int x = 0; x < results.length; x += 2 )
{
//Calculate the magnitude squared (power) value from each bin's real
//and imaginary value and scale it to the DFT bin size squared.
//Convert the scaled value to decibels.
float decibels = 10.0f * (float)Math.log10(
( ( results[ x ] * results[ x ] ) +
( results[ x + 1 ] * results[ x + 1 ] ) ) * dftBinSizeScalor );
// We have to swap the upper and lower halves of the JTransforms
// DFT results for correct display
int index = x / 2;
if( index >= middle )
{
processed[ index - middle ] = decibels;
}
else
{
processed[ index + middle ] = decibels;
}
}
dispatch( processed );
}
}