Mercurial > hg > audiostuff
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 ------------------------------------------------------------*/ |