OLD | NEW |
(Empty) | |
| 1 /* Copyright (C) 2002-2006 Jean-Marc Valin |
| 2 File: nb_celp.c |
| 3 |
| 4 Redistribution and use in source and binary forms, with or without |
| 5 modification, are permitted provided that the following conditions |
| 6 are met: |
| 7 |
| 8 - Redistributions of source code must retain the above copyright |
| 9 notice, this list of conditions and the following disclaimer. |
| 10 |
| 11 - Redistributions in binary form must reproduce the above copyright |
| 12 notice, this list of conditions and the following disclaimer in the |
| 13 documentation and/or other materials provided with the distribution. |
| 14 |
| 15 - Neither the name of the Xiph.org Foundation nor the names of its |
| 16 contributors may be used to endorse or promote products derived from |
| 17 this software without specific prior written permission. |
| 18 |
| 19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 20 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 21 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 22 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR |
| 23 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| 24 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| 25 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| 26 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
| 27 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| 28 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| 29 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 30 */ |
| 31 |
| 32 #ifdef HAVE_CONFIG_H |
| 33 #include "config.h" |
| 34 #endif |
| 35 |
| 36 #include <math.h> |
| 37 #include "nb_celp.h" |
| 38 #include "lpc.h" |
| 39 #include "lsp.h" |
| 40 #include "ltp.h" |
| 41 #include "quant_lsp.h" |
| 42 #include "cb_search.h" |
| 43 #include "filters.h" |
| 44 #include "stack_alloc.h" |
| 45 #include "vq.h" |
| 46 #include <speex/speex_bits.h> |
| 47 #include "vbr.h" |
| 48 #include "arch.h" |
| 49 #include "math_approx.h" |
| 50 #include "os_support.h" |
| 51 #include <speex/speex_callbacks.h> |
| 52 |
| 53 #ifdef VORBIS_PSYCHO |
| 54 #include "vorbis_psy.h" |
| 55 #endif |
| 56 |
| 57 #ifndef M_PI |
| 58 #define M_PI 3.14159265358979323846 /* pi */ |
| 59 #endif |
| 60 |
| 61 #ifndef NULL |
| 62 #define NULL 0 |
| 63 #endif |
| 64 |
| 65 #define SUBMODE(x) st->submodes[st->submodeID]->x |
| 66 |
| 67 /* Default size for the encoder and decoder stack (can be changed at compile tim
e). |
| 68 This does not apply when using variable-size arrays or alloca. */ |
| 69 #ifndef NB_ENC_STACK |
| 70 #define NB_ENC_STACK (8000*sizeof(spx_sig_t)) |
| 71 #endif |
| 72 |
| 73 #ifndef NB_DEC_STACK |
| 74 #define NB_DEC_STACK (4000*sizeof(spx_sig_t)) |
| 75 #endif |
| 76 |
| 77 |
| 78 #ifdef FIXED_POINT |
| 79 const spx_word32_t ol_gain_table[32]={18900, 25150, 33468, 44536, 59265, 78865,
104946, 139653, 185838, 247297, 329081, 437913, 582736, 775454, 1031906, 1373169
, 1827293, 2431601, 3235761, 4305867, 5729870, 7624808, 10146425, 13501971, 1796
7238, 23909222, 31816294, 42338330, 56340132, 74972501, 99766822, 132760927}; |
| 80 const spx_word16_t exc_gain_quant_scal3_bound[7]={1841, 3883, 6051, 8062, 10444,
13580, 18560}; |
| 81 const spx_word16_t exc_gain_quant_scal3[8]={1002, 2680, 5086, 7016, 9108, 11781,
15380, 21740}; |
| 82 const spx_word16_t exc_gain_quant_scal1_bound[1]={14385}; |
| 83 const spx_word16_t exc_gain_quant_scal1[2]={11546, 17224}; |
| 84 |
| 85 #define LSP_MARGIN 16 |
| 86 #define LSP_DELTA1 6553 |
| 87 #define LSP_DELTA2 1638 |
| 88 |
| 89 #else |
| 90 |
| 91 const float exc_gain_quant_scal3_bound[7]={0.112338f, 0.236980f, 0.369316f, 0.49
2054f, 0.637471f, 0.828874f, 1.132784f}; |
| 92 const float exc_gain_quant_scal3[8]={0.061130f, 0.163546f, 0.310413f, 0.428220f,
0.555887f, 0.719055f, 0.938694f, 1.326874f}; |
| 93 const float exc_gain_quant_scal1_bound[1]={0.87798f}; |
| 94 const float exc_gain_quant_scal1[2]={0.70469f, 1.05127f}; |
| 95 |
| 96 #define LSP_MARGIN .002f |
| 97 #define LSP_DELTA1 .2f |
| 98 #define LSP_DELTA2 .05f |
| 99 |
| 100 #endif |
| 101 |
| 102 #ifdef VORBIS_PSYCHO |
| 103 #define EXTRA_BUFFER 100 |
| 104 #else |
| 105 #define EXTRA_BUFFER 0 |
| 106 #endif |
| 107 |
| 108 |
| 109 #define sqr(x) ((x)*(x)) |
| 110 |
| 111 extern const spx_word16_t lag_window[]; |
| 112 extern const spx_word16_t lpc_window[]; |
| 113 |
| 114 void *nb_encoder_init(const SpeexMode *m) |
| 115 { |
| 116 EncState *st; |
| 117 const SpeexNBMode *mode; |
| 118 int i; |
| 119 |
| 120 mode=(const SpeexNBMode *)m->mode; |
| 121 st = (EncState*)speex_alloc(sizeof(EncState)); |
| 122 if (!st) |
| 123 return NULL; |
| 124 #if defined(VAR_ARRAYS) || defined (USE_ALLOCA) |
| 125 st->stack = NULL; |
| 126 #else |
| 127 st->stack = (char*)speex_alloc_scratch(NB_ENC_STACK); |
| 128 #endif |
| 129 |
| 130 st->mode=m; |
| 131 |
| 132 st->frameSize = mode->frameSize; |
| 133 st->nbSubframes=mode->frameSize/mode->subframeSize; |
| 134 st->subframeSize=mode->subframeSize; |
| 135 st->windowSize = st->frameSize+st->subframeSize; |
| 136 st->lpcSize = mode->lpcSize; |
| 137 st->gamma1=mode->gamma1; |
| 138 st->gamma2=mode->gamma2; |
| 139 st->min_pitch=mode->pitchStart; |
| 140 st->max_pitch=mode->pitchEnd; |
| 141 st->lpc_floor = mode->lpc_floor; |
| 142 |
| 143 st->submodes=mode->submodes; |
| 144 st->submodeID=st->submodeSelect=mode->defaultSubmode; |
| 145 st->bounded_pitch = 1; |
| 146 |
| 147 st->encode_submode = 1; |
| 148 |
| 149 #ifdef VORBIS_PSYCHO |
| 150 st->psy = vorbis_psy_init(8000, 256); |
| 151 st->curve = (float*)speex_alloc(128*sizeof(float)); |
| 152 st->old_curve = (float*)speex_alloc(128*sizeof(float)); |
| 153 st->psy_window = (float*)speex_alloc(256*sizeof(float)); |
| 154 #endif |
| 155 |
| 156 st->cumul_gain = 1024; |
| 157 |
| 158 /* Allocating input buffer */ |
| 159 st->winBuf = (spx_word16_t*)speex_alloc((st->windowSize-st->frameSize)*sizeof
(spx_word16_t)); |
| 160 /* Allocating excitation buffer */ |
| 161 st->excBuf = (spx_word16_t*)speex_alloc((mode->frameSize+mode->pitchEnd+2)*si
zeof(spx_word16_t)); |
| 162 st->exc = st->excBuf + mode->pitchEnd + 2; |
| 163 st->swBuf = (spx_word16_t*)speex_alloc((mode->frameSize+mode->pitchEnd+2)*siz
eof(spx_word16_t)); |
| 164 st->sw = st->swBuf + mode->pitchEnd + 2; |
| 165 |
| 166 st->window= lpc_window; |
| 167 |
| 168 /* Create the window for autocorrelation (lag-windowing) */ |
| 169 st->lagWindow = lag_window; |
| 170 |
| 171 st->old_lsp = (spx_lsp_t*)speex_alloc((st->lpcSize)*sizeof(spx_lsp_t)); |
| 172 st->old_qlsp = (spx_lsp_t*)speex_alloc((st->lpcSize)*sizeof(spx_lsp_t)); |
| 173 st->first = 1; |
| 174 for (i=0;i<st->lpcSize;i++) |
| 175 st->old_lsp[i]= DIV32(MULT16_16(QCONST16(3.1415927f, LSP_SHIFT), i+1), st-
>lpcSize+1); |
| 176 |
| 177 st->mem_sp = (spx_mem_t*)speex_alloc((st->lpcSize)*sizeof(spx_mem_t)); |
| 178 st->mem_sw = (spx_mem_t*)speex_alloc((st->lpcSize)*sizeof(spx_mem_t)); |
| 179 st->mem_sw_whole = (spx_mem_t*)speex_alloc((st->lpcSize)*sizeof(spx_mem_t)); |
| 180 st->mem_exc = (spx_mem_t*)speex_alloc((st->lpcSize)*sizeof(spx_mem_t)); |
| 181 st->mem_exc2 = (spx_mem_t*)speex_alloc((st->lpcSize)*sizeof(spx_mem_t)); |
| 182 |
| 183 st->pi_gain = (spx_word32_t*)speex_alloc((st->nbSubframes)*sizeof(spx_word32_
t)); |
| 184 st->innov_rms_save = NULL; |
| 185 |
| 186 st->pitch = (int*)speex_alloc((st->nbSubframes)*sizeof(int)); |
| 187 |
| 188 #ifndef DISABLE_VBR |
| 189 st->vbr = (VBRState*)speex_alloc(sizeof(VBRState)); |
| 190 vbr_init(st->vbr); |
| 191 st->vbr_quality = 8; |
| 192 st->vbr_enabled = 0; |
| 193 st->vbr_max = 0; |
| 194 st->vad_enabled = 0; |
| 195 st->dtx_enabled = 0; |
| 196 st->dtx_count=0; |
| 197 st->abr_enabled = 0; |
| 198 st->abr_drift = 0; |
| 199 st->abr_drift2 = 0; |
| 200 #endif /* #ifndef DISABLE_VBR */ |
| 201 |
| 202 st->plc_tuning = 2; |
| 203 st->complexity=2; |
| 204 st->sampling_rate=8000; |
| 205 st->isWideband = 0; |
| 206 st->highpass_enabled = 1; |
| 207 |
| 208 #ifdef ENABLE_VALGRIND |
| 209 VALGRIND_MAKE_READABLE(st, NB_ENC_STACK); |
| 210 #endif |
| 211 return st; |
| 212 } |
| 213 |
| 214 void nb_encoder_destroy(void *state) |
| 215 { |
| 216 EncState *st=(EncState *)state; |
| 217 /* Free all allocated memory */ |
| 218 #if !(defined(VAR_ARRAYS) || defined (USE_ALLOCA)) |
| 219 speex_free_scratch(st->stack); |
| 220 #endif |
| 221 |
| 222 speex_free (st->winBuf); |
| 223 speex_free (st->excBuf); |
| 224 speex_free (st->old_qlsp); |
| 225 speex_free (st->swBuf); |
| 226 |
| 227 speex_free (st->old_lsp); |
| 228 speex_free (st->mem_sp); |
| 229 speex_free (st->mem_sw); |
| 230 speex_free (st->mem_sw_whole); |
| 231 speex_free (st->mem_exc); |
| 232 speex_free (st->mem_exc2); |
| 233 speex_free (st->pi_gain); |
| 234 speex_free (st->pitch); |
| 235 |
| 236 #ifndef DISABLE_VBR |
| 237 vbr_destroy(st->vbr); |
| 238 speex_free (st->vbr); |
| 239 #endif /* #ifndef DISABLE_VBR */ |
| 240 |
| 241 #ifdef VORBIS_PSYCHO |
| 242 vorbis_psy_destroy(st->psy); |
| 243 speex_free (st->curve); |
| 244 speex_free (st->old_curve); |
| 245 speex_free (st->psy_window); |
| 246 #endif |
| 247 |
| 248 /*Free state memory... should be last*/ |
| 249 speex_free(st); |
| 250 } |
| 251 |
| 252 int nb_encode(void *state, void *vin, SpeexBits *bits) |
| 253 { |
| 254 EncState *st; |
| 255 int i, sub, roots; |
| 256 int ol_pitch; |
| 257 spx_word16_t ol_pitch_coef; |
| 258 spx_word32_t ol_gain; |
| 259 VARDECL(spx_word16_t *ringing); |
| 260 VARDECL(spx_word16_t *target); |
| 261 VARDECL(spx_sig_t *innov); |
| 262 VARDECL(spx_word32_t *exc32); |
| 263 VARDECL(spx_mem_t *mem); |
| 264 VARDECL(spx_coef_t *bw_lpc1); |
| 265 VARDECL(spx_coef_t *bw_lpc2); |
| 266 VARDECL(spx_coef_t *lpc); |
| 267 VARDECL(spx_lsp_t *lsp); |
| 268 VARDECL(spx_lsp_t *qlsp); |
| 269 VARDECL(spx_lsp_t *interp_lsp); |
| 270 VARDECL(spx_lsp_t *interp_qlsp); |
| 271 VARDECL(spx_coef_t *interp_lpc); |
| 272 VARDECL(spx_coef_t *interp_qlpc); |
| 273 char *stack; |
| 274 VARDECL(spx_word16_t *syn_resp); |
| 275 VARDECL(spx_word16_t *real_exc); |
| 276 |
| 277 spx_word32_t ener=0; |
| 278 spx_word16_t fine_gain; |
| 279 spx_word16_t *in = (spx_word16_t*)vin; |
| 280 |
| 281 st=(EncState *)state; |
| 282 stack=st->stack; |
| 283 |
| 284 ALLOC(lpc, st->lpcSize, spx_coef_t); |
| 285 ALLOC(bw_lpc1, st->lpcSize, spx_coef_t); |
| 286 ALLOC(bw_lpc2, st->lpcSize, spx_coef_t); |
| 287 ALLOC(lsp, st->lpcSize, spx_lsp_t); |
| 288 ALLOC(qlsp, st->lpcSize, spx_lsp_t); |
| 289 ALLOC(interp_lsp, st->lpcSize, spx_lsp_t); |
| 290 ALLOC(interp_qlsp, st->lpcSize, spx_lsp_t); |
| 291 ALLOC(interp_lpc, st->lpcSize, spx_coef_t); |
| 292 ALLOC(interp_qlpc, st->lpcSize, spx_coef_t); |
| 293 |
| 294 /* Move signals 1 frame towards the past */ |
| 295 SPEEX_MOVE(st->excBuf, st->excBuf+st->frameSize, st->max_pitch+2); |
| 296 SPEEX_MOVE(st->swBuf, st->swBuf+st->frameSize, st->max_pitch+2); |
| 297 |
| 298 if (st->highpass_enabled) |
| 299 highpass(in, in, st->frameSize, (st->isWideband?HIGHPASS_WIDEBAND:HIGHPASS
_NARROWBAND)|HIGHPASS_INPUT, st->mem_hp); |
| 300 |
| 301 { |
| 302 VARDECL(spx_word16_t *w_sig); |
| 303 VARDECL(spx_word16_t *autocorr); |
| 304 ALLOC(w_sig, st->windowSize, spx_word16_t); |
| 305 ALLOC(autocorr, st->lpcSize+1, spx_word16_t); |
| 306 /* Window for analysis */ |
| 307 for (i=0;i<st->windowSize-st->frameSize;i++) |
| 308 w_sig[i] = EXTRACT16(SHR32(MULT16_16(st->winBuf[i],st->window[i]),SIG_S
HIFT)); |
| 309 for (;i<st->windowSize;i++) |
| 310 w_sig[i] = EXTRACT16(SHR32(MULT16_16(in[i-st->windowSize+st->frameSize]
,st->window[i]),SIG_SHIFT)); |
| 311 /* Compute auto-correlation */ |
| 312 _spx_autocorr(w_sig, autocorr, st->lpcSize+1, st->windowSize); |
| 313 autocorr[0] = ADD16(autocorr[0],MULT16_16_Q15(autocorr[0],st->lpc_floor));
/* Noise floor in auto-correlation domain */ |
| 314 |
| 315 /* Lag windowing: equivalent to filtering in the power-spectrum domain */ |
| 316 for (i=0;i<st->lpcSize+1;i++) |
| 317 autocorr[i] = MULT16_16_Q14(autocorr[i],st->lagWindow[i]); |
| 318 |
| 319 /* Levinson-Durbin */ |
| 320 _spx_lpc(lpc, autocorr, st->lpcSize); |
| 321 /* LPC to LSPs (x-domain) transform */ |
| 322 roots=lpc_to_lsp (lpc, st->lpcSize, lsp, 10, LSP_DELTA1, stack); |
| 323 /* Check if we found all the roots */ |
| 324 if (roots!=st->lpcSize) |
| 325 { |
| 326 /*If we can't find all LSP's, do some damage control and use previous f
ilter*/ |
| 327 for (i=0;i<st->lpcSize;i++) |
| 328 { |
| 329 lsp[i]=st->old_lsp[i]; |
| 330 } |
| 331 } |
| 332 } |
| 333 |
| 334 |
| 335 |
| 336 |
| 337 /* Whole frame analysis (open-loop estimation of pitch and excitation gain) *
/ |
| 338 { |
| 339 int diff = st->windowSize-st->frameSize; |
| 340 if (st->first) |
| 341 for (i=0;i<st->lpcSize;i++) |
| 342 interp_lsp[i] = lsp[i]; |
| 343 else |
| 344 lsp_interpolate(st->old_lsp, lsp, interp_lsp, st->lpcSize, st->nbSubfra
mes, st->nbSubframes<<1); |
| 345 |
| 346 lsp_enforce_margin(interp_lsp, st->lpcSize, LSP_MARGIN); |
| 347 |
| 348 /* Compute interpolated LPCs (unquantized) for whole frame*/ |
| 349 lsp_to_lpc(interp_lsp, interp_lpc, st->lpcSize,stack); |
| 350 |
| 351 |
| 352 /*Open-loop pitch*/ |
| 353 if (!st->submodes[st->submodeID] || (st->complexity>2 && SUBMODE(have_subf
rame_gain)<3) || SUBMODE(forced_pitch_gain) || SUBMODE(lbr_pitch) != -1 |
| 354 #ifndef DISABLE_VBR |
| 355 || st->vbr_enabled || st->vad_enabled |
| 356 #endif |
| 357 ) |
| 358 { |
| 359 int nol_pitch[6]; |
| 360 spx_word16_t nol_pitch_coef[6]; |
| 361 |
| 362 bw_lpc(st->gamma1, interp_lpc, bw_lpc1, st->lpcSize); |
| 363 bw_lpc(st->gamma2, interp_lpc, bw_lpc2, st->lpcSize); |
| 364 |
| 365 SPEEX_COPY(st->sw, st->winBuf, diff); |
| 366 SPEEX_COPY(st->sw+diff, in, st->frameSize-diff); |
| 367 filter_mem16(st->sw, bw_lpc1, bw_lpc2, st->sw, st->frameSize, st->lpcSi
ze, st->mem_sw_whole, stack); |
| 368 |
| 369 open_loop_nbest_pitch(st->sw, st->min_pitch, st->max_pitch, st->frameSi
ze, |
| 370 nol_pitch, nol_pitch_coef, 6, stack); |
| 371 ol_pitch=nol_pitch[0]; |
| 372 ol_pitch_coef = nol_pitch_coef[0]; |
| 373 /*Try to remove pitch multiples*/ |
| 374 for (i=1;i<6;i++) |
| 375 { |
| 376 #ifdef FIXED_POINT |
| 377 if ((nol_pitch_coef[i]>MULT16_16_Q15(nol_pitch_coef[0],27853)) && |
| 378 #else |
| 379 if ((nol_pitch_coef[i]>.85*nol_pitch_coef[0]) && |
| 380 #endif |
| 381 (ABS(2*nol_pitch[i]-ol_pitch)<=2 || ABS(3*nol_pitch[i]-ol_pitch)
<=3 || |
| 382 ABS(4*nol_pitch[i]-ol_pitch)<=4 || ABS(5*nol_pitch[i]-ol_pitch)
<=5)) |
| 383 { |
| 384 /*ol_pitch_coef=nol_pitch_coef[i];*/ |
| 385 ol_pitch = nol_pitch[i]; |
| 386 } |
| 387 } |
| 388 /*if (ol_pitch>50) |
| 389 ol_pitch/=2;*/ |
| 390 /*ol_pitch_coef = sqrt(ol_pitch_coef);*/ |
| 391 |
| 392 } else { |
| 393 ol_pitch=0; |
| 394 ol_pitch_coef=0; |
| 395 } |
| 396 |
| 397 /*Compute "real" excitation*/ |
| 398 SPEEX_COPY(st->exc, st->winBuf, diff); |
| 399 SPEEX_COPY(st->exc+diff, in, st->frameSize-diff); |
| 400 fir_mem16(st->exc, interp_lpc, st->exc, st->frameSize, st->lpcSize, st->me
m_exc, stack); |
| 401 |
| 402 /* Compute open-loop excitation gain */ |
| 403 { |
| 404 spx_word16_t g = compute_rms16(st->exc, st->frameSize); |
| 405 if (st->submodeID!=1 && ol_pitch>0) |
| 406 ol_gain = MULT16_16(g, MULT16_16_Q14(QCONST16(1.1,14), |
| 407 spx_sqrt(QCONST32(1.,28)-MULT16_32_Q15(QCONST16(
.8,15),SHL32(MULT16_16(ol_pitch_coef,ol_pitch_coef),16))))); |
| 408 else |
| 409 ol_gain = SHL32(EXTEND32(g),SIG_SHIFT); |
| 410 } |
| 411 } |
| 412 |
| 413 #ifdef VORBIS_PSYCHO |
| 414 SPEEX_MOVE(st->psy_window, st->psy_window+st->frameSize, 256-st->frameSize); |
| 415 SPEEX_COPY(&st->psy_window[256-st->frameSize], in, st->frameSize); |
| 416 compute_curve(st->psy, st->psy_window, st->curve); |
| 417 /*print_vec(st->curve, 128, "curve");*/ |
| 418 if (st->first) |
| 419 SPEEX_COPY(st->old_curve, st->curve, 128); |
| 420 #endif |
| 421 |
| 422 /*VBR stuff*/ |
| 423 #ifndef DISABLE_VBR |
| 424 if (st->vbr && (st->vbr_enabled||st->vad_enabled)) |
| 425 { |
| 426 float lsp_dist=0; |
| 427 for (i=0;i<st->lpcSize;i++) |
| 428 lsp_dist += (st->old_lsp[i] - lsp[i])*(st->old_lsp[i] - lsp[i]); |
| 429 lsp_dist /= LSP_SCALING*LSP_SCALING; |
| 430 |
| 431 if (st->abr_enabled) |
| 432 { |
| 433 float qual_change=0; |
| 434 if (st->abr_drift2 * st->abr_drift > 0) |
| 435 { |
| 436 /* Only adapt if long-term and short-term drift are the same sign */ |
| 437 qual_change = -.00001*st->abr_drift/(1+st->abr_count); |
| 438 if (qual_change>.05) |
| 439 qual_change=.05; |
| 440 if (qual_change<-.05) |
| 441 qual_change=-.05; |
| 442 } |
| 443 st->vbr_quality += qual_change; |
| 444 if (st->vbr_quality>10) |
| 445 st->vbr_quality=10; |
| 446 if (st->vbr_quality<0) |
| 447 st->vbr_quality=0; |
| 448 } |
| 449 |
| 450 st->relative_quality = vbr_analysis(st->vbr, in, st->frameSize, ol_pitch,
GAIN_SCALING_1*ol_pitch_coef); |
| 451 /*if (delta_qual<0)*/ |
| 452 /* delta_qual*=.1*(3+st->vbr_quality);*/ |
| 453 if (st->vbr_enabled) |
| 454 { |
| 455 spx_int32_t mode; |
| 456 int choice=0; |
| 457 float min_diff=100; |
| 458 mode = 8; |
| 459 while (mode) |
| 460 { |
| 461 int v1; |
| 462 float thresh; |
| 463 v1=(int)floor(st->vbr_quality); |
| 464 if (v1==10) |
| 465 thresh = vbr_nb_thresh[mode][v1]; |
| 466 else |
| 467 thresh = (st->vbr_quality-v1)*vbr_nb_thresh[mode][v1+1] + (1+v1-s
t->vbr_quality)*vbr_nb_thresh[mode][v1]; |
| 468 if (st->relative_quality > thresh && |
| 469 st->relative_quality-thresh<min_diff) |
| 470 { |
| 471 choice = mode; |
| 472 min_diff = st->relative_quality-thresh; |
| 473 } |
| 474 mode--; |
| 475 } |
| 476 mode=choice; |
| 477 if (mode==0) |
| 478 { |
| 479 if (st->dtx_count==0 || lsp_dist>.05 || !st->dtx_enabled || st->dtx_
count>20) |
| 480 { |
| 481 mode=1; |
| 482 st->dtx_count=1; |
| 483 } else { |
| 484 mode=0; |
| 485 st->dtx_count++; |
| 486 } |
| 487 } else { |
| 488 st->dtx_count=0; |
| 489 } |
| 490 |
| 491 speex_encoder_ctl(state, SPEEX_SET_MODE, &mode); |
| 492 if (st->vbr_max>0) |
| 493 { |
| 494 spx_int32_t rate; |
| 495 speex_encoder_ctl(state, SPEEX_GET_BITRATE, &rate); |
| 496 if (rate > st->vbr_max) |
| 497 { |
| 498 rate = st->vbr_max; |
| 499 speex_encoder_ctl(state, SPEEX_SET_BITRATE, &rate); |
| 500 } |
| 501 } |
| 502 |
| 503 if (st->abr_enabled) |
| 504 { |
| 505 spx_int32_t bitrate; |
| 506 speex_encoder_ctl(state, SPEEX_GET_BITRATE, &bitrate); |
| 507 st->abr_drift+=(bitrate-st->abr_enabled); |
| 508 st->abr_drift2 = .95*st->abr_drift2 + .05*(bitrate-st->abr_enabled); |
| 509 st->abr_count += 1.0; |
| 510 } |
| 511 |
| 512 } else { |
| 513 /*VAD only case*/ |
| 514 int mode; |
| 515 if (st->relative_quality<2) |
| 516 { |
| 517 if (st->dtx_count==0 || lsp_dist>.05 || !st->dtx_enabled || st->dtx_
count>20) |
| 518 { |
| 519 st->dtx_count=1; |
| 520 mode=1; |
| 521 } else { |
| 522 mode=0; |
| 523 st->dtx_count++; |
| 524 } |
| 525 } else { |
| 526 st->dtx_count = 0; |
| 527 mode=st->submodeSelect; |
| 528 } |
| 529 /*speex_encoder_ctl(state, SPEEX_SET_MODE, &mode);*/ |
| 530 st->submodeID=mode; |
| 531 } |
| 532 } else { |
| 533 st->relative_quality = -1; |
| 534 } |
| 535 #endif /* #ifndef DISABLE_VBR */ |
| 536 |
| 537 if (st->encode_submode) |
| 538 { |
| 539 /* First, transmit a zero for narrowband */ |
| 540 speex_bits_pack(bits, 0, 1); |
| 541 |
| 542 /* Transmit the sub-mode we use for this frame */ |
| 543 speex_bits_pack(bits, st->submodeID, NB_SUBMODE_BITS); |
| 544 |
| 545 } |
| 546 |
| 547 /* If null mode (no transmission), just set a couple things to zero*/ |
| 548 if (st->submodes[st->submodeID] == NULL) |
| 549 { |
| 550 for (i=0;i<st->frameSize;i++) |
| 551 st->exc[i]=st->sw[i]=VERY_SMALL; |
| 552 |
| 553 for (i=0;i<st->lpcSize;i++) |
| 554 st->mem_sw[i]=0; |
| 555 st->first=1; |
| 556 st->bounded_pitch = 1; |
| 557 |
| 558 SPEEX_COPY(st->winBuf, in+2*st->frameSize-st->windowSize, st->windowSize-s
t->frameSize); |
| 559 |
| 560 /* Clear memory (no need to really compute it) */ |
| 561 for (i=0;i<st->lpcSize;i++) |
| 562 st->mem_sp[i] = 0; |
| 563 return 0; |
| 564 |
| 565 } |
| 566 |
| 567 /* LSP Quantization */ |
| 568 if (st->first) |
| 569 { |
| 570 for (i=0;i<st->lpcSize;i++) |
| 571 st->old_lsp[i] = lsp[i]; |
| 572 } |
| 573 |
| 574 |
| 575 /*Quantize LSPs*/ |
| 576 #if 1 /*0 for unquantized*/ |
| 577 SUBMODE(lsp_quant)(lsp, qlsp, st->lpcSize, bits); |
| 578 #else |
| 579 for (i=0;i<st->lpcSize;i++) |
| 580 qlsp[i]=lsp[i]; |
| 581 #endif |
| 582 |
| 583 /*If we use low bit-rate pitch mode, transmit open-loop pitch*/ |
| 584 if (SUBMODE(lbr_pitch)!=-1) |
| 585 { |
| 586 speex_bits_pack(bits, ol_pitch-st->min_pitch, 7); |
| 587 } |
| 588 |
| 589 if (SUBMODE(forced_pitch_gain)) |
| 590 { |
| 591 int quant; |
| 592 /* This just damps the pitch a bit, because it tends to be too aggressive
when forced */ |
| 593 ol_pitch_coef = MULT16_16_Q15(QCONST16(.9,15), ol_pitch_coef); |
| 594 #ifdef FIXED_POINT |
| 595 quant = PSHR16(MULT16_16_16(15, ol_pitch_coef),GAIN_SHIFT); |
| 596 #else |
| 597 quant = (int)floor(.5+15*ol_pitch_coef*GAIN_SCALING_1); |
| 598 #endif |
| 599 if (quant>15) |
| 600 quant=15; |
| 601 if (quant<0) |
| 602 quant=0; |
| 603 speex_bits_pack(bits, quant, 4); |
| 604 ol_pitch_coef=MULT16_16_P15(QCONST16(0.066667,15),SHL16(quant,GAIN_SHIFT))
; |
| 605 } |
| 606 |
| 607 |
| 608 /*Quantize and transmit open-loop excitation gain*/ |
| 609 #ifdef FIXED_POINT |
| 610 { |
| 611 int qe = scal_quant32(ol_gain, ol_gain_table, 32); |
| 612 /*ol_gain = exp(qe/3.5)*SIG_SCALING;*/ |
| 613 ol_gain = MULT16_32_Q15(28406,ol_gain_table[qe]); |
| 614 speex_bits_pack(bits, qe, 5); |
| 615 } |
| 616 #else |
| 617 { |
| 618 int qe = (int)(floor(.5+3.5*log(ol_gain*1.0/SIG_SCALING))); |
| 619 if (qe<0) |
| 620 qe=0; |
| 621 if (qe>31) |
| 622 qe=31; |
| 623 ol_gain = exp(qe/3.5)*SIG_SCALING; |
| 624 speex_bits_pack(bits, qe, 5); |
| 625 } |
| 626 #endif |
| 627 |
| 628 |
| 629 |
| 630 /* Special case for first frame */ |
| 631 if (st->first) |
| 632 { |
| 633 for (i=0;i<st->lpcSize;i++) |
| 634 st->old_qlsp[i] = qlsp[i]; |
| 635 } |
| 636 |
| 637 /* Target signal */ |
| 638 ALLOC(target, st->subframeSize, spx_word16_t); |
| 639 ALLOC(innov, st->subframeSize, spx_sig_t); |
| 640 ALLOC(exc32, st->subframeSize, spx_word32_t); |
| 641 ALLOC(ringing, st->subframeSize, spx_word16_t); |
| 642 ALLOC(syn_resp, st->subframeSize, spx_word16_t); |
| 643 ALLOC(real_exc, st->subframeSize, spx_word16_t); |
| 644 ALLOC(mem, st->lpcSize, spx_mem_t); |
| 645 |
| 646 /* Loop on sub-frames */ |
| 647 for (sub=0;sub<st->nbSubframes;sub++) |
| 648 { |
| 649 int offset; |
| 650 spx_word16_t *sw; |
| 651 spx_word16_t *exc; |
| 652 int pitch; |
| 653 int response_bound = st->subframeSize; |
| 654 |
| 655 /* Offset relative to start of frame */ |
| 656 offset = st->subframeSize*sub; |
| 657 /* Excitation */ |
| 658 exc=st->exc+offset; |
| 659 /* Weighted signal */ |
| 660 sw=st->sw+offset; |
| 661 |
| 662 /* LSP interpolation (quantized and unquantized) */ |
| 663 lsp_interpolate(st->old_lsp, lsp, interp_lsp, st->lpcSize, sub, st->nbSubf
rames); |
| 664 lsp_interpolate(st->old_qlsp, qlsp, interp_qlsp, st->lpcSize, sub, st->nbS
ubframes); |
| 665 |
| 666 /* Make sure the filters are stable */ |
| 667 lsp_enforce_margin(interp_lsp, st->lpcSize, LSP_MARGIN); |
| 668 lsp_enforce_margin(interp_qlsp, st->lpcSize, LSP_MARGIN); |
| 669 |
| 670 /* Compute interpolated LPCs (quantized and unquantized) */ |
| 671 lsp_to_lpc(interp_lsp, interp_lpc, st->lpcSize,stack); |
| 672 |
| 673 lsp_to_lpc(interp_qlsp, interp_qlpc, st->lpcSize, stack); |
| 674 |
| 675 /* Compute analysis filter gain at w=pi (for use in SB-CELP) */ |
| 676 { |
| 677 spx_word32_t pi_g=LPC_SCALING; |
| 678 for (i=0;i<st->lpcSize;i+=2) |
| 679 { |
| 680 /*pi_g += -st->interp_qlpc[i] + st->interp_qlpc[i+1];*/ |
| 681 pi_g = ADD32(pi_g, SUB32(EXTEND32(interp_qlpc[i+1]),EXTEND32(interp_
qlpc[i]))); |
| 682 } |
| 683 st->pi_gain[sub] = pi_g; |
| 684 } |
| 685 |
| 686 #ifdef VORBIS_PSYCHO |
| 687 { |
| 688 float curr_curve[128]; |
| 689 float fact = ((float)sub+1.0f)/st->nbSubframes; |
| 690 for (i=0;i<128;i++) |
| 691 curr_curve[i] = (1.0f-fact)*st->old_curve[i] + fact*st->curve[i]; |
| 692 curve_to_lpc(st->psy, curr_curve, bw_lpc1, bw_lpc2, 10); |
| 693 } |
| 694 #else |
| 695 /* Compute bandwidth-expanded (unquantized) LPCs for perceptual weighting
*/ |
| 696 bw_lpc(st->gamma1, interp_lpc, bw_lpc1, st->lpcSize); |
| 697 if (st->gamma2>=0) |
| 698 bw_lpc(st->gamma2, interp_lpc, bw_lpc2, st->lpcSize); |
| 699 else |
| 700 { |
| 701 for (i=0;i<st->lpcSize;i++) |
| 702 bw_lpc2[i]=0; |
| 703 } |
| 704 /*print_vec(st->bw_lpc1, 10, "bw_lpc");*/ |
| 705 #endif |
| 706 |
| 707 /*FIXME: This will break if we change the window size */ |
| 708 speex_assert(st->windowSize-st->frameSize == st->subframeSize); |
| 709 if (sub==0) |
| 710 { |
| 711 for (i=0;i<st->subframeSize;i++) |
| 712 real_exc[i] = sw[i] = st->winBuf[i]; |
| 713 } else { |
| 714 for (i=0;i<st->subframeSize;i++) |
| 715 real_exc[i] = sw[i] = in[i+((sub-1)*st->subframeSize)]; |
| 716 } |
| 717 fir_mem16(real_exc, interp_qlpc, real_exc, st->subframeSize, st->lpcSize,
st->mem_exc2, stack); |
| 718 |
| 719 if (st->complexity==0) |
| 720 response_bound >>= 1; |
| 721 compute_impulse_response(interp_qlpc, bw_lpc1, bw_lpc2, syn_resp, response
_bound, st->lpcSize, stack); |
| 722 for (i=response_bound;i<st->subframeSize;i++) |
| 723 syn_resp[i]=VERY_SMALL; |
| 724 |
| 725 /* Compute zero response of A(z/g1) / ( A(z/g2) * A(z) ) */ |
| 726 for (i=0;i<st->lpcSize;i++) |
| 727 mem[i]=SHL32(st->mem_sp[i],1); |
| 728 for (i=0;i<st->subframeSize;i++) |
| 729 ringing[i] = VERY_SMALL; |
| 730 #ifdef SHORTCUTS2 |
| 731 iir_mem16(ringing, interp_qlpc, ringing, response_bound, st->lpcSize, mem,
stack); |
| 732 for (i=0;i<st->lpcSize;i++) |
| 733 mem[i]=SHL32(st->mem_sw[i],1); |
| 734 filter_mem16(ringing, st->bw_lpc1, st->bw_lpc2, ringing, response_bound, s
t->lpcSize, mem, stack); |
| 735 SPEEX_MEMSET(&ringing[response_bound], 0, st->subframeSize-response_bound)
; |
| 736 #else |
| 737 iir_mem16(ringing, interp_qlpc, ringing, st->subframeSize, st->lpcSize, me
m, stack); |
| 738 for (i=0;i<st->lpcSize;i++) |
| 739 mem[i]=SHL32(st->mem_sw[i],1); |
| 740 filter_mem16(ringing, bw_lpc1, bw_lpc2, ringing, st->subframeSize, st->lpc
Size, mem, stack); |
| 741 #endif |
| 742 |
| 743 /* Compute weighted signal */ |
| 744 for (i=0;i<st->lpcSize;i++) |
| 745 mem[i]=st->mem_sw[i]; |
| 746 filter_mem16(sw, bw_lpc1, bw_lpc2, sw, st->subframeSize, st->lpcSize, mem,
stack); |
| 747 |
| 748 if (st->complexity==0) |
| 749 for (i=0;i<st->lpcSize;i++) |
| 750 st->mem_sw[i]=mem[i]; |
| 751 |
| 752 /* Compute target signal (saturation prevents overflows on clipped input s
peech) */ |
| 753 for (i=0;i<st->subframeSize;i++) |
| 754 target[i]=EXTRACT16(SATURATE(SUB32(sw[i],PSHR32(ringing[i],1)),32767)); |
| 755 |
| 756 /* Reset excitation */ |
| 757 SPEEX_MEMSET(exc, 0, st->subframeSize); |
| 758 |
| 759 /* If we have a long-term predictor (otherwise, something's wrong) */ |
| 760 speex_assert (SUBMODE(ltp_quant)); |
| 761 { |
| 762 int pit_min, pit_max; |
| 763 /* Long-term prediction */ |
| 764 if (SUBMODE(lbr_pitch) != -1) |
| 765 { |
| 766 /* Low bit-rate pitch handling */ |
| 767 int margin; |
| 768 margin = SUBMODE(lbr_pitch); |
| 769 if (margin) |
| 770 { |
| 771 if (ol_pitch < st->min_pitch+margin-1) |
| 772 ol_pitch=st->min_pitch+margin-1; |
| 773 if (ol_pitch > st->max_pitch-margin) |
| 774 ol_pitch=st->max_pitch-margin; |
| 775 pit_min = ol_pitch-margin+1; |
| 776 pit_max = ol_pitch+margin; |
| 777 } else { |
| 778 pit_min=pit_max=ol_pitch; |
| 779 } |
| 780 } else { |
| 781 pit_min = st->min_pitch; |
| 782 pit_max = st->max_pitch; |
| 783 } |
| 784 |
| 785 /* Force pitch to use only the current frame if needed */ |
| 786 if (st->bounded_pitch && pit_max>offset) |
| 787 pit_max=offset; |
| 788 |
| 789 /* Perform pitch search */ |
| 790 pitch = SUBMODE(ltp_quant)(target, sw, interp_qlpc, bw_lpc1, bw_lpc2, |
| 791 exc32, SUBMODE(ltp_params), pit_min, pit_max
, ol_pitch_coef, |
| 792 st->lpcSize, st->subframeSize, bits, stack, |
| 793 exc, syn_resp, st->complexity, 0, st->plc_tu
ning, &st->cumul_gain); |
| 794 |
| 795 st->pitch[sub]=pitch; |
| 796 } |
| 797 /* Quantization of innovation */ |
| 798 SPEEX_MEMSET(innov, 0, st->subframeSize); |
| 799 |
| 800 /* FIXME: Make sure this is save from overflows (so far so good) */ |
| 801 for (i=0;i<st->subframeSize;i++) |
| 802 real_exc[i] = EXTRACT16(SUB32(EXTEND32(real_exc[i]), PSHR32(exc32[i],SI
G_SHIFT-1))); |
| 803 |
| 804 ener = SHL32(EXTEND32(compute_rms16(real_exc, st->subframeSize)),SIG_SHIFT
); |
| 805 |
| 806 /*FIXME: Should use DIV32_16 and make sure result fits in 16 bits */ |
| 807 #ifdef FIXED_POINT |
| 808 { |
| 809 spx_word32_t f = PDIV32(ener,PSHR32(ol_gain,SIG_SHIFT)); |
| 810 if (f<=32767) |
| 811 fine_gain = f; |
| 812 else |
| 813 fine_gain = 32767; |
| 814 } |
| 815 #else |
| 816 fine_gain = PDIV32_16(ener,PSHR32(ol_gain,SIG_SHIFT)); |
| 817 #endif |
| 818 /* Calculate gain correction for the sub-frame (if any) */ |
| 819 if (SUBMODE(have_subframe_gain)) |
| 820 { |
| 821 int qe; |
| 822 if (SUBMODE(have_subframe_gain)==3) |
| 823 { |
| 824 qe = scal_quant(fine_gain, exc_gain_quant_scal3_bound, 8); |
| 825 speex_bits_pack(bits, qe, 3); |
| 826 ener=MULT16_32_Q14(exc_gain_quant_scal3[qe],ol_gain); |
| 827 } else { |
| 828 qe = scal_quant(fine_gain, exc_gain_quant_scal1_bound, 2); |
| 829 speex_bits_pack(bits, qe, 1); |
| 830 ener=MULT16_32_Q14(exc_gain_quant_scal1[qe],ol_gain); |
| 831 } |
| 832 } else { |
| 833 ener=ol_gain; |
| 834 } |
| 835 |
| 836 /*printf ("%f %f\n", ener, ol_gain);*/ |
| 837 |
| 838 /* Normalize innovation */ |
| 839 signal_div(target, target, ener, st->subframeSize); |
| 840 |
| 841 /* Quantize innovation */ |
| 842 speex_assert (SUBMODE(innovation_quant)); |
| 843 { |
| 844 /* Codebook search */ |
| 845 SUBMODE(innovation_quant)(target, interp_qlpc, bw_lpc1, bw_lpc2, |
| 846 SUBMODE(innovation_params), st->lpcSize, st->subframeSize, |
| 847 innov, syn_resp, bits, stack, st->complexity, SUBMODE(double_c
odebook)); |
| 848 |
| 849 /* De-normalize innovation and update excitation */ |
| 850 signal_mul(innov, innov, ener, st->subframeSize); |
| 851 |
| 852 for (i=0;i<st->subframeSize;i++) |
| 853 exc[i] = EXTRACT16(SATURATE32(PSHR32(ADD32(SHL32(exc32[i],1),innov[i
]),SIG_SHIFT),32767)); |
| 854 |
| 855 /* In some (rare) modes, we do a second search (more bits) to reduce no
ise even more */ |
| 856 if (SUBMODE(double_codebook)) { |
| 857 char *tmp_stack=stack; |
| 858 VARDECL(spx_sig_t *innov2); |
| 859 ALLOC(innov2, st->subframeSize, spx_sig_t); |
| 860 SPEEX_MEMSET(innov2, 0, st->subframeSize); |
| 861 for (i=0;i<st->subframeSize;i++) |
| 862 target[i]=MULT16_16_P13(QCONST16(2.2f,13), target[i]); |
| 863 SUBMODE(innovation_quant)(target, interp_qlpc, bw_lpc1, bw_lpc2, |
| 864 SUBMODE(innovation_params), st->lpcSize, s
t->subframeSize, |
| 865 innov2, syn_resp, bits, stack, st->complex
ity, 0); |
| 866 signal_mul(innov2, innov2, MULT16_32_Q15(QCONST16(0.454545f,15),ener
), st->subframeSize); |
| 867 for (i=0;i<st->subframeSize;i++) |
| 868 innov[i] = ADD32(innov[i],innov2[i]); |
| 869 stack = tmp_stack; |
| 870 } |
| 871 for (i=0;i<st->subframeSize;i++) |
| 872 exc[i] = EXTRACT16(SATURATE32(PSHR32(ADD32(SHL32(exc32[i],1),innov[i
]),SIG_SHIFT),32767)); |
| 873 if (st->innov_rms_save) |
| 874 { |
| 875 st->innov_rms_save[sub] = compute_rms(innov, st->subframeSize); |
| 876 } |
| 877 } |
| 878 |
| 879 /* Final signal synthesis from excitation */ |
| 880 iir_mem16(exc, interp_qlpc, sw, st->subframeSize, st->lpcSize, st->mem_sp,
stack); |
| 881 |
| 882 /* Compute weighted signal again, from synthesized speech (not sure it's t
he right thing) */ |
| 883 if (st->complexity!=0) |
| 884 filter_mem16(sw, bw_lpc1, bw_lpc2, sw, st->subframeSize, st->lpcSize, s
t->mem_sw, stack); |
| 885 |
| 886 } |
| 887 |
| 888 /* Store the LSPs for interpolation in the next frame */ |
| 889 if (st->submodeID>=1) |
| 890 { |
| 891 for (i=0;i<st->lpcSize;i++) |
| 892 st->old_lsp[i] = lsp[i]; |
| 893 for (i=0;i<st->lpcSize;i++) |
| 894 st->old_qlsp[i] = qlsp[i]; |
| 895 } |
| 896 |
| 897 #ifdef VORBIS_PSYCHO |
| 898 if (st->submodeID>=1) |
| 899 SPEEX_COPY(st->old_curve, st->curve, 128); |
| 900 #endif |
| 901 |
| 902 if (st->submodeID==1) |
| 903 { |
| 904 #ifndef DISABLE_VBR |
| 905 if (st->dtx_count) |
| 906 speex_bits_pack(bits, 15, 4); |
| 907 else |
| 908 #endif |
| 909 speex_bits_pack(bits, 0, 4); |
| 910 } |
| 911 |
| 912 /* The next frame will not be the first (Duh!) */ |
| 913 st->first = 0; |
| 914 SPEEX_COPY(st->winBuf, in+2*st->frameSize-st->windowSize, st->windowSize-st->
frameSize); |
| 915 |
| 916 if (SUBMODE(innovation_quant) == noise_codebook_quant || st->submodeID==0) |
| 917 st->bounded_pitch = 1; |
| 918 else |
| 919 st->bounded_pitch = 0; |
| 920 |
| 921 return 1; |
| 922 } |
| 923 |
| 924 void *nb_decoder_init(const SpeexMode *m) |
| 925 { |
| 926 DecState *st; |
| 927 const SpeexNBMode *mode; |
| 928 int i; |
| 929 |
| 930 mode=(const SpeexNBMode*)m->mode; |
| 931 st = (DecState *)speex_alloc(sizeof(DecState)); |
| 932 if (!st) |
| 933 return NULL; |
| 934 #if defined(VAR_ARRAYS) || defined (USE_ALLOCA) |
| 935 st->stack = NULL; |
| 936 #else |
| 937 st->stack = (char*)speex_alloc_scratch(NB_DEC_STACK); |
| 938 #endif |
| 939 |
| 940 st->mode=m; |
| 941 |
| 942 |
| 943 st->encode_submode = 1; |
| 944 |
| 945 st->first=1; |
| 946 /* Codec parameters, should eventually have several "modes"*/ |
| 947 st->frameSize = mode->frameSize; |
| 948 st->nbSubframes=mode->frameSize/mode->subframeSize; |
| 949 st->subframeSize=mode->subframeSize; |
| 950 st->lpcSize = mode->lpcSize; |
| 951 st->min_pitch=mode->pitchStart; |
| 952 st->max_pitch=mode->pitchEnd; |
| 953 |
| 954 st->submodes=mode->submodes; |
| 955 st->submodeID=mode->defaultSubmode; |
| 956 |
| 957 st->lpc_enh_enabled=1; |
| 958 |
| 959 st->excBuf = (spx_word16_t*)speex_alloc((st->frameSize + 2*st->max_pitch + st
->subframeSize + 12)*sizeof(spx_word16_t)); |
| 960 st->exc = st->excBuf + 2*st->max_pitch + st->subframeSize + 6; |
| 961 SPEEX_MEMSET(st->excBuf, 0, st->frameSize + st->max_pitch); |
| 962 |
| 963 st->interp_qlpc = (spx_coef_t*)speex_alloc(st->lpcSize*sizeof(spx_coef_t)); |
| 964 st->old_qlsp = (spx_lsp_t*)speex_alloc(st->lpcSize*sizeof(spx_lsp_t)); |
| 965 st->mem_sp = (spx_mem_t*)speex_alloc(st->lpcSize*sizeof(spx_mem_t)); |
| 966 st->pi_gain = (spx_word32_t*)speex_alloc((st->nbSubframes)*sizeof(spx_word32_
t)); |
| 967 st->last_pitch = 40; |
| 968 st->count_lost=0; |
| 969 st->pitch_gain_buf[0] = st->pitch_gain_buf[1] = st->pitch_gain_buf[2] = 0; |
| 970 st->pitch_gain_buf_idx = 0; |
| 971 st->seed = 1000; |
| 972 |
| 973 st->sampling_rate=8000; |
| 974 st->last_ol_gain = 0; |
| 975 |
| 976 st->user_callback.func = &speex_default_user_handler; |
| 977 st->user_callback.data = NULL; |
| 978 for (i=0;i<16;i++) |
| 979 st->speex_callbacks[i].func = NULL; |
| 980 |
| 981 st->voc_m1=st->voc_m2=st->voc_mean=0; |
| 982 st->voc_offset=0; |
| 983 st->dtx_enabled=0; |
| 984 st->isWideband = 0; |
| 985 st->highpass_enabled = 1; |
| 986 |
| 987 #ifdef ENABLE_VALGRIND |
| 988 VALGRIND_MAKE_READABLE(st, NB_DEC_STACK); |
| 989 #endif |
| 990 return st; |
| 991 } |
| 992 |
| 993 void nb_decoder_destroy(void *state) |
| 994 { |
| 995 DecState *st; |
| 996 st=(DecState*)state; |
| 997 |
| 998 #if !(defined(VAR_ARRAYS) || defined (USE_ALLOCA)) |
| 999 speex_free_scratch(st->stack); |
| 1000 #endif |
| 1001 |
| 1002 speex_free (st->excBuf); |
| 1003 speex_free (st->interp_qlpc); |
| 1004 speex_free (st->old_qlsp); |
| 1005 speex_free (st->mem_sp); |
| 1006 speex_free (st->pi_gain); |
| 1007 |
| 1008 speex_free(state); |
| 1009 } |
| 1010 |
| 1011 #define median3(a, b, c) ((a) < (b) ? ((b) < (c) ? (b) : ((a) < (c) ? (c)
: (a))) : ((c) < (b) ? (b) : ((c) < (a) ? (c) : (a)))) |
| 1012 |
| 1013 #ifdef FIXED_POINT |
| 1014 const spx_word16_t attenuation[10] = {32767, 31483, 27923, 22861, 17278, 12055,
7764, 4616, 2533, 1283}; |
| 1015 #else |
| 1016 const spx_word16_t attenuation[10] = {1., 0.961, 0.852, 0.698, 0.527, 0.368, 0.2
37, 0.141, 0.077, 0.039}; |
| 1017 |
| 1018 #endif |
| 1019 |
| 1020 static void nb_decode_lost(DecState *st, spx_word16_t *out, char *stack) |
| 1021 { |
| 1022 int i; |
| 1023 int pitch_val; |
| 1024 spx_word16_t pitch_gain; |
| 1025 spx_word16_t fact; |
| 1026 spx_word16_t gain_med; |
| 1027 spx_word16_t innov_gain; |
| 1028 spx_word16_t noise_gain; |
| 1029 |
| 1030 if (st->count_lost<10) |
| 1031 fact = attenuation[st->count_lost]; |
| 1032 else |
| 1033 fact = 0; |
| 1034 |
| 1035 gain_med = median3(st->pitch_gain_buf[0], st->pitch_gain_buf[1], st->pitch_ga
in_buf[2]); |
| 1036 if (gain_med < st->last_pitch_gain) |
| 1037 st->last_pitch_gain = gain_med; |
| 1038 |
| 1039 #ifdef FIXED_POINT |
| 1040 pitch_gain = st->last_pitch_gain; |
| 1041 if (pitch_gain>54) |
| 1042 pitch_gain = 54; |
| 1043 pitch_gain = SHL16(pitch_gain, 9); |
| 1044 #else |
| 1045 pitch_gain = GAIN_SCALING_1*st->last_pitch_gain; |
| 1046 if (pitch_gain>.85) |
| 1047 pitch_gain=.85; |
| 1048 #endif |
| 1049 pitch_gain = MULT16_16_Q15(fact,pitch_gain) + VERY_SMALL; |
| 1050 /* FIXME: This was rms of innovation (not exc) */ |
| 1051 innov_gain = compute_rms16(st->exc, st->frameSize); |
| 1052 noise_gain = MULT16_16_Q15(innov_gain, MULT16_16_Q15(fact, SUB16(Q15ONE,MULT1
6_16_Q15(pitch_gain,pitch_gain)))); |
| 1053 /* Shift all buffers by one frame */ |
| 1054 SPEEX_MOVE(st->excBuf, st->excBuf+st->frameSize, 2*st->max_pitch + st->subfra
meSize + 12); |
| 1055 |
| 1056 |
| 1057 pitch_val = st->last_pitch + SHR32((spx_int32_t)speex_rand(1+st->count_lost,
&st->seed),SIG_SHIFT); |
| 1058 if (pitch_val > st->max_pitch) |
| 1059 pitch_val = st->max_pitch; |
| 1060 if (pitch_val < st->min_pitch) |
| 1061 pitch_val = st->min_pitch; |
| 1062 for (i=0;i<st->frameSize;i++) |
| 1063 { |
| 1064 st->exc[i]= MULT16_16_Q15(pitch_gain, (st->exc[i-pitch_val]+VERY_SMALL)) +
|
| 1065 speex_rand(noise_gain, &st->seed); |
| 1066 } |
| 1067 |
| 1068 bw_lpc(QCONST16(.98,15), st->interp_qlpc, st->interp_qlpc, st->lpcSize); |
| 1069 iir_mem16(&st->exc[-st->subframeSize], st->interp_qlpc, out, st->frameSize, |
| 1070 st->lpcSize, st->mem_sp, stack); |
| 1071 highpass(out, out, st->frameSize, HIGHPASS_NARROWBAND|HIGHPASS_OUTPUT, st->me
m_hp); |
| 1072 |
| 1073 st->first = 0; |
| 1074 st->count_lost++; |
| 1075 st->pitch_gain_buf[st->pitch_gain_buf_idx++] = PSHR16(pitch_gain,9); |
| 1076 if (st->pitch_gain_buf_idx > 2) /* rollover */ |
| 1077 st->pitch_gain_buf_idx = 0; |
| 1078 } |
| 1079 |
| 1080 /* Just so we don't need to carry the complete wideband mode information */ |
| 1081 static const int wb_skip_table[8] = {0, 36, 112, 192, 352, 0, 0, 0}; |
| 1082 |
| 1083 int nb_decode(void *state, SpeexBits *bits, void *vout) |
| 1084 { |
| 1085 DecState *st; |
| 1086 int i, sub; |
| 1087 int pitch; |
| 1088 spx_word16_t pitch_gain[3]; |
| 1089 spx_word32_t ol_gain=0; |
| 1090 int ol_pitch=0; |
| 1091 spx_word16_t ol_pitch_coef=0; |
| 1092 int best_pitch=40; |
| 1093 spx_word16_t best_pitch_gain=0; |
| 1094 int wideband; |
| 1095 int m; |
| 1096 char *stack; |
| 1097 VARDECL(spx_sig_t *innov); |
| 1098 VARDECL(spx_word32_t *exc32); |
| 1099 VARDECL(spx_coef_t *ak); |
| 1100 VARDECL(spx_lsp_t *qlsp); |
| 1101 spx_word16_t pitch_average=0; |
| 1102 |
| 1103 spx_word16_t *out = (spx_word16_t*)vout; |
| 1104 VARDECL(spx_lsp_t *interp_qlsp); |
| 1105 |
| 1106 st=(DecState*)state; |
| 1107 stack=st->stack; |
| 1108 |
| 1109 /* Check if we're in DTX mode*/ |
| 1110 if (!bits && st->dtx_enabled) |
| 1111 { |
| 1112 st->submodeID=0; |
| 1113 } else |
| 1114 { |
| 1115 /* If bits is NULL, consider the packet to be lost (what could we do anywa
y) */ |
| 1116 if (!bits) |
| 1117 { |
| 1118 nb_decode_lost(st, out, stack); |
| 1119 return 0; |
| 1120 } |
| 1121 |
| 1122 if (st->encode_submode) |
| 1123 { |
| 1124 |
| 1125 /* Search for next narrowband block (handle requests, skip wideband blocks
) */ |
| 1126 do { |
| 1127 if (speex_bits_remaining(bits)<5) |
| 1128 return -1; |
| 1129 wideband = speex_bits_unpack_unsigned(bits, 1); |
| 1130 if (wideband) /* Skip wideband block (for compatibility) */ |
| 1131 { |
| 1132 int submode; |
| 1133 int advance; |
| 1134 advance = submode = speex_bits_unpack_unsigned(bits, SB_SUBMODE_BITS
); |
| 1135 /*speex_mode_query(&speex_wb_mode, SPEEX_SUBMODE_BITS_PER_FRAME, &ad
vance);*/ |
| 1136 advance = wb_skip_table[submode]; |
| 1137 if (advance < 0) |
| 1138 { |
| 1139 speex_notify("Invalid mode encountered. The stream is corrupted."
); |
| 1140 return -2; |
| 1141 } |
| 1142 advance -= (SB_SUBMODE_BITS+1); |
| 1143 speex_bits_advance(bits, advance); |
| 1144 |
| 1145 if (speex_bits_remaining(bits)<5) |
| 1146 return -1; |
| 1147 wideband = speex_bits_unpack_unsigned(bits, 1); |
| 1148 if (wideband) |
| 1149 { |
| 1150 advance = submode = speex_bits_unpack_unsigned(bits, SB_SUBMODE_B
ITS); |
| 1151 /*speex_mode_query(&speex_wb_mode, SPEEX_SUBMODE_BITS_PER_FRAME,
&advance);*/ |
| 1152 advance = wb_skip_table[submode]; |
| 1153 if (advance < 0) |
| 1154 { |
| 1155 speex_notify("Invalid mode encountered. The stream is corrupte
d."); |
| 1156 return -2; |
| 1157 } |
| 1158 advance -= (SB_SUBMODE_BITS+1); |
| 1159 speex_bits_advance(bits, advance); |
| 1160 wideband = speex_bits_unpack_unsigned(bits, 1); |
| 1161 if (wideband) |
| 1162 { |
| 1163 speex_notify("More than two wideband layers found. The stream
is corrupted."); |
| 1164 return -2; |
| 1165 } |
| 1166 |
| 1167 } |
| 1168 } |
| 1169 if (speex_bits_remaining(bits)<4) |
| 1170 return -1; |
| 1171 /* FIXME: Check for overflow */ |
| 1172 m = speex_bits_unpack_unsigned(bits, 4); |
| 1173 if (m==15) /* We found a terminator */ |
| 1174 { |
| 1175 return -1; |
| 1176 } else if (m==14) /* Speex in-band request */ |
| 1177 { |
| 1178 int ret = speex_inband_handler(bits, st->speex_callbacks, state); |
| 1179 if (ret) |
| 1180 return ret; |
| 1181 } else if (m==13) /* User in-band request */ |
| 1182 { |
| 1183 int ret = st->user_callback.func(bits, state, st->user_callback.data
); |
| 1184 if (ret) |
| 1185 return ret; |
| 1186 } else if (m>8) /* Invalid mode */ |
| 1187 { |
| 1188 speex_notify("Invalid mode encountered. The stream is corrupted."); |
| 1189 return -2; |
| 1190 } |
| 1191 |
| 1192 } while (m>8); |
| 1193 |
| 1194 /* Get the sub-mode that was used */ |
| 1195 st->submodeID = m; |
| 1196 } |
| 1197 |
| 1198 } |
| 1199 |
| 1200 /* Shift all buffers by one frame */ |
| 1201 SPEEX_MOVE(st->excBuf, st->excBuf+st->frameSize, 2*st->max_pitch + st->subfra
meSize + 12); |
| 1202 |
| 1203 /* If null mode (no transmission), just set a couple things to zero*/ |
| 1204 if (st->submodes[st->submodeID] == NULL) |
| 1205 { |
| 1206 VARDECL(spx_coef_t *lpc); |
| 1207 ALLOC(lpc, st->lpcSize, spx_coef_t); |
| 1208 bw_lpc(QCONST16(0.93f,15), st->interp_qlpc, lpc, st->lpcSize); |
| 1209 { |
| 1210 spx_word16_t innov_gain=0; |
| 1211 /* FIXME: This was innov, not exc */ |
| 1212 innov_gain = compute_rms16(st->exc, st->frameSize); |
| 1213 for (i=0;i<st->frameSize;i++) |
| 1214 st->exc[i]=speex_rand(innov_gain, &st->seed); |
| 1215 } |
| 1216 |
| 1217 |
| 1218 st->first=1; |
| 1219 |
| 1220 /* Final signal synthesis from excitation */ |
| 1221 iir_mem16(st->exc, lpc, out, st->frameSize, st->lpcSize, st->mem_sp, stack
); |
| 1222 |
| 1223 st->count_lost=0; |
| 1224 return 0; |
| 1225 } |
| 1226 |
| 1227 ALLOC(qlsp, st->lpcSize, spx_lsp_t); |
| 1228 |
| 1229 /* Unquantize LSPs */ |
| 1230 SUBMODE(lsp_unquant)(qlsp, st->lpcSize, bits); |
| 1231 |
| 1232 /*Damp memory if a frame was lost and the LSP changed too much*/ |
| 1233 if (st->count_lost) |
| 1234 { |
| 1235 spx_word16_t fact; |
| 1236 spx_word32_t lsp_dist=0; |
| 1237 for (i=0;i<st->lpcSize;i++) |
| 1238 lsp_dist = ADD32(lsp_dist, EXTEND32(ABS(st->old_qlsp[i] - qlsp[i]))); |
| 1239 #ifdef FIXED_POINT |
| 1240 fact = SHR16(19661,SHR32(lsp_dist,LSP_SHIFT+2)); |
| 1241 #else |
| 1242 fact = .6*exp(-.2*lsp_dist); |
| 1243 #endif |
| 1244 for (i=0;i<st->lpcSize;i++) |
| 1245 st->mem_sp[i] = MULT16_32_Q15(fact,st->mem_sp[i]); |
| 1246 } |
| 1247 |
| 1248 |
| 1249 /* Handle first frame and lost-packet case */ |
| 1250 if (st->first || st->count_lost) |
| 1251 { |
| 1252 for (i=0;i<st->lpcSize;i++) |
| 1253 st->old_qlsp[i] = qlsp[i]; |
| 1254 } |
| 1255 |
| 1256 /* Get open-loop pitch estimation for low bit-rate pitch coding */ |
| 1257 if (SUBMODE(lbr_pitch)!=-1) |
| 1258 { |
| 1259 ol_pitch = st->min_pitch+speex_bits_unpack_unsigned(bits, 7); |
| 1260 } |
| 1261 |
| 1262 if (SUBMODE(forced_pitch_gain)) |
| 1263 { |
| 1264 int quant; |
| 1265 quant = speex_bits_unpack_unsigned(bits, 4); |
| 1266 ol_pitch_coef=MULT16_16_P15(QCONST16(0.066667,15),SHL16(quant,GAIN_SHIFT))
; |
| 1267 } |
| 1268 |
| 1269 /* Get global excitation gain */ |
| 1270 { |
| 1271 int qe; |
| 1272 qe = speex_bits_unpack_unsigned(bits, 5); |
| 1273 #ifdef FIXED_POINT |
| 1274 /* FIXME: Perhaps we could slightly lower the gain here when the output is
going to saturate? */ |
| 1275 ol_gain = MULT16_32_Q15(28406,ol_gain_table[qe]); |
| 1276 #else |
| 1277 ol_gain = SIG_SCALING*exp(qe/3.5); |
| 1278 #endif |
| 1279 } |
| 1280 |
| 1281 ALLOC(ak, st->lpcSize, spx_coef_t); |
| 1282 ALLOC(innov, st->subframeSize, spx_sig_t); |
| 1283 ALLOC(exc32, st->subframeSize, spx_word32_t); |
| 1284 |
| 1285 if (st->submodeID==1) |
| 1286 { |
| 1287 int extra; |
| 1288 extra = speex_bits_unpack_unsigned(bits, 4); |
| 1289 |
| 1290 if (extra==15) |
| 1291 st->dtx_enabled=1; |
| 1292 else |
| 1293 st->dtx_enabled=0; |
| 1294 } |
| 1295 if (st->submodeID>1) |
| 1296 st->dtx_enabled=0; |
| 1297 |
| 1298 /*Loop on subframes */ |
| 1299 for (sub=0;sub<st->nbSubframes;sub++) |
| 1300 { |
| 1301 int offset; |
| 1302 spx_word16_t *exc; |
| 1303 spx_word16_t *sp; |
| 1304 spx_word16_t *innov_save = NULL; |
| 1305 spx_word16_t tmp; |
| 1306 |
| 1307 /* Offset relative to start of frame */ |
| 1308 offset = st->subframeSize*sub; |
| 1309 /* Excitation */ |
| 1310 exc=st->exc+offset; |
| 1311 /* Original signal */ |
| 1312 sp=out+offset; |
| 1313 if (st->innov_save) |
| 1314 innov_save = st->innov_save+offset; |
| 1315 |
| 1316 |
| 1317 /* Reset excitation */ |
| 1318 SPEEX_MEMSET(exc, 0, st->subframeSize); |
| 1319 |
| 1320 /*Adaptive codebook contribution*/ |
| 1321 speex_assert (SUBMODE(ltp_unquant)); |
| 1322 { |
| 1323 int pit_min, pit_max; |
| 1324 /* Handle pitch constraints if any */ |
| 1325 if (SUBMODE(lbr_pitch) != -1) |
| 1326 { |
| 1327 int margin; |
| 1328 margin = SUBMODE(lbr_pitch); |
| 1329 if (margin) |
| 1330 { |
| 1331 /* GT - need optimization? |
| 1332 if (ol_pitch < st->min_pitch+margin-1) |
| 1333 ol_pitch=st->min_pitch+margin-1; |
| 1334 if (ol_pitch > st->max_pitch-margin) |
| 1335 ol_pitch=st->max_pitch-margin; |
| 1336 pit_min = ol_pitch-margin+1; |
| 1337 pit_max = ol_pitch+margin; |
| 1338 */ |
| 1339 pit_min = ol_pitch-margin+1; |
| 1340 if (pit_min < st->min_pitch) |
| 1341 pit_min = st->min_pitch; |
| 1342 pit_max = ol_pitch+margin; |
| 1343 if (pit_max > st->max_pitch) |
| 1344 pit_max = st->max_pitch; |
| 1345 } else { |
| 1346 pit_min = pit_max = ol_pitch; |
| 1347 } |
| 1348 } else { |
| 1349 pit_min = st->min_pitch; |
| 1350 pit_max = st->max_pitch; |
| 1351 } |
| 1352 |
| 1353 |
| 1354 |
| 1355 SUBMODE(ltp_unquant)(exc, exc32, pit_min, pit_max, ol_pitch_coef, SUBMO
DE(ltp_params), |
| 1356 st->subframeSize, &pitch, &pitch_gain[0], bits, stack, |
| 1357 st->count_lost, offset, st->last_pitch_gain, 0); |
| 1358 |
| 1359 /* Ensuring that things aren't blowing up as would happen if e.g. an en
coder is |
| 1360 crafting packets to make us produce NaNs and slow down the decoder (vag
ue DoS threat). |
| 1361 We can probably be even more aggressive and limit to 15000 or so. */ |
| 1362 sanitize_values32(exc32, NEG32(QCONST32(32000,SIG_SHIFT-1)), QCONST32(3
2000,SIG_SHIFT-1), st->subframeSize); |
| 1363 |
| 1364 tmp = gain_3tap_to_1tap(pitch_gain); |
| 1365 |
| 1366 pitch_average += tmp; |
| 1367 if ((tmp>best_pitch_gain&&ABS(2*best_pitch-pitch)>=3&&ABS(3*best_pitch-
pitch)>=4&&ABS(4*best_pitch-pitch)>=5) |
| 1368 || (tmp>MULT16_16_Q15(QCONST16(.6,15),best_pitch_gain)&&(ABS(best_
pitch-2*pitch)<3||ABS(best_pitch-3*pitch)<4||ABS(best_pitch-4*pitch)<5)) |
| 1369 || (MULT16_16_Q15(QCONST16(.67,15),tmp)>best_pitch_gain&&(ABS(2*be
st_pitch-pitch)<3||ABS(3*best_pitch-pitch)<4||ABS(4*best_pitch-pitch)<5)) ) |
| 1370 { |
| 1371 best_pitch = pitch; |
| 1372 if (tmp > best_pitch_gain) |
| 1373 best_pitch_gain = tmp; |
| 1374 } |
| 1375 } |
| 1376 |
| 1377 /* Unquantize the innovation */ |
| 1378 { |
| 1379 int q_energy; |
| 1380 spx_word32_t ener; |
| 1381 |
| 1382 SPEEX_MEMSET(innov, 0, st->subframeSize); |
| 1383 |
| 1384 /* Decode sub-frame gain correction */ |
| 1385 if (SUBMODE(have_subframe_gain)==3) |
| 1386 { |
| 1387 q_energy = speex_bits_unpack_unsigned(bits, 3); |
| 1388 ener = MULT16_32_Q14(exc_gain_quant_scal3[q_energy],ol_gain); |
| 1389 } else if (SUBMODE(have_subframe_gain)==1) |
| 1390 { |
| 1391 q_energy = speex_bits_unpack_unsigned(bits, 1); |
| 1392 ener = MULT16_32_Q14(exc_gain_quant_scal1[q_energy],ol_gain); |
| 1393 } else { |
| 1394 ener = ol_gain; |
| 1395 } |
| 1396 |
| 1397 speex_assert (SUBMODE(innovation_unquant)); |
| 1398 { |
| 1399 /*Fixed codebook contribution*/ |
| 1400 SUBMODE(innovation_unquant)(innov, SUBMODE(innovation_params), st->s
ubframeSize, bits, stack, &st->seed); |
| 1401 /* De-normalize innovation and update excitation */ |
| 1402 |
| 1403 signal_mul(innov, innov, ener, st->subframeSize); |
| 1404 |
| 1405 /* Decode second codebook (only for some modes) */ |
| 1406 if (SUBMODE(double_codebook)) |
| 1407 { |
| 1408 char *tmp_stack=stack; |
| 1409 VARDECL(spx_sig_t *innov2); |
| 1410 ALLOC(innov2, st->subframeSize, spx_sig_t); |
| 1411 SPEEX_MEMSET(innov2, 0, st->subframeSize); |
| 1412 SUBMODE(innovation_unquant)(innov2, SUBMODE(innovation_params), s
t->subframeSize, bits, stack, &st->seed); |
| 1413 signal_mul(innov2, innov2, MULT16_32_Q15(QCONST16(0.454545f,15),e
ner), st->subframeSize); |
| 1414 for (i=0;i<st->subframeSize;i++) |
| 1415 innov[i] = ADD32(innov[i], innov2[i]); |
| 1416 stack = tmp_stack; |
| 1417 } |
| 1418 for (i=0;i<st->subframeSize;i++) |
| 1419 exc[i]=EXTRACT16(SATURATE32(PSHR32(ADD32(SHL32(exc32[i],1),innov[
i]),SIG_SHIFT),32767)); |
| 1420 /*print_vec(exc, 40, "innov");*/ |
| 1421 if (innov_save) |
| 1422 { |
| 1423 for (i=0;i<st->subframeSize;i++) |
| 1424 innov_save[i] = EXTRACT16(PSHR32(innov[i], SIG_SHIFT)); |
| 1425 } |
| 1426 } |
| 1427 |
| 1428 /*Vocoder mode*/ |
| 1429 if (st->submodeID==1) |
| 1430 { |
| 1431 spx_word16_t g=ol_pitch_coef; |
| 1432 g=MULT16_16_P14(QCONST16(1.5f,14),(g-QCONST16(.2f,6))); |
| 1433 if (g<0) |
| 1434 g=0; |
| 1435 if (g>GAIN_SCALING) |
| 1436 g=GAIN_SCALING; |
| 1437 |
| 1438 SPEEX_MEMSET(exc, 0, st->subframeSize); |
| 1439 while (st->voc_offset<st->subframeSize) |
| 1440 { |
| 1441 /* exc[st->voc_offset]= g*sqrt(2*ol_pitch)*ol_gain; |
| 1442 Not quite sure why we need the factor of two in the sqrt */ |
| 1443 if (st->voc_offset>=0) |
| 1444 exc[st->voc_offset]=MULT16_16(spx_sqrt(MULT16_16_16(2,ol_pitch
)),EXTRACT16(PSHR32(MULT16_16(g,PSHR32(ol_gain,SIG_SHIFT)),6))); |
| 1445 st->voc_offset+=ol_pitch; |
| 1446 } |
| 1447 st->voc_offset -= st->subframeSize; |
| 1448 |
| 1449 for (i=0;i<st->subframeSize;i++) |
| 1450 { |
| 1451 spx_word16_t exci=exc[i]; |
| 1452 exc[i]= ADD16(ADD16(MULT16_16_Q15(QCONST16(.7f,15),exc[i]) , MULT
16_16_Q15(QCONST16(.3f,15),st->voc_m1)), |
| 1453 SUB16(MULT16_16_Q15(Q15_ONE-MULT16_16_16(QCONST16(.
85f,9),g),EXTRACT16(PSHR32(innov[i],SIG_SHIFT))), |
| 1454 MULT16_16_Q15(MULT16_16_16(QCONST16(.15f,9),g
),EXTRACT16(PSHR32(st->voc_m2,SIG_SHIFT))) |
| 1455 )); |
| 1456 st->voc_m1 = exci; |
| 1457 st->voc_m2=innov[i]; |
| 1458 st->voc_mean = EXTRACT16(PSHR32(ADD32(MULT16_16(QCONST16(.8f,15),
st->voc_mean), MULT16_16(QCONST16(.2f,15),exc[i])), 15)); |
| 1459 exc[i]-=st->voc_mean; |
| 1460 } |
| 1461 } |
| 1462 |
| 1463 } |
| 1464 } |
| 1465 |
| 1466 ALLOC(interp_qlsp, st->lpcSize, spx_lsp_t); |
| 1467 |
| 1468 if (st->lpc_enh_enabled && SUBMODE(comb_gain)>0 && !st->count_lost) |
| 1469 { |
| 1470 multicomb(st->exc-st->subframeSize, out, st->interp_qlpc, st->lpcSize, 2*s
t->subframeSize, best_pitch, 40, SUBMODE(comb_gain), stack); |
| 1471 multicomb(st->exc+st->subframeSize, out+2*st->subframeSize, st->interp_qlp
c, st->lpcSize, 2*st->subframeSize, best_pitch, 40, SUBMODE(comb_gain), stack); |
| 1472 } else { |
| 1473 SPEEX_COPY(out, &st->exc[-st->subframeSize], st->frameSize); |
| 1474 } |
| 1475 |
| 1476 /* If the last packet was lost, re-scale the excitation to obtain the same en
ergy as encoded in ol_gain */ |
| 1477 if (st->count_lost) |
| 1478 { |
| 1479 spx_word16_t exc_ener; |
| 1480 spx_word32_t gain32; |
| 1481 spx_word16_t gain; |
| 1482 exc_ener = compute_rms16 (st->exc, st->frameSize); |
| 1483 gain32 = PDIV32(ol_gain, ADD16(exc_ener,1)); |
| 1484 #ifdef FIXED_POINT |
| 1485 if (gain32 > 32767) |
| 1486 gain32 = 32767; |
| 1487 gain = EXTRACT16(gain32); |
| 1488 #else |
| 1489 if (gain32 > 2) |
| 1490 gain32=2; |
| 1491 gain = gain32; |
| 1492 #endif |
| 1493 for (i=0;i<st->frameSize;i++) |
| 1494 { |
| 1495 st->exc[i] = MULT16_16_Q14(gain, st->exc[i]); |
| 1496 out[i]=st->exc[i-st->subframeSize]; |
| 1497 } |
| 1498 } |
| 1499 |
| 1500 /*Loop on subframes */ |
| 1501 for (sub=0;sub<st->nbSubframes;sub++) |
| 1502 { |
| 1503 int offset; |
| 1504 spx_word16_t *sp; |
| 1505 spx_word16_t *exc; |
| 1506 /* Offset relative to start of frame */ |
| 1507 offset = st->subframeSize*sub; |
| 1508 /* Original signal */ |
| 1509 sp=out+offset; |
| 1510 /* Excitation */ |
| 1511 exc=st->exc+offset; |
| 1512 |
| 1513 /* LSP interpolation (quantized and unquantized) */ |
| 1514 lsp_interpolate(st->old_qlsp, qlsp, interp_qlsp, st->lpcSize, sub, st->nbS
ubframes); |
| 1515 |
| 1516 /* Make sure the LSP's are stable */ |
| 1517 lsp_enforce_margin(interp_qlsp, st->lpcSize, LSP_MARGIN); |
| 1518 |
| 1519 /* Compute interpolated LPCs (unquantized) */ |
| 1520 lsp_to_lpc(interp_qlsp, ak, st->lpcSize, stack); |
| 1521 |
| 1522 /* Compute analysis filter at w=pi */ |
| 1523 { |
| 1524 spx_word32_t pi_g=LPC_SCALING; |
| 1525 for (i=0;i<st->lpcSize;i+=2) |
| 1526 { |
| 1527 /*pi_g += -st->interp_qlpc[i] + st->interp_qlpc[i+1];*/ |
| 1528 pi_g = ADD32(pi_g, SUB32(EXTEND32(ak[i+1]),EXTEND32(ak[i]))); |
| 1529 } |
| 1530 st->pi_gain[sub] = pi_g; |
| 1531 } |
| 1532 |
| 1533 iir_mem16(sp, st->interp_qlpc, sp, st->subframeSize, st->lpcSize, |
| 1534 st->mem_sp, stack); |
| 1535 |
| 1536 for (i=0;i<st->lpcSize;i++) |
| 1537 st->interp_qlpc[i] = ak[i]; |
| 1538 |
| 1539 } |
| 1540 |
| 1541 if (st->highpass_enabled) |
| 1542 highpass(out, out, st->frameSize, (st->isWideband?HIGHPASS_WIDEBAND:HIGHPA
SS_NARROWBAND)|HIGHPASS_OUTPUT, st->mem_hp); |
| 1543 /*for (i=0;i<st->frameSize;i++) |
| 1544 printf ("%d\n", (int)st->frame[i]);*/ |
| 1545 |
| 1546 /* Tracking output level */ |
| 1547 st->level = 1+PSHR32(ol_gain,SIG_SHIFT); |
| 1548 st->max_level = MAX16(MULT16_16_Q15(QCONST16(.99f,15), st->max_level), st->le
vel); |
| 1549 st->min_level = MIN16(ADD16(1,MULT16_16_Q14(QCONST16(1.01f,14), st->min_level
)), st->level); |
| 1550 if (st->max_level < st->min_level+1) |
| 1551 st->max_level = st->min_level+1; |
| 1552 /*printf ("%f %f %f %d\n", og, st->min_level, st->max_level, update);*/ |
| 1553 |
| 1554 /* Store the LSPs for interpolation in the next frame */ |
| 1555 for (i=0;i<st->lpcSize;i++) |
| 1556 st->old_qlsp[i] = qlsp[i]; |
| 1557 |
| 1558 /* The next frame will not be the first (Duh!) */ |
| 1559 st->first = 0; |
| 1560 st->count_lost=0; |
| 1561 st->last_pitch = best_pitch; |
| 1562 #ifdef FIXED_POINT |
| 1563 st->last_pitch_gain = PSHR16(pitch_average,2); |
| 1564 #else |
| 1565 st->last_pitch_gain = .25*pitch_average; |
| 1566 #endif |
| 1567 st->pitch_gain_buf[st->pitch_gain_buf_idx++] = st->last_pitch_gain; |
| 1568 if (st->pitch_gain_buf_idx > 2) /* rollover */ |
| 1569 st->pitch_gain_buf_idx = 0; |
| 1570 |
| 1571 st->last_ol_gain = ol_gain; |
| 1572 |
| 1573 return 0; |
| 1574 } |
| 1575 |
| 1576 int nb_encoder_ctl(void *state, int request, void *ptr) |
| 1577 { |
| 1578 EncState *st; |
| 1579 st=(EncState*)state; |
| 1580 switch(request) |
| 1581 { |
| 1582 case SPEEX_GET_FRAME_SIZE: |
| 1583 (*(spx_int32_t*)ptr) = st->frameSize; |
| 1584 break; |
| 1585 case SPEEX_SET_LOW_MODE: |
| 1586 case SPEEX_SET_MODE: |
| 1587 st->submodeSelect = st->submodeID = (*(spx_int32_t*)ptr); |
| 1588 break; |
| 1589 case SPEEX_GET_LOW_MODE: |
| 1590 case SPEEX_GET_MODE: |
| 1591 (*(spx_int32_t*)ptr) = st->submodeID; |
| 1592 break; |
| 1593 #ifndef DISABLE_VBR |
| 1594 case SPEEX_SET_VBR: |
| 1595 st->vbr_enabled = (*(spx_int32_t*)ptr); |
| 1596 break; |
| 1597 case SPEEX_GET_VBR: |
| 1598 (*(spx_int32_t*)ptr) = st->vbr_enabled; |
| 1599 break; |
| 1600 case SPEEX_SET_VAD: |
| 1601 st->vad_enabled = (*(spx_int32_t*)ptr); |
| 1602 break; |
| 1603 case SPEEX_GET_VAD: |
| 1604 (*(spx_int32_t*)ptr) = st->vad_enabled; |
| 1605 break; |
| 1606 case SPEEX_SET_DTX: |
| 1607 st->dtx_enabled = (*(spx_int32_t*)ptr); |
| 1608 break; |
| 1609 case SPEEX_GET_DTX: |
| 1610 (*(spx_int32_t*)ptr) = st->dtx_enabled; |
| 1611 break; |
| 1612 case SPEEX_SET_ABR: |
| 1613 st->abr_enabled = (*(spx_int32_t*)ptr); |
| 1614 st->vbr_enabled = st->abr_enabled!=0; |
| 1615 if (st->vbr_enabled) |
| 1616 { |
| 1617 spx_int32_t i=10; |
| 1618 spx_int32_t rate, target; |
| 1619 float vbr_qual; |
| 1620 target = (*(spx_int32_t*)ptr); |
| 1621 while (i>=0) |
| 1622 { |
| 1623 speex_encoder_ctl(st, SPEEX_SET_QUALITY, &i); |
| 1624 speex_encoder_ctl(st, SPEEX_GET_BITRATE, &rate); |
| 1625 if (rate <= target) |
| 1626 break; |
| 1627 i--; |
| 1628 } |
| 1629 vbr_qual=i; |
| 1630 if (vbr_qual<0) |
| 1631 vbr_qual=0; |
| 1632 speex_encoder_ctl(st, SPEEX_SET_VBR_QUALITY, &vbr_qual); |
| 1633 st->abr_count=0; |
| 1634 st->abr_drift=0; |
| 1635 st->abr_drift2=0; |
| 1636 } |
| 1637 |
| 1638 break; |
| 1639 case SPEEX_GET_ABR: |
| 1640 (*(spx_int32_t*)ptr) = st->abr_enabled; |
| 1641 break; |
| 1642 #endif /* #ifndef DISABLE_VBR */ |
| 1643 #if !defined(DISABLE_VBR) && !defined(DISABLE_FLOAT_API) |
| 1644 case SPEEX_SET_VBR_QUALITY: |
| 1645 st->vbr_quality = (*(float*)ptr); |
| 1646 break; |
| 1647 case SPEEX_GET_VBR_QUALITY: |
| 1648 (*(float*)ptr) = st->vbr_quality; |
| 1649 break; |
| 1650 #endif /* !defined(DISABLE_VBR) && !defined(DISABLE_FLOAT_API) */ |
| 1651 case SPEEX_SET_QUALITY: |
| 1652 { |
| 1653 int quality = (*(spx_int32_t*)ptr); |
| 1654 if (quality < 0) |
| 1655 quality = 0; |
| 1656 if (quality > 10) |
| 1657 quality = 10; |
| 1658 st->submodeSelect = st->submodeID = ((const SpeexNBMode*)(st->mode->mod
e))->quality_map[quality]; |
| 1659 } |
| 1660 break; |
| 1661 case SPEEX_SET_COMPLEXITY: |
| 1662 st->complexity = (*(spx_int32_t*)ptr); |
| 1663 if (st->complexity<0) |
| 1664 st->complexity=0; |
| 1665 break; |
| 1666 case SPEEX_GET_COMPLEXITY: |
| 1667 (*(spx_int32_t*)ptr) = st->complexity; |
| 1668 break; |
| 1669 case SPEEX_SET_BITRATE: |
| 1670 { |
| 1671 spx_int32_t i=10; |
| 1672 spx_int32_t rate, target; |
| 1673 target = (*(spx_int32_t*)ptr); |
| 1674 while (i>=0) |
| 1675 { |
| 1676 speex_encoder_ctl(st, SPEEX_SET_QUALITY, &i); |
| 1677 speex_encoder_ctl(st, SPEEX_GET_BITRATE, &rate); |
| 1678 if (rate <= target) |
| 1679 break; |
| 1680 i--; |
| 1681 } |
| 1682 } |
| 1683 break; |
| 1684 case SPEEX_GET_BITRATE: |
| 1685 if (st->submodes[st->submodeID]) |
| 1686 (*(spx_int32_t*)ptr) = st->sampling_rate*SUBMODE(bits_per_frame)/st->fr
ameSize; |
| 1687 else |
| 1688 (*(spx_int32_t*)ptr) = st->sampling_rate*(NB_SUBMODE_BITS+1)/st->frameS
ize; |
| 1689 break; |
| 1690 case SPEEX_SET_SAMPLING_RATE: |
| 1691 st->sampling_rate = (*(spx_int32_t*)ptr); |
| 1692 break; |
| 1693 case SPEEX_GET_SAMPLING_RATE: |
| 1694 (*(spx_int32_t*)ptr)=st->sampling_rate; |
| 1695 break; |
| 1696 case SPEEX_RESET_STATE: |
| 1697 { |
| 1698 int i; |
| 1699 st->bounded_pitch = 1; |
| 1700 st->first = 1; |
| 1701 for (i=0;i<st->lpcSize;i++) |
| 1702 st->old_lsp[i]= DIV32(MULT16_16(QCONST16(3.1415927f, LSP_SHIFT), i+1
), st->lpcSize+1); |
| 1703 for (i=0;i<st->lpcSize;i++) |
| 1704 st->mem_sw[i]=st->mem_sw_whole[i]=st->mem_sp[i]=st->mem_exc[i]=0; |
| 1705 for (i=0;i<st->frameSize+st->max_pitch+1;i++) |
| 1706 st->excBuf[i]=st->swBuf[i]=0; |
| 1707 for (i=0;i<st->windowSize-st->frameSize;i++) |
| 1708 st->winBuf[i]=0; |
| 1709 } |
| 1710 break; |
| 1711 case SPEEX_SET_SUBMODE_ENCODING: |
| 1712 st->encode_submode = (*(spx_int32_t*)ptr); |
| 1713 break; |
| 1714 case SPEEX_GET_SUBMODE_ENCODING: |
| 1715 (*(spx_int32_t*)ptr) = st->encode_submode; |
| 1716 break; |
| 1717 case SPEEX_GET_LOOKAHEAD: |
| 1718 (*(spx_int32_t*)ptr)=(st->windowSize-st->frameSize); |
| 1719 break; |
| 1720 case SPEEX_SET_PLC_TUNING: |
| 1721 st->plc_tuning = (*(spx_int32_t*)ptr); |
| 1722 if (st->plc_tuning>100) |
| 1723 st->plc_tuning=100; |
| 1724 break; |
| 1725 case SPEEX_GET_PLC_TUNING: |
| 1726 (*(spx_int32_t*)ptr)=(st->plc_tuning); |
| 1727 break; |
| 1728 #ifndef DISABLE_VBR |
| 1729 case SPEEX_SET_VBR_MAX_BITRATE: |
| 1730 st->vbr_max = (*(spx_int32_t*)ptr); |
| 1731 break; |
| 1732 case SPEEX_GET_VBR_MAX_BITRATE: |
| 1733 (*(spx_int32_t*)ptr) = st->vbr_max; |
| 1734 break; |
| 1735 #endif /* #ifndef DISABLE_VBR */ |
| 1736 case SPEEX_SET_HIGHPASS: |
| 1737 st->highpass_enabled = (*(spx_int32_t*)ptr); |
| 1738 break; |
| 1739 case SPEEX_GET_HIGHPASS: |
| 1740 (*(spx_int32_t*)ptr) = st->highpass_enabled; |
| 1741 break; |
| 1742 |
| 1743 /* This is all internal stuff past this point */ |
| 1744 case SPEEX_GET_PI_GAIN: |
| 1745 { |
| 1746 int i; |
| 1747 spx_word32_t *g = (spx_word32_t*)ptr; |
| 1748 for (i=0;i<st->nbSubframes;i++) |
| 1749 g[i]=st->pi_gain[i]; |
| 1750 } |
| 1751 break; |
| 1752 case SPEEX_GET_EXC: |
| 1753 { |
| 1754 int i; |
| 1755 for (i=0;i<st->nbSubframes;i++) |
| 1756 ((spx_word16_t*)ptr)[i] = compute_rms16(st->exc+i*st->subframeSize,
st->subframeSize); |
| 1757 } |
| 1758 break; |
| 1759 #ifndef DISABLE_VBR |
| 1760 case SPEEX_GET_RELATIVE_QUALITY: |
| 1761 (*(float*)ptr)=st->relative_quality; |
| 1762 break; |
| 1763 #endif /* #ifndef DISABLE_VBR */ |
| 1764 case SPEEX_SET_INNOVATION_SAVE: |
| 1765 st->innov_rms_save = (spx_word16_t*)ptr; |
| 1766 break; |
| 1767 case SPEEX_SET_WIDEBAND: |
| 1768 st->isWideband = *((spx_int32_t*)ptr); |
| 1769 break; |
| 1770 case SPEEX_GET_STACK: |
| 1771 *((char**)ptr) = st->stack; |
| 1772 break; |
| 1773 default: |
| 1774 speex_warning_int("Unknown nb_ctl request: ", request); |
| 1775 return -1; |
| 1776 } |
| 1777 return 0; |
| 1778 } |
| 1779 |
| 1780 int nb_decoder_ctl(void *state, int request, void *ptr) |
| 1781 { |
| 1782 DecState *st; |
| 1783 st=(DecState*)state; |
| 1784 switch(request) |
| 1785 { |
| 1786 case SPEEX_SET_LOW_MODE: |
| 1787 case SPEEX_SET_MODE: |
| 1788 st->submodeID = (*(spx_int32_t*)ptr); |
| 1789 break; |
| 1790 case SPEEX_GET_LOW_MODE: |
| 1791 case SPEEX_GET_MODE: |
| 1792 (*(spx_int32_t*)ptr) = st->submodeID; |
| 1793 break; |
| 1794 case SPEEX_SET_ENH: |
| 1795 st->lpc_enh_enabled = *((spx_int32_t*)ptr); |
| 1796 break; |
| 1797 case SPEEX_GET_ENH: |
| 1798 *((spx_int32_t*)ptr) = st->lpc_enh_enabled; |
| 1799 break; |
| 1800 case SPEEX_GET_FRAME_SIZE: |
| 1801 (*(spx_int32_t*)ptr) = st->frameSize; |
| 1802 break; |
| 1803 case SPEEX_GET_BITRATE: |
| 1804 if (st->submodes[st->submodeID]) |
| 1805 (*(spx_int32_t*)ptr) = st->sampling_rate*SUBMODE(bits_per_frame)/st->fr
ameSize; |
| 1806 else |
| 1807 (*(spx_int32_t*)ptr) = st->sampling_rate*(NB_SUBMODE_BITS+1)/st->frameS
ize; |
| 1808 break; |
| 1809 case SPEEX_SET_SAMPLING_RATE: |
| 1810 st->sampling_rate = (*(spx_int32_t*)ptr); |
| 1811 break; |
| 1812 case SPEEX_GET_SAMPLING_RATE: |
| 1813 (*(spx_int32_t*)ptr)=st->sampling_rate; |
| 1814 break; |
| 1815 case SPEEX_SET_HANDLER: |
| 1816 { |
| 1817 SpeexCallback *c = (SpeexCallback*)ptr; |
| 1818 st->speex_callbacks[c->callback_id].func=c->func; |
| 1819 st->speex_callbacks[c->callback_id].data=c->data; |
| 1820 st->speex_callbacks[c->callback_id].callback_id=c->callback_id; |
| 1821 } |
| 1822 break; |
| 1823 case SPEEX_SET_USER_HANDLER: |
| 1824 { |
| 1825 SpeexCallback *c = (SpeexCallback*)ptr; |
| 1826 st->user_callback.func=c->func; |
| 1827 st->user_callback.data=c->data; |
| 1828 st->user_callback.callback_id=c->callback_id; |
| 1829 } |
| 1830 break; |
| 1831 case SPEEX_RESET_STATE: |
| 1832 { |
| 1833 int i; |
| 1834 for (i=0;i<st->lpcSize;i++) |
| 1835 st->mem_sp[i]=0; |
| 1836 for (i=0;i<st->frameSize + st->max_pitch + 1;i++) |
| 1837 st->excBuf[i]=0; |
| 1838 } |
| 1839 break; |
| 1840 case SPEEX_SET_SUBMODE_ENCODING: |
| 1841 st->encode_submode = (*(spx_int32_t*)ptr); |
| 1842 break; |
| 1843 case SPEEX_GET_SUBMODE_ENCODING: |
| 1844 (*(spx_int32_t*)ptr) = st->encode_submode; |
| 1845 break; |
| 1846 case SPEEX_GET_LOOKAHEAD: |
| 1847 (*(spx_int32_t*)ptr)=st->subframeSize; |
| 1848 break; |
| 1849 case SPEEX_SET_HIGHPASS: |
| 1850 st->highpass_enabled = (*(spx_int32_t*)ptr); |
| 1851 break; |
| 1852 case SPEEX_GET_HIGHPASS: |
| 1853 (*(spx_int32_t*)ptr) = st->highpass_enabled; |
| 1854 break; |
| 1855 /* FIXME: Convert to fixed-point and re-enable even when float API is disa
bled */ |
| 1856 #ifndef DISABLE_FLOAT_API |
| 1857 case SPEEX_GET_ACTIVITY: |
| 1858 { |
| 1859 float ret; |
| 1860 ret = log(st->level/st->min_level)/log(st->max_level/st->min_level); |
| 1861 if (ret>1) |
| 1862 ret = 1; |
| 1863 /* Done in a strange way to catch NaNs as well */ |
| 1864 if (!(ret > 0)) |
| 1865 ret = 0; |
| 1866 /*printf ("%f %f %f %f\n", st->level, st->min_level, st->max_level, ret);*
/ |
| 1867 (*(spx_int32_t*)ptr) = (int)(100*ret); |
| 1868 } |
| 1869 break; |
| 1870 #endif |
| 1871 case SPEEX_GET_PI_GAIN: |
| 1872 { |
| 1873 int i; |
| 1874 spx_word32_t *g = (spx_word32_t*)ptr; |
| 1875 for (i=0;i<st->nbSubframes;i++) |
| 1876 g[i]=st->pi_gain[i]; |
| 1877 } |
| 1878 break; |
| 1879 case SPEEX_GET_EXC: |
| 1880 { |
| 1881 int i; |
| 1882 for (i=0;i<st->nbSubframes;i++) |
| 1883 ((spx_word16_t*)ptr)[i] = compute_rms16(st->exc+i*st->subframeSize,
st->subframeSize); |
| 1884 } |
| 1885 break; |
| 1886 case SPEEX_GET_DTX_STATUS: |
| 1887 *((spx_int32_t*)ptr) = st->dtx_enabled; |
| 1888 break; |
| 1889 case SPEEX_SET_INNOVATION_SAVE: |
| 1890 st->innov_save = (spx_word16_t*)ptr; |
| 1891 break; |
| 1892 case SPEEX_SET_WIDEBAND: |
| 1893 st->isWideband = *((spx_int32_t*)ptr); |
| 1894 break; |
| 1895 case SPEEX_GET_STACK: |
| 1896 *((char**)ptr) = st->stack; |
| 1897 break; |
| 1898 default: |
| 1899 speex_warning_int("Unknown nb_ctl request: ", request); |
| 1900 return -1; |
| 1901 } |
| 1902 return 0; |
| 1903 } |
OLD | NEW |