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