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 ------------------------------------------------------------*/ | 
