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 #include "module.H"
22 
23 #include <math.h>
24 
25 #define ROUND(number) floor((number)+0.5)
26 
27 static void
init_sigsb(Module * m)28 init_sigsb(Module * m) {
29 
30   // set up member values
31   m->set_name (string("sigsb"));
32   m->set_desc (string("number of subbands with a significant level calculated via a threshold, resolution: window"));
33   m->set_author (string("CSIRO-MIS AAS Thomas VINCENT"));
34   m->set_copyright (string("(c) 2002 CSIRO"));
35   m->set_url (string("http://www.cmis.csiro.au/Maaate/docs/modules.html"));
36 
37   // set up input parameter list
38   m->inputSpecs()->clear();
39 
40   // first parameter: sound file
41   m->inputSpecs()->push_back
42     (ModuleParamSpec(string("soundfile"),
43 		     string("the SOUND file for which the number of "
44 			    "subbands gets calculated"),
45 		     MAAATE_TYPE_SOUNDFILE,
46 		     new ModuleParam((SOUNDfile*)NULL)) // default
47      );
48 
49   // second parameter: start time
50   MaaateConstraint * constraint = new MaaateConstraint();
51   constraint->addConstraintGreaterThan(0.0);
52   m->inputSpecs()->push_back
53     (ModuleParamSpec(string("starttime"),
54 		     string("time instant from which to start the "
55 			    "calculation"),
56 		     MAAATE_TYPE_REAL,
57 		     new ModuleParam((double)0.0), // default
58 		     constraint));
59 
60   // third parameter: end time
61   constraint = new MaaateConstraint();
62   constraint->clear();
63   constraint->addConstraintGreaterThan(0.0);
64   m->inputSpecs()->push_back
65     (ModuleParamSpec(string("endtime"),
66 		     string("time instant until which to calculate "
67 			    "the number of significant subbands"),
68 		     MAAATE_TYPE_REAL,
69 		     new ModuleParam((double)DBL_MAX), // default
70 		     constraint));
71 
72 
73   // fourth parameter: threshold
74   constraint = new MaaateConstraint();
75   constraint->clear();
76   constraint->addConstraintRange(0.0,1.0);
77   m->inputSpecs()->push_back
78     (ModuleParamSpec(string("threshold"),
79 		     string("normalised threshold which permit to find out"
80 			    "the number of significant subbands"),
81 		     MAAATE_TYPE_REAL,
82 		     new ModuleParam((double)0.1), // default                      XXX: try it
83 		     constraint));
84 
85 
86   // set up output parameter list
87   m->outputSpecs()->clear();
88 
89   // first parameter: significant subbands curve
90   m->outputSpecs()->push_back
91     (ModuleParamSpec(string("number of significant subbands curve"),
92 		     string("indicator of speech/music"),
93 		     MAAATE_TYPE_SEGMENTDATA,
94 		     new ModuleParam((SegmentData*)NULL)) // default
95      );
96 
97 };
98 
99 
100 // function to suggest parameter values given that some of the input
101 // parameters have already been set; also changes constraints accordingly
102 static void
suggest_sigsb(Module * m,list<ModuleParam> * paramsIn)103 suggest_sigsb (Module * m, list<ModuleParam> * paramsIn) {
104   list<ModuleParam>::iterator iter;
105 
106   // get module's input parameter specifications
107   list<ModuleParamSpec> * inSpecs = m->inputSpecs();
108   list<ModuleParamSpec>::iterator iterSpecs;
109 
110   iter = paramsIn->begin(); // SOUND file
111   iterSpecs = inSpecs->begin();
112   if (iter == paramsIn->end()) return;
113   SOUNDfile * mf = (*iter).get_sf();
114   if (mf == NULL) return;
115 
116   ++iter; // start time
117   ++iterSpecs;
118   (*iterSpecs).constraint()->clear();
119   (*iterSpecs).constraint()->addConstraintRange(0.0, mf->file_duration());
120   double startTime = (*iter).get_r();
121 
122   ++iter; // end time
123   ++iterSpecs;
124   (*iterSpecs).constraint()->clear();
125   (*iterSpecs).constraint()->addConstraintRange(0.0, mf->file_duration());
126   double endTime = (*iter).get_r();
127 
128   //check time
129   if (endTime < startTime) {
130     endTime = startTime;
131     (*iter).set(startTime);
132   }
133 
134   //nothing to check for threshold
135 }
136 
137 // function to work on input parameters and return output parameters
138 static list<ModuleParam> *
apply_sigsb(Module * m,list<ModuleParam> * paramsIn)139 apply_sigsb (Module * m, list<ModuleParam> * paramsIn) {
140 
141   // the output parameter list
142   list<ModuleParam> * mpl = new list<ModuleParam>();
143 
144   // iterator in input parmeter list
145   list<ModuleParam>::iterator iter;
146 
147   //Getting input parameters and last checking
148   //SOUND file
149   iter = paramsIn->begin();
150   if (iter == paramsIn->end()) return mpl;
151   SOUNDfile * mf = (*iter).get_sf();
152   if (mf == NULL) return mpl;
153 
154   //start time
155   ++iter;
156   double startTime = (*iter).get_r();
157 
158   //end time
159   ++iter;
160   double endTime = (*iter).get_r();
161 
162   //check time
163   if (endTime < startTime) {
164     endTime = startTime;
165   }
166 
167   //threshold
168   ++iter;
169   double Ts = (*iter).get_r();  //normalised value
170 
171   //End getting and checking
172 
173   //convert time into window number
174   long start = mf->time2window(startTime);
175 
176   long end = mf->time2window(endTime);
177 
178   // go to start window within soundfile
179     if (!mf->seek_window(start)) {
180       cerr << "MaaateM: Error when positioning" << endl;
181       cerr << "         startposition = 0.0" << endl;
182       mf->seek_window(0);
183     }
184 
185 
186   //analyse first window
187   if (!mf->next_window(HIGH)) {
188     cerr << "MaaateM: error parsing frame header" << endl;
189     return mpl;
190   }
191 
192   //columns number
193   int columns = end - start;
194   columns = (columns > mf->file_window_number()) ? mf->file_window_number() : columns;
195 
196   //bandwidth
197   SegmentData *result = new SegmentData(startTime,
198 					endTime,
199 					columns,
200 					1);
201 
202 
203   //total no of subbands
204   int nb_SB = mf->nb_subbands(HIGH);
205 
206   //temporary results
207   int sb;
208   double *array = new double[nb_SB];
209   double thresh;
210 
211   while (mf->at_window() <= end) {
212 
213     //find the threshold using the normalised value and the local max
214     thresh = 0.0;
215     //find maximum of that window
216     for (sb = 0; sb < nb_SB; sb++) {
217       array[sb] =  mf->subband_mean(sb,HIGH);
218       if ( array[sb] > thresh ) {
219 	thresh = array[sb];
220       }
221     }
222     thresh = (thresh == 0.0) ? DBL_MAX : (thresh * Ts);
223 
224     //count the significant subbands
225     int count = 0;
226     for (sb = 0; sb < nb_SB; sb++) {
227       if ( array[sb] >= thresh ) count++;
228     }
229 
230     result->data[result->colFilled++][0] = count;
231 
232     // analyse next window
233     if (!mf->next_window(HIGH)) {
234       break;
235     }
236 
237   }
238 
239 #ifdef DEBUG
240   cout << "Columns filled:" << result->colFilled << endl;
241   cout << "Sum:" << result->sum() << endl;
242   cout << "Average:" << result->avg() << endl;
243   cout << *result;
244 #endif
245 
246   mpl->push_back(ModuleParam(result));
247 
248   delete[] array;
249   array = 0;
250 
251   return mpl;
252 
253 
254 }
255 
256 Module
loadsigsbModule(void)257 loadsigsbModule (void)
258 {
259   return Module(init_sigsb,
260 		NULL,
261 		suggest_sigsb,
262 		apply_sigsb,
263 		NULL,
264 		NULL);
265 }
266