CLAM-Development  1.4.0
SpectrumAdder.cxx
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2001-2004 MUSIC TECHNOLOGY GROUP (MTG)
3  * UNIVERSITAT POMPEU FABRA
4  *
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  */
21 
22 #include "Complex.hxx"
23 #include "SpectrumAdder.hxx"
24 #include "SpectrumConfig.hxx"
25 
26 #include <sstream>
27 
28 namespace CLAM {
29 
31  {
32  AddNInputs();
33  UpdateData();
34  SetNInputs(0);
35  }
36 
37 
39  : mSize(0),
40  mInputs(0),
41  complex_bufs(0),polar_bufs(0),mag_bufs(0),phase_bufs(0),
42  remove(0),
43  mOut("Output",this),
44  mProtoState(SOther)
45  {
47  }
48 
50  : mSize(0),
51  mInputs(0),
52  complex_bufs(0),polar_bufs(0),mag_bufs(0),phase_bufs(0),
53  remove(0),
54  mOut("Output",this),
55  mProtoState(SOther)
56  {
57  Configure(c);
58  }
59 
60  std::string SpectrumAdder::NewUniqueName()
61  {
62  static int ObjectCount=0;
63 
64  std::stringstream name;
65 
66  name << "SpectrumAdder_" << ObjectCount++;
67 
68  return name.str();
69  }
70 
71  bool SpectrumAdder::ConcreteConfigure(const ProcessingConfig&c)
72  {
73  int oldNInputs;
74 
75  // Nothing specific to configure here...
76  if (mConfig.HasNInputs())
77  oldNInputs = mConfig.GetNInputs();
78  else
79  oldNInputs = 0;
80 
81  CopyAsConcreteConfig(mConfig, c);
82  if ( !mConfig.HasNInputs() ||
83  mConfig.GetNInputs() <= 0 ) {
84  mNInputs = 0;
85  return false;
86  }
87 
88  mNInputs = mConfig.GetNInputs();
89 
90  if (mNInputs == oldNInputs)
91  return true;
92 
93 
94  if (mInputs)
95  delete(mInputs);
96 
97  if (complex_bufs) {
98  delete(complex_bufs);
99  complex_bufs=0;
100  }
101  if (polar_bufs) {
102  delete(polar_bufs);
103  polar_bufs=0;
104  }
105  if (mag_bufs) {
106  delete(mag_bufs);
107  mag_bufs=0;
108  }
109  if (phase_bufs) {
110  delete(phase_bufs);
111  phase_bufs=0;
112  }
113  if (remove) {
114  delete(remove);
115  remove=0;
116  }
117 
118  mInputs = new InPort<Spectrum>*[mNInputs];
119  complex_bufs = new Complex*[mNInputs];
120  polar_bufs = new Polar*[mNInputs];
121  mag_bufs = new TData*[mNInputs];
122  phase_bufs = new TData*[mNInputs];
123  remove = new bool[mNInputs];
124 
125  for (int i=0; i<mNInputs; i++) {
126  std::stringstream name;
127  name << "Input " << i;
128  mInputs[i]=new InPort<Spectrum>(name.str(),this);
129  }
130 
131  return true;
132  }
133 
135  {
136  if (mInputs)
137  delete(mInputs);
138 
139  if (complex_bufs) {
140  delete(complex_bufs);
141  complex_bufs=0;
142  }
143  if (polar_bufs) {
144  delete(polar_bufs);
145  polar_bufs=0;
146  }
147  if (mag_bufs) {
148  delete(mag_bufs);
149  mag_bufs=0;
150  }
151  if (phase_bufs) {
152  delete(phase_bufs);
153  phase_bufs=0;
154  }
155  if (remove) {
156  delete(remove);
157  remove=0;
158  }
159  }
160 
161 
162  // Unsupervised Do() function.
163  bool SpectrumAdder::Do(Spectrum **inputs, Spectrum& out)
164  {
166  "SpectrumAdder::Do(): Not in execution mode");
167 
168  switch (mProtoState) {
169  // Fast prototype configurations
170  case SMagPhase:
171  AddMagPhase(inputs,out);
172  break;
173  case SComplex:
174  AddComplex(inputs,out);
175  break;
176  case SPolar:
177  AddPolar(inputs,out);
178  break;
179  case ShasBPF:
180  CLAM_ASSERT(false,"SpectrumAdder::Do(): BPF addition not implemented");
181  break;
182  // Slow type configurations
183  case SOther:
184  Add(inputs,out);
185  break;
186  default:
187  CLAM_ASSERT(false,"Do(...) : internal inconsistency (invalid mProtoState)");
188  }
189 
190  return true;
191  }
192 
193  bool SpectrumAdder::Do(void)
194  {
195  CLAM_ASSERT(false,"SpectrumAdder::Do(): Not implemented");
196  }
197 
198  // This function analyses the inputs and decides which prototypes to use
199  // For the sum computation.
201  {
203  "SpectrumAdder::SetPrototypes(): Not configured");
204  CLAM_ASSERT(mNInputs > 0,
205  "SpectrumAdder::SetPrototypes(): Inconsistent mNInputs");
206 
207  // Check common attributes
208  SpectrumConfig *si = new SpectrumConfig[mNInputs];
209  SpectrumConfig so;
210  SpecTypeFlags *ti = new SpecTypeFlags[mNInputs];
211  SpecTypeFlags to;
212 
213  for (int i=0; i<mNInputs; i++) {
214  inputs[i]->GetConfig(si[i]);
215  inputs[i]->GetType(ti[i]);
216  }
217  out.GetConfig(so);
218  out.GetType(to);
219 
220 
221  // Do we have the necesary attributes?
223  for (int i=0;i<mNInputs; i++)
224  CLAM_ASSERT(ti[i].bMagPhase || ti[i].bComplex || ti[i].bPolar,
225  "SpectrumAdders: Output spectrum object with no non-BPF attributes");
226  CLAM_ASSERT(to.bMagPhase || to.bComplex || to.bPolar,
227  "SpectrumAdders: Output spectrum object with no non-BPF attributes");
228  // We check that the size, the spectral range and the scale of the arrays all match.
229  CLAM_ASSERT(so.GetSize(), "SpectrumAdder::SetPrototypes: Zero size spectrum output");
231 
232  mSize=so.GetSize();
233  TData range = so.GetSpectralRange();
234  EScale scale = so.GetScale();
235 
237  for (int i=0; i<mNInputs; i++) {
238  CLAM_ASSERT(mSize == si[i].GetSize(),
239  "SpectrumAdder::SetPrototypes: Size mismatch in spectrum sum");
240  CLAM_ASSERT(range == si[i].GetSpectralRange(),
241  "SpectrumAdder::SetPrototypes: Spectral range mismatch in spectrum sum");
242  CLAM_ASSERT(scale == si[i].GetScale(),
243  "SpectrumAdder::SetPrototypes: Scale mismatch in spectrum sum");
244  }
246 
247  if (scale == EScale::eLinear)
248  mScaleState=Slin;
249  else
250  mScaleState=Slog;
251 
252  // Prototypes.
253 
254  // We first count how many inputs have each type of attribute
255  // instantiated.
256  int Ncomplex=0,Npolar=0,Nmagphase=0;
257  for (int i=0; i<mNInputs;i++) {
258  if (ti[i].bMagPhase)
259  Nmagphase++;
260  if (ti[i].bComplex)
261  Ncomplex++;
262  if (ti[i].bPolar)
263  Npolar++;
264  }
265  if (to.bMagPhase)
266  Nmagphase++;
267  if (to.bComplex)
268  Ncomplex++;
269  if (to.bPolar)
270  Npolar++;
271 
272  // Now we look for the best choice.
273  for (int i=mNInputs+1; i>0; i--) {
274  if (Nmagphase == i) {
275  mProtoState=SMagPhase;
276  return true;
277  }
278  if (Ncomplex == i) {
279  mProtoState=SComplex;
280  return true;
281  }
282  if (Npolar == i) {
283  mProtoState=SPolar;
284  return true;
285  }
286  }
287  CLAM_ASSERT(false,"SpectrumAdder::SetPrototypes: Prototype inconsistency");
288  }
289 
290 
292  {
293  CLAM_ASSERT(false,"SpectrumAdder::SetPrototypes(): Not implemented");
294  }
295 
297  {
298  mProtoState=SOther;
299  return true;
300  }
301 
302 
303  void SpectrumAdder::Add(Spectrum **inputs, Spectrum& out)
304  {
305  PrototypeState state_copy = mProtoState;
306  ScaleState state2_copy = mScaleState;
307 
308  SetPrototypes(inputs,out);
309  Do(inputs,out);
310 
311  mProtoState = state_copy;
312  mScaleState = state2_copy;
313  }
314 
315 
316  void SpectrumAdder::AddMagPhase(Spectrum **inputs, Spectrum& out)
317  {
318  switch(mScaleState) {
319  case Slin:
320  AddMagPhaseLin(inputs,out);
321  break;
322  case Slog:
323  AddMagPhaseLog(inputs,out);
324  break;
325  }
326  }
327 
328  void SpectrumAdder::AddMagPhaseLin(Spectrum **inputs, Spectrum& out)
329  {
330  bool removeo=false;
331  SpecTypeFlags f;
332  int i;
333 
334  // This function was choosed because some of the data objects had
335  // their MagPhase attribute instantiated. We don't know which of
336  // them, though, so we must check and instantiate the attribute
337  // if it is missing.
338  for (i=0;i<mNInputs; i++) {
339  inputs[i]->GetType(f);
340  if (!f.bMagPhase) {
341  remove[i]=true;
342  f.bMagPhase=true;
343  inputs[i]->SetTypeSynchronize(f);
344  }
345  else
346  remove[i]=false;
347  mag_bufs[i] = inputs[i]->GetMagBuffer().GetPtr();
348  phase_bufs[i] = inputs[i]->GetPhaseBuffer().GetPtr();
349 
350  }
351  out.GetType(f);
352  if (!f.bMagPhase) {
353  removeo=true;
354  f.bMagPhase=true;
355  out.SetType(f);
356  }
357  TData *mo = out.GetMagBuffer().GetPtr();
358  TData *fo = out.GetPhaseBuffer().GetPtr();
359 
360  for (int s=0;s<mSize; s++) {
361  TData re=0.0,im=0.0;
362  for (i=0;i<mNInputs; i++) {
363  re+=mag_bufs[i][s]*TData(cos(phase_bufs[i][s]));
364  im+=mag_bufs[i][s]*TData(sin(phase_bufs[i][s]));
365  }
366  mo[s]=TData(sqrt(re*re+im*im));
367  fo[s]=TData(atan2(im,re));
368  }
369 
370  f.bComplex=f.bPolar=f.bMagPhaseBPF=false;
371  f.bMagPhase=true;
372  out.SynchronizeTo(f);
373 
374  for (i=0; i<mNInputs; i++)
375  if (remove[i]) {
376  inputs[i]->RemoveMagBuffer();
377  inputs[i]->RemovePhaseBuffer();
378  inputs[i]->UpdateData();
379  }
380  if (removeo) {
381  out.RemoveMagBuffer();
382  out.RemovePhaseBuffer();
383  out.UpdateData();
384  }
385 
386  }
387 
388  void SpectrumAdder::AddComplex(Spectrum **inputs, Spectrum& out)
389  {
390  switch(mScaleState) {
391  case Slin:
392  AddComplexLin(inputs,out);
393  break;
394  case Slog:
395  AddComplexLog(inputs,out);
396  break;
397  }
398  }
399 
400  void SpectrumAdder::AddComplexLin(Spectrum **inputs, Spectrum& out)
401  {
402  bool removeo=false;
403  SpecTypeFlags f;
404  int i;
405 
406  // This function was choosed because some of the data objects had
407  // their Complex attribute instantiated. We don't know which of
408  // them, though, so we must check and instantiate the attribute
409  // it it is missed. This could be optimised out by adding more
410  // States, see coments on this in the class declaration.
411  for (i=0;i<mNInputs; i++) {
412  inputs[i]->GetType(f);
413  if (!f.bComplex) {
414  remove[i]=true;
415  f.bComplex=true;
416  inputs[i]->SetTypeSynchronize(f);
417  }
418  else
419  remove[i]=false;
420  complex_bufs[i] = inputs[i]->GetComplexArray().GetPtr();
421 
422  }
423  out.GetType(f);
424  if (!f.bComplex) {
425  removeo=true;
426  f.bComplex=true;
427  out.SetType(f);
428  }
429  Complex *co = out.GetComplexArray().GetPtr();
430 
431  for (int s=0;s<mSize;s++) {
432  co[s]=0;
433  for (i=0;i<mNInputs; i++)
434  co[s]+=complex_bufs[i][s];
435  }
436 
437  f.bMagPhase=f.bPolar=f.bMagPhaseBPF=false;
438  f.bComplex=true;
439  out.SynchronizeTo(f);
440 
441  for (i=0; i<mNInputs; i++)
442  if (remove[i]) {
443  inputs[i]->RemoveComplexArray();
444  inputs[i]->UpdateData();
445  }
446  if (removeo) {
447  out.RemoveComplexArray();
448  out.UpdateData();
449  }
450  }
451 
452 
453  void SpectrumAdder::AddPolar(Spectrum **inputs, Spectrum& out)
454  {
455  switch(mScaleState) {
456  case Slin:
457  AddPolarLin(inputs,out);
458  break;
459  case Slog:
460  AddPolarLog(inputs,out);
461  break;
462  }
463  }
464 
465  void SpectrumAdder::AddPolarLin(Spectrum **inputs, Spectrum& out)
466  {
467  bool removeo=false;
468  SpecTypeFlags f;
469  int i;
470 
471  // This function was choosed because some of the data objects had
472  // their Polar attribute instantiated. We don't know which of
473  // them, though, so we must check and instantiate the attribute
474  // it it is missed. This could be optimised out by adding more
475  // States, see coments on this in the class declaration.
476  for (i=0;i<mNInputs; i++) {
477  inputs[i]->GetType(f);
478  if (!f.bPolar) {
479  remove[i]=true;
480  f.bPolar=true;
481  inputs[i]->SetTypeSynchronize(f);
482  }
483  else
484  remove[i]=false;
485  polar_bufs[i] = inputs[i]->GetPolarArray().GetPtr();
486 
487  }
488  out.GetType(f);
489  if (!f.bPolar) {
490  removeo=true;
491  f.bPolar=true;
492  out.SetType(f);
493  }
494 
495  Polar *po = out.GetPolarArray().GetPtr();
496  for (int s=0;s<mSize;s++) {
497  po[s]=Polar(0.0,0.0);
498  for (i=0;i<mNInputs;i++)
499  po[s]+=polar_bufs[i][s];
500  }
501 
502  f.bComplex=f.bMagPhase=f.bMagPhaseBPF=false;
503  f.bPolar=true;
504  out.SynchronizeTo(f);
505 
506  for (i=0; i<mNInputs; i++)
507  if (remove[i]) {
508  inputs[i]->RemovePolarArray();
509  inputs[i]->UpdateData();
510  }
511  if (removeo) {
512  out.RemovePolarArray();
513  out.UpdateData();
514  }
515  }
516 
517 
518  // UNINMPLEMENTED METHODS. Some day...
519  void SpectrumAdder::AddMagPhaseLog(Spectrum **inputs, Spectrum& out)
520  {
521  CLAM_ASSERT(false,"AddMagPhaseLog: Not implemented");
522  }
523  void SpectrumAdder::AddComplexLog(Spectrum **inputs, Spectrum& out)
524  {
525  CLAM_ASSERT(false,"AddComplexLog: Not implemented");
526  }
527  void SpectrumAdder::AddPolarLog(Spectrum **inputs, Spectrum& out)
528  {
529  CLAM_ASSERT(false,"AddPolarLog: Not implemented");
530  }
531 }
532