Edinburgh Speech Tools  2.4-release
 All Classes Functions Variables Typedefs Enumerations Enumerator Friends Pages
delta.cc
1 /*************************************************************************/
2 /* */
3 /* Centre for Speech Technology Research */
4 /* University of Edinburgh, UK */
5 /* Copyright (c) 1995,1996 */
6 /* All Rights Reserved. */
7 /* */
8 /* Permission is hereby granted, free of charge, to use and distribute */
9 /* this software and its documentation without restriction, including */
10 /* without limitation the rights to use, copy, modify, merge, publish, */
11 /* distribute, sublicense, and/or sell copies of this work, and to */
12 /* permit persons to whom this work is furnished to do so, subject to */
13 /* the following conditions: */
14 /* 1. The code must retain the above copyright notice, this list of */
15 /* conditions and the following disclaimer. */
16 /* 2. Any modifications must be clearly marked as such. */
17 /* 3. Original authors' names are not deleted. */
18 /* 4. The authors' names are not used to endorse or promote products */
19 /* derived from this software without specific prior written */
20 /* permission. */
21 /* */
22 /* THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK */
23 /* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
24 /* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
25 /* SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE */
26 /* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
27 /* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
28 /* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
29 /* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
30 /* THIS SOFTWARE. */
31 /* */
32 /*************************************************************************/
33 /* Author : Simon King */
34 /* Date : July 1995 */
35 /*-----------------------------------------------------------------------*/
36 /* Compute delta coefficients for */
37 /* Tracks and Tracks */
38 /* */
39 /*=======================================================================*/
40 #include <cstdlib>
41 #include "EST_Track.h"
42 #include "EST_Wave.h"
43 # define MAX_DELTA_ORDER 2
44 /// max. number of points on which the delta co-eff is based
45 # define MAX_REGRESSION_LENGTH 4
46 
47 static float compute_gradient(const EST_FVector &x, int num_points);
48 
49 void delta(EST_Track &tr, EST_Track &d, int regression_length)
50 {
51  int reg_index, this_index;
52 
53  // need at least two points to compute gradient
54  if ((regression_length < 2)||(regression_length > MAX_REGRESSION_LENGTH)){
55  cerr << "delta(EST_Track&, int) : ERROR : regression_length is "
56  << regression_length << endl;
57  exit(0);
58  }
59 
60  // temp stores the points passed to compute_gradient
61  EST_FVector temp(regression_length);
62 
63  for (int j = 0; j < tr.num_channels(); j++ )
64  for (int i = 0; i < tr.num_frames(); i++)
65  {
66  // copy values needed to compute gradient into temp[]
67  for (reg_index=0; reg_index<regression_length; reg_index++)
68  {
69  // gradient is computed from points to left of current time
70  // rather than points centred around the current time
71  this_index = i - reg_index;
72  if (this_index >= 0)
73  temp[reg_index] = tr.a(this_index, j);
74  }
75 
76  // gradient at frame 0 is defined as 0
77  if (i < 1)
78  d.a(i, j) = 0.0;
79  else if (i < regression_length - 1)
80  // enough data, but would prefer more
81  // number of points available is only i+1
82  d.a(i, j) = compute_gradient(temp, i + 1);
83  else
84  // plenty of data, use the last regression_length points
85  d.a(i, j) = compute_gradient(temp, regression_length);
86  }
87 }
88 
89 void delta(EST_Wave &tr, EST_Wave &d, int regression_length)
90 {
91  int reg_index, this_index;
92 
93  // need at least two points to compute gradient
94  if ((regression_length < 2)||(regression_length > MAX_REGRESSION_LENGTH)){
95  cerr << "delta(EST_Track&, int) : ERROR : regression_length is "
96  << regression_length << endl;
97  exit(0);
98  }
99 
100  // temp stores the points passed to compute_gradient
101  EST_FVector temp(regression_length);
102 
103  for (int j = 0; j < tr.num_channels(); j++ )
104  for (int i = 0; i < tr.num_samples(); i++)
105  {
106  // copy values needed to compute gradient into temp[]
107  for (reg_index=0; reg_index<regression_length; reg_index++)
108  {
109  // gradient is computed from points to left of current time
110  // rather than points centred around the current time
111  this_index = i - reg_index;
112  if (this_index >= 0)
113  temp.a_no_check(reg_index) = (float)tr.a(this_index, j);
114  }
115 
116  // gradient at frame 0 is defined as 0
117  if (i < 1)
118  d.a(i, j) = 0;
119  else if (i < regression_length - 1)
120  // enough data, but would prefer more
121  // number of points available is only i+1
122  d.a(i, j) = (short)compute_gradient(temp, i + 1);
123  else
124  // plenty of data, use the last regression_length points
125  d.a(i, j) = (short)compute_gradient(temp, regression_length);
126  }
127 }
128 
129 static float compute_gradient(const EST_FVector &x, int num_points)
130 {
131  float gradient;
132 
133  // NB x[0] is the point LATEST in time
134  // so x[1] is really x[t-1]
135 
136  // time between points is assumed to be one unit
137 
138  // These are solutions to least-squares fit of straight line
139  // to num_points points.
140  switch (num_points){
141 
142  case 1:
143  gradient = 0.0;
144  break;
145 
146  case 2:
147  gradient = x(0) - x(1);
148  break;
149 
150  case 3:
151  gradient = (x(0) -x(2)) / 2.0;
152  break;
153 
154  case 4:
155  gradient = ( (3.0*x(0)) + x(1) - x(2) - (3.0 * x(3)) ) / 10.0;
156  break;
157 
158  default:
159 
160  cerr << "compute_gradient(float*, int) : ERROR : num_points is"
161  << num_points << endl;
162 
163  exit(0);
164  break;
165  }
166 
167  return gradient;
168 }
169