/** * Copyright 2007 DFKI GmbH. * All Rights Reserved. Use is subject to license terms. * * This file is part of MARY TTS. * * MARY TTS is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, version 3 of the License. * * 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ package marytts.signalproc.effects; import marytts.signalproc.filter.BandPassFilter; import marytts.signalproc.filter.BandRejectFilter; import marytts.signalproc.filter.HighPassFilter; import marytts.signalproc.filter.LowPassFilter; import marytts.signalproc.process.FrameOverlapAddSource; import marytts.signalproc.process.InlineDataProcessor; import marytts.signalproc.window.Window; import marytts.util.data.BufferedDoubleDataSource; import marytts.util.data.DoubleDataSource; import marytts.util.math.MathUtils; import marytts.util.signal.SignalProcUtils; /** * @author Oytun Türk */ public class FilterEffectBase extends BaseAudioEffect { double cutOffFreqInHz1; double cutOffFreqInHz2; int filterType; int frameLength; double normalizedCutOffFreq1; double normalizedCutOffFreq2; InlineDataProcessor filter; public static int NULL_FILTER = 0; public static int LOWPASS_FILTER = 1; public static int HIGHPASS_FILTER = 2; public static int BANDPASS_FILTER = 3; public static int BANDREJECT_FILTER = 4; public static int DEFAULT_FILTER = BANDPASS_FILTER; public static double DEFAULT_CUTOFF1 = 500.0; public static double DEFAULT_CUTOFF2 = 2000.0; // Unlike most of the other effect parameters the following are sampling rate dependent double MIN_CUTOFF1; double MAX_CUTOFF1; double MAX_CUTOFF2; double MIN_CUTOFF2; // public FilterEffectBase() { this(4000.0, 16000); } public FilterEffectBase(double cutOffHz, int samplingRate, int type) { super(samplingRate); setExampleParameters("type" + chParamEquals + String.valueOf(BANDPASS_FILTER) + chParamSeparator + " " + "fc1" + chParamEquals + String.valueOf(DEFAULT_CUTOFF1) + chParamSeparator + " " + "fc2" + chParamEquals + String.valueOf(DEFAULT_CUTOFF2)); strHelpText = getHelpText(); cutOffFreqInHz1 = cutOffHz; cutOffFreqInHz2 = -1.0; filterType = type; MIN_CUTOFF1 = 20.0; MAX_CUTOFF1 = 0.5 * samplingRate - 20.0; MIN_CUTOFF2 = 20.0; MAX_CUTOFF2 = 0.5 * samplingRate - 20.0; } public FilterEffectBase(double cutOffHz, int samplingRate) { this(cutOffHz, samplingRate, LOWPASS_FILTER); } public FilterEffectBase(double cutOffHz1, double cutOffHz2, int samplingRate, int type) { super(samplingRate); setExampleParameters("type" + chParamEquals + String.valueOf(BANDPASS_FILTER) + chParamSeparator + " " + "fc1" + chParamEquals + String.valueOf(DEFAULT_CUTOFF1) + chParamSeparator + " " + "fc2" + chParamEquals + String.valueOf(DEFAULT_CUTOFF2)); strHelpText = getHelpText(); cutOffFreqInHz1 = cutOffHz1; cutOffFreqInHz2 = cutOffHz2; filterType = type; MIN_CUTOFF1 = 20.0; MAX_CUTOFF1 = 0.5 * samplingRate - 20.0; MIN_CUTOFF2 = 20.0; MAX_CUTOFF2 = 0.5 * samplingRate - 20.0; } public FilterEffectBase(double cutOffHz1, double cutOffHz2, int samplingRate) { this(cutOffHz1, cutOffHz2, samplingRate, BANDPASS_FILTER); } // A filter that does nothing public FilterEffectBase(int samplingRate) { super(samplingRate); setExampleParameters("type" + chParamEquals + String.valueOf(BANDPASS_FILTER) + chParamSeparator + " " + "fc1" + chParamEquals + String.valueOf(DEFAULT_CUTOFF1) + chParamSeparator + " " + "fc2" + chParamEquals + String.valueOf(DEFAULT_CUTOFF2)); strHelpText = getHelpText(); cutOffFreqInHz1 = -1.0; cutOffFreqInHz2 = -1.0; filterType = NULL_FILTER; MIN_CUTOFF1 = 20.0; MAX_CUTOFF1 = 0.5 * samplingRate - 20.0; MIN_CUTOFF2 = 20.0; MAX_CUTOFF2 = 0.5 * samplingRate - 20.0; } public void parseParameters(String param) { super.parseParameters(param); filterType = expectIntParameter("type"); if (filterType == NULL_INT_PARAM) filterType = DEFAULT_FILTER; if (filterType == LOWPASS_FILTER || filterType == HIGHPASS_FILTER) cutOffFreqInHz1 = expectDoubleParameter("fc1"); else cutOffFreqInHz1 = expectDoubleParameter("fc1"); if (cutOffFreqInHz1 == NULL_DOUBLE_PARAM) cutOffFreqInHz1 = DEFAULT_CUTOFF1; cutOffFreqInHz2 = expectDoubleParameter("fc2"); if (cutOffFreqInHz2 == NULL_DOUBLE_PARAM) cutOffFreqInHz2 = DEFAULT_CUTOFF2; cutOffFreqInHz1 = MathUtils.CheckLimits(cutOffFreqInHz1, MIN_CUTOFF1, MAX_CUTOFF1); cutOffFreqInHz2 = MathUtils.CheckLimits(cutOffFreqInHz2, MIN_CUTOFF1, MAX_CUTOFF2); if (cutOffFreqInHz2 < cutOffFreqInHz1) { double tmp = cutOffFreqInHz1; cutOffFreqInHz1 = cutOffFreqInHz2; cutOffFreqInHz2 = tmp; } initialise(); } public void initialise() { frameLength = 8 * SignalProcUtils.getDFTSize(fs); normalizedCutOffFreq1 = cutOffFreqInHz1 / fs; normalizedCutOffFreq2 = cutOffFreqInHz2 / fs; filter = null; if (filterType == LOWPASS_FILTER && normalizedCutOffFreq1 > 0.0) filter = new LowPassFilter(normalizedCutOffFreq1); else if (filterType == HIGHPASS_FILTER && normalizedCutOffFreq1 > 0.0) filter = new HighPassFilter(normalizedCutOffFreq1); else if (filterType == BANDPASS_FILTER && normalizedCutOffFreq1 > 0.0 && normalizedCutOffFreq2 > 0.0) { if (normalizedCutOffFreq1 > normalizedCutOffFreq2) { double tmp = normalizedCutOffFreq1; normalizedCutOffFreq1 = normalizedCutOffFreq2; normalizedCutOffFreq2 = tmp; } filter = new BandPassFilter(normalizedCutOffFreq1, normalizedCutOffFreq2); } else if (filterType == BANDREJECT_FILTER && normalizedCutOffFreq1 > 0.0 && normalizedCutOffFreq2 > 0.0) { if (normalizedCutOffFreq1 > normalizedCutOffFreq2) { double tmp = normalizedCutOffFreq1; normalizedCutOffFreq1 = normalizedCutOffFreq2; normalizedCutOffFreq2 = tmp; } filter = new BandRejectFilter(normalizedCutOffFreq1, normalizedCutOffFreq2); } } public DoubleDataSource process(DoubleDataSource input) { if (filter != null) { FrameOverlapAddSource foas = new FrameOverlapAddSource(input, Window.HANNING, true, frameLength, fs, filter); return new BufferedDoubleDataSource(foas); } else { return input; } } public String getHelpText() { String strRange1 = ""; for (int i = LOWPASS_FILTER; i < BANDREJECT_FILTER; i++) strRange1 += String.valueOf(i) + ","; strRange1 += String.valueOf(BANDREJECT_FILTER); String strRange2 = "[0.0, fs/2.0] where fs is the sampling rate in Hz"; String strHelp = "FIR filtering:" + strLineBreak + "Filters the input signal by an FIR filter." + strLineBreak + "Parameters:" + strLineBreak + " <type>" + strLineBreak + " Definition : Type of filter (1:Lowpass, 2:Highpass, 3:Bandpass, 4:Bandreject)" + strLineBreak + " Range : {" + strRange1 + "}" + strLineBreak + " <fc>" + " Definition : Cutoff frequency in Hz for lowpass and highpass filters" + strLineBreak + " Range : " + strRange2 + strLineBreak + " <fc1>" + " Definition : Lower frequency cutoff in Hz for bandpass and bandreject filters" + strLineBreak + " Range : " + strRange2 + strLineBreak + " <fc2>" + " Definition : Higher frequency cutoff in Hz for bandpass and bandreject filters" + strLineBreak + " Range : " + strRange2 + strLineBreak + "Example: (A band-pass filter)" + strLineBreak + getExampleParameters(); return strHelp; } public String getName() { return "FIRFilter"; } }