comparison spandsp-0.0.3/spandsp-0.0.3/src/lpc10_placev.c @ 5:f762bf195c4b

import spandsp-0.0.3
author Peter Meerwald <pmeerw@cosy.sbg.ac.at>
date Fri, 25 Jun 2010 16:00:21 +0200
parents
children
comparison
equal deleted inserted replaced
4:26cd8f1ef0b1 5:f762bf195c4b
1 /*
2 * SpanDSP - a series of DSP components for telephony
3 *
4 * lpc10_placev.c - LPC10 low bit rate speech codec.
5 *
6 * Written by Steve Underwood <steveu@coppice.org>
7 *
8 * Copyright (C) 2006 Steve Underwood
9 *
10 * All rights reserved.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2, as
14 * published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 * This code is based on the U.S. Department of Defense reference
26 * implementation of the LPC-10 2400 bps Voice Coder. They do not
27 * exert copyright claims on their code, and it may be freely used.
28 *
29 * $Id: lpc10_placev.c,v 1.11 2006/11/21 13:32:27 steveu Exp $
30 */
31
32 #ifdef HAVE_CONFIG_H
33 #include <config.h>
34 #endif
35
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <inttypes.h>
39 #include <memory.h>
40 #if defined(HAVE_TGMATH_H)
41 #include <tgmath.h>
42 #endif
43 #if defined(HAVE_MATH_H)
44 #include <math.h>
45 #endif
46
47 #include "spandsp/telephony.h"
48 #include "spandsp/dc_restore.h"
49 #include "spandsp/lpc10.h"
50
51 #include "lpc10_encdecs.h"
52
53 #define subsc(x,y) (((x) << 1) + (y))
54
55 void lpc10_placea(int32_t *ipitch,
56 int32_t voibuf[3][2],
57 int32_t *obound,
58 int32_t af,
59 int32_t vwin[3][2],
60 int32_t awin[3][2],
61 int32_t ewin[3][2],
62 int32_t lframe,
63 int32_t maxwin)
64 {
65 int allv;
66 int winv;
67 int32_t i;
68 int32_t j;
69 int32_t k;
70 int32_t l;
71 int32_t hrange;
72 int ephase;
73 int32_t lrange;
74
75 lrange = (af - 2)*lframe + 1;
76 hrange = af*lframe;
77
78 /* Place the analysis window based on the voicing window placement,
79 onsets, tentative voicing decision, and pitch. */
80
81 /* Case 1: Sustained voiced speech
82 If the five most recent voicing decisions are
83 voiced, then the window is placed phase-synchronously with the
84 previous window, as close to the present voicing window if possible.
85 If onsets bound the voicing window, then preference is given to
86 a phase-synchronous placement which does not overlap these onsets. */
87
88 /* Case 2: Voiced transition
89 If at least one voicing decision in AF is voicied, and there are no
90 onsets, then the window is placed as in case 1. */
91
92 /* Case 3: Unvoiced speech or onsets
93 If both voicing decisions in AF are unvoiced, or there are onsets
94 then the window is placed coincident with the voicing window. */
95
96 /* Note: During phase-synchronous placement of windows, the length
97 is not altered from MAXWIN, since this would defeat the purpose
98 of phase-synchronous placement. */
99
100 /* Check for case 1 and case 2 */
101 allv = voibuf[af - 2][1] == 1
102 &&
103 voibuf[af - 1][0] == 1
104 &&
105 voibuf[af - 1][1] == 1
106 &&
107 voibuf[af][0] == 1
108 &&
109 voibuf[af][1] == 1;
110 winv = voibuf[af][0] == 1 || voibuf[af][1] == 1;
111 if (allv || (winv && *obound == 0))
112 {
113 /* APHASE: Phase synchronous window placement. */
114 /* Get minimum lower index of the window. */
115 i = (lrange + *ipitch - 1 - awin[af - 2][0]) / *ipitch;
116 i *= *ipitch;
117 i += awin[af - 2][0];
118 /* l = the actual length of this frame's analysis window. */
119 l = maxwin;
120 /* Calculate the location where a perfectly centered window would start. */
121 k = (vwin[af - 1][0] + vwin[af - 1][1] + 1 - l)/2;
122 /* Choose the actual location to be the pitch multiple closest to this */
123 awin[af - 1][0] = i + lroundf((float) (k - i) / (float) *ipitch) * *ipitch;
124 awin[af - 1][1] = awin[af - 1][0] + l - 1;
125 /* If there is an onset bounding the right of the voicing window and the
126 analysis window overlaps that, then move the analysis window backward
127 to avoid this onset. */
128 if (*obound >= 2 && awin[af - 1][1] > vwin[af - 1][1])
129 {
130 awin[af - 1][0] -= *ipitch;
131 awin[af - 1][1] -= *ipitch;
132 }
133 /* Similarly for the left of the voicing window. */
134 if ((*obound == 1 || *obound == 3) && awin[af - 1][0] < vwin[af - 1][0])
135 {
136 awin[af - 1][0] += *ipitch;
137 awin[af - 1][1] += *ipitch;
138 }
139 /* If this placement puts the analysis window above HRANGE, then
140 move it backward an integer number of pitch periods. */
141 while (awin[af - 1][1] > hrange)
142 {
143 awin[af - 1][0] -= *ipitch;
144 awin[af - 1][1] -= *ipitch;
145 }
146 /* Similarly if the placement puts the analysis window below LRANGE. */
147 while (awin[af - 1][0] < lrange)
148 {
149 awin[af - 1][0] += *ipitch;
150 awin[af - 1][1] += *ipitch;
151 }
152 /* Make energy window be phase-synchronous. */
153 ephase = TRUE;
154 }
155 else
156 {
157 /* Case 3 */
158 awin[af - 1][0] = vwin[af - 1][0];
159 awin[af - 1][1] = vwin[af - 1][1];
160 ephase = FALSE;
161 }
162 /* RMS is computed over an integer number of pitch periods in the analysis
163 window. When it is not placed phase-synchronously, it is placed as close
164 as possible to onsets. */
165 j = (awin[af - 1][1] - awin[af - 1][0] + 1) / *ipitch * *ipitch;
166 if (j == 0 || !winv)
167 {
168 ewin[af - 1][0] = vwin[af - 1][0];
169 ewin[af - 1][1] = vwin[af - 1][1];
170 }
171 else if (!ephase && *obound == 2)
172 {
173 ewin[af - 1][0] = awin[af - 1][1] - j + 1;
174 ewin[af - 1][1] = awin[af - 1][1];
175 }
176 else
177 {
178 ewin[af - 1][0] = awin[af - 1][0];
179 ewin[af - 1][1] = awin[af - 1][0] + j - 1;
180 }
181 }
182 /*- End of function --------------------------------------------------------*/
183
184 void lpc10_placev(int32_t *osbuf,
185 int32_t *osptr,
186 int32_t oslen,
187 int32_t *obound,
188 int32_t vwin[3][2],
189 int32_t af,
190 int32_t lframe,
191 int32_t minwin,
192 int32_t maxwin,
193 int32_t dvwinl,
194 int32_t dvwinh)
195 {
196 int32_t i1;
197 int32_t i2;
198 int crit;
199 int32_t q;
200 int32_t osptr1;
201 int32_t hrange;
202 int32_t lrange;
203 int i;
204
205 /* Voicing window placement */
206
207 /* __________________ __________________ ______________ */
208 /* | | | */
209 /* | 1F | 2F | 3F ... */
210 /* |__________________|__________________|______________ */
211
212 /* Previous | */
213 /* Window | */
214 /* ...________| */
215
216 /* | | */
217 /* ------>| This window's placement range |<------ */
218 /* | | */
219
220 /* There are three cases. Note these are different from those
221 given in the LPC-10e phase 1 report. */
222
223 /* 1. If there are no onsets in this range, then the voicing window
224 is centered in the pitch window. If such a placement is not within
225 the window's placement range, then the window is placed in the left-most
226 portion of the placement range. Its length is always MAXWIN. */
227
228 /* 2. If the first onset is in 2F and there is sufficient room to place
229 the window immediately before this onset, then the window is placed
230 there, and its length is set to the maximum possible under these
231 constraints. */
232
233 /* "Critical Region Exception": If there is another onset in 2F
234 such that a window can be placed between the two onsets, the
235 window is placed there (ie, as in case 3). */
236
237 /* 3. Otherwise, the window is placed immediately after the onset. The
238 window's length is the longest length that can fit in the range under these
239 constraints, except that the window may be shortened even further to avoid
240 overlapping other onsets in the placement range. In any case, the window's
241 length is at least MINWIN. */
242
243 /* Note that the values of MINWIN and LFRAME must be chosen such
244 that case 2 = false implies case 3 = true. This means that
245 MINWIN <= LFRAME/2. If this were not the case, then a fourth case
246 would have to be added for when the window cannot fit either before
247 or after the onset. */
248
249 /* Note also that onsets which weren't in 2F last time may be in 1F this
250 time, due to the filter delays in computing onsets. The result is that
251 occasionally a voicing window will overlap that onset. The only way
252 to circumvent this problem is to add more delay in processing input
253 speech. In the trade-off between delay and window-placement, window
254 placement lost. */
255
256 /* Compute the placement range */
257
258 /* Computing MAX */
259 i1 = vwin[af - 2][1] + 1;
260 i2 = (af - 2)*lframe + 1;
261 lrange = max(i1, i2);
262 hrange = af*lframe;
263 /* Compute OSPTR1, so the following code only looks at relevant onsets. */
264 for (osptr1 = *osptr - 1; osptr1 >= 1; osptr1--)
265 {
266 if (osbuf[osptr1 - 1] <= hrange)
267 break;
268 }
269 osptr1++;
270 /* Check for case 1 first (fast case) */
271 if (osptr1 <= 1 || osbuf[osptr1 - 2] < lrange)
272 {
273 /* Compute max */
274 i1 = vwin[af - 2][1] + 1;
275 vwin[af - 1][0] = max(i1, dvwinl);
276 vwin[af - 1][1] = vwin[af - 1][0] + maxwin - 1;
277 *obound = 0;
278 }
279 else
280 {
281 /* Search backward in OSBUF for first onset in range. */
282 /* This code relies on the above check being performed first. */
283 for (q = osptr1 - 1; q >= 1; q--)
284 {
285 if (osbuf[q - 1] < lrange)
286 break;
287 }
288 q++;
289 /* Check for case 2 (placement before onset): */
290 /* Check for critical region exception: */
291 crit = FALSE;
292 for (i = q + 1; i < osptr1; i++)
293 {
294 if (osbuf[i - 1] - osbuf[q - 1] >= minwin)
295 {
296 crit = TRUE;
297 break;
298 }
299 }
300 /* Compute max */
301 i1 = (af - 1)*lframe;
302 i2 = lrange + minwin - 1;
303 if (!crit && osbuf[q - 1] > max(i1, i2))
304 {
305 vwin[af - 1][1] = osbuf[q - 1] - 1;
306 /* Compute max */
307 i2 = vwin[af - 1][1] - maxwin + 1;
308 vwin[af - 1][0] = max(lrange, i2);
309 *obound = 2;
310 }
311 else
312 {
313 /* Case 3 (placement after onset) */
314 vwin[af - 1][0] = osbuf[q - 1];
315 do
316 {
317 if (++q >= osptr1
318 ||
319 osbuf[q - 1] > vwin[af - 1][0] + maxwin)
320 {
321 /* Compute min */
322 i1 = vwin[af - 1][0] + maxwin - 1;
323 vwin[af - 1][1] = min(i1, hrange);
324 *obound = 1;
325 return;
326 }
327 }
328 while (osbuf[q - 1] < vwin[af - 1][0] + minwin);
329 vwin[af - 1][1] = osbuf[q - 1] - 1;
330 *obound = 3;
331 }
332 }
333 }
334 /*- End of function --------------------------------------------------------*/
335 /*- End of file ------------------------------------------------------------*/

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.