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 "tools.H"
24
25 #include <math.h>
26
27 #define ROUND(number) floor((number)+0.5)
28
29 // initialisation
30 static void
init_bandnrjratio(Module * m)31 init_bandnrjratio(Module * m) {
32
33 // set up member values
34 m->set_name (string("BandNrjRatio"));
35 m->set_desc (string("Band Energy Ratio for one granule"));
36 m->set_author (string("CSIRO-MIS AAS Thomas VINCENT"));
37 m->set_copyright (string("(c) 2002 CSIRO"));
38 m->set_url (string("http://www.cmis.csiro.au/Maaate/docs/modules.html"));
39
40 // set up input parameter list
41 m->inputSpecs()->clear();
42
43 // first parameter: sound file
44 m->inputSpecs()->push_back
45 (ModuleParamSpec(string("soundfile"),
46 string("the SOUND file for which the signal "
47 "energy gets calculated"),
48 MAAATE_TYPE_SOUNDFILE,
49 new ModuleParam((SOUNDfile*)NULL)) // default
50 );
51
52 // second parameter: start time
53 MaaateConstraint * constraint = new MaaateConstraint();
54 constraint->addConstraintGreaterThan(0.0);
55 m->inputSpecs()->push_back
56 (ModuleParamSpec(string("starttime"),
57 string("time instant from which to start the "
58 "band energy ratio calculation"),
59 MAAATE_TYPE_REAL,
60 new ModuleParam((double)0.0), // default
61 constraint));
62
63 // third parameter: end time
64 constraint = new MaaateConstraint();
65 constraint->clear();
66 constraint->addConstraintGreaterThan(0.0);
67 m->inputSpecs()->push_back
68 (ModuleParamSpec(string("endtime"),
69 string("time instant until which to calculate "
70 "the band energy ratio"),
71 MAAATE_TYPE_REAL,
72 new ModuleParam((double)DBL_MAX), // default
73 constraint));
74
75 // forth parameter: I subband boundary
76 constraint = new MaaateConstraint();
77 constraint->clear();
78 constraint->addConstraintGreaterThan(1);
79 m->inputSpecs()->push_back
80 (ModuleParamSpec(string("subbandboundary"),
81 string("subband boundary between low and"
82 "high frequencies"),
83 MAAATE_TYPE_INT,
84 new ModuleParam(3), // default
85 constraint));
86
87 // fifth parameter: window function
88 constraint = new MaaateConstraint();
89 constraint->clear();
90 constraint->addConstraintRange(0, 3);
91 m->inputSpecs()->push_back
92 (ModuleParamSpec(string("window-numero"),
93 string("choice the window function to apply"
94 "during the calculation"),
95 MAAATE_TYPE_INT,
96 new ModuleParam(0), // default
97 constraint));
98
99
100 // set up output parameter list
101 m->outputSpecs()->clear();
102
103 // first parameter: subband energies curves
104 m->outputSpecs()->push_back
105 (ModuleParamSpec(string("Band energy ratio curve"),
106 string("indicator of voice/unvoice signal"),
107 MAAATE_TYPE_SEGMENTDATA,
108 new ModuleParam((SegmentData*)NULL)) // default
109 );
110
111 };
112
113
114 // function to suggest parameter values given that some of the input
115 // parameters have already been set; also changes constraints accordingly
116 static void
suggest_bandnrjratio(Module * m,list<ModuleParam> * paramsIn)117 suggest_bandnrjratio (Module * m, list<ModuleParam> * paramsIn) {
118 list<ModuleParam>::iterator iter;
119
120 // get module's input parameter specifications
121 list<ModuleParamSpec> * inSpecs = m->inputSpecs();
122 list<ModuleParamSpec>::iterator iterSpecs;
123
124 iter = paramsIn->begin(); // SOUND file
125 iterSpecs = inSpecs->begin();
126 if (iter == paramsIn->end()) return;
127 SOUNDfile * mf = (*iter).get_sf();
128 if (mf == NULL) return;
129
130 ++iter; // start time
131 ++iterSpecs;
132 (*iterSpecs).constraint()->clear();
133 (*iterSpecs).constraint()->addConstraintRange(0.0, mf->file_duration());
134 double startTime = (*iter).get_r();
135
136 ++iter; // end time
137 ++iterSpecs;
138 (*iterSpecs).constraint()->clear();
139 (*iterSpecs).constraint()->addConstraintRange(0.0, mf->file_duration());
140 double endTime = (*iter).get_r();
141
142 //check time
143 if (endTime < startTime) {
144 endTime = startTime;
145 (*iter).set(startTime);
146 }
147
148 //I subband boundary
149 ++iter;
150 ++iterSpecs;
151 (*iterSpecs).constraint()->clear();
152 (*iterSpecs).constraint()->addConstraintRange(1, (mf->nb_subbands(LOW) - 1) );
153
154 //nothing more to check for window number
155
156 }
157
158 // function to work on input parameters and return output parameters
159 static list<ModuleParam> *
apply_bandnrjratio(Module * m,list<ModuleParam> * paramsIn)160 apply_bandnrjratio (Module * m, list<ModuleParam> * paramsIn) {
161
162 // the output parameter list
163 list<ModuleParam> * mpl = new list<ModuleParam>();
164
165 // iterator in input parmeter list
166 list<ModuleParam>::iterator iter;
167
168 //Getting input parameters and last checking
169 //SOUND file
170 iter = paramsIn->begin();
171 if (iter == paramsIn->end()) return mpl;
172 SOUNDfile * mf = (*iter).get_sf();
173 if (mf == NULL) return mpl;
174
175 //start time
176 ++iter;
177 double startTime = (*iter).get_r();
178
179 //end time
180 ++iter;
181 double endTime = (*iter).get_r();
182
183 //check time
184 if (endTime < startTime) {
185 endTime = startTime;
186 }
187
188 //subband boundary
189 ++iter;
190 int I = (*iter).get_i();
191
192 //getting window numero
193 ++iter;
194 int window = (*iter).get_i();
195
196 //End getting and checking
197
198
199 //convert time into window number
200 long start = mf->time2window( (float)startTime);
201
202 long end = mf->time2window( (float)endTime);
203
204 // go to start window within soundfile
205 if (!mf->seek_window(start)) {
206 cerr << "MaaateM: Error when positioning" << endl;
207 cerr << " startposition = 0.0" << endl;
208 mf->seek_window(0);
209 start = 0;
210 }
211
212
213 // go to the first window to analyse
214 if (!mf->next_window(LOW)) {
215 cerr << "MaaateM: Warning: could not analyse first window." << endl;
216 return mpl;
217 }
218
219 //number of colunms
220 long columns = end - start;
221 columns = (columns > mf->file_window_number()) ? mf->file_window_number() : columns;
222
223
224 SegmentData *result = new SegmentData(startTime,
225 endTime,
226 columns,
227 1);
228
229 //set window function:
230 double (* h) (unsigned int, int) = 0;
231 switch (window) {
232 case 0: //Square
233 h = &square_window;
234 break;
235 case 1: //Hamming
236 h = &hamming_window;
237 break;
238 case 2: //Welch
239 h = &welch_window;
240 break;
241 case 3: //Bartlett
242 h = &bartlett_window;
243 break;
244 default:
245 h = &square_window;
246 break; //never used
247 }
248
249 // value of the window at one given time
250 double hvalue;
251
252
253 //temporary value of the sum
254 double sumup = 0.0;
255 double sumdown = 0.0;
256 double temp;
257 int nb_SB, Mmax, sb;
258
259 while (mf->at_window() <= end) {
260 // nb of samples in one window, it is also on how many samples
261 //the signal energy is calculated
262 Mmax = mf->timeticks(LOW);
263
264 nb_SB = mf->nb_subbands(LOW);
265
266 //sum in the time domain
267 for (int m = 0; m < Mmax; m++) {
268 //calculate the value of h(n-m) for this value of m, with n=Mmax-1
269 //hvalue = square_window ( Mmax-1, (Mmax-1)-m);
270 hvalue = (*h) (Mmax-1, (Mmax -1)-m);
271
272 temp = 0.0;
273
274 //sumup in the frequency domain
275 for (sb = 0; sb < I; sb++)
276 {
277 temp += pow(mf->freqvalue_st_mean(sb,m,LOW),2);
278 }
279 sumup += hvalue * temp;
280
281 temp = 0.0;
282
283 //sumdown in the frequency domain
284 for (sb = I; sb < nb_SB; sb++) {
285 temp += pow(mf->freqvalue_st_mean(sb,m,LOW),2);
286 }
287 sumdown += hvalue * temp;
288 }
289
290 //final result
291 if ( sumdown != 0.0 ) {
292 result->data[result->colFilled++][0] = sumup / sumdown;
293 } else {
294 result->data[result->colFilled++][0] = DBL_MAX;
295 }
296 //init sums
297 sumup=0.0;
298 sumdown=0.0;
299
300
301 // analyse next window
302 if (!mf->next_window(LOW)) {
303 break;
304 }
305
306 }
307
308 #ifdef DEBUG
309 cout << "Columns filled:" << result->colFilled << endl;
310 cout << "Sum:" << result->sum() << endl;
311 cout << "Average:" << result->avg() << endl;
312 cout << *result;
313 #endif
314
315 mpl->push_back(ModuleParam(result));
316
317 return mpl;
318
319 };
320
321
322 Module
loadBandNrjRatioModule(void)323 loadBandNrjRatioModule (void)
324 {
325 return Module(init_bandnrjratio,
326 NULL,
327 suggest_bandnrjratio,
328 apply_bandnrjratio ,
329 NULL,
330 NULL);
331 }
332