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 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 //#include <curses.h> //for getchar()
26 #include <cfloat>
27 #include <iostream>
28 #include <cstdlib>
29 #include <cstring>
30 #include "segmentData.H"
31
32 // constructor
33 CSAPI_TIER2
SegmentData(double t1,double t2,int col,int row,int i,char f,double cnf)34 SegmentData::SegmentData(double t1, double t2, int col, int row,
35 int i, char f, double cnf) :
36 starttime(t1), endtime(t2), columns(col), rows(row),
37 id(i), flag(f), conf(cnf) {
38 if (col<0) col=0;
39 if (row<0) row=0;
40 if (col>0 || row>0) {
41 data = new double*[col];
42 if (!data) {
43 cerr << "MaaateA: SegmentData: No space available" << endl;
44 exit(1);
45 }
46 for (int i=0; i<col; i++) {
47 data[i] = new double[row];
48 if (!data[i]) {
49 cerr << "MaaateA: SegmentData: No space available" << endl;
50 exit(1);
51 }
52 memset(data[i],0,sizeof(double)*row);
53 }
54 } else {
55 data = NULL;
56 }
57
58 // initialize summarizing values
59 clear_all();
60 colFilled = 0;
61 }
62
63 // destructor
64 CSAPI_TIER2
~SegmentData()65 SegmentData::~SegmentData() {
66 for (int i=0; i<columns; i++)
67 delete[] data[i];
68 delete[] data;
69 }
70
71 // copy constructor
72 CSAPI_TIER2
SegmentData(const SegmentData & sd)73 SegmentData::SegmentData(const SegmentData& sd) {
74 starttime = sd.starttime;
75 endtime = sd.endtime;
76 columns = sd.columns;
77 rows = sd.rows;
78 id = sd.id;
79 flag = sd.flag;
80 conf = sd.conf;
81 // no previously stored data: just allocate storage
82 data = new double*[columns];
83 for (int i=0; i<columns; i++) {
84 data[i] = new double[rows];
85 for (int j=0; j<rows; j++) {
86 data[i][j] = sd.data[i][j];
87 }
88 }
89
90 // initialize summarizing values
91 clear_all();
92 colFilled = sd.colFilled;
93 }
94
95
96 // partial copy constructor
97 CSAPI_TIER2
SegmentData(const SegmentData & sd,int st_row,int end_row,int i,char f,double cnf)98 SegmentData::SegmentData(const SegmentData& sd,
99 int st_row, int end_row,
100 int i, char f, double cnf)
101 {
102 int nb_rows;
103
104 /* row check */
105 if ( st_row > end_row ) end_row = st_row;
106 if ( st_row >= sd.rows ) st_row = sd.rows-1;
107 if ( end_row >= sd.rows ) end_row = sd.rows-1;
108
109 nb_rows = end_row - st_row + 1;
110
111 starttime = sd.starttime;
112 endtime = sd.endtime;
113 columns = sd.columns;
114 rows = nb_rows;
115 id = i;
116 flag = f;
117 conf = cnf;
118
119 // no previously stored data: just allocate storage
120 data = new double*[columns];
121 for (int j=0; j<columns; j++) {
122 data[j] = new double[nb_rows];
123 for (int k=0; k<nb_rows; k++) {
124 data[j][k] = sd.data[j][k+st_row];
125 }
126 }
127
128 // initialize summarizing values
129 clear_all();
130 colFilled = sd.colFilled;
131 }
132
133 // overload =
134 CSAPI_TIER2 SegmentData&
operator =(const SegmentData & sd)135 SegmentData::operator=(const SegmentData& sd) {
136 if (this == &sd)
137 return *this;
138 starttime = sd.starttime;
139 endtime = sd.endtime;
140 columns = sd.columns;
141 rows = sd.rows;
142 id = sd.id;
143 flag = sd.flag;
144 conf = sd.conf;
145 // delete previously stored data
146 if (data != NULL) {
147 for (int i=0; i<columns; i++)
148 delete[] data[i];
149 delete[] data;
150 }
151 data = new double*[columns];
152 for (int i=0; i<columns; i++) {
153 data[i] = new double[rows];
154 for (int j=0; j<rows; j++) {
155 data[i][j] = sd.data[i][j];
156 }
157 }
158
159 // initialize summarizing values
160 clear_all();
161 colFilled = sd.colFilled;
162
163 return *this;
164 }
165
166
167 // overload friend operator <<
168 // main usage: debugging
169 CSAPI_TIER2 ostream&
operator <<(ostream & os,const SegmentData & sd)170 operator<<(ostream& os, const SegmentData& sd) {
171 // print all contained data
172 cout << "Start: " << sd.start() << endl;
173 cout << "End: " << sd.end() << endl;
174 cout << "ID=" << sd.ident() << "\tflag=" << sd.uflag() << endl;
175 cout << "Confidence=" << sd.confidence() << endl;
176 cout << "Columns=" << sd.no_columns() << "\tRows=" << sd.no_rows() << endl;
177 cout << "Filled until column: " << sd.col_filled() << endl;
178 // os << "Start: " << sd.start() << endl;
179 // os << "End: " << sd.end() << endl;
180 // os << "ID=" << sd.ident() << "\tflag=" << sd.uflag() << endl;
181 // os << "Confidence=" << sd.confidence() << endl;
182 // os << "Columns=" << sd.no_columns() << "\tRows=" << sd.no_rows() << endl;
183 // os << "Filled until column: " << sd.col_filled() << endl;
184 for (int i=0; i<sd.col_filled(); i++) {
185 cout << i << ":\t";
186 // os << i << ":\t";
187 for (int j=0; j<sd.no_rows(); j++) {
188 cout << sd.data[i][j] << " ";
189 // os << sd.data[i][j] << " ";
190 }
191 os << endl;
192 }
193 os << "--- END OF ENTRY ---" << endl;
194 return os;
195 }
196
197
198 // convert from a time to a colum number
199 CSAPI_TIER2 int
time2col(double time) const200 SegmentData::time2col(double time) const {
201 // assert that the time is between starttime and endtime
202 if (time <= starttime) return 0;
203 if (time >= endtime) return columns;
204 return (int) ((time - starttime)/resolution());
205 }
206
207
208 // sum a part of contained data
209 CSAPI_TIER2 double
sum(int start,int end,int startrow,int endrow)210 SegmentData::sum(int start, int end, int startrow, int endrow) {
211 if (start < 0) start = 0;
212 if (end < 0) end = 0;
213 if (start >= colFilled) start = colFilled - 1;
214 if (end >= colFilled) end = colFilled - 1;
215 if (startrow < 0) startrow = 0;
216 if (endrow < 0) endrow = 0;
217 if (startrow >= rows) startrow = rows-1;
218 if (endrow >= rows) endrow = rows-1;
219
220 double sum = 0.0;
221
222 for (int i=start; i<=end; i++) {
223 for (int j=startrow; j<=endrow; j++) {
224 sum += data[i][j];
225 }
226 }
227 return sum;
228 }
229
230
231 // minimum of contained data within start and end times
232 CSAPI_TIER2 double
smin(double start,double end,int startrow,int endrow)233 SegmentData::smin(double start, double end, int startrow, int endrow) {
234 double minimum = DBL_MAX;
235 if (start < starttime) start = starttime;
236 if (end > endtime) end = endtime;
237 if (startrow < 0) startrow = 0;
238 if (endrow < 0) endrow = 0;
239 if (startrow >= rows) startrow = rows-1;
240 if (endrow >= rows) endrow = rows-1;
241
242 // check whether min of all data is requested
243 if (start == starttime && end == endtime &&
244 startrow == 0 && endrow == rows-1) {
245 return smin();
246 }
247
248 int startcol = time2col(start);
249 int endcol = time2col(end);
250 if (colFilled < endcol) endcol = colFilled;
251
252 for (int i=startcol; i<endcol; i++) {
253 for (int j=startrow; j<=endrow; j++) {
254 if (data[i][j] < minimum) minimum = data[i][j];
255 }
256 }
257 return minimum;
258 }
259
260 // maximum of contained data within start and end times
261 CSAPI_TIER2 double
smax(double start,double end,int startrow,int endrow)262 SegmentData::smax(double start, double end, int startrow, int endrow) {
263 double maximum = DBL_MIN;
264 if (start < starttime) start = starttime;
265 if (end > endtime) end = endtime;
266 if (startrow < 0) startrow = 0;
267 if (endrow < 0) endrow = 0;
268 if (startrow >= rows) startrow = rows-1;
269 if (endrow >= rows) endrow = rows-1;
270
271 // check whether max of all data is requested
272 if (start == starttime && end == endtime &&
273 startrow == 0 && endrow == rows-1) {
274 return smax();
275 }
276
277 int startcol = time2col(start);
278 int endcol = time2col(end);
279 if (colFilled < endcol) endcol = colFilled;
280
281 for (int i=startcol; i<endcol; i++) {
282 for (int j=startrow; j<=endrow; j++) {
283 if (data[i][j] > maximum) maximum = data[i][j];
284 }
285 }
286 return maximum;
287 }
288
289 // mean of data within a part of the data
290 CSAPI_TIER2 double
avg(int start,int end,int startrow,int endrow)291 SegmentData::avg(int start, int end, int startrow, int endrow) {
292 if (start < 0) start = 0;
293 if (end < 0) end = 0;
294 if (start >= colFilled) start = colFilled - 1;
295 if (end >= colFilled) end = colFilled - 1;
296 if (startrow < 0) startrow = 0;
297 if (endrow < 0) endrow = 0;
298 if (startrow >= rows) startrow = rows-1;
299 if (endrow >= rows) endrow = rows-1;
300
301 int nb = (end - start + 1) * (endrow - startrow + 1);
302
303 return (sum(start, end, startrow, endrow)/nb);
304 }
305
306
307 /*--------------------- Tools for Normalisations --------------------*/
308
309 // sum of all contained data
310 CSAPI_TIER2 double
sum()311 SegmentData::sum() {
312 if (sum_save!=0.0) {
313 return sum_save;
314 }
315
316 // if not yet calculated, do that now
317 for (int i=0; i<colFilled; i++) {
318 for (int j=0; j<rows; j++) {
319 sum_save += data[i][j];
320 }
321 }
322 return sum_save;
323 }
324
325
326 // minimum of all contained data
327 CSAPI_TIER2 double
smin(double downto)328 SegmentData::smin(double downto) {
329
330 double * ptr;
331
332 if (min_save!=DBL_MAX) {
333 return min_save;
334 }
335
336 // if not yet calculated, do that now
337 for (int i=0; i<colFilled; i++) {
338 for (int j=0; j<rows; j++) {
339 ptr = &(data[i][j]);
340 if ((*ptr) < min_save && (*ptr) >= downto ) {
341 min_save = (*ptr);
342 }
343 }
344 }
345 return min_save;
346 }
347
348
349 // maximum of all contained data
350 CSAPI_TIER2 double
smax(double upto)351 SegmentData::smax(double upto) {
352
353 double * ptr;
354
355 if (max_save!=-DBL_MAX) {
356 return max_save;
357 }
358
359 // if not yet calculated, do that now
360 for (int i=0; i<colFilled; i++) {
361 for (int j=0; j<rows; j++) {
362 ptr = &(data[i][j]);
363 if ((*ptr) > max_save && (*ptr) <= upto ) {
364 max_save = (*ptr);
365 }
366 }
367 }
368 return max_save;
369 }
370
371
372 // mean of all contained data
373 CSAPI_TIER2 double
avg()374 SegmentData::avg() {
375 return (sum()/(colFilled*rows));
376 }
377
378 /*--------------------- Normalisation --------------------*/
379
380 // normalize data values to [0;1], clipping outside of [downto;upto]
381 CSAPI_TIER2 bool
normalise(double downto,double upto)382 SegmentData::normalise(double downto, double upto) {
383
384 double * ptr;
385
386 //initialising summarised values
387 clear_all();
388
389 // calculate factor for normalisation
390 double factor;
391 factor = smax(upto) - smin(downto);
392
393 // check if normalisation possible
394 if (factor <= 0.0) {
395 return false;
396 }
397
398 // perform normalisation
399 for (int i=0; i<colFilled; i++) {
400 for (int j=0; j<rows; j++) {
401 //pointer to the value to normalise
402 ptr = &(data[i][j]);
403 if ((*ptr) < downto) {
404 //clipping min
405 (*ptr) = 0.0;
406 } else if ((*ptr) > upto) {
407 //clipping max
408 (*ptr) = 1.0;
409 } else {
410 (*ptr) = ((*ptr) - min_save) / factor;
411 }
412 }
413 }
414
415 // initialize summarizing values
416 clear_all();
417
418 return true;
419 }
420
421
422 /*--------------------- Smoothing --------------------*/
423
424 // smoothes the data in time with a mean filter of the order order
425
426 CSAPI_TIER2 bool
smooth(int start,int end,int startrow,int endrow,int order)427 SegmentData::smooth(int start, int end, int startrow, int endrow, int order)
428 {
429
430 // cheching of input
431 if (start < 0) start = 0;
432 if (end < 0) end = 0;
433 if (start >= colFilled) start = colFilled - 1;
434 if (end >= colFilled) end = colFilled - 1;
435 if (startrow < 0) startrow = 0;
436 if (endrow < 0) endrow = 0;
437 if (startrow >= rows) startrow = rows-1;
438 if (endrow >= rows) endrow = rows-1;
439 if (order%2==0)
440 {
441 cerr << "order should be odd, it is now set to an odd value by adding 1" <<endl;
442 order += 1;
443 }
444
445
446 int bufferSize = colFilled;
447 int orderHalf;
448 double mean;
449 int i, n, j; //index variables
450 double *oldValues;
451
452 // initialisation
453 orderHalf = (int)(order/2);
454 oldValues = new double[orderHalf+1];
455
456 for (i=startrow; i<=endrow; i++) //loop over rows
457 {
458
459 memset (oldValues,0,(orderHalf+1)*sizeof(double));
460 mean = 0;
461
462 //calculation of first mean
463 for (n=0; n<=orderHalf; n++)
464 mean += data[n][i];
465 mean = mean / (orderHalf + 1);
466 oldValues[0] = data[0][i];
467 data[0][i] = mean;
468
469 //loop to calculate mean in the range of order for first values
470 for (n=1; n<(orderHalf+1); n++)
471 {
472 mean = (mean*(orderHalf+n) + data[n+orderHalf][i])/(orderHalf+n+1);
473 oldValues[n] = data[n][i];
474 data[n][i] = mean;
475 }
476
477 //loop for middle value
478 for (n=(orderHalf+1); n<(bufferSize-orderHalf); n++)
479 {
480 mean = (mean*order - oldValues[n%(orderHalf+1)] + data[n+orderHalf][i])/order;
481 oldValues[n%(orderHalf+1)] = data[n][i];
482 data[n][i] = mean;
483 }
484
485 //loop for last values
486 j = 0;
487 for (n=(bufferSize-orderHalf); n<bufferSize; n++)
488 {
489 mean = (mean*(order-j) - oldValues[n%(orderHalf+1)])/(order-j-1);
490 data[n][i] = mean;
491 j++;
492 }
493 } //end loop over rows
494
495 delete[] oldValues;
496
497 return true;
498
499 }
500
501 /*--------------------- MATLAB output --------------------*/
502
503 // saves the data in the MATLAB binary *.mat format
504
505 // view with plot(varName) for 1-dimensional curves (i.e. sscf)
506 // or imagesc(varName) for 2-dimensional data(i.e. sbmean)
507
508 CSAPI_TIER2 bool
matOut(char * fileName)509 SegmentData::matOut(char* fileName)
510 {
511
512 struct matHeader
513 {
514 signed int adf [4]; // Array data format fields
515 };
516
517
518 FILE *fd = 0; // File handler
519 struct matHeader hdr; // Header for MATLAB file
520 struct matHeader varHdr; // Header for additional Variables
521 char arrayName [64]; // MATLAB name of array
522 signed int nameLength = 0; // Number of bytes of arrayName in header
523 char varName [64]; // Name of additional Variables
524 signed int varNameLength = 0;
525 double sample = 0;
526
527 char matFileName [128]; // Name of output file, with or without path
528
529 unsigned long i, j, k; // Index variable
530
531 strncpy(matFileName, fileName, 128);
532 if ( strstr(matFileName, ".mat") == NULL)
533 strcat(matFileName, ".mat");
534
535 // Open mat-file
536 fd = fopen (matFileName, "w+b");
537
538 if (!fd)
539 {
540 cerr << "Can't create MAT file " << matFileName <<endl;
541 cerr << "Filename default.mat is used instead" <<endl;
542 strncpy("default.mat", matFileName, 128);
543 for (i=11;i<128;i++) matFileName[i] = ' ';
544 fd = fopen (matFileName, "w+b");
545 }
546
547 // Header Field for Array Dimensions
548 hdr.adf[0] = (signed int) 0;
549 hdr.adf[1] = (signed int) rows; // This is the number of rows
550 hdr.adf[2] = (signed int) columns; // This is the number of columns
551 hdr.adf[3] = (signed int) 0;
552
553 // Array Name
554 // We'll use matFileName for the matlab array name (as well as the file name).
555 // If fileName is 4 characters or less, empty space will be added
556 nameLength = (signed int)strlen(matFileName);
557 if (strstr(matFileName,".mat"))
558 nameLength -=4;
559 if (nameLength > 31)
560 nameLength = 31; // Truncate name to 31 characters
561 strncpy (arrayName, matFileName, nameLength);
562
563 if (nameLength < 4) // Addition of empty space
564 {
565 for (i=nameLength; i<4; i++)
566 {
567 arrayName[i] = 0;
568 nameLength++;
569 }
570 }
571 arrayName [nameLength++] = '\0';
572
573 // Write the header
574 if (fwrite (&hdr, 16, 1, fd) != 1)
575 {
576 cerr << "Error writing to file " << matFileName <<endl;
577 return false;
578 }
579
580 // Write MATLAB array name
581 if (fwrite (&nameLength, 4, 1, fd) != 1)
582 {
583 cerr << "Error writing to file " << matFileName <<endl;
584 return false;
585 }
586 if (fwrite (arrayName, nameLength, 1, fd) != 1)
587 {
588 cerr << "Error writing to file " << matFileName <<endl;
589 return false;
590 }
591
592 cout << "Creating MAT-file containing MATLAB array " << arrayName <<endl;
593
594 // Write data
595 for (k=0; k<colFilled; k++)
596 {
597 for (j=0; j<rows; j++)
598 {
599 sample = data[k][j];
600 if (fwrite (&sample, 8, 1, fd) != 1)
601 {
602 cerr << "Error writing to file " << matFileName <<endl;
603 return false;
604 }
605 }
606
607 }
608
609 // Write Resolution in mat-file
610
611 // Header Field for Resolution
612 varHdr.adf[0] = (signed int) 0;
613 varHdr.adf[1] = (signed int) 1; // This is the number of rows
614 varHdr.adf[2] = (signed int) 1; // This is the number of columns
615 varHdr.adf[3] = (signed int) 0;
616
617 char tmp1 [64] = "resolution";
618 varNameLength = 10;
619 strncpy (varName, tmp1, varNameLength);
620 varName [varNameLength++] = 0;
621
622 // Write the header
623 if (fwrite (&varHdr, 16, 1, fd) != 1)
624 {
625 cerr << "Error writing to file " << matFileName <<endl;
626 return false;
627 }
628
629 // Write Variable name
630 if (fwrite (&varNameLength, 4, 1, fd) != 1)
631 {
632 cerr << "Error writing to file " << matFileName <<endl;
633 return false;
634 }
635 if (fwrite (varName, varNameLength, 1, fd) != 1)
636 {
637 cerr << "Error writing to file " << matFileName <<endl;
638 return false;
639 }
640
641 // Write Variable Value
642 sample = resolution();
643 if (fwrite (&sample, 8, 1, fd) != 1)
644 {
645 cerr << "Error writing to file " << matFileName <<endl;
646 return false;
647 }
648
649 // Write Resolution in mat-file
650
651 // Header Field for Resolution
652 varHdr.adf[0] = (signed int) 0;
653 varHdr.adf[1] = (signed int) 1; // This is the number of rows
654 varHdr.adf[2] = (signed int) 1; // This is the number of columns
655 varHdr.adf[3] = (signed int) 0;
656
657 char tmp2 [64] = "startTime";
658 varNameLength = 9;
659 strncpy (varName, tmp2, varNameLength);
660 varName [varNameLength++] = 0;
661
662 // Write the header
663 if (fwrite (&varHdr, 16, 1, fd) != 1)
664 {
665 cerr << "Error writing to file " << matFileName <<endl;
666 return false;
667 }
668
669 // Write Variable name
670 if (fwrite (&varNameLength, 4, 1, fd) != 1)
671 {
672 cerr << "Error writing to file " << matFileName <<endl;
673 return false;
674 }
675 if (fwrite (varName, varNameLength, 1, fd) != 1)
676 {
677 cerr << "Error writing to file " << matFileName <<endl;
678 return false;
679 }
680
681 // Write Variable Value
682 sample = starttime;
683 if (fwrite (&sample, 8, 1, fd) != 1)
684 {
685 cerr << "Error writing to file " << matFileName <<endl;
686 return false;
687 }
688
689 // Write EndTime in mat-file
690
691 // Header Field for Resolution
692 varHdr.adf[0] = (signed int) 0;
693 varHdr.adf[1] = (signed int) 1; // This is the number of rows
694 varHdr.adf[2] = (signed int) 1; // This is the number of columns
695 varHdr.adf[3] = (signed int) 0;
696
697 char tmp3 [64] = "endTime";
698 varNameLength = 7;
699 strncpy (varName, tmp3, varNameLength);
700 varName [varNameLength++] = 0;
701
702 // Write the header
703 if (fwrite (&varHdr, 16, 1, fd) != 1)
704 {
705 cerr << "Error writing to file " << matFileName <<endl;
706 return false;
707 }
708
709 // Write Variable name
710 if (fwrite (&varNameLength, 4, 1, fd) != 1)
711 {
712 cerr << "Error writing to file " << matFileName <<endl;
713 return false;
714 }
715 if (fwrite (varName, varNameLength, 1, fd) != 1)
716 {
717 cerr << "Error writing to file " << matFileName <<endl;
718 return false;
719 }
720
721 // Write Variable Value
722 sample = endtime;
723 if (fwrite (&sample, 8, 1, fd) != 1)
724 {
725 cerr << "Error writing to file " << matFileName <<endl;
726 return false;
727 }
728
729 fclose (fd);
730
731 return true;
732
733 }
734
735 /*------------------- Initialisation ------------------*/
736
737 CSAPI_TIER2 void
initData(double val)738 SegmentData::initData (double val) {
739 // initialize data values to val
740 for (int i=0; i<columns; i++) {
741 for (int j=0; j<rows; j++) {
742 data[i][j] = val;
743 }
744 }
745
746 return;
747 }
748