CLAM-Development
1.1
|
00001 /* 00002 * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG) 00003 * UNIVERSITAT POMPEU FABRA 00004 * 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software 00018 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00019 * 00020 */ 00021 00022 #include "FDFilterGen.hxx" 00023 #include "CLAM_Math.hxx" 00024 #include <iostream> 00025 00027 #define MINUSINFINITY -99 //Value for an infinitely negative number 00028 00029 namespace CLAM { 00030 void FDFilterGenConfig::DefaultInit(void) 00031 { 00032 AddAll(); 00033 UpdateData(); 00034 00035 SetGain(0); 00036 00037 SetHighCutOff(0); 00038 SetLowCutOff(0); 00039 00040 SetPassBandSlope(0); 00041 SetStopBandSlope(0); 00042 00043 SetSpectralRange(22050); //default value for consistency between classes 00044 00045 } 00046 00047 00048 00049 FDFilterGen::FDFilterGen() : 00050 Output("Output",this), 00051 Gain("Gain",this, &FDFilterGen::UpdateControlChangedFlag), 00052 HighCutOff( "High Cutoff Frequency",this, &FDFilterGen::UpdateControlChangedFlag), 00053 LowCutOff( "Low Cutoff Frequency",this, &FDFilterGen::UpdateControlChangedFlag), 00054 PassBandSlope("Pass Band Slope",this, &FDFilterGen::UpdateControlChangedFlag), 00055 StopBandSlope( "Stop Band Slope",this, &FDFilterGen::UpdateControlChangedFlag), 00056 SpectralRange(0), 00057 Type( EFDFilterType::eLowPass ), 00058 mControlChanged( false ) 00059 00060 { 00061 Configure(FDFilterGenConfig()); // here all controls are initialized 00062 }; 00063 00064 FDFilterGen::FDFilterGen( const FDFilterGenConfig& c) : 00065 Output("Output",this), 00066 Gain("Gain",this, &FDFilterGen::UpdateControlChangedFlag), 00067 HighCutOff( "High Cutoff Frecuency",this, &FDFilterGen::UpdateControlChangedFlag), 00068 LowCutOff( "Low Cutoff Frecuency",this, &FDFilterGen::UpdateControlChangedFlag), 00069 PassBandSlope("Pass Band Slope",this, &FDFilterGen::UpdateControlChangedFlag), 00070 StopBandSlope( "Stop Band Slope",this, &FDFilterGen::UpdateControlChangedFlag), 00071 SpectralRange(0), 00072 Type( EFDFilterType::eLowPass ), 00073 mControlChanged( false ) 00074 { 00075 Configure(c); // here all controls are initialized 00076 }; 00077 00078 00079 00080 bool FDFilterGen::ConcreteConfigure(const ProcessingConfig& c) 00081 { 00082 CopyAsConcreteConfig(mConfig, c); 00083 00084 mControlChanged=true; //we want the next Do to perform an action 00085 if (mConfig.HasSpectralRange()) 00086 SpectralRange=mConfig.GetSpectralRange(); 00087 if (mConfig.HasGain()) 00088 Gain.DoControl(mConfig.GetGain()); 00089 if (mConfig.HasHighCutOff()) 00090 HighCutOff.DoControl(mConfig.GetHighCutOff()); 00091 if (mConfig.HasLowCutOff()) 00092 LowCutOff.DoControl(mConfig.GetLowCutOff()); 00093 if (mConfig.HasPassBandSlope()) 00094 PassBandSlope.DoControl(mConfig.GetPassBandSlope()); 00095 if (mConfig.HasStopBandSlope()) 00096 StopBandSlope.DoControl(mConfig.GetStopBandSlope()); 00097 if (mConfig.HasType()) 00098 Type=mConfig.GetType(); 00099 00100 00101 return true; 00102 } 00103 00104 int FDFilterGen::UpdateControlChangedFlag(TControlData val) 00105 { 00106 mControlChanged=true; 00107 return 0; 00108 } 00109 00110 00111 bool FDFilterGen::Do(void) 00112 { 00113 return 0; 00114 } 00115 00116 bool FDFilterGen::Do(Spectrum &out) 00117 { 00118 // Only do something after have received an incontrol. 00119 if (!mControlChanged) return false; 00120 mControlChanged=false; 00121 00122 // Instantiate the BPF buffer of the spectrum if necessary. 00123 out.AddMagBPF(); 00124 out.AddPhaseBPF(); 00125 if (out.UpdateData()) { 00126 out.SetBPFSize(10); 00127 } 00128 else if (out.GetBPFSize()<10) 00129 out.SetBPFSize(10); 00130 00131 00132 EScale originalScale = out.GetScale(); 00133 out.SetScale(EScale(EScale::eLog)); 00134 00135 TData g,flc,fhc,spb,ssb,fsr; 00136 g=Gain.GetLastValue(); 00137 flc=LowCutOff.GetLastValue(); 00138 fhc=HighCutOff.GetLastValue(); 00139 spb=PassBandSlope.GetLastValue(); 00140 ssb=StopBandSlope.GetLastValue(); 00141 fsr=SpectralRange; 00142 00143 // Legend: 00144 // g stands for Gain 00145 // flc stands for Lower cutoff frequency 00146 // fhc stands for Higher cutoff frequency 00147 // spb stands for Slope for the pass band 00148 // ssb stands for Slope for the stop band 00149 // fsr stands for Sampling Rate Frequency 00150 00151 switch((int)Type) 00152 { 00153 case EFDFilterType::eLowPass: 00154 { 00155 // We add four points to the BPF ( the four control points for the filter ) 00156 out.SetBPFSize(4); 00157 00158 TData fsr_by_flc = fsr/flc; 00159 00160 SetFilterPoint(out,0,0,g); 00161 SetFilterPoint(out,1,flc*CLAM_pow(2.0,-3.0/ssb),g); 00162 SetFilterPoint(out,2,flc,g-3); 00163 SetFilterPoint(out,3,fsr,g-3-ssb*(log(fsr_by_flc)/log(TData(2)))); 00164 break; 00165 } 00166 case EFDFilterType::eHighPass: 00167 { 00168 out.SetBPFSize(4); 00169 SetFilterPoint(out,0,0,MINUSINFINITY); 00170 SetFilterPoint(out,1,fhc,g-3); 00171 SetFilterPoint(out,2,fhc*CLAM_pow(2.0,3.0/spb),g); 00172 SetFilterPoint(out,3,fsr,g); 00173 break; 00174 } 00175 case EFDFilterType::eBandPass: 00176 { 00177 out.SetBPFSize(6); 00178 SetFilterPoint(out,0,0,MINUSINFINITY); 00179 SetFilterPoint(out,1,flc,g-3); 00180 SetFilterPoint(out,2,flc*CLAM_pow(2.0,3.0/spb),g); 00181 SetFilterPoint(out,3,fhc*CLAM_pow(2.0,-3.0/ssb),g); 00182 SetFilterPoint(out,4,fhc,g-3); 00183 SetFilterPoint(out,5,fsr,MINUSINFINITY); 00184 00185 break; 00186 } 00187 case EFDFilterType::eStopBand: 00188 { 00189 out.SetBPFSize(7); 00190 SetFilterPoint(out,0,0,g); 00191 SetFilterPoint(out,1,flc*CLAM_pow(2.0,-3.0/ssb),g); 00192 SetFilterPoint(out,2,flc,g-3); 00193 TData crossFreq=(CLAM_pow((double)flc,(1.0/(1.0-spb/ssb)))/CLAM_pow((double)fhc,(1.0/(ssb/spb-1.0)))); 00194 TData crossf_by_flc = crossFreq/flc; 00195 SetFilterPoint(out,3,crossFreq,g-3-ssb*(log(crossf_by_flc)/log(TData(2)))); 00196 SetFilterPoint(out,4,fhc,g-3); 00197 SetFilterPoint(out,5,fhc*CLAM_pow(2.0,3.0/spb),g); 00198 SetFilterPoint(out,6,fsr,g); 00199 break; 00200 } 00201 00202 } 00203 if (originalScale==EScale::eLinear) 00204 { 00205 int bpfSize=out.GetBPFSize(); 00206 BPF& bpf=out.GetMagBPF(); 00207 00208 for (int i=0; i<bpfSize; i++) { 00209 00210 TData tmpValue = bpf.GetValueFromIndex(i); 00211 00212 tmpValue = (tmpValue==0.0001) ? 0 : CLAM_pow(10.0,tmpValue/20.0); 00213 bpf.SetValue(i, tmpValue); 00214 } 00215 out.SetScale(EScale(EScale::eLinear)); 00216 } 00217 00218 return true; 00219 } 00220 00221 void FDFilterGen::SetFilterPoint(Spectrum& out,TIndex pos,TData freq,TData mag,TData phase) 00222 { 00223 out.GetMagBPF().SetValue(pos, mag); 00224 out.GetMagBPF().SetXValue(pos,freq); 00225 out.GetPhaseBPF().SetValue(pos,phase); 00226 out.GetPhaseBPF().SetXValue(pos,freq); 00227 } 00228 00229 } 00230