/*
* FilterDesign.java
*
* This file is part of Tritonus: http://www.tritonus.org/
*/
/*
* Copyright (c) 2002 by Matthias Pfisterer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as published
* by the Free Software Foundation; either version 2 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 Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
|<--- this code is formatted to fit into 80 columns --->|
*/
package org.tritonus.lowlevel.dsp;
import org.tritonus.share.TDebug;
/** Several methods to design digital filters.
This is a design method for FIR filters.
*/
public class FilterDesign
{
public static final int WINDOW_UNKNOWN = -1;
public static final int WINDOW_RECTANGULAR = 0;
public static final int WINDOW_HAMMING = 1;
private static final Window[] WINDOWS =
{
new RectangularWindow(),
new HammingWindow(),
};
private static final boolean DEBUG = false;
/** Filter design by frequency sampling.
This is a design method for FIR filters.
It allows to design filters with arbitrary
frequency response.
*/
public static double[] designFrequencySampling(double[] adFrequencyResponse)
{
int nHalfLength = adFrequencyResponse.length;
int nFullLength = nHalfLength * 2;
Complex[] aFrequencyResponse = new Complex[nFullLength];
//double dScaleFactor = (double) (nFullLength - 1) / (double) nFullLength;
for (int k = 0; k < nHalfLength; k++)
{
//double dPhase = -Math.PI * k * dScaleFactor;
}
// TODO: middle point has to be 0
// TOO: check loop bounds
for (int k = nHalfLength; k < nFullLength; k++)
{
//double dPhase = Math.PI - Math.PI * k * dScaleFactor;
}
Complex[] aComplexCoefficients = Util.IDFT(aFrequencyResponse);
double[] aRealCoefficients = new double[nFullLength];
for (int i = 0; i < nFullLength; i++)
{
aRealCoefficients[i] = aComplexCoefficients[i].real();
if (DEBUG) { TDebug.out("FilterDesign.designFrequencySampling(): coefficient, imaginary part: " + aComplexCoefficients[i].imag()); }
}
return aRealCoefficients;
}
///////////////////////////////////////////////////
//
// Rectangular Window methods
//
///////////////////////////////////////////////////
/**
nOrder should be odd.
*/
public static double[] designRectangularLowPass(int nOrder,
double dCornerOmega)
{
double[] adH = new double[nOrder];
int nMiddle = nOrder / 2;
for (int n = 0; n < nOrder; n++)
{
adH[n] = Math.sin(dCornerOmega * (n - nMiddle))
/ (Math.PI * (n - nMiddle));
}
return adH;
}
/**
nOrder should be odd.
*/
public static double[] designRectangularHighPass(int nOrder,
double dCornerOmega)
{
double[] adH = new double[nOrder];
int nMiddle = nOrder / 2;
for (int n = 0; n < nOrder; n++)
{
adH[n] = 1.0
- Math.sin(dCornerOmega * (n - nMiddle))
/ (Math.PI * (n - nMiddle));
}
return adH;
}
/**
nOrder should be odd.
o1 < o2 required
*/
public static double[] designRectangularBandPass(int nOrder,
double dCornerOmega1,
double dCornerOmega2)
{
double[] adH = new double[nOrder];
int nMiddle = nOrder / 2;
for (int n = 0; n < nOrder; n++)
{
adH[n] = (Math.sin(dCornerOmega2 * (n - nMiddle))
- Math.sin(dCornerOmega1 * (n - nMiddle)))
/ (Math.PI * (n - nMiddle));
}
return adH;
}
/**
nOrder should be odd.
*/
public static double[] designRectangularBandStop(int nOrder,
double dCornerOmega1,
double dCornerOmega2)
{
double[] adH = new double[nOrder];
int nMiddle = nOrder / 2;
for (int n = 0; n < nOrder; n++)
{
adH[n] = 1.0
- (Math.sin(dCornerOmega2 * (n - nMiddle))
- Math.sin(dCornerOmega1 * (n - nMiddle)))
/ (Math.PI * (n - nMiddle));
}
return adH;
}
///////////////////////////////////////////////////
//
// Window methods
//
///////////////////////////////////////////////////
public static double[] designWindowLowPass(int nOrder, double dCornerOmega, int nWindow)
{
Window window = WINDOWS[nWindow];
return designWindowLowPass(nOrder, dCornerOmega, window);
}
public static double[] designWindowHighPass(int nOrder, double dCornerOmega, int nWindow)
{
Window window = WINDOWS[nWindow];
return designWindowHighPass(nOrder, dCornerOmega, window);
}
public static double[] designWindowBandPass(int nOrder,
double dCornerOmega1,
double dCornerOmega2,
int nWindow)
{
Window window = WINDOWS[nWindow];
return designWindowBandPass(nOrder,
dCornerOmega1,
dCornerOmega2,
window);
}
public static double[] designWindowBandStop(int nOrder,
double dCornerOmega1,
double dCornerOmega2,
int nWindow)
{
Window window = WINDOWS[nWindow];
return designWindowBandStop(nOrder,
dCornerOmega1,
dCornerOmega2,
window);
}
public static double[] designWindowLowPass(int nOrder,
double dCornerOmega,
Window window)
{
double[] adRectangular = designRectangularLowPass(nOrder, dCornerOmega);
double[] adWindow = window.getWindow(nOrder);
double[] adH = Util.multiply(adRectangular, adWindow);
return adH;
}
public static double[] designWindowHighPass(int nOrder,
double dCornerOmega,
Window window)
{
double[] adRectangular = designRectangularHighPass(
nOrder,
dCornerOmega);
double[] adWindow = window.getWindow(nOrder);
double[] adH = Util.multiply(adRectangular, adWindow);
return adH;
}
public static double[] designWindowBandPass(int nOrder,
double dCornerOmega1,
double dCornerOmega2,
Window window)
{
double[] adRectangular = designRectangularBandPass(
nOrder,
dCornerOmega1,
dCornerOmega2);
double[] adWindow = window.getWindow(nOrder);
double[] adH = Util.multiply(adRectangular, adWindow);
return adH;
}
public static double[] designWindowBandStop(int nOrder,
double dCornerOmega1,
double dCornerOmega2,
Window window)
{
double[] adRectangular = designRectangularBandStop(
nOrder,
dCornerOmega1,
dCornerOmega2);
double[] adWindow = window.getWindow(nOrder);
double[] adH = Util.multiply(adRectangular, adWindow);
return adH;
}
}
/*** FilterDesign.java ***/