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