/*******************************************************************************
* 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 dsp.filter;
import java.util.Arrays;
/**
* Window creator
*
* Blackman, Hamming and Hanning windows
* based on windowing methods described at:
* http://www.mstarlabs.com/dsp/goertzel/goertzel.html
* and
* Understanding Digital Signal Processing 3e, Lyons, p.91
* and
* Digital Filters for Everyone, Allred, p. 132
*
*/
public class Window
{
public static double[] getWindow( WindowType type, int length )
{
switch( type )
{
case BLACKMAN:
return getBlackmanWindow( length );
case COSINE:
return getCosineWindow( length );
case HAMMING:
return getHammingWindow( length );
case HANNING:
return getHanningWindow( length );
case NONE:
default:
return getRectangularWindow( length );
}
}
public static double[] getRectangularWindow( int length )
{
double[] coefficients = new double[ length ];
Arrays.fill( coefficients, 1.0d );
return coefficients;
}
public static double[] getCosineWindow( int length )
{
double[] coefficients = new double[ length ];
if( length % 2 == 0 ) //Even length
{
int half = (int)( ( length - 1 ) / 2 );
for( int x = -half; x < length / 2 + 1; x++ )
{
coefficients[ x + half ] = Math.cos(
( (double)x * Math.PI ) / ( (double)length + 1.0d ) );
}
}
else //Odd length
{
int half = (int) length / 2;
for( int x = -half; x < half + 1; x++ )
{
coefficients[ x + half ] = Math.cos(
( (double)x * Math.PI ) / ( (double)length + 1.0d ) );
}
}
return coefficients;
}
public static double[] getBlackmanWindow( int length )
{
double[] coefficients = new double[ length ];
for( int x = 0; x < length; x++ )
{
coefficients[ x ] = .426591D -
( .496561D * Math.cos( ( Math.PI * 2.0D * (double)x ) / (double)( length - 1 ) ) +
( .076848D * Math.cos( ( Math.PI * 4.0D * (double)x ) / (double)( length - 1 ) ) ) );
}
return coefficients;
}
public static double[] getHammingWindow( int length )
{
double[] coefficients = new double[ length ];
if( length % 2 == 0 ) //Even length
{
for( int x = 0; x < length; x++ )
{
coefficients[ x ] = .54D - ( .46D *
Math.cos( ( Math.PI * ( 2.0D * (double)x + 1.0d ) ) / (double)( length - 1 ) ) );
}
}
else //Odd length
{
for( int x = 0; x < length; x++ )
{
coefficients[ x ] = .54D - ( .46D *
Math.cos( ( 2.0D * Math.PI * (double)x ) / (double)( length - 1 ) ) );
}
}
return coefficients;
}
public static double[] getHanningWindow( int length )
{
double[] coefficients = new double[ length ];
if( length % 2 == 0 ) //Even length
{
for( int x = 0; x < length; x++ )
{
coefficients[ x ] = .5D - ( .5D *
Math.cos( ( Math.PI * ( 2.0D * (double)x + 1 ) ) / (double)( length - 1 ) ) );
}
}
else //Odd length
{
for( int x = 0; x < length; x++ )
{
coefficients[ x ] = .5D - ( .5D *
Math.cos( ( 2.0D * Math.PI * (double)x ) / (double)( length - 1 ) ) );
}
}
return coefficients;
}
/**
* Apply the window against an array of float-type samples
*/
public static float[] apply( double[] coefficients, float[] samples )
{
for( int x = 0; x < coefficients.length; x++ )
{
samples[ x ] = (float)( samples[ x ] * coefficients[ x ] );
}
return samples;
}
public static float[] apply( WindowType type, float[] samples )
{
double[] coefficients = getWindow( type, samples.length );
return apply( coefficients, samples );
}
/**
* Apply the window against an array of float-type samples
*/
public static double[] apply( double[] coefficients, double[] samples )
{
for( int x = 0; x < coefficients.length; x++ )
{
samples[ x ] = samples[ x ] * coefficients[ x ];
}
return samples;
}
public static double[] apply( WindowType type, double[] samples )
{
double[] coefficients = getWindow( type, samples.length );
return apply( coefficients, samples );
}
/**
* Window types
*/
public enum WindowType
{
BLACKMAN, COSINE, HAMMING, HANNING, NONE;
}
/**
* Utility to log the double arrays
*/
public static String arrayToString( double[] array, boolean breaks )
{
StringBuilder sb = new StringBuilder();
for( int x = 0; x < array.length; x++ )
{
sb.append( x + ":" + array[ x ] );
if( breaks )
{
sb.append( "\n" );
}
else
{
if( x % 8 == 7 )
{
sb.append( "\n" );
}
else
{
sb.append( "\t" );
}
}
}
return sb.toString();
}
}