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