1 /*
2 MPEG Maaate: An Australian MPEG audio analysis toolkit
3 Copyright (C) 2000 Commonwealth Scientific and Industrial Research Organisation
4 (CSIRO), Australia.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include "module.H"
27
28 // copy constructor (XXX is it necessary anyway?)
29 CSAPI_TIER2
ModuleParam(const ModuleParam & mp)30 ModuleParam::ModuleParam (const ModuleParam& mp) {
31 type = mp.getType();
32 switch(type) {
33 case MAAATE_TYPE_SOUNDFILE:
34 sf = mp.get_sf(); break;
35 case MAAATE_TYPE_SEGMENTTABLE:
36 st = mp.get_st(); break;
37 case MAAATE_TYPE_SEGMENTDATA:
38 sd = mp.sd; break;
39 case MAAATE_TYPE_BOOL:
40 b = mp.get_b(); break;
41 case MAAATE_TYPE_INT:
42 i = mp.get_i(); break;
43 case MAAATE_TYPE_REAL:
44 r = mp.get_r(); break;
45 case MAAATE_TYPE_STRING:
46 s = strdup(mp.get_s()); break;
47 }
48 }
49
50 // overload friend operator <<
51 // main usage: debugging
52 CSAPI_TIER2 ostream&
operator <<(ostream & os,ModuleParam const & mp)53 operator<<(ostream& os, ModuleParam const & mp) {
54 switch (mp.getType()) {
55 case MAAATE_TYPE_SOUNDFILE:
56 if (mp.get_sf() != NULL) {
57 os << mp.get_sf()->file();
58 }
59 break;
60 case MAAATE_TYPE_SEGMENTTABLE:
61 if (mp.get_st() != NULL) {
62 os << mp.get_st();
63 }
64 break;
65 case MAAATE_TYPE_SEGMENTDATA:
66 if (mp.get_sd() != NULL) {
67 os << mp.get_sd();
68 }
69 break;
70 case MAAATE_TYPE_BOOL:
71 os << mp.get_b();
72 break;
73 case MAAATE_TYPE_INT:
74 os << mp.get_i();
75 break;
76 case MAAATE_TYPE_REAL:
77 os << mp.get_r();
78 break;
79 case MAAATE_TYPE_STRING:
80 if (mp.get_s() != NULL) {
81 os << mp.get_s();
82 }
83 break;
84 }
85 return os;
86 }
87
88 CSAPI_TIER2 bool
operator ==(ModuleParam const & mp1,ModuleParam const & mp2)89 operator== (ModuleParam const & mp1, ModuleParam const & mp2) {
90 if (mp1.getType() != mp2.getType()) return (false);
91
92 switch(mp1.getType()) {
93 case MAAATE_TYPE_SOUNDFILE:
94 return (mp1.get_sf() == mp2.get_sf());
95 case MAAATE_TYPE_SEGMENTTABLE:
96 return (mp1.get_st() == mp2.get_st());
97 case MAAATE_TYPE_SEGMENTDATA:
98 return (mp1.get_sd() == mp2.get_sd());
99 case MAAATE_TYPE_BOOL:
100 return (mp1.get_b() == mp2.get_b());
101 case MAAATE_TYPE_INT:
102 return (mp1.get_i() == mp2.get_i());
103 case MAAATE_TYPE_REAL:
104 return (mp1.get_r() == mp2.get_r());
105 case MAAATE_TYPE_STRING:
106 return (!strcmp (mp1.get_s(), mp2.get_s()));
107 default:
108 return false;
109 }
110
111 return false;
112 }
113
114 CSAPI_TIER2 ModuleParam&
operator =(const ModuleParam & mp)115 ModuleParam::operator= (const ModuleParam & mp) {
116 if (this == &mp)
117 return *this;
118 type = mp.getType();
119 switch(type) {
120 case MAAATE_TYPE_SOUNDFILE:
121 sf = mp.get_sf();
122 break;
123 case MAAATE_TYPE_SEGMENTTABLE:
124 st = mp.get_st();
125 break;
126 case MAAATE_TYPE_SEGMENTDATA:
127 sd = mp.sd;
128 break;
129 case MAAATE_TYPE_BOOL:
130 b = mp.get_b();
131 break;
132 case MAAATE_TYPE_INT:
133 i = mp.get_i();
134 break;
135 case MAAATE_TYPE_REAL:
136 r = mp.get_r();
137 break;
138 case MAAATE_TYPE_STRING:
139 strcpy (s, mp.get_s());
140 break;
141 }
142 return *this;
143 }
144
145 CSAPI_TIER2 double
operator -(ModuleParam const & mp1,ModuleParam const & mp2)146 operator- (ModuleParam const & mp1, ModuleParam const & mp2) {
147 if (mp1.getType() != mp2.getType()) return (false);
148
149 switch(mp1.getType()) {
150 case MAAATE_TYPE_SOUNDFILE:
151 return (DBL_MAX);
152 case MAAATE_TYPE_SEGMENTTABLE:
153 return (DBL_MAX);
154 case MAAATE_TYPE_SEGMENTDATA:
155 return (DBL_MAX);
156 case MAAATE_TYPE_BOOL:
157 return (mp1.get_b() == mp2.get_b() ? 0.0 : DBL_MAX);
158 case MAAATE_TYPE_INT:
159 return ((double)(mp1.get_i() - mp2.get_i()));
160 case MAAATE_TYPE_REAL:
161 return (mp1.get_r() - mp2.get_r());
162 case MAAATE_TYPE_STRING:
163 return ((double)strcmp (mp1.get_s(), mp2.get_s()));
164 default:
165 return false;
166 }
167 return false;
168 }
169
170 CSAPI_TIER2 bool
operator <(ModuleParam const & mp1,ModuleParam const & mp2)171 operator< (ModuleParam const & mp1, ModuleParam const & mp2) {
172 if (mp1.getType() != mp2.getType()) return (false);
173
174 switch(mp1.getType()) {
175 case MAAATE_TYPE_SOUNDFILE:
176 return (false);
177 case MAAATE_TYPE_SEGMENTTABLE:
178 return (false);
179 case MAAATE_TYPE_SEGMENTDATA:
180 return (false);
181 case MAAATE_TYPE_BOOL:
182 return (mp1.get_b() != mp2.get_b());
183 case MAAATE_TYPE_INT:
184 return (mp1.get_i() < mp2.get_i());
185 case MAAATE_TYPE_REAL:
186 return (mp1.get_r() < mp2.get_r());
187 case MAAATE_TYPE_STRING:
188 return (strcmp (mp1.get_s(), mp2.get_s()) < 0);
189 default:
190 return (false);
191 }
192 return false;
193 }
194
195 CSAPI_TIER2 bool
operator >(ModuleParam const & mp1,ModuleParam const & mp2)196 operator> (ModuleParam const & mp1, ModuleParam const & mp2) {
197 if (mp1.getType() != mp2.getType()) return (false);
198
199 switch(mp1.getType()) {
200 case MAAATE_TYPE_SOUNDFILE:
201 return (false);
202 case MAAATE_TYPE_SEGMENTTABLE:
203 return (false);
204 case MAAATE_TYPE_SEGMENTDATA:
205 return (false);
206 case MAAATE_TYPE_BOOL:
207 return (mp1.get_b() != mp2.get_b());
208 case MAAATE_TYPE_INT:
209 return (mp1.get_i() > mp2.get_i());
210 case MAAATE_TYPE_REAL:
211 return (mp1.get_r() > mp2.get_r());
212 case MAAATE_TYPE_STRING:
213 return (strcmp (mp1.get_s(), mp2.get_s()) > 0);
214 default:
215 return false;
216 }
217 return false;
218 }
219
220 CSAPI_TIER2 bool
operator <=(ModuleParam const & mp1,ModuleParam const & mp2)221 operator<= ( ModuleParam const & mp1, ModuleParam const & mp2) {
222 return ((operator<((const ModuleParam&) mp1,mp2)) || (mp1 == mp2));
223 }
224
225 CSAPI_TIER2 bool
operator >=(ModuleParam const & mp1,ModuleParam const & mp2)226 operator>= (ModuleParam const & mp1, ModuleParam const & mp2) {
227 return ((mp1 > mp2) || (mp1 == mp2));
228 }
229
230 CSAPI_TIER2 bool
isZero()231 ModuleParam::isZero () {
232 switch(type) {
233 case MAAATE_TYPE_SOUNDFILE:
234 return (sf == NULL);
235 case MAAATE_TYPE_SEGMENTTABLE:
236 return (st == NULL);
237 case MAAATE_TYPE_SEGMENTDATA:
238 return (sd == NULL);
239 case MAAATE_TYPE_BOOL:
240 return (!b);
241 case MAAATE_TYPE_INT:
242 return (i == 0);
243 case MAAATE_TYPE_REAL:
244 return (r == 0.0);
245 case MAAATE_TYPE_STRING:
246 return (!strcmp (s, ""));
247 default:
248 return (false);
249 }
250 return false;
251 }
252
253 CSAPI_TIER2 bool
set(SOUNDfile * spf)254 ModuleParam::set (SOUNDfile * spf) {
255 if (type == MAAATE_TYPE_SOUNDFILE) {
256 sf = spf;
257 return true;
258 } else {
259 return false;
260 }
261 }
262
263 CSAPI_TIER2 bool
set(SegmentTable * sgt)264 ModuleParam::set (SegmentTable * sgt) {
265 if (type == MAAATE_TYPE_SEGMENTTABLE) {
266 st = sgt;
267 return true;
268 } else {
269 return false;
270 }
271 }
272
273 CSAPI_TIER2 bool
set(SegmentData * sgd)274 ModuleParam::set (SegmentData * sgd) {
275 if (type == MAAATE_TYPE_SEGMENTDATA) {
276 sd = sgd;
277 return true;
278 } else {
279 return false;
280 }
281 }
282
283 CSAPI_TIER2 bool
set(bool bl)284 ModuleParam::set (bool bl) {
285 if (type == MAAATE_TYPE_BOOL) {
286 b = bl;
287 return true;
288 } else {
289 return false;
290 }
291 }
292
293 CSAPI_TIER2 bool
set(int it)294 ModuleParam::set (int it) {
295 if (type == MAAATE_TYPE_INT) {
296 i = it;
297 return true;
298 } else {
299 return false;
300 }
301 }
302
303 CSAPI_TIER2 bool
set(double rl)304 ModuleParam::set (double rl) {
305 if (type == MAAATE_TYPE_REAL) {
306 r = rl;
307 return true;
308 } else {
309 return false;
310 }
311 }
312
313 CSAPI_TIER2 bool
set(char * sg)314 ModuleParam::set (char * sg) {
315 if (type == MAAATE_TYPE_STRING) {
316 s = strdup(sg);
317 return true;
318 } else {
319 return false;
320 }
321 }
322
323 // overload friend operator <<
324 // main usage: debugging
325 CSAPI_TIER2 ostream&
operator <<(ostream & os,ModuleParamRange const & mpr)326 operator<<(ostream& os, ModuleParamRange const & mpr) {
327 if (mpr.lowerBound() && mpr.upperBound() && mpr.step()) {
328 os << "[" << mpr.lowerBound() << ";" << mpr.upperBound() << "] step " << mpr.step();
329 } else if (mpr.lowerBound() && mpr.upperBound()) {
330 os << "[" << mpr.lowerBound() << ";" << mpr.upperBound() << "]";
331 } else if (mpr.lowerBound()) {
332 os << "[" << mpr.lowerBound() << ";infinity]";
333 } else if (mpr.upperBound()) {
334 os << "[-infinity;" << mpr.lowerBound() << "]";
335 }
336 return os;
337 }
338
339 // overload friend operator <<
340 // main usage: debugging
341 CSAPI_TIER2 ostream&
operator <<(ostream & os,ModuleParamConstraint & mpc)342 operator<<(ostream& os, ModuleParamConstraint & mpc) {
343 switch (mpc.Type()) {
344 case MAAATE_CONSTRAINT_NONE:
345 os << "No constraint" << endl;
346 break;
347 case MAAATE_CONSTRAINT_VALUE:
348 os << mpc.Value() << endl;
349 break;
350 case MAAATE_CONSTRAINT_RANGE:
351 os << mpc.Value()->constraintRange() << endl;
352 break;
353 default:
354 break;
355 }
356 return os;
357 }
358
359 CSAPI_TIER2 bool
within(ModuleParam param)360 ModuleParamConstraint::within (ModuleParam param) {
361 switch (type) {
362 case MAAATE_CONSTRAINT_NONE:
363 return true;
364 case MAAATE_CONSTRAINT_VALUE:
365 if (*(constraint->constraintValue()) == (param)) {
366 return true;
367 }
368 break;
369 case MAAATE_CONSTRAINT_RANGE:
370 if (*(constraint->constraintRange()->lowerBound()) <= (param) &&
371 *(constraint->constraintRange()->upperBound()) >= (param)) {
372 return true;
373 }
374 break;
375 default:
376 break;
377 }
378 return false;
379
380 }
381
382 CSAPI_TIER2 ModuleParam *
closest(ModuleParam param)383 ModuleParamConstraint::closest (ModuleParam param) {
384 if (within(param)) return ¶m;
385
386 switch (type) {
387 case MAAATE_CONSTRAINT_VALUE:
388 return constraint->constraintValue();
389 case MAAATE_CONSTRAINT_RANGE:
390 if (param > * (constraint->constraintRange()->upperBound())) {
391 return constraint->constraintRange()->upperBound();
392 } else {
393 return constraint->constraintRange()->lowerBound();
394 }
395 break;
396 default:
397 return NULL;
398 }
399 }
400
401 CSAPI_TIER2 double
distance(ModuleParam param)402 ModuleParamConstraint::distance (ModuleParam param) {
403 if (within(param)) return 0.0;
404
405 switch (type) {
406 case MAAATE_CONSTRAINT_VALUE:
407 return abs(param - constraint->constraintValue());
408 case MAAATE_CONSTRAINT_RANGE:
409 if (param > *(constraint->constraintRange()->upperBound())) {
410 return (param - constraint->constraintRange()->upperBound());
411 } else {
412 return (constraint->constraintRange()->lowerBound() - param);
413 }
414 break;
415 default:
416 return DBL_MAX;
417 }
418 }
419
420 // overload friend operator <<
421 // main usage: debugging
422 CSAPI_TIER2 ostream&
operator <<(ostream & os,MaaateConstraint & mc)423 operator<<(ostream& os, MaaateConstraint & mc) {
424 list<ModuleParamConstraint>::iterator constraintIter;
425
426 if (mc.getConstraints()->empty()) {
427 return os;
428 }
429
430 for (constraintIter = mc.getConstraints()->begin();
431 constraintIter != mc.getConstraints()->end();
432 ++constraintIter) {
433 os << *constraintIter;
434 }
435
436 return os;
437 }
438
439 CSAPI_TIER2 void
addConstraint(ModuleParam * value)440 MaaateConstraint::addConstraint (ModuleParam * value) {
441 constraints.push_back
442 (ModuleParamConstraint(MAAATE_CONSTRAINT_VALUE,
443 new ModuleParamConstraintValue(value)));
444 }
445
446 CSAPI_TIER2 void
addConstraintRange(ModuleParam * lowerBound,ModuleParam * upperBound,ModuleParam * step)447 MaaateConstraint::addConstraintRange (ModuleParam * lowerBound,
448 ModuleParam * upperBound,
449 ModuleParam * step)
450 {
451 constraints.push_back
452 (ModuleParamConstraint(MAAATE_CONSTRAINT_RANGE,
453 new ModuleParamConstraintValue
454 (new ModuleParamRange
455 (lowerBound, upperBound,
456 ((step == NULL || step->isZero()) ?
457 (ModuleParam *)NULL : step)))));
458 }
459
460 CSAPI_TIER2 void
addConstraintRange(int lowerBound,int upperBound,int step)461 MaaateConstraint::addConstraintRange (int lowerBound,
462 int upperBound,
463 int step) {
464 addConstraintRange(new ModuleParam(lowerBound),
465 new ModuleParam(upperBound),
466 (step == 0 ? (ModuleParam *)NULL :
467 new ModuleParam(step)));
468 }
469
470 CSAPI_TIER2 void
addConstraintRange(double lowerBound,double upperBound,double step)471 MaaateConstraint::addConstraintRange (double lowerBound,
472 double upperBound,
473 double step) {
474 addConstraintRange(new ModuleParam(lowerBound),
475 new ModuleParam(upperBound),
476 (step == 0.0 ? (ModuleParam *)NULL :
477 new ModuleParam(step)));
478 }
479
480 CSAPI_TIER2 void
addConstraintGreaterThan(int i)481 MaaateConstraint::addConstraintGreaterThan(int i) {
482 addConstraintRange(new ModuleParam(i));
483 }
484
485 CSAPI_TIER2 void
addConstraintGreaterThan(double d)486 MaaateConstraint::addConstraintGreaterThan(double d) {
487 addConstraintRange(new ModuleParam(d));
488 }
489
490 CSAPI_TIER2 void
addConstraintLessThan(int i)491 MaaateConstraint::addConstraintLessThan(int i) {
492 addConstraintRange((ModuleParam *)NULL, new ModuleParam(i));
493 }
494
495 CSAPI_TIER2 void
addConstraintLessThan(double d)496 MaaateConstraint::addConstraintLessThan(double d) {
497 addConstraintRange((ModuleParam *)NULL, new ModuleParam(d));
498 }
499
500 CSAPI_TIER2 bool
withinConstraints(ModuleParam param)501 MaaateConstraint::withinConstraints (ModuleParam param) {
502 list<ModuleParamConstraint>::iterator constraintIter;
503
504 if (constraints.empty()) {
505 return true;
506 }
507
508 for (constraintIter = constraints.begin();
509 constraintIter != constraints.end();
510 ++constraintIter) {
511 if ((*constraintIter).within(param)) {
512 return true;
513 }
514 }
515
516 return false;
517 }
518
519 // return NULL if there is no closer value; eg. if value is already
520 // the closest, or if there is no distance function
521 CSAPI_TIER2 ModuleParam *
closestConstraintValue(ModuleParam param)522 MaaateConstraint::closestConstraintValue (ModuleParam param) {
523 MaaateType type;
524 ModuleParam * closest;
525 list<ModuleParamConstraint>::iterator constraintIter;
526 double thisDistance = 0, minDistance = DBL_MAX;
527
528 // XXX: assume the MaaateType of value is the same as that of the
529 // constraint; constraints.getType() would be better
530 type = param.getType();
531 if (type == MAAATE_TYPE_SOUNDFILE || type == MAAATE_TYPE_SEGMENTTABLE ||
532 type == MAAATE_TYPE_SEGMENTDATA) {
533 return NULL;
534 }
535
536 if (constraints.size() == 0) {
537 return NULL;
538 }
539
540 closest = new ModuleParam (param);
541 for (constraintIter = constraints.begin();
542 constraintIter != constraints.end();
543 ++constraintIter) {
544
545 if ((*constraintIter).within(param)) {
546 return NULL;
547 }
548
549 thisDistance = (*constraintIter).distance(param);
550 if (thisDistance < minDistance) {
551 closest = (*constraintIter).closest(param);
552 minDistance = thisDistance;
553 }
554 }
555 return closest;
556
557 }
558
559 // functions that do nothing for the insane case
560 CSAPI_TIER2
defaultNoop(Module * m)561 list<ModuleParam> * defaultNoop (Module * m) {
562 list<ModuleParam> * result = new list<ModuleParam>();
563 return result;
564 };
565
566 CSAPI_TIER2
suggestNoop(Module * m,list<ModuleParam> * paramsIn)567 void suggestNoop (Module * m, list<ModuleParam> * paramsIn) {};
applyNoop(Module * m,list<ModuleParam> * params_in)568 list<ModuleParam> * applyNoop (Module * m, list<ModuleParam> * params_in) {
569 list<ModuleParam> * result = new list<ModuleParam>();
570 return result;
571 };
572
573 CSAPI_TIER2
resetNoop(Module * m)574 void resetNoop (Module * m) {};
575
576 CSAPI_TIER2
destroyD(Module * m)577 void destroyD (Module * m) {
578 m->inputSpecs()->clear();
579 m->outputSpecs()->clear();
580 // modParamInSpecs.~list<ModuleParamSpec>();
581 // modParamOutSpecs.~list<ModuleParamSpec>();
582 };
583
584 CSAPI_TIER2
585 list<ModuleParam> *
defaultD(Module * m)586 defaultD (Module * m) {
587 list<ModuleParamSpec>::iterator iter;
588 list<ModuleParam> * plist = new list<ModuleParam>();
589 ModuleParam * mp;
590
591 for (iter = m->inputSpecs()->begin();
592 iter != m->inputSpecs()->end();
593 ++iter) {
594 mp = (*iter).defaultValue();
595 plist->push_back(*mp);
596 }
597
598 return plist;
599 }
600
601 CSAPI_TIER2
Module(ModuleInitFunc initF,ModuleDefaultFunc defaultF,ModuleSuggestValues suggestF,ModuleApplyFunc applyF,ModuleResetFunc resetF,ModuleDestroyFunc destroyF)602 Module::Module(ModuleInitFunc initF,
603 ModuleDefaultFunc defaultF,
604 ModuleSuggestValues suggestF,
605 ModuleApplyFunc applyF,
606 ModuleResetFunc resetF,
607 ModuleDestroyFunc destroyF) {
608 // execute init function if supplied
609 if (initF != NULL) {
610 initF(this);
611 // XXX: delete whitespace from modName !!!
612
613 // set function pointers to other functions
614 defaultM = (defaultF==NULL ? defaultD : defaultF);
615 suggestM = (suggestF==NULL ? suggestNoop : suggestF);
616 applyM = (applyF==NULL ? applyNoop : applyF);
617 destroyM = (destroyF==NULL ? destroyD : destroyF);
618
619 saneM = true;
620 } else {
621 modName = string("Insane_Module");
622 modDesc = string("This module has not been properly initialised.");
623 modAuthor = string("");
624 modCopyright = string("");
625 modUrl = string("");
626 modParamInSpecs.clear();
627 modParamOutSpecs.clear();
628
629 defaultM = defaultNoop;
630 suggestM = suggestNoop;
631 applyM = applyNoop;
632 destroyM = NULL;
633
634 saneM = false;
635 }
636 }
637
638 // returns true if params got changed; false otherwise
639 CSAPI_TIER2 bool
checkConstraints(list<ModuleParam> * paramsIn)640 Module::checkConstraints (list<ModuleParam> * paramsIn) {
641 list<ModuleParamSpec>::iterator specIter;
642 list<ModuleParam>::iterator paramIter;
643 MaaateConstraint * constraint;
644 ModuleParam * suggest;
645 bool change = false;
646
647 for (specIter = modParamInSpecs.begin(), paramIter = paramsIn->begin();
648 specIter != modParamInSpecs.end() && paramIter != paramsIn->end();
649 ++specIter, ++paramIter) {
650 constraint = (*specIter).constraint();
651
652 if (!constraint || constraint->withinConstraints (*paramIter)) {
653 continue;
654 }
655
656 suggest = constraint->closestConstraintValue (*paramIter);
657 if (suggest != NULL) {
658 *paramIter = *suggest;
659 change = true;
660 }
661 }
662 return change;
663 }
664