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 "Complex.hxx" 00023 #include "SpectrumAdder.hxx" 00024 #include "SpectrumConfig.hxx" 00025 00026 #include <sstream> 00027 00028 namespace CLAM { 00029 00030 void SpecAdderConfig::DefaultInit() 00031 { 00032 AddNInputs(); 00033 UpdateData(); 00034 SetNInputs(0); 00035 } 00036 00037 00038 SpectrumAdder::SpectrumAdder() 00039 : mSize(0), 00040 mInputs(0), 00041 complex_bufs(0),polar_bufs(0),mag_bufs(0),phase_bufs(0), 00042 remove(0), 00043 mOut("Output",this), 00044 mProtoState(SOther) 00045 { 00046 Configure(SpecAdderConfig()); 00047 } 00048 00049 SpectrumAdder::SpectrumAdder(const SpecAdderConfig &c) 00050 : mSize(0), 00051 mInputs(0), 00052 complex_bufs(0),polar_bufs(0),mag_bufs(0),phase_bufs(0), 00053 remove(0), 00054 mOut("Output",this), 00055 mProtoState(SOther) 00056 { 00057 Configure(c); 00058 } 00059 00060 std::string SpectrumAdder::NewUniqueName() 00061 { 00062 static int ObjectCount=0; 00063 00064 std::stringstream name; 00065 00066 name << "SpectrumAdder_" << ObjectCount++; 00067 00068 return name.str(); 00069 } 00070 00071 bool SpectrumAdder::ConcreteConfigure(const ProcessingConfig&c) 00072 { 00073 int oldNInputs; 00074 00075 // Nothing specific to configure here... 00076 if (mConfig.HasNInputs()) 00077 oldNInputs = mConfig.GetNInputs(); 00078 else 00079 oldNInputs = 0; 00080 00081 CopyAsConcreteConfig(mConfig, c); 00082 if ( !mConfig.HasNInputs() || 00083 mConfig.GetNInputs() <= 0 ) { 00084 mNInputs = 0; 00085 return false; 00086 } 00087 00088 mNInputs = mConfig.GetNInputs(); 00089 00090 if (mNInputs == oldNInputs) 00091 return true; 00092 00093 00094 if (mInputs) 00095 delete(mInputs); 00096 00097 if (complex_bufs) { 00098 delete(complex_bufs); 00099 complex_bufs=0; 00100 } 00101 if (polar_bufs) { 00102 delete(polar_bufs); 00103 polar_bufs=0; 00104 } 00105 if (mag_bufs) { 00106 delete(mag_bufs); 00107 mag_bufs=0; 00108 } 00109 if (phase_bufs) { 00110 delete(phase_bufs); 00111 phase_bufs=0; 00112 } 00113 if (remove) { 00114 delete(remove); 00115 remove=0; 00116 } 00117 00118 mInputs = new InPort<Spectrum>*[mNInputs]; 00119 complex_bufs = new Complex*[mNInputs]; 00120 polar_bufs = new Polar*[mNInputs]; 00121 mag_bufs = new TData*[mNInputs]; 00122 phase_bufs = new TData*[mNInputs]; 00123 remove = new bool[mNInputs]; 00124 00125 for (int i=0; i<mNInputs; i++) { 00126 std::stringstream name; 00127 name << "Input " << i; 00128 mInputs[i]=new InPort<Spectrum>(name.str(),this); 00129 } 00130 00131 return true; 00132 } 00133 00134 SpectrumAdder::~SpectrumAdder() 00135 { 00136 if (mInputs) 00137 delete(mInputs); 00138 00139 if (complex_bufs) { 00140 delete(complex_bufs); 00141 complex_bufs=0; 00142 } 00143 if (polar_bufs) { 00144 delete(polar_bufs); 00145 polar_bufs=0; 00146 } 00147 if (mag_bufs) { 00148 delete(mag_bufs); 00149 mag_bufs=0; 00150 } 00151 if (phase_bufs) { 00152 delete(phase_bufs); 00153 phase_bufs=0; 00154 } 00155 if (remove) { 00156 delete(remove); 00157 remove=0; 00158 } 00159 } 00160 00161 00162 // Unsupervised Do() function. 00163 bool SpectrumAdder::Do(Spectrum **inputs, Spectrum& out) 00164 { 00165 CLAM_DEBUG_ASSERT( IsRunning(), 00166 "SpectrumAdder::Do(): Not in execution mode"); 00167 00168 switch (mProtoState) { 00169 // Fast prototype configurations 00170 case SMagPhase: 00171 AddMagPhase(inputs,out); 00172 break; 00173 case SComplex: 00174 AddComplex(inputs,out); 00175 break; 00176 case SPolar: 00177 AddPolar(inputs,out); 00178 break; 00179 case ShasBPF: 00180 CLAM_ASSERT(false,"SpectrumAdder::Do(): BPF addition not implemented"); 00181 break; 00182 // Slow type configurations 00183 case SOther: 00184 Add(inputs,out); 00185 break; 00186 default: 00187 CLAM_ASSERT(false,"Do(...) : internal inconsistency (invalid mProtoState)"); 00188 } 00189 00190 return true; 00191 } 00192 00193 bool SpectrumAdder::Do(void) 00194 { 00195 CLAM_ASSERT(false,"SpectrumAdder::Do(): Not implemented"); 00196 } 00197 00198 // This function analyses the inputs and decides which prototypes to use 00199 // For the sum computation. 00200 bool SpectrumAdder::SetPrototypes(Spectrum **inputs,const Spectrum& out) 00201 { 00202 CLAM_ASSERT(IsConfigured(), 00203 "SpectrumAdder::SetPrototypes(): Not configured"); 00204 CLAM_ASSERT(mNInputs > 0, 00205 "SpectrumAdder::SetPrototypes(): Inconsistent mNInputs"); 00206 00207 // Check common attributes 00208 SpectrumConfig *si = new SpectrumConfig[mNInputs]; 00209 SpectrumConfig so; 00210 SpecTypeFlags *ti = new SpecTypeFlags[mNInputs]; 00211 SpecTypeFlags to; 00212 00213 for (int i=0; i<mNInputs; i++) { 00214 inputs[i]->GetConfig(si[i]); 00215 inputs[i]->GetType(ti[i]); 00216 } 00217 out.GetConfig(so); 00218 out.GetType(to); 00219 00220 00221 // Do we have the necesary attributes? 00222 CLAM_BEGIN_CHECK 00223 for (int i=0;i<mNInputs; i++) 00224 CLAM_ASSERT(ti[i].bMagPhase || ti[i].bComplex || ti[i].bPolar, 00225 "SpectrumAdders: Output spectrum object with no non-BPF attributes"); 00226 CLAM_ASSERT(to.bMagPhase || to.bComplex || to.bPolar, 00227 "SpectrumAdders: Output spectrum object with no non-BPF attributes"); 00228 // We check that the size, the spectral range and the scale of the arrays all match. 00229 CLAM_ASSERT(so.GetSize(), "SpectrumAdder::SetPrototypes: Zero size spectrum output"); 00230 CLAM_END_CHECK 00231 00232 mSize=so.GetSize(); 00233 TData range = so.GetSpectralRange(); 00234 EScale scale = so.GetScale(); 00235 00236 CLAM_BEGIN_CHECK 00237 for (int i=0; i<mNInputs; i++) { 00238 CLAM_ASSERT(mSize == si[i].GetSize(), 00239 "SpectrumAdder::SetPrototypes: Size mismatch in spectrum sum"); 00240 CLAM_ASSERT(range == si[i].GetSpectralRange(), 00241 "SpectrumAdder::SetPrototypes: Spectral range mismatch in spectrum sum"); 00242 CLAM_ASSERT(scale == si[i].GetScale(), 00243 "SpectrumAdder::SetPrototypes: Scale mismatch in spectrum sum"); 00244 } 00245 CLAM_END_CHECK 00246 00247 if (scale == EScale::eLinear) 00248 mScaleState=Slin; 00249 else 00250 mScaleState=Slog; 00251 00252 // Prototypes. 00253 00254 // We first count how many inputs have each type of attribute 00255 // instantiated. 00256 int Ncomplex=0,Npolar=0,Nmagphase=0; 00257 for (int i=0; i<mNInputs;i++) { 00258 if (ti[i].bMagPhase) 00259 Nmagphase++; 00260 if (ti[i].bComplex) 00261 Ncomplex++; 00262 if (ti[i].bPolar) 00263 Npolar++; 00264 } 00265 if (to.bMagPhase) 00266 Nmagphase++; 00267 if (to.bComplex) 00268 Ncomplex++; 00269 if (to.bPolar) 00270 Npolar++; 00271 00272 // Now we look for the best choice. 00273 for (int i=mNInputs+1; i>0; i--) { 00274 if (Nmagphase == i) { 00275 mProtoState=SMagPhase; 00276 return true; 00277 } 00278 if (Ncomplex == i) { 00279 mProtoState=SComplex; 00280 return true; 00281 } 00282 if (Npolar == i) { 00283 mProtoState=SPolar; 00284 return true; 00285 } 00286 } 00287 CLAM_ASSERT(false,"SpectrumAdder::SetPrototypes: Prototype inconsistency"); 00288 } 00289 00290 00291 bool SpectrumAdder::SetPrototypes() 00292 { 00293 CLAM_ASSERT(false,"SpectrumAdder::SetPrototypes(): Not implemented"); 00294 } 00295 00296 bool SpectrumAdder::UnsetPrototypes() 00297 { 00298 mProtoState=SOther; 00299 return true; 00300 } 00301 00302 00303 void SpectrumAdder::Add(Spectrum **inputs, Spectrum& out) 00304 { 00305 PrototypeState state_copy = mProtoState; 00306 ScaleState state2_copy = mScaleState; 00307 00308 SetPrototypes(inputs,out); 00309 Do(inputs,out); 00310 00311 mProtoState = state_copy; 00312 mScaleState = state2_copy; 00313 } 00314 00315 00316 void SpectrumAdder::AddMagPhase(Spectrum **inputs, Spectrum& out) 00317 { 00318 switch(mScaleState) { 00319 case Slin: 00320 AddMagPhaseLin(inputs,out); 00321 break; 00322 case Slog: 00323 AddMagPhaseLog(inputs,out); 00324 break; 00325 } 00326 } 00327 00328 void SpectrumAdder::AddMagPhaseLin(Spectrum **inputs, Spectrum& out) 00329 { 00330 bool removeo=false; 00331 SpecTypeFlags f; 00332 int i; 00333 00334 // This function was choosed because some of the data objects had 00335 // their MagPhase attribute instantiated. We don't know which of 00336 // them, though, so we must check and instantiate the attribute 00337 // if it is missing. 00338 for (i=0;i<mNInputs; i++) { 00339 inputs[i]->GetType(f); 00340 if (!f.bMagPhase) { 00341 remove[i]=true; 00342 f.bMagPhase=true; 00343 inputs[i]->SetTypeSynchronize(f); 00344 } 00345 else 00346 remove[i]=false; 00347 mag_bufs[i] = inputs[i]->GetMagBuffer().GetPtr(); 00348 phase_bufs[i] = inputs[i]->GetPhaseBuffer().GetPtr(); 00349 00350 } 00351 out.GetType(f); 00352 if (!f.bMagPhase) { 00353 removeo=true; 00354 f.bMagPhase=true; 00355 out.SetType(f); 00356 } 00357 TData *mo = out.GetMagBuffer().GetPtr(); 00358 TData *fo = out.GetPhaseBuffer().GetPtr(); 00359 00360 for (int s=0;s<mSize; s++) { 00361 TData re=0.0,im=0.0; 00362 for (i=0;i<mNInputs; i++) { 00363 re+=mag_bufs[i][s]*TData(cos(phase_bufs[i][s])); 00364 im+=mag_bufs[i][s]*TData(sin(phase_bufs[i][s])); 00365 } 00366 mo[s]=TData(sqrt(re*re+im*im)); 00367 fo[s]=TData(atan2(im,re)); 00368 } 00369 00370 f.bComplex=f.bPolar=f.bMagPhaseBPF=false; 00371 f.bMagPhase=true; 00372 out.SynchronizeTo(f); 00373 00374 for (i=0; i<mNInputs; i++) 00375 if (remove[i]) { 00376 inputs[i]->RemoveMagBuffer(); 00377 inputs[i]->RemovePhaseBuffer(); 00378 inputs[i]->UpdateData(); 00379 } 00380 if (removeo) { 00381 out.RemoveMagBuffer(); 00382 out.RemovePhaseBuffer(); 00383 out.UpdateData(); 00384 } 00385 00386 } 00387 00388 void SpectrumAdder::AddComplex(Spectrum **inputs, Spectrum& out) 00389 { 00390 switch(mScaleState) { 00391 case Slin: 00392 AddComplexLin(inputs,out); 00393 break; 00394 case Slog: 00395 AddComplexLog(inputs,out); 00396 break; 00397 } 00398 } 00399 00400 void SpectrumAdder::AddComplexLin(Spectrum **inputs, Spectrum& out) 00401 { 00402 bool removeo=false; 00403 SpecTypeFlags f; 00404 int i; 00405 00406 // This function was choosed because some of the data objects had 00407 // their Complex attribute instantiated. We don't know which of 00408 // them, though, so we must check and instantiate the attribute 00409 // it it is missed. This could be optimised out by adding more 00410 // States, see coments on this in the class declaration. 00411 for (i=0;i<mNInputs; i++) { 00412 inputs[i]->GetType(f); 00413 if (!f.bComplex) { 00414 remove[i]=true; 00415 f.bComplex=true; 00416 inputs[i]->SetTypeSynchronize(f); 00417 } 00418 else 00419 remove[i]=false; 00420 complex_bufs[i] = inputs[i]->GetComplexArray().GetPtr(); 00421 00422 } 00423 out.GetType(f); 00424 if (!f.bComplex) { 00425 removeo=true; 00426 f.bComplex=true; 00427 out.SetType(f); 00428 } 00429 Complex *co = out.GetComplexArray().GetPtr(); 00430 00431 for (int s=0;s<mSize;s++) { 00432 co[s]=0; 00433 for (i=0;i<mNInputs; i++) 00434 co[s]+=complex_bufs[i][s]; 00435 } 00436 00437 f.bMagPhase=f.bPolar=f.bMagPhaseBPF=false; 00438 f.bComplex=true; 00439 out.SynchronizeTo(f); 00440 00441 for (i=0; i<mNInputs; i++) 00442 if (remove[i]) { 00443 inputs[i]->RemoveComplexArray(); 00444 inputs[i]->UpdateData(); 00445 } 00446 if (removeo) { 00447 out.RemoveComplexArray(); 00448 out.UpdateData(); 00449 } 00450 } 00451 00452 00453 void SpectrumAdder::AddPolar(Spectrum **inputs, Spectrum& out) 00454 { 00455 switch(mScaleState) { 00456 case Slin: 00457 AddPolarLin(inputs,out); 00458 break; 00459 case Slog: 00460 AddPolarLog(inputs,out); 00461 break; 00462 } 00463 } 00464 00465 void SpectrumAdder::AddPolarLin(Spectrum **inputs, Spectrum& out) 00466 { 00467 bool removeo=false; 00468 SpecTypeFlags f; 00469 int i; 00470 00471 // This function was choosed because some of the data objects had 00472 // their Polar attribute instantiated. We don't know which of 00473 // them, though, so we must check and instantiate the attribute 00474 // it it is missed. This could be optimised out by adding more 00475 // States, see coments on this in the class declaration. 00476 for (i=0;i<mNInputs; i++) { 00477 inputs[i]->GetType(f); 00478 if (!f.bPolar) { 00479 remove[i]=true; 00480 f.bPolar=true; 00481 inputs[i]->SetTypeSynchronize(f); 00482 } 00483 else 00484 remove[i]=false; 00485 polar_bufs[i] = inputs[i]->GetPolarArray().GetPtr(); 00486 00487 } 00488 out.GetType(f); 00489 if (!f.bPolar) { 00490 removeo=true; 00491 f.bPolar=true; 00492 out.SetType(f); 00493 } 00494 00495 Polar *po = out.GetPolarArray().GetPtr(); 00496 for (int s=0;s<mSize;s++) { 00497 po[s]=Polar(0.0,0.0); 00498 for (i=0;i<mNInputs;i++) 00499 po[s]+=polar_bufs[i][s]; 00500 } 00501 00502 f.bComplex=f.bMagPhase=f.bMagPhaseBPF=false; 00503 f.bPolar=true; 00504 out.SynchronizeTo(f); 00505 00506 for (i=0; i<mNInputs; i++) 00507 if (remove[i]) { 00508 inputs[i]->RemovePolarArray(); 00509 inputs[i]->UpdateData(); 00510 } 00511 if (removeo) { 00512 out.RemovePolarArray(); 00513 out.UpdateData(); 00514 } 00515 } 00516 00517 00518 // UNINMPLEMENTED METHODS. Some day... 00519 void SpectrumAdder::AddMagPhaseLog(Spectrum **inputs, Spectrum& out) 00520 { 00521 CLAM_ASSERT(false,"AddMagPhaseLog: Not implemented"); 00522 } 00523 void SpectrumAdder::AddComplexLog(Spectrum **inputs, Spectrum& out) 00524 { 00525 CLAM_ASSERT(false,"AddComplexLog: Not implemented"); 00526 } 00527 void SpectrumAdder::AddPolarLog(Spectrum **inputs, Spectrum& out) 00528 { 00529 CLAM_ASSERT(false,"AddPolarLog: Not implemented"); 00530 } 00531 } 00532