comparison spandsp-0.0.6pre17/src/lpc10_placev.c @ 4:26cd8f1ef0b1

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

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