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_SBmean(Module * m)28 init_SBmean(Module * m) {
29 
30   // set up member values
31   m->set_name (string("SBmean"));
32   m->set_desc (string("subband mean over each subband"));
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 subband "
44 			    "mean 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 			    "subband mean 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 subband mean"),
68 		     MAAATE_TYPE_REAL,
69 		     new ModuleParam((double)DBL_MAX), // default
70 		     constraint));
71 
72   // fourth parameter: start subband
73   constraint = new MaaateConstraint();
74   constraint->clear();
75   constraint->addConstraintGreaterThan(0);
76   m->inputSpecs()->push_back
77     (ModuleParamSpec(string("start-subband"),
78 		     string("subband from which to start the subband "
79 			    "mean calculation"),
80 		     MAAATE_TYPE_INT,
81 		     new ModuleParam(0), // default
82 		     constraint));
83 
84   // fifth parameter: end subband
85   constraint = new MaaateConstraint();
86   constraint->clear();
87   constraint->addConstraintGreaterThan(0);
88   m->inputSpecs()->push_back
89     (ModuleParamSpec(string("end-subband"),
90 		     string("subband at which to end the subband"
91 			    "mean calculation"),
92 		     MAAATE_TYPE_INT,
93 		     new ModuleParam(0), // default
94 		     constraint));
95 
96   // set up output parameter list
97   m->outputSpecs()->clear();
98 
99   // first parameter: subband mean curves
100   m->outputSpecs()->push_back
101     (ModuleParamSpec(string("subband mean curves"),
102 		     string("an approximation of subband mean for the "
103 			    "requested time interval for each subband"),
104 		     MAAATE_TYPE_SEGMENTDATA,
105 		     new ModuleParam((SegmentData*)NULL)) // default
106      );
107 
108 };
109 
110 
111 // function to suggest parameter values given that some of the input
112 // parameters have already been set; also changes constraints accordingly
113 static void
suggest_SBmean(Module * m,list<ModuleParam> * paramsIn)114 suggest_SBmean (Module * m, list<ModuleParam> * paramsIn) {
115   list<ModuleParam>::iterator iter;
116 
117   // get module's input parameter specifications
118   list<ModuleParamSpec> * inSpecs = m->inputSpecs();
119   list<ModuleParamSpec>::iterator iterSpecs;
120 
121   iter = paramsIn->begin(); // SOUND file
122   iterSpecs = inSpecs->begin();
123   if (iter == paramsIn->end()) return;
124   SOUNDfile * mf = (*iter).get_sf();
125   if (mf == NULL) return;
126 
127   ++iter; // start time
128   ++iterSpecs;
129   (*iterSpecs).constraint()->clear();
130   (*iterSpecs).constraint()->addConstraintRange(0.0, mf->file_duration());
131   double startTime = (*iter).get_r();
132 
133   ++iter; // end time
134   ++iterSpecs;
135   (*iterSpecs).constraint()->clear();
136   (*iterSpecs).constraint()->addConstraintRange(0.0, mf->file_duration());
137   double endTime = (*iter).get_r();
138 
139   //check time
140   if (endTime < startTime) {
141     endTime = startTime;
142     (*iter).set(startTime);
143   }
144 
145   ++iter; // start subband
146   ++iterSpecs;
147   (*iterSpecs).constraint()->clear();
148   (*iterSpecs).constraint()->addConstraintRange(0, (mf->nb_subbands(HIGH) - 1) );
149   int startSubband = (*iter).get_i();
150 
151   ++iter; // end subband
152   ++iterSpecs;
153   (*iterSpecs).constraint()->clear();
154   (*iterSpecs).constraint()->addConstraintRange(0, (mf->nb_subbands(HIGH) - 1) );
155 
156   // check nr of subbands
157   int endSubband = (*iter).get_i();
158   if (endSubband < startSubband) {
159     endSubband = startSubband;
160     (*iter).set(startSubband);
161   }
162 
163 }
164 
165 // function to work on input parameters and return output parameters
166 static list<ModuleParam> *
apply_SBmean(Module * m,list<ModuleParam> * paramsIn)167 apply_SBmean (Module * m, list<ModuleParam> * paramsIn) {
168 
169   // the output parameter list
170   list<ModuleParam> * mpl = new list<ModuleParam>();
171 
172   // iterator in input parmeter list
173   list<ModuleParam>::iterator iter;
174 
175   //Getting input parameters and last checking
176   //SOUND file
177   iter = paramsIn->begin();
178   if (iter == paramsIn->end()) return mpl;
179   SOUNDfile * mf = (*iter).get_sf();
180   if (mf == NULL) return mpl;
181 
182   //start time
183   ++iter;
184   double startTime = (*iter).get_r();
185 
186   //end time
187   ++iter;
188   double endTime = (*iter).get_r();
189 
190   //check time
191   if (endTime < startTime) {
192     endTime = startTime;
193   }
194 
195   // start subband
196   ++iter;
197   int startSubband = (*iter).get_i();
198 
199   //end subband
200   ++iter;
201   int endSubband = (*iter).get_i();
202 
203   //check subband
204   if (endSubband < startSubband) {
205       endSubband = startSubband;
206   }
207   //End getting and checking
208 
209 
210   //convert time into window number
211   long start = mf->time2window( (float)startTime);
212 
213   long end = mf->time2window( (float)endTime);
214 
215   // go to start window  within soundfile
216   if (!mf->seek_window(start)) {
217     cerr << "MaaateM: Error when positioning" << endl;
218     cerr << "         startposition = 0.0" << endl;
219     mf->seek_window(0);
220     start = 0;
221   }
222 
223 
224   // analyse first window
225   if (!mf->next_window(HIGH)) {
226     cerr << "MaaateM: Warning: could not analyse first window." << endl;
227     return mpl;
228   }
229 
230   //colunms number
231   long columns = end - start;
232   columns = (columns > mf->file_window_number()) ? mf->file_window_number() : columns;
233 
234   //rows number
235   int nbsubband = endSubband - startSubband + 1;
236 
237   SegmentData *result = new SegmentData(startTime,
238 					endTime,
239 					columns,
240 					nbsubband);
241 
242   //extract subband means
243   while (mf->at_window() <= end) {
244 
245     for (int sb = startSubband; sb <= endSubband; sb++) {  //from one subband to another
246       result->data[result->colFilled][sb-startSubband] =  mf->subband_mean (sb,HIGH);
247     }
248 
249     result->colFilled++;
250 
251     // analyse next window
252     if (!mf->next_window(HIGH)) {
253       break;
254     }
255 
256   }
257 
258 #ifdef DEBUG
259   cout << "Columns filled:" << result->colFilled << endl;
260   cout << "Sum:" << result->sum() << endl;
261   cout << "Average:" << result->avg() << endl;
262   cout << *result;
263 #endif
264 
265   mpl->push_back(ModuleParam(result));
266 
267   return mpl;
268 
269 };
270 
271 
272 Module
loadSBmeanModule(void)273 loadSBmeanModule (void)
274 {
275   return Module(init_SBmean,
276 		NULL,
277 		suggest_SBmean,
278 		apply_SBmean ,
279 		NULL,
280 		NULL);
281 }
282