Mans Rullgard | 219e262 | 2011-04-22 09:22:33 +0300 | [diff] [blame] | 1 | /* |
| 2 | ** Copyright 2003-2010, VisualOn, Inc. |
| 3 | ** |
| 4 | ** Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | ** you may not use this file except in compliance with the License. |
| 6 | ** You may obtain a copy of the License at |
| 7 | ** |
| 8 | ** http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | ** |
| 10 | ** Unless required by applicable law or agreed to in writing, software |
| 11 | ** distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | ** See the License for the specific language governing permissions and |
| 14 | ** limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | /*********************************************************************** |
| 18 | * File: voAMRWBEnc.c * |
| 19 | * * |
| 20 | * Description: Performs the main encoder routine * |
| 21 | * Fixed-point C simulation of AMR WB ACELP coding * |
| 22 | * algorithm with 20 msspeech frames for * |
| 23 | * wideband speech signals. * |
| 24 | * * |
| 25 | ************************************************************************/ |
| 26 | |
| 27 | #include <stdio.h> |
| 28 | #include <stdlib.h> |
| 29 | #include "typedef.h" |
| 30 | #include "basic_op.h" |
| 31 | #include "oper_32b.h" |
| 32 | #include "math_op.h" |
| 33 | #include "cnst.h" |
| 34 | #include "acelp.h" |
| 35 | #include "cod_main.h" |
| 36 | #include "bits.h" |
| 37 | #include "main.h" |
| 38 | #include "voAMRWB.h" |
| 39 | #include "mem_align.h" |
| 40 | #include "cmnMemory.h" |
| 41 | |
| 42 | #ifdef __cplusplus |
| 43 | extern "C" { |
| 44 | #endif |
| 45 | |
| 46 | /* LPC interpolation coef {0.45, 0.8, 0.96, 1.0}; in Q15 */ |
| 47 | static Word16 interpol_frac[NB_SUBFR] = {14746, 26214, 31457, 32767}; |
| 48 | |
| 49 | /* isp tables for initialization */ |
| 50 | static Word16 isp_init[M] = |
| 51 | { |
| 52 | 32138, 30274, 27246, 23170, 18205, 12540, 6393, 0, |
| 53 | -6393, -12540, -18205, -23170, -27246, -30274, -32138, 1475 |
| 54 | }; |
| 55 | |
| 56 | static Word16 isf_init[M] = |
| 57 | { |
| 58 | 1024, 2048, 3072, 4096, 5120, 6144, 7168, 8192, |
| 59 | 9216, 10240, 11264, 12288, 13312, 14336, 15360, 3840 |
| 60 | }; |
| 61 | |
| 62 | /* High Band encoding */ |
| 63 | static const Word16 HP_gain[16] = |
| 64 | { |
| 65 | 3624, 4673, 5597, 6479, 7425, 8378, 9324, 10264, |
| 66 | 11210, 12206, 13391, 14844, 16770, 19655, 24289, 32728 |
| 67 | }; |
| 68 | |
| 69 | /* Private function declaration */ |
| 70 | static Word16 synthesis( |
| 71 | Word16 Aq[], /* A(z) : quantized Az */ |
| 72 | Word16 exc[], /* (i) : excitation at 12kHz */ |
| 73 | Word16 Q_new, /* (i) : scaling performed on exc */ |
| 74 | Word16 synth16k[], /* (o) : 16kHz synthesis signal */ |
| 75 | Coder_State * st /* (i/o) : State structure */ |
| 76 | ); |
| 77 | |
| 78 | /* Codec some parameters initialization */ |
| 79 | void Reset_encoder(void *st, Word16 reset_all) |
| 80 | { |
| 81 | Word16 i; |
| 82 | Coder_State *cod_state; |
| 83 | cod_state = (Coder_State *) st; |
| 84 | Set_zero(cod_state->old_exc, PIT_MAX + L_INTERPOL); |
| 85 | Set_zero(cod_state->mem_syn, M); |
| 86 | Set_zero(cod_state->past_isfq, M); |
| 87 | cod_state->mem_w0 = 0; |
| 88 | cod_state->tilt_code = 0; |
| 89 | cod_state->first_frame = 1; |
| 90 | Init_gp_clip(cod_state->gp_clip); |
| 91 | cod_state->L_gc_thres = 0; |
| 92 | if (reset_all != 0) |
| 93 | { |
| 94 | /* Static vectors to zero */ |
| 95 | Set_zero(cod_state->old_speech, L_TOTAL - L_FRAME); |
| 96 | Set_zero(cod_state->old_wsp, (PIT_MAX / OPL_DECIM)); |
| 97 | Set_zero(cod_state->mem_decim2, 3); |
| 98 | /* routines initialization */ |
| 99 | Init_Decim_12k8(cod_state->mem_decim); |
| 100 | Init_HP50_12k8(cod_state->mem_sig_in); |
| 101 | Init_Levinson(cod_state->mem_levinson); |
| 102 | Init_Q_gain2(cod_state->qua_gain); |
| 103 | Init_Hp_wsp(cod_state->hp_wsp_mem); |
| 104 | /* isp initialization */ |
| 105 | Copy(isp_init, cod_state->ispold, M); |
| 106 | Copy(isp_init, cod_state->ispold_q, M); |
| 107 | /* variable initialization */ |
| 108 | cod_state->mem_preemph = 0; |
| 109 | cod_state->mem_wsp = 0; |
| 110 | cod_state->Q_old = 15; |
| 111 | cod_state->Q_max[0] = 15; |
| 112 | cod_state->Q_max[1] = 15; |
| 113 | cod_state->old_wsp_max = 0; |
| 114 | cod_state->old_wsp_shift = 0; |
| 115 | /* pitch ol initialization */ |
| 116 | cod_state->old_T0_med = 40; |
| 117 | cod_state->ol_gain = 0; |
| 118 | cod_state->ada_w = 0; |
| 119 | cod_state->ol_wght_flg = 0; |
| 120 | for (i = 0; i < 5; i++) |
| 121 | { |
| 122 | cod_state->old_ol_lag[i] = 40; |
| 123 | } |
| 124 | Set_zero(cod_state->old_hp_wsp, (L_FRAME / 2) / OPL_DECIM + (PIT_MAX / OPL_DECIM)); |
| 125 | Set_zero(cod_state->mem_syn_hf, M); |
| 126 | Set_zero(cod_state->mem_syn_hi, M); |
| 127 | Set_zero(cod_state->mem_syn_lo, M); |
| 128 | Init_HP50_12k8(cod_state->mem_sig_out); |
| 129 | Init_Filt_6k_7k(cod_state->mem_hf); |
| 130 | Init_HP400_12k8(cod_state->mem_hp400); |
| 131 | Copy(isf_init, cod_state->isfold, M); |
| 132 | cod_state->mem_deemph = 0; |
| 133 | cod_state->seed2 = 21845; |
| 134 | Init_Filt_6k_7k(cod_state->mem_hf2); |
| 135 | cod_state->gain_alpha = 32767; |
| 136 | cod_state->vad_hist = 0; |
| 137 | wb_vad_reset(cod_state->vadSt); |
| 138 | dtx_enc_reset(cod_state->dtx_encSt, isf_init); |
| 139 | } |
| 140 | return; |
| 141 | } |
| 142 | |
| 143 | /*-----------------------------------------------------------------* |
| 144 | * Funtion coder * |
| 145 | * ~~~~~ * |
| 146 | * ->Main coder routine. * |
| 147 | * * |
| 148 | *-----------------------------------------------------------------*/ |
| 149 | void coder( |
| 150 | Word16 * mode, /* input : used mode */ |
| 151 | Word16 speech16k[], /* input : 320 new speech samples (at 16 kHz) */ |
| 152 | Word16 prms[], /* output: output parameters */ |
| 153 | Word16 * ser_size, /* output: bit rate of the used mode */ |
| 154 | void *spe_state, /* i/o : State structure */ |
| 155 | Word16 allow_dtx /* input : DTX ON/OFF */ |
| 156 | ) |
| 157 | { |
| 158 | /* Coder states */ |
| 159 | Coder_State *st; |
| 160 | /* Speech vector */ |
| 161 | Word16 old_speech[L_TOTAL]; |
| 162 | Word16 *new_speech, *speech, *p_window; |
| 163 | |
| 164 | /* Weighted speech vector */ |
| 165 | Word16 old_wsp[L_FRAME + (PIT_MAX / OPL_DECIM)]; |
| 166 | Word16 *wsp; |
| 167 | |
| 168 | /* Excitation vector */ |
| 169 | Word16 old_exc[(L_FRAME + 1) + PIT_MAX + L_INTERPOL]; |
| 170 | Word16 *exc; |
| 171 | |
| 172 | /* LPC coefficients */ |
| 173 | Word16 r_h[M + 1], r_l[M + 1]; /* Autocorrelations of windowed speech */ |
| 174 | Word16 rc[M]; /* Reflection coefficients. */ |
| 175 | Word16 Ap[M + 1]; /* A(z) with spectral expansion */ |
| 176 | Word16 ispnew[M]; /* immittance spectral pairs at 4nd sfr */ |
| 177 | Word16 ispnew_q[M]; /* quantized ISPs at 4nd subframe */ |
| 178 | Word16 isf[M]; /* ISF (frequency domain) at 4nd sfr */ |
| 179 | Word16 *p_A, *p_Aq; /* ptr to A(z) for the 4 subframes */ |
| 180 | Word16 A[NB_SUBFR * (M + 1)]; /* A(z) unquantized for the 4 subframes */ |
| 181 | Word16 Aq[NB_SUBFR * (M + 1)]; /* A(z) quantized for the 4 subframes */ |
| 182 | |
| 183 | /* Other vectors */ |
| 184 | Word16 xn[L_SUBFR]; /* Target vector for pitch search */ |
| 185 | Word16 xn2[L_SUBFR]; /* Target vector for codebook search */ |
| 186 | Word16 dn[L_SUBFR]; /* Correlation between xn2 and h1 */ |
| 187 | Word16 cn[L_SUBFR]; /* Target vector in residual domain */ |
| 188 | Word16 h1[L_SUBFR]; /* Impulse response vector */ |
| 189 | Word16 h2[L_SUBFR]; /* Impulse response vector */ |
| 190 | Word16 code[L_SUBFR]; /* Fixed codebook excitation */ |
| 191 | Word16 y1[L_SUBFR]; /* Filtered adaptive excitation */ |
| 192 | Word16 y2[L_SUBFR]; /* Filtered adaptive excitation */ |
| 193 | Word16 error[M + L_SUBFR]; /* error of quantization */ |
| 194 | Word16 synth[L_SUBFR]; /* 12.8kHz synthesis vector */ |
| 195 | Word16 exc2[L_FRAME]; /* excitation vector */ |
| 196 | Word16 buf[L_FRAME]; /* VAD buffer */ |
| 197 | |
| 198 | /* Scalars */ |
| 199 | Word32 i, j, i_subfr, select, pit_flag, clip_gain, vad_flag; |
| 200 | Word16 codec_mode; |
| 201 | Word16 T_op, T_op2, T0, T0_min, T0_max, T0_frac, index; |
| 202 | Word16 gain_pit, gain_code, g_coeff[4], g_coeff2[4]; |
| 203 | Word16 tmp, gain1, gain2, exp, Q_new, mu, shift, max; |
| 204 | Word16 voice_fac; |
| 205 | Word16 indice[8]; |
| 206 | Word32 L_tmp, L_gain_code, L_max, L_tmp1; |
| 207 | Word16 code2[L_SUBFR]; /* Fixed codebook excitation */ |
| 208 | Word16 stab_fac, fac, gain_code_lo; |
| 209 | |
| 210 | Word16 corr_gain; |
| 211 | Word16 *vo_p0, *vo_p1, *vo_p2, *vo_p3; |
| 212 | |
| 213 | st = (Coder_State *) spe_state; |
| 214 | |
| 215 | *ser_size = nb_of_bits[*mode]; |
| 216 | codec_mode = *mode; |
| 217 | |
| 218 | /*--------------------------------------------------------------------------* |
| 219 | * Initialize pointers to speech vector. * |
| 220 | * * |
| 221 | * * |
| 222 | * |-------|-------|-------|-------|-------|-------| * |
| 223 | * past sp sf1 sf2 sf3 sf4 L_NEXT * |
| 224 | * <------- Total speech buffer (L_TOTAL) ------> * |
| 225 | * old_speech * |
| 226 | * <------- LPC analysis window (L_WINDOW) ------> * |
| 227 | * | <-- present frame (L_FRAME) ----> * |
| 228 | * p_window | <----- new speech (L_FRAME) ----> * |
| 229 | * | | * |
| 230 | * speech | * |
| 231 | * new_speech * |
| 232 | *--------------------------------------------------------------------------*/ |
| 233 | |
| 234 | new_speech = old_speech + L_TOTAL - L_FRAME - L_FILT; /* New speech */ |
| 235 | speech = old_speech + L_TOTAL - L_FRAME - L_NEXT; /* Present frame */ |
| 236 | p_window = old_speech + L_TOTAL - L_WINDOW; |
| 237 | |
| 238 | exc = old_exc + PIT_MAX + L_INTERPOL; |
| 239 | wsp = old_wsp + (PIT_MAX / OPL_DECIM); |
| 240 | |
| 241 | /* copy coder memory state into working space */ |
| 242 | Copy(st->old_speech, old_speech, L_TOTAL - L_FRAME); |
| 243 | Copy(st->old_wsp, old_wsp, PIT_MAX / OPL_DECIM); |
| 244 | Copy(st->old_exc, old_exc, PIT_MAX + L_INTERPOL); |
| 245 | |
| 246 | /*---------------------------------------------------------------* |
| 247 | * Down sampling signal from 16kHz to 12.8kHz * |
| 248 | * -> The signal is extended by L_FILT samples (padded to zero) * |
| 249 | * to avoid additional delay (L_FILT samples) in the coder. * |
| 250 | * The last L_FILT samples are approximated after decimation and * |
| 251 | * are used (and windowed) only in autocorrelations. * |
| 252 | *---------------------------------------------------------------*/ |
| 253 | |
| 254 | Decim_12k8(speech16k, L_FRAME16k, new_speech, st->mem_decim); |
| 255 | |
| 256 | /* last L_FILT samples for autocorrelation window */ |
| 257 | Copy(st->mem_decim, code, 2 * L_FILT16k); |
| 258 | Set_zero(error, L_FILT16k); /* set next sample to zero */ |
| 259 | Decim_12k8(error, L_FILT16k, new_speech + L_FRAME, code); |
| 260 | |
| 261 | /*---------------------------------------------------------------* |
| 262 | * Perform 50Hz HP filtering of input signal. * |
| 263 | *---------------------------------------------------------------*/ |
| 264 | |
| 265 | HP50_12k8(new_speech, L_FRAME, st->mem_sig_in); |
| 266 | |
| 267 | /* last L_FILT samples for autocorrelation window */ |
| 268 | Copy(st->mem_sig_in, code, 6); |
| 269 | HP50_12k8(new_speech + L_FRAME, L_FILT, code); |
| 270 | |
| 271 | /*---------------------------------------------------------------* |
| 272 | * Perform fixed preemphasis through 1 - g z^-1 * |
| 273 | * Scale signal to get maximum of precision in filtering * |
| 274 | *---------------------------------------------------------------*/ |
| 275 | |
| 276 | mu = PREEMPH_FAC >> 1; /* Q15 --> Q14 */ |
| 277 | |
| 278 | /* get max of new preemphased samples (L_FRAME+L_FILT) */ |
| 279 | L_tmp = new_speech[0] << 15; |
| 280 | L_tmp -= (st->mem_preemph * mu)<<1; |
| 281 | L_max = L_abs(L_tmp); |
| 282 | |
| 283 | for (i = 1; i < L_FRAME + L_FILT; i++) |
| 284 | { |
| 285 | L_tmp = new_speech[i] << 15; |
| 286 | L_tmp -= (new_speech[i - 1] * mu)<<1; |
| 287 | L_tmp = L_abs(L_tmp); |
| 288 | if(L_tmp > L_max) |
| 289 | { |
| 290 | L_max = L_tmp; |
| 291 | } |
| 292 | } |
| 293 | |
| 294 | /* get scaling factor for new and previous samples */ |
| 295 | /* limit scaling to Q_MAX to keep dynamic for ringing in low signal */ |
| 296 | /* limit scaling to Q_MAX also to avoid a[0]<1 in syn_filt_32 */ |
| 297 | tmp = extract_h(L_max); |
| 298 | if (tmp == 0) |
| 299 | { |
| 300 | shift = Q_MAX; |
| 301 | } else |
| 302 | { |
| 303 | shift = norm_s(tmp) - 1; |
| 304 | if (shift < 0) |
| 305 | { |
| 306 | shift = 0; |
| 307 | } |
| 308 | if (shift > Q_MAX) |
| 309 | { |
| 310 | shift = Q_MAX; |
| 311 | } |
| 312 | } |
| 313 | Q_new = shift; |
| 314 | if (Q_new > st->Q_max[0]) |
| 315 | { |
| 316 | Q_new = st->Q_max[0]; |
| 317 | } |
| 318 | if (Q_new > st->Q_max[1]) |
| 319 | { |
| 320 | Q_new = st->Q_max[1]; |
| 321 | } |
| 322 | exp = (Q_new - st->Q_old); |
| 323 | st->Q_old = Q_new; |
| 324 | st->Q_max[1] = st->Q_max[0]; |
| 325 | st->Q_max[0] = shift; |
| 326 | |
| 327 | /* preemphasis with scaling (L_FRAME+L_FILT) */ |
| 328 | tmp = new_speech[L_FRAME - 1]; |
| 329 | |
| 330 | for (i = L_FRAME + L_FILT - 1; i > 0; i--) |
| 331 | { |
| 332 | L_tmp = new_speech[i] << 15; |
| 333 | L_tmp -= (new_speech[i - 1] * mu)<<1; |
| 334 | L_tmp = (L_tmp << Q_new); |
| 335 | new_speech[i] = vo_round(L_tmp); |
| 336 | } |
| 337 | |
| 338 | L_tmp = new_speech[0] << 15; |
| 339 | L_tmp -= (st->mem_preemph * mu)<<1; |
| 340 | L_tmp = (L_tmp << Q_new); |
| 341 | new_speech[0] = vo_round(L_tmp); |
| 342 | |
| 343 | st->mem_preemph = tmp; |
| 344 | |
| 345 | /* scale previous samples and memory */ |
| 346 | |
| 347 | Scale_sig(old_speech, L_TOTAL - L_FRAME - L_FILT, exp); |
| 348 | Scale_sig(old_exc, PIT_MAX + L_INTERPOL, exp); |
| 349 | Scale_sig(st->mem_syn, M, exp); |
| 350 | Scale_sig(st->mem_decim2, 3, exp); |
| 351 | Scale_sig(&(st->mem_wsp), 1, exp); |
| 352 | Scale_sig(&(st->mem_w0), 1, exp); |
| 353 | |
| 354 | /*------------------------------------------------------------------------* |
| 355 | * Call VAD * |
| 356 | * Preemphesis scale down signal in low frequency and keep dynamic in HF.* |
| 357 | * Vad work slightly in futur (new_speech = speech + L_NEXT - L_FILT). * |
| 358 | *------------------------------------------------------------------------*/ |
| 359 | Copy(new_speech, buf, L_FRAME); |
| 360 | |
| 361 | #ifdef ASM_OPT /* asm optimization branch */ |
| 362 | Scale_sig_opt(buf, L_FRAME, 1 - Q_new); |
| 363 | #else |
| 364 | Scale_sig(buf, L_FRAME, 1 - Q_new); |
| 365 | #endif |
| 366 | |
| 367 | vad_flag = wb_vad(st->vadSt, buf); /* Voice Activity Detection */ |
| 368 | if (vad_flag == 0) |
| 369 | { |
| 370 | st->vad_hist = (st->vad_hist + 1); |
| 371 | } else |
| 372 | { |
| 373 | st->vad_hist = 0; |
| 374 | } |
| 375 | |
| 376 | /* DTX processing */ |
| 377 | if (allow_dtx != 0) |
| 378 | { |
| 379 | /* Note that mode may change here */ |
| 380 | tx_dtx_handler(st->dtx_encSt, vad_flag, mode); |
| 381 | *ser_size = nb_of_bits[*mode]; |
| 382 | } |
| 383 | |
| 384 | if(*mode != MRDTX) |
| 385 | { |
| 386 | Parm_serial(vad_flag, 1, &prms); |
| 387 | } |
| 388 | /*------------------------------------------------------------------------* |
| 389 | * Perform LPC analysis * |
| 390 | * ~~~~~~~~~~~~~~~~~~~~ * |
| 391 | * - autocorrelation + lag windowing * |
| 392 | * - Levinson-durbin algorithm to find a[] * |
| 393 | * - convert a[] to isp[] * |
| 394 | * - convert isp[] to isf[] for quantization * |
| 395 | * - quantize and code the isf[] * |
| 396 | * - convert isf[] to isp[] for interpolation * |
| 397 | * - find the interpolated ISPs and convert to a[] for the 4 subframes * |
| 398 | *------------------------------------------------------------------------*/ |
| 399 | |
| 400 | /* LP analysis centered at 4nd subframe */ |
| 401 | Autocorr(p_window, M, r_h, r_l); /* Autocorrelations */ |
| 402 | Lag_window(r_h, r_l); /* Lag windowing */ |
| 403 | Levinson(r_h, r_l, A, rc, st->mem_levinson); /* Levinson Durbin */ |
| 404 | Az_isp(A, ispnew, st->ispold); /* From A(z) to ISP */ |
| 405 | |
| 406 | /* Find the interpolated ISPs and convert to a[] for all subframes */ |
| 407 | Int_isp(st->ispold, ispnew, interpol_frac, A); |
| 408 | |
| 409 | /* update ispold[] for the next frame */ |
| 410 | Copy(ispnew, st->ispold, M); |
| 411 | |
| 412 | /* Convert ISPs to frequency domain 0..6400 */ |
| 413 | Isp_isf(ispnew, isf, M); |
| 414 | |
| 415 | /* check resonance for pitch clipping algorithm */ |
| 416 | Gp_clip_test_isf(isf, st->gp_clip); |
| 417 | |
| 418 | /*----------------------------------------------------------------------* |
| 419 | * Perform PITCH_OL analysis * |
| 420 | * ~~~~~~~~~~~~~~~~~~~~~~~~~ * |
| 421 | * - Find the residual res[] for the whole speech frame * |
| 422 | * - Find the weighted input speech wsp[] for the whole speech frame * |
| 423 | * - scale wsp[] to avoid overflow in pitch estimation * |
| 424 | * - Find open loop pitch lag for whole speech frame * |
| 425 | *----------------------------------------------------------------------*/ |
| 426 | p_A = A; |
| 427 | for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR) |
| 428 | { |
| 429 | /* Weighting of LPC coefficients */ |
| 430 | Weight_a(p_A, Ap, GAMMA1, M); |
| 431 | |
| 432 | #ifdef ASM_OPT /* asm optimization branch */ |
| 433 | Residu_opt(Ap, &speech[i_subfr], &wsp[i_subfr], L_SUBFR); |
| 434 | #else |
| 435 | Residu(Ap, &speech[i_subfr], &wsp[i_subfr], L_SUBFR); |
| 436 | #endif |
| 437 | |
| 438 | p_A += (M + 1); |
| 439 | } |
| 440 | |
| 441 | Deemph2(wsp, TILT_FAC, L_FRAME, &(st->mem_wsp)); |
| 442 | |
| 443 | /* find maximum value on wsp[] for 12 bits scaling */ |
| 444 | max = 0; |
| 445 | for (i = 0; i < L_FRAME; i++) |
| 446 | { |
| 447 | tmp = abs_s(wsp[i]); |
| 448 | if(tmp > max) |
| 449 | { |
| 450 | max = tmp; |
| 451 | } |
| 452 | } |
| 453 | tmp = st->old_wsp_max; |
| 454 | if(max > tmp) |
| 455 | { |
| 456 | tmp = max; /* tmp = max(wsp_max, old_wsp_max) */ |
| 457 | } |
| 458 | st->old_wsp_max = max; |
| 459 | |
| 460 | shift = norm_s(tmp) - 3; |
| 461 | if (shift > 0) |
| 462 | { |
| 463 | shift = 0; /* shift = 0..-3 */ |
| 464 | } |
| 465 | /* decimation of wsp[] to search pitch in LF and to reduce complexity */ |
| 466 | LP_Decim2(wsp, L_FRAME, st->mem_decim2); |
| 467 | |
| 468 | /* scale wsp[] in 12 bits to avoid overflow */ |
| 469 | #ifdef ASM_OPT /* asm optimization branch */ |
| 470 | Scale_sig_opt(wsp, L_FRAME / OPL_DECIM, shift); |
| 471 | #else |
| 472 | Scale_sig(wsp, L_FRAME / OPL_DECIM, shift); |
| 473 | #endif |
| 474 | /* scale old_wsp (warning: exp must be Q_new-Q_old) */ |
| 475 | exp = exp + (shift - st->old_wsp_shift); |
| 476 | st->old_wsp_shift = shift; |
| 477 | |
| 478 | Scale_sig(old_wsp, PIT_MAX / OPL_DECIM, exp); |
| 479 | Scale_sig(st->old_hp_wsp, PIT_MAX / OPL_DECIM, exp); |
| 480 | |
| 481 | scale_mem_Hp_wsp(st->hp_wsp_mem, exp); |
| 482 | |
| 483 | /* Find open loop pitch lag for whole speech frame */ |
| 484 | |
| 485 | if(*ser_size == NBBITS_7k) |
| 486 | { |
| 487 | /* Find open loop pitch lag for whole speech frame */ |
| 488 | T_op = Pitch_med_ol(wsp, st, L_FRAME / OPL_DECIM); |
| 489 | } else |
| 490 | { |
| 491 | /* Find open loop pitch lag for first 1/2 frame */ |
| 492 | T_op = Pitch_med_ol(wsp, st, (L_FRAME/2) / OPL_DECIM); |
| 493 | } |
| 494 | |
| 495 | if(st->ol_gain > 19661) /* 0.6 in Q15 */ |
| 496 | { |
| 497 | st->old_T0_med = Med_olag(T_op, st->old_ol_lag); |
| 498 | st->ada_w = 32767; |
| 499 | } else |
| 500 | { |
| 501 | st->ada_w = vo_mult(st->ada_w, 29491); |
| 502 | } |
| 503 | |
| 504 | if(st->ada_w < 26214) |
| 505 | st->ol_wght_flg = 0; |
| 506 | else |
| 507 | st->ol_wght_flg = 1; |
| 508 | |
| 509 | wb_vad_tone_detection(st->vadSt, st->ol_gain); |
| 510 | T_op *= OPL_DECIM; |
| 511 | |
| 512 | if(*ser_size != NBBITS_7k) |
| 513 | { |
| 514 | /* Find open loop pitch lag for second 1/2 frame */ |
| 515 | T_op2 = Pitch_med_ol(wsp + ((L_FRAME / 2) / OPL_DECIM), st, (L_FRAME/2) / OPL_DECIM); |
| 516 | |
| 517 | if(st->ol_gain > 19661) /* 0.6 in Q15 */ |
| 518 | { |
| 519 | st->old_T0_med = Med_olag(T_op2, st->old_ol_lag); |
| 520 | st->ada_w = 32767; |
| 521 | } else |
| 522 | { |
| 523 | st->ada_w = mult(st->ada_w, 29491); |
| 524 | } |
| 525 | |
| 526 | if(st->ada_w < 26214) |
| 527 | st->ol_wght_flg = 0; |
| 528 | else |
| 529 | st->ol_wght_flg = 1; |
| 530 | |
| 531 | wb_vad_tone_detection(st->vadSt, st->ol_gain); |
| 532 | |
| 533 | T_op2 *= OPL_DECIM; |
| 534 | |
| 535 | } else |
| 536 | { |
| 537 | T_op2 = T_op; |
| 538 | } |
| 539 | /*----------------------------------------------------------------------* |
| 540 | * DTX-CNG * |
| 541 | *----------------------------------------------------------------------*/ |
| 542 | if(*mode == MRDTX) /* CNG mode */ |
| 543 | { |
| 544 | /* Buffer isf's and energy */ |
| 545 | #ifdef ASM_OPT /* asm optimization branch */ |
| 546 | Residu_opt(&A[3 * (M + 1)], speech, exc, L_FRAME); |
| 547 | #else |
| 548 | Residu(&A[3 * (M + 1)], speech, exc, L_FRAME); |
| 549 | #endif |
| 550 | |
| 551 | for (i = 0; i < L_FRAME; i++) |
| 552 | { |
| 553 | exc2[i] = shr(exc[i], Q_new); |
| 554 | } |
| 555 | |
| 556 | L_tmp = 0; |
| 557 | for (i = 0; i < L_FRAME; i++) |
| 558 | L_tmp += (exc2[i] * exc2[i])<<1; |
| 559 | |
| 560 | L_tmp >>= 1; |
| 561 | |
| 562 | dtx_buffer(st->dtx_encSt, isf, L_tmp, codec_mode); |
| 563 | |
| 564 | /* Quantize and code the ISFs */ |
| 565 | dtx_enc(st->dtx_encSt, isf, exc2, &prms); |
| 566 | |
| 567 | /* Convert ISFs to the cosine domain */ |
| 568 | Isf_isp(isf, ispnew_q, M); |
| 569 | Isp_Az(ispnew_q, Aq, M, 0); |
| 570 | |
| 571 | for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR) |
| 572 | { |
| 573 | corr_gain = synthesis(Aq, &exc2[i_subfr], 0, &speech16k[i_subfr * 5 / 4], st); |
| 574 | } |
| 575 | Copy(isf, st->isfold, M); |
| 576 | |
| 577 | /* reset speech coder memories */ |
| 578 | Reset_encoder(st, 0); |
| 579 | |
| 580 | /*--------------------------------------------------* |
| 581 | * Update signal for next frame. * |
| 582 | * -> save past of speech[] and wsp[]. * |
| 583 | *--------------------------------------------------*/ |
| 584 | |
| 585 | Copy(&old_speech[L_FRAME], st->old_speech, L_TOTAL - L_FRAME); |
| 586 | Copy(&old_wsp[L_FRAME / OPL_DECIM], st->old_wsp, PIT_MAX / OPL_DECIM); |
| 587 | |
| 588 | return; |
| 589 | } |
| 590 | /*----------------------------------------------------------------------* |
| 591 | * ACELP * |
| 592 | *----------------------------------------------------------------------*/ |
| 593 | |
| 594 | /* Quantize and code the ISFs */ |
| 595 | |
| 596 | if (*ser_size <= NBBITS_7k) |
| 597 | { |
| 598 | Qpisf_2s_36b(isf, isf, st->past_isfq, indice, 4); |
| 599 | |
| 600 | Parm_serial(indice[0], 8, &prms); |
| 601 | Parm_serial(indice[1], 8, &prms); |
| 602 | Parm_serial(indice[2], 7, &prms); |
| 603 | Parm_serial(indice[3], 7, &prms); |
| 604 | Parm_serial(indice[4], 6, &prms); |
| 605 | } else |
| 606 | { |
| 607 | Qpisf_2s_46b(isf, isf, st->past_isfq, indice, 4); |
| 608 | |
| 609 | Parm_serial(indice[0], 8, &prms); |
| 610 | Parm_serial(indice[1], 8, &prms); |
| 611 | Parm_serial(indice[2], 6, &prms); |
| 612 | Parm_serial(indice[3], 7, &prms); |
| 613 | Parm_serial(indice[4], 7, &prms); |
| 614 | Parm_serial(indice[5], 5, &prms); |
| 615 | Parm_serial(indice[6], 5, &prms); |
| 616 | } |
| 617 | |
| 618 | /* Check stability on isf : distance between old isf and current isf */ |
| 619 | |
| 620 | L_tmp = 0; |
| 621 | for (i = 0; i < M - 1; i++) |
| 622 | { |
| 623 | tmp = vo_sub(isf[i], st->isfold[i]); |
| 624 | L_tmp += (tmp * tmp)<<1; |
| 625 | } |
| 626 | |
| 627 | tmp = extract_h(L_shl2(L_tmp, 8)); |
| 628 | |
| 629 | tmp = vo_mult(tmp, 26214); /* tmp = L_tmp*0.8/256 */ |
| 630 | tmp = vo_sub(20480, tmp); /* 1.25 - tmp (in Q14) */ |
| 631 | |
| 632 | stab_fac = shl(tmp, 1); |
| 633 | |
| 634 | if (stab_fac < 0) |
| 635 | { |
| 636 | stab_fac = 0; |
| 637 | } |
| 638 | Copy(isf, st->isfold, M); |
| 639 | |
| 640 | /* Convert ISFs to the cosine domain */ |
| 641 | Isf_isp(isf, ispnew_q, M); |
| 642 | |
| 643 | if (st->first_frame != 0) |
| 644 | { |
| 645 | st->first_frame = 0; |
| 646 | Copy(ispnew_q, st->ispold_q, M); |
| 647 | } |
| 648 | /* Find the interpolated ISPs and convert to a[] for all subframes */ |
| 649 | |
| 650 | Int_isp(st->ispold_q, ispnew_q, interpol_frac, Aq); |
| 651 | |
| 652 | /* update ispold[] for the next frame */ |
| 653 | Copy(ispnew_q, st->ispold_q, M); |
| 654 | |
| 655 | p_Aq = Aq; |
| 656 | for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR) |
| 657 | { |
| 658 | #ifdef ASM_OPT /* asm optimization branch */ |
| 659 | Residu_opt(p_Aq, &speech[i_subfr], &exc[i_subfr], L_SUBFR); |
| 660 | #else |
| 661 | Residu(p_Aq, &speech[i_subfr], &exc[i_subfr], L_SUBFR); |
| 662 | #endif |
| 663 | p_Aq += (M + 1); |
| 664 | } |
| 665 | |
| 666 | /* Buffer isf's and energy for dtx on non-speech frame */ |
| 667 | if (vad_flag == 0) |
| 668 | { |
| 669 | for (i = 0; i < L_FRAME; i++) |
| 670 | { |
| 671 | exc2[i] = exc[i] >> Q_new; |
| 672 | } |
| 673 | L_tmp = 0; |
| 674 | for (i = 0; i < L_FRAME; i++) |
| 675 | L_tmp += (exc2[i] * exc2[i])<<1; |
| 676 | L_tmp >>= 1; |
| 677 | |
| 678 | dtx_buffer(st->dtx_encSt, isf, L_tmp, codec_mode); |
| 679 | } |
| 680 | /* range for closed loop pitch search in 1st subframe */ |
| 681 | |
| 682 | T0_min = T_op - 8; |
| 683 | if (T0_min < PIT_MIN) |
| 684 | { |
| 685 | T0_min = PIT_MIN; |
| 686 | } |
| 687 | T0_max = (T0_min + 15); |
| 688 | |
| 689 | if(T0_max > PIT_MAX) |
| 690 | { |
| 691 | T0_max = PIT_MAX; |
| 692 | T0_min = T0_max - 15; |
| 693 | } |
| 694 | /*------------------------------------------------------------------------* |
| 695 | * Loop for every subframe in the analysis frame * |
| 696 | *------------------------------------------------------------------------* |
| 697 | * To find the pitch and innovation parameters. The subframe size is * |
| 698 | * L_SUBFR and the loop is repeated L_FRAME/L_SUBFR times. * |
| 699 | * - compute the target signal for pitch search * |
| 700 | * - compute impulse response of weighted synthesis filter (h1[]) * |
| 701 | * - find the closed-loop pitch parameters * |
| 702 | * - encode the pitch dealy * |
| 703 | * - find 2 lt prediction (with / without LP filter for lt pred) * |
| 704 | * - find 2 pitch gains and choose the best lt prediction. * |
| 705 | * - find target vector for codebook search * |
| 706 | * - update the impulse response h1[] for codebook search * |
| 707 | * - correlation between target vector and impulse response * |
| 708 | * - codebook search and encoding * |
| 709 | * - VQ of pitch and codebook gains * |
| 710 | * - find voicing factor and tilt of code for next subframe. * |
| 711 | * - update states of weighting filter * |
| 712 | * - find excitation and synthesis speech * |
| 713 | *------------------------------------------------------------------------*/ |
| 714 | p_A = A; |
| 715 | p_Aq = Aq; |
| 716 | for (i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR) |
| 717 | { |
| 718 | pit_flag = i_subfr; |
| 719 | if ((i_subfr == 2 * L_SUBFR) && (*ser_size > NBBITS_7k)) |
| 720 | { |
| 721 | pit_flag = 0; |
| 722 | /* range for closed loop pitch search in 3rd subframe */ |
| 723 | T0_min = (T_op2 - 8); |
| 724 | |
| 725 | if (T0_min < PIT_MIN) |
| 726 | { |
| 727 | T0_min = PIT_MIN; |
| 728 | } |
| 729 | T0_max = (T0_min + 15); |
| 730 | if (T0_max > PIT_MAX) |
| 731 | { |
| 732 | T0_max = PIT_MAX; |
| 733 | T0_min = (T0_max - 15); |
| 734 | } |
| 735 | } |
| 736 | /*-----------------------------------------------------------------------* |
| 737 | * * |
| 738 | * Find the target vector for pitch search: * |
| 739 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * |
| 740 | * * |
| 741 | * |------| res[n] * |
| 742 | * speech[n]---| A(z) |-------- * |
| 743 | * |------| | |--------| error[n] |------| * |
| 744 | * zero -- (-)--| 1/A(z) |-----------| W(z) |-- target * |
| 745 | * exc |--------| |------| * |
| 746 | * * |
| 747 | * Instead of subtracting the zero-input response of filters from * |
| 748 | * the weighted input speech, the above configuration is used to * |
| 749 | * compute the target vector. * |
| 750 | * * |
| 751 | *-----------------------------------------------------------------------*/ |
| 752 | |
| 753 | for (i = 0; i < M; i++) |
| 754 | { |
| 755 | error[i] = vo_sub(speech[i + i_subfr - M], st->mem_syn[i]); |
| 756 | } |
| 757 | |
| 758 | #ifdef ASM_OPT /* asm optimization branch */ |
| 759 | Residu_opt(p_Aq, &speech[i_subfr], &exc[i_subfr], L_SUBFR); |
| 760 | #else |
| 761 | Residu(p_Aq, &speech[i_subfr], &exc[i_subfr], L_SUBFR); |
| 762 | #endif |
| 763 | Syn_filt(p_Aq, &exc[i_subfr], error + M, L_SUBFR, error, 0); |
| 764 | Weight_a(p_A, Ap, GAMMA1, M); |
| 765 | |
| 766 | #ifdef ASM_OPT /* asm optimization branch */ |
| 767 | Residu_opt(Ap, error + M, xn, L_SUBFR); |
| 768 | #else |
| 769 | Residu(Ap, error + M, xn, L_SUBFR); |
| 770 | #endif |
| 771 | Deemph2(xn, TILT_FAC, L_SUBFR, &(st->mem_w0)); |
| 772 | |
| 773 | /*----------------------------------------------------------------------* |
| 774 | * Find approx. target in residual domain "cn[]" for inovation search. * |
| 775 | *----------------------------------------------------------------------*/ |
| 776 | /* first half: xn[] --> cn[] */ |
| 777 | Set_zero(code, M); |
| 778 | Copy(xn, code + M, L_SUBFR / 2); |
| 779 | tmp = 0; |
| 780 | Preemph2(code + M, TILT_FAC, L_SUBFR / 2, &tmp); |
| 781 | Weight_a(p_A, Ap, GAMMA1, M); |
| 782 | Syn_filt(Ap,code + M, code + M, L_SUBFR / 2, code, 0); |
| 783 | |
| 784 | #ifdef ASM_OPT /* asm optimization branch */ |
| 785 | Residu_opt(p_Aq,code + M, cn, L_SUBFR / 2); |
| 786 | #else |
| 787 | Residu(p_Aq,code + M, cn, L_SUBFR / 2); |
| 788 | #endif |
| 789 | |
| 790 | /* second half: res[] --> cn[] (approximated and faster) */ |
| 791 | Copy(&exc[i_subfr + (L_SUBFR / 2)], cn + (L_SUBFR / 2), L_SUBFR / 2); |
| 792 | |
| 793 | /*---------------------------------------------------------------* |
| 794 | * Compute impulse response, h1[], of weighted synthesis filter * |
| 795 | *---------------------------------------------------------------*/ |
| 796 | |
| 797 | Set_zero(error, M + L_SUBFR); |
| 798 | Weight_a(p_A, error + M, GAMMA1, M); |
| 799 | |
| 800 | vo_p0 = error+M; |
| 801 | vo_p3 = h1; |
| 802 | for (i = 0; i < L_SUBFR; i++) |
| 803 | { |
| 804 | L_tmp = *vo_p0 << 14; /* x4 (Q12 to Q14) */ |
| 805 | vo_p1 = p_Aq + 1; |
| 806 | vo_p2 = vo_p0-1; |
| 807 | for (j = 1; j <= M/4; j++) |
| 808 | { |
| 809 | L_tmp -= *vo_p1++ * *vo_p2--; |
| 810 | L_tmp -= *vo_p1++ * *vo_p2--; |
| 811 | L_tmp -= *vo_p1++ * *vo_p2--; |
| 812 | L_tmp -= *vo_p1++ * *vo_p2--; |
| 813 | } |
| 814 | *vo_p3++ = *vo_p0++ = vo_round((L_tmp <<4)); |
| 815 | } |
| 816 | /* deemph without division by 2 -> Q14 to Q15 */ |
| 817 | tmp = 0; |
| 818 | Deemph2(h1, TILT_FAC, L_SUBFR, &tmp); /* h1 in Q14 */ |
| 819 | |
| 820 | /* h2 in Q12 for codebook search */ |
| 821 | Copy(h1, h2, L_SUBFR); |
| 822 | |
| 823 | /*---------------------------------------------------------------* |
| 824 | * scale xn[] and h1[] to avoid overflow in dot_product12() * |
| 825 | *---------------------------------------------------------------*/ |
| 826 | #ifdef ASM_OPT /* asm optimization branch */ |
| 827 | Scale_sig_opt(h2, L_SUBFR, -2); |
| 828 | Scale_sig_opt(xn, L_SUBFR, shift); /* scaling of xn[] to limit dynamic at 12 bits */ |
| 829 | Scale_sig_opt(h1, L_SUBFR, 1 + shift); /* set h1[] in Q15 with scaling for convolution */ |
| 830 | #else |
| 831 | Scale_sig(h2, L_SUBFR, -2); |
| 832 | Scale_sig(xn, L_SUBFR, shift); /* scaling of xn[] to limit dynamic at 12 bits */ |
| 833 | Scale_sig(h1, L_SUBFR, 1 + shift); /* set h1[] in Q15 with scaling for convolution */ |
| 834 | #endif |
| 835 | /*----------------------------------------------------------------------* |
| 836 | * Closed-loop fractional pitch search * |
| 837 | *----------------------------------------------------------------------*/ |
| 838 | /* find closed loop fractional pitch lag */ |
| 839 | if(*ser_size <= NBBITS_9k) |
| 840 | { |
| 841 | T0 = Pitch_fr4(&exc[i_subfr], xn, h1, T0_min, T0_max, &T0_frac, |
| 842 | pit_flag, PIT_MIN, PIT_FR1_8b, L_SUBFR); |
| 843 | |
| 844 | /* encode pitch lag */ |
| 845 | if (pit_flag == 0) /* if 1st/3rd subframe */ |
| 846 | { |
| 847 | /*--------------------------------------------------------------* |
| 848 | * The pitch range for the 1st/3rd subframe is encoded with * |
| 849 | * 8 bits and is divided as follows: * |
| 850 | * PIT_MIN to PIT_FR1-1 resolution 1/2 (frac = 0 or 2) * |
| 851 | * PIT_FR1 to PIT_MAX resolution 1 (frac = 0) * |
| 852 | *--------------------------------------------------------------*/ |
| 853 | if (T0 < PIT_FR1_8b) |
| 854 | { |
| 855 | index = ((T0 << 1) + (T0_frac >> 1) - (PIT_MIN<<1)); |
| 856 | } else |
| 857 | { |
| 858 | index = ((T0 - PIT_FR1_8b) + ((PIT_FR1_8b - PIT_MIN)*2)); |
| 859 | } |
| 860 | |
| 861 | Parm_serial(index, 8, &prms); |
| 862 | |
| 863 | /* find T0_min and T0_max for subframe 2 and 4 */ |
| 864 | T0_min = (T0 - 8); |
| 865 | if (T0_min < PIT_MIN) |
| 866 | { |
| 867 | T0_min = PIT_MIN; |
| 868 | } |
| 869 | T0_max = T0_min + 15; |
| 870 | if (T0_max > PIT_MAX) |
| 871 | { |
| 872 | T0_max = PIT_MAX; |
| 873 | T0_min = (T0_max - 15); |
| 874 | } |
| 875 | } else |
| 876 | { /* if subframe 2 or 4 */ |
| 877 | /*--------------------------------------------------------------* |
| 878 | * The pitch range for subframe 2 or 4 is encoded with 5 bits: * |
| 879 | * T0_min to T0_max resolution 1/2 (frac = 0 or 2) * |
| 880 | *--------------------------------------------------------------*/ |
| 881 | i = (T0 - T0_min); |
| 882 | index = (i << 1) + (T0_frac >> 1); |
| 883 | |
| 884 | Parm_serial(index, 5, &prms); |
| 885 | } |
| 886 | } else |
| 887 | { |
| 888 | T0 = Pitch_fr4(&exc[i_subfr], xn, h1, T0_min, T0_max, &T0_frac, |
| 889 | pit_flag, PIT_FR2, PIT_FR1_9b, L_SUBFR); |
| 890 | |
| 891 | /* encode pitch lag */ |
| 892 | if (pit_flag == 0) /* if 1st/3rd subframe */ |
| 893 | { |
| 894 | /*--------------------------------------------------------------* |
| 895 | * The pitch range for the 1st/3rd subframe is encoded with * |
| 896 | * 9 bits and is divided as follows: * |
| 897 | * PIT_MIN to PIT_FR2-1 resolution 1/4 (frac = 0,1,2 or 3) * |
| 898 | * PIT_FR2 to PIT_FR1-1 resolution 1/2 (frac = 0 or 1) * |
| 899 | * PIT_FR1 to PIT_MAX resolution 1 (frac = 0) * |
| 900 | *--------------------------------------------------------------*/ |
| 901 | |
| 902 | if (T0 < PIT_FR2) |
| 903 | { |
| 904 | index = ((T0 << 2) + T0_frac) - (PIT_MIN << 2); |
| 905 | } else if(T0 < PIT_FR1_9b) |
| 906 | { |
| 907 | index = ((((T0 << 1) + (T0_frac >> 1)) - (PIT_FR2<<1)) + ((PIT_FR2 - PIT_MIN)<<2)); |
| 908 | } else |
| 909 | { |
| 910 | index = (((T0 - PIT_FR1_9b) + ((PIT_FR2 - PIT_MIN)<<2)) + ((PIT_FR1_9b - PIT_FR2)<<1)); |
| 911 | } |
| 912 | |
| 913 | Parm_serial(index, 9, &prms); |
| 914 | |
| 915 | /* find T0_min and T0_max for subframe 2 and 4 */ |
| 916 | |
| 917 | T0_min = (T0 - 8); |
| 918 | if (T0_min < PIT_MIN) |
| 919 | { |
| 920 | T0_min = PIT_MIN; |
| 921 | } |
| 922 | T0_max = T0_min + 15; |
| 923 | |
| 924 | if (T0_max > PIT_MAX) |
| 925 | { |
| 926 | T0_max = PIT_MAX; |
| 927 | T0_min = (T0_max - 15); |
| 928 | } |
| 929 | } else |
| 930 | { /* if subframe 2 or 4 */ |
| 931 | /*--------------------------------------------------------------* |
| 932 | * The pitch range for subframe 2 or 4 is encoded with 6 bits: * |
| 933 | * T0_min to T0_max resolution 1/4 (frac = 0,1,2 or 3) * |
| 934 | *--------------------------------------------------------------*/ |
| 935 | i = (T0 - T0_min); |
| 936 | index = (i << 2) + T0_frac; |
| 937 | Parm_serial(index, 6, &prms); |
| 938 | } |
| 939 | } |
| 940 | |
| 941 | /*-----------------------------------------------------------------* |
| 942 | * Gain clipping test to avoid unstable synthesis on frame erasure * |
| 943 | *-----------------------------------------------------------------*/ |
| 944 | |
| 945 | clip_gain = 0; |
| 946 | if((st->gp_clip[0] < 154) && (st->gp_clip[1] > 14746)) |
| 947 | clip_gain = 1; |
| 948 | |
| 949 | /*-----------------------------------------------------------------* |
| 950 | * - find unity gain pitch excitation (adaptive codebook entry) * |
| 951 | * with fractional interpolation. * |
| 952 | * - find filtered pitch exc. y1[]=exc[] convolved with h1[]) * |
| 953 | * - compute pitch gain1 * |
| 954 | *-----------------------------------------------------------------*/ |
| 955 | /* find pitch exitation */ |
| 956 | #ifdef ASM_OPT /* asm optimization branch */ |
| 957 | pred_lt4_asm(&exc[i_subfr], T0, T0_frac, L_SUBFR + 1); |
| 958 | #else |
| 959 | Pred_lt4(&exc[i_subfr], T0, T0_frac, L_SUBFR + 1); |
| 960 | #endif |
| 961 | if (*ser_size > NBBITS_9k) |
| 962 | { |
| 963 | #ifdef ASM_OPT /* asm optimization branch */ |
| 964 | Convolve_asm(&exc[i_subfr], h1, y1, L_SUBFR); |
| 965 | #else |
| 966 | Convolve(&exc[i_subfr], h1, y1, L_SUBFR); |
| 967 | #endif |
| 968 | gain1 = G_pitch(xn, y1, g_coeff, L_SUBFR); |
| 969 | /* clip gain if necessary to avoid problem at decoder */ |
| 970 | if ((clip_gain != 0) && (gain1 > GP_CLIP)) |
| 971 | { |
| 972 | gain1 = GP_CLIP; |
| 973 | } |
| 974 | /* find energy of new target xn2[] */ |
| 975 | Updt_tar(xn, dn, y1, gain1, L_SUBFR); /* dn used temporary */ |
| 976 | } else |
| 977 | { |
| 978 | gain1 = 0; |
| 979 | } |
| 980 | /*-----------------------------------------------------------------* |
| 981 | * - find pitch excitation filtered by 1st order LP filter. * |
| 982 | * - find filtered pitch exc. y2[]=exc[] convolved with h1[]) * |
| 983 | * - compute pitch gain2 * |
| 984 | *-----------------------------------------------------------------*/ |
| 985 | /* find pitch excitation with lp filter */ |
| 986 | vo_p0 = exc + i_subfr-1; |
| 987 | vo_p1 = code; |
| 988 | /* find pitch excitation with lp filter */ |
| 989 | for (i = 0; i < L_SUBFR/2; i++) |
| 990 | { |
| 991 | L_tmp = 5898 * *vo_p0++; |
| 992 | L_tmp1 = 5898 * *vo_p0; |
| 993 | L_tmp += 20972 * *vo_p0++; |
| 994 | L_tmp1 += 20972 * *vo_p0++; |
| 995 | L_tmp1 += 5898 * *vo_p0--; |
| 996 | L_tmp += 5898 * *vo_p0; |
| 997 | *vo_p1++ = (L_tmp + 0x4000)>>15; |
| 998 | *vo_p1++ = (L_tmp1 + 0x4000)>>15; |
| 999 | } |
| 1000 | |
| 1001 | #ifdef ASM_OPT /* asm optimization branch */ |
| 1002 | Convolve_asm(code, h1, y2, L_SUBFR); |
| 1003 | #else |
| 1004 | Convolve(code, h1, y2, L_SUBFR); |
| 1005 | #endif |
| 1006 | |
| 1007 | gain2 = G_pitch(xn, y2, g_coeff2, L_SUBFR); |
| 1008 | |
| 1009 | /* clip gain if necessary to avoid problem at decoder */ |
| 1010 | if ((clip_gain != 0) && (gain2 > GP_CLIP)) |
| 1011 | { |
| 1012 | gain2 = GP_CLIP; |
| 1013 | } |
| 1014 | /* find energy of new target xn2[] */ |
| 1015 | Updt_tar(xn, xn2, y2, gain2, L_SUBFR); |
| 1016 | /*-----------------------------------------------------------------* |
| 1017 | * use the best prediction (minimise quadratic error). * |
| 1018 | *-----------------------------------------------------------------*/ |
| 1019 | select = 0; |
| 1020 | if(*ser_size > NBBITS_9k) |
| 1021 | { |
| 1022 | L_tmp = 0L; |
| 1023 | vo_p0 = dn; |
| 1024 | vo_p1 = xn2; |
| 1025 | for (i = 0; i < L_SUBFR/2; i++) |
| 1026 | { |
| 1027 | L_tmp += *vo_p0 * *vo_p0; |
| 1028 | vo_p0++; |
| 1029 | L_tmp -= *vo_p1 * *vo_p1; |
| 1030 | vo_p1++; |
| 1031 | L_tmp += *vo_p0 * *vo_p0; |
| 1032 | vo_p0++; |
| 1033 | L_tmp -= *vo_p1 * *vo_p1; |
| 1034 | vo_p1++; |
| 1035 | } |
| 1036 | |
| 1037 | if (L_tmp <= 0) |
| 1038 | { |
| 1039 | select = 1; |
| 1040 | } |
| 1041 | Parm_serial(select, 1, &prms); |
| 1042 | } |
| 1043 | if (select == 0) |
| 1044 | { |
| 1045 | /* use the lp filter for pitch excitation prediction */ |
| 1046 | gain_pit = gain2; |
| 1047 | Copy(code, &exc[i_subfr], L_SUBFR); |
| 1048 | Copy(y2, y1, L_SUBFR); |
| 1049 | Copy(g_coeff2, g_coeff, 4); |
| 1050 | } else |
| 1051 | { |
| 1052 | /* no filter used for pitch excitation prediction */ |
| 1053 | gain_pit = gain1; |
| 1054 | Copy(dn, xn2, L_SUBFR); /* target vector for codebook search */ |
| 1055 | } |
| 1056 | /*-----------------------------------------------------------------* |
| 1057 | * - update cn[] for codebook search * |
| 1058 | *-----------------------------------------------------------------*/ |
| 1059 | Updt_tar(cn, cn, &exc[i_subfr], gain_pit, L_SUBFR); |
| 1060 | |
| 1061 | #ifdef ASM_OPT /* asm optimization branch */ |
| 1062 | Scale_sig_opt(cn, L_SUBFR, shift); /* scaling of cn[] to limit dynamic at 12 bits */ |
| 1063 | #else |
| 1064 | Scale_sig(cn, L_SUBFR, shift); /* scaling of cn[] to limit dynamic at 12 bits */ |
| 1065 | #endif |
| 1066 | /*-----------------------------------------------------------------* |
| 1067 | * - include fixed-gain pitch contribution into impulse resp. h1[] * |
| 1068 | *-----------------------------------------------------------------*/ |
| 1069 | tmp = 0; |
| 1070 | Preemph(h2, st->tilt_code, L_SUBFR, &tmp); |
| 1071 | |
| 1072 | if (T0_frac > 2) |
| 1073 | T0 = (T0 + 1); |
| 1074 | Pit_shrp(h2, T0, PIT_SHARP, L_SUBFR); |
| 1075 | /*-----------------------------------------------------------------* |
| 1076 | * - Correlation between target xn2[] and impulse response h1[] * |
| 1077 | * - Innovative codebook search * |
| 1078 | *-----------------------------------------------------------------*/ |
| 1079 | cor_h_x(h2, xn2, dn); |
| 1080 | if (*ser_size <= NBBITS_7k) |
| 1081 | { |
| 1082 | ACELP_2t64_fx(dn, cn, h2, code, y2, indice); |
| 1083 | |
| 1084 | Parm_serial(indice[0], 12, &prms); |
| 1085 | } else if(*ser_size <= NBBITS_9k) |
| 1086 | { |
| 1087 | ACELP_4t64_fx(dn, cn, h2, code, y2, 20, *ser_size, indice); |
| 1088 | |
| 1089 | Parm_serial(indice[0], 5, &prms); |
| 1090 | Parm_serial(indice[1], 5, &prms); |
| 1091 | Parm_serial(indice[2], 5, &prms); |
| 1092 | Parm_serial(indice[3], 5, &prms); |
| 1093 | } else if(*ser_size <= NBBITS_12k) |
| 1094 | { |
| 1095 | ACELP_4t64_fx(dn, cn, h2, code, y2, 36, *ser_size, indice); |
| 1096 | |
| 1097 | Parm_serial(indice[0], 9, &prms); |
| 1098 | Parm_serial(indice[1], 9, &prms); |
| 1099 | Parm_serial(indice[2], 9, &prms); |
| 1100 | Parm_serial(indice[3], 9, &prms); |
| 1101 | } else if(*ser_size <= NBBITS_14k) |
| 1102 | { |
| 1103 | ACELP_4t64_fx(dn, cn, h2, code, y2, 44, *ser_size, indice); |
| 1104 | |
| 1105 | Parm_serial(indice[0], 13, &prms); |
| 1106 | Parm_serial(indice[1], 13, &prms); |
| 1107 | Parm_serial(indice[2], 9, &prms); |
| 1108 | Parm_serial(indice[3], 9, &prms); |
| 1109 | } else if(*ser_size <= NBBITS_16k) |
| 1110 | { |
| 1111 | ACELP_4t64_fx(dn, cn, h2, code, y2, 52, *ser_size, indice); |
| 1112 | |
| 1113 | Parm_serial(indice[0], 13, &prms); |
| 1114 | Parm_serial(indice[1], 13, &prms); |
| 1115 | Parm_serial(indice[2], 13, &prms); |
| 1116 | Parm_serial(indice[3], 13, &prms); |
| 1117 | } else if(*ser_size <= NBBITS_18k) |
| 1118 | { |
| 1119 | ACELP_4t64_fx(dn, cn, h2, code, y2, 64, *ser_size, indice); |
| 1120 | |
| 1121 | Parm_serial(indice[0], 2, &prms); |
| 1122 | Parm_serial(indice[1], 2, &prms); |
| 1123 | Parm_serial(indice[2], 2, &prms); |
| 1124 | Parm_serial(indice[3], 2, &prms); |
| 1125 | Parm_serial(indice[4], 14, &prms); |
| 1126 | Parm_serial(indice[5], 14, &prms); |
| 1127 | Parm_serial(indice[6], 14, &prms); |
| 1128 | Parm_serial(indice[7], 14, &prms); |
| 1129 | } else if(*ser_size <= NBBITS_20k) |
| 1130 | { |
| 1131 | ACELP_4t64_fx(dn, cn, h2, code, y2, 72, *ser_size, indice); |
| 1132 | |
| 1133 | Parm_serial(indice[0], 10, &prms); |
| 1134 | Parm_serial(indice[1], 10, &prms); |
| 1135 | Parm_serial(indice[2], 2, &prms); |
| 1136 | Parm_serial(indice[3], 2, &prms); |
| 1137 | Parm_serial(indice[4], 10, &prms); |
| 1138 | Parm_serial(indice[5], 10, &prms); |
| 1139 | Parm_serial(indice[6], 14, &prms); |
| 1140 | Parm_serial(indice[7], 14, &prms); |
| 1141 | } else |
| 1142 | { |
| 1143 | ACELP_4t64_fx(dn, cn, h2, code, y2, 88, *ser_size, indice); |
| 1144 | |
| 1145 | Parm_serial(indice[0], 11, &prms); |
| 1146 | Parm_serial(indice[1], 11, &prms); |
| 1147 | Parm_serial(indice[2], 11, &prms); |
| 1148 | Parm_serial(indice[3], 11, &prms); |
| 1149 | Parm_serial(indice[4], 11, &prms); |
| 1150 | Parm_serial(indice[5], 11, &prms); |
| 1151 | Parm_serial(indice[6], 11, &prms); |
| 1152 | Parm_serial(indice[7], 11, &prms); |
| 1153 | } |
| 1154 | /*-------------------------------------------------------* |
| 1155 | * - Add the fixed-gain pitch contribution to code[]. * |
| 1156 | *-------------------------------------------------------*/ |
| 1157 | tmp = 0; |
| 1158 | Preemph(code, st->tilt_code, L_SUBFR, &tmp); |
| 1159 | Pit_shrp(code, T0, PIT_SHARP, L_SUBFR); |
| 1160 | /*----------------------------------------------------------* |
| 1161 | * - Compute the fixed codebook gain * |
| 1162 | * - quantize fixed codebook gain * |
| 1163 | *----------------------------------------------------------*/ |
| 1164 | if(*ser_size <= NBBITS_9k) |
| 1165 | { |
| 1166 | index = Q_gain2(xn, y1, Q_new + shift, y2, code, g_coeff, L_SUBFR, 6, |
| 1167 | &gain_pit, &L_gain_code, clip_gain, st->qua_gain); |
| 1168 | Parm_serial(index, 6, &prms); |
| 1169 | } else |
| 1170 | { |
| 1171 | index = Q_gain2(xn, y1, Q_new + shift, y2, code, g_coeff, L_SUBFR, 7, |
| 1172 | &gain_pit, &L_gain_code, clip_gain, st->qua_gain); |
| 1173 | Parm_serial(index, 7, &prms); |
| 1174 | } |
| 1175 | /* test quantized gain of pitch for pitch clipping algorithm */ |
| 1176 | Gp_clip_test_gain_pit(gain_pit, st->gp_clip); |
| 1177 | |
| 1178 | L_tmp = L_shl(L_gain_code, Q_new); |
| 1179 | gain_code = extract_h(L_add(L_tmp, 0x8000)); |
| 1180 | |
| 1181 | /*----------------------------------------------------------* |
| 1182 | * Update parameters for the next subframe. * |
| 1183 | * - tilt of code: 0.0 (unvoiced) to 0.5 (voiced) * |
| 1184 | *----------------------------------------------------------*/ |
| 1185 | /* find voice factor in Q15 (1=voiced, -1=unvoiced) */ |
| 1186 | Copy(&exc[i_subfr], exc2, L_SUBFR); |
| 1187 | |
| 1188 | #ifdef ASM_OPT /* asm optimization branch */ |
| 1189 | Scale_sig_opt(exc2, L_SUBFR, shift); |
| 1190 | #else |
| 1191 | Scale_sig(exc2, L_SUBFR, shift); |
| 1192 | #endif |
| 1193 | voice_fac = voice_factor(exc2, shift, gain_pit, code, gain_code, L_SUBFR); |
| 1194 | /* tilt of code for next subframe: 0.5=voiced, 0=unvoiced */ |
| 1195 | st->tilt_code = ((voice_fac >> 2) + 8192); |
| 1196 | /*------------------------------------------------------* |
| 1197 | * - Update filter's memory "mem_w0" for finding the * |
| 1198 | * target vector in the next subframe. * |
| 1199 | * - Find the total excitation * |
| 1200 | * - Find synthesis speech to update mem_syn[]. * |
| 1201 | *------------------------------------------------------*/ |
| 1202 | |
| 1203 | /* y2 in Q9, gain_pit in Q14 */ |
| 1204 | L_tmp = (gain_code * y2[L_SUBFR - 1])<<1; |
| 1205 | L_tmp = L_shl(L_tmp, (5 + shift)); |
| 1206 | L_tmp = L_negate(L_tmp); |
| 1207 | L_tmp += (xn[L_SUBFR - 1] * 16384)<<1; |
| 1208 | L_tmp -= (y1[L_SUBFR - 1] * gain_pit)<<1; |
| 1209 | L_tmp = L_shl(L_tmp, (1 - shift)); |
| 1210 | st->mem_w0 = extract_h(L_add(L_tmp, 0x8000)); |
| 1211 | |
| 1212 | if (*ser_size >= NBBITS_24k) |
| 1213 | Copy(&exc[i_subfr], exc2, L_SUBFR); |
| 1214 | |
| 1215 | for (i = 0; i < L_SUBFR; i++) |
| 1216 | { |
| 1217 | /* code in Q9, gain_pit in Q14 */ |
| 1218 | L_tmp = (gain_code * code[i])<<1; |
| 1219 | L_tmp = (L_tmp << 5); |
| 1220 | L_tmp += (exc[i + i_subfr] * gain_pit)<<1; |
| 1221 | L_tmp = L_shl2(L_tmp, 1); |
| 1222 | exc[i + i_subfr] = extract_h(L_add(L_tmp, 0x8000)); |
| 1223 | } |
| 1224 | |
| 1225 | Syn_filt(p_Aq,&exc[i_subfr], synth, L_SUBFR, st->mem_syn, 1); |
| 1226 | |
| 1227 | if(*ser_size >= NBBITS_24k) |
| 1228 | { |
| 1229 | /*------------------------------------------------------------* |
| 1230 | * phase dispersion to enhance noise in low bit rate * |
| 1231 | *------------------------------------------------------------*/ |
| 1232 | /* L_gain_code in Q16 */ |
| 1233 | VO_L_Extract(L_gain_code, &gain_code, &gain_code_lo); |
| 1234 | |
| 1235 | /*------------------------------------------------------------* |
| 1236 | * noise enhancer * |
| 1237 | * ~~~~~~~~~~~~~~ * |
| 1238 | * - Enhance excitation on noise. (modify gain of code) * |
| 1239 | * If signal is noisy and LPC filter is stable, move gain * |
| 1240 | * of code 1.5 dB toward gain of code threshold. * |
| 1241 | * This decrease by 3 dB noise energy variation. * |
| 1242 | *------------------------------------------------------------*/ |
| 1243 | tmp = (16384 - (voice_fac >> 1)); /* 1=unvoiced, 0=voiced */ |
| 1244 | fac = vo_mult(stab_fac, tmp); |
| 1245 | L_tmp = L_gain_code; |
| 1246 | if(L_tmp < st->L_gc_thres) |
| 1247 | { |
| 1248 | L_tmp = vo_L_add(L_tmp, Mpy_32_16(gain_code, gain_code_lo, 6226)); |
| 1249 | if(L_tmp > st->L_gc_thres) |
| 1250 | { |
| 1251 | L_tmp = st->L_gc_thres; |
| 1252 | } |
| 1253 | } else |
| 1254 | { |
| 1255 | L_tmp = Mpy_32_16(gain_code, gain_code_lo, 27536); |
| 1256 | if(L_tmp < st->L_gc_thres) |
| 1257 | { |
| 1258 | L_tmp = st->L_gc_thres; |
| 1259 | } |
| 1260 | } |
| 1261 | st->L_gc_thres = L_tmp; |
| 1262 | |
| 1263 | L_gain_code = Mpy_32_16(gain_code, gain_code_lo, (32767 - fac)); |
| 1264 | VO_L_Extract(L_tmp, &gain_code, &gain_code_lo); |
| 1265 | L_gain_code = vo_L_add(L_gain_code, Mpy_32_16(gain_code, gain_code_lo, fac)); |
| 1266 | |
| 1267 | /*------------------------------------------------------------* |
| 1268 | * pitch enhancer * |
| 1269 | * ~~~~~~~~~~~~~~ * |
| 1270 | * - Enhance excitation on voice. (HP filtering of code) * |
| 1271 | * On voiced signal, filtering of code by a smooth fir HP * |
| 1272 | * filter to decrease energy of code in low frequency. * |
| 1273 | *------------------------------------------------------------*/ |
| 1274 | |
| 1275 | tmp = ((voice_fac >> 3) + 4096); /* 0.25=voiced, 0=unvoiced */ |
| 1276 | |
| 1277 | L_tmp = L_deposit_h(code[0]); |
| 1278 | L_tmp -= (code[1] * tmp)<<1; |
| 1279 | code2[0] = vo_round(L_tmp); |
| 1280 | |
| 1281 | for (i = 1; i < L_SUBFR - 1; i++) |
| 1282 | { |
| 1283 | L_tmp = L_deposit_h(code[i]); |
| 1284 | L_tmp -= (code[i + 1] * tmp)<<1; |
| 1285 | L_tmp -= (code[i - 1] * tmp)<<1; |
| 1286 | code2[i] = vo_round(L_tmp); |
| 1287 | } |
| 1288 | |
| 1289 | L_tmp = L_deposit_h(code[L_SUBFR - 1]); |
| 1290 | L_tmp -= (code[L_SUBFR - 2] * tmp)<<1; |
| 1291 | code2[L_SUBFR - 1] = vo_round(L_tmp); |
| 1292 | |
| 1293 | /* build excitation */ |
| 1294 | gain_code = vo_round(L_shl(L_gain_code, Q_new)); |
| 1295 | |
| 1296 | for (i = 0; i < L_SUBFR; i++) |
| 1297 | { |
| 1298 | L_tmp = (code2[i] * gain_code)<<1; |
| 1299 | L_tmp = (L_tmp << 5); |
| 1300 | L_tmp += (exc2[i] * gain_pit)<<1; |
| 1301 | L_tmp = (L_tmp << 1); |
| 1302 | exc2[i] = vo_round(L_tmp); |
| 1303 | } |
| 1304 | |
| 1305 | corr_gain = synthesis(p_Aq, exc2, Q_new, &speech16k[i_subfr * 5 / 4], st); |
| 1306 | Parm_serial(corr_gain, 4, &prms); |
| 1307 | } |
| 1308 | p_A += (M + 1); |
| 1309 | p_Aq += (M + 1); |
| 1310 | } /* end of subframe loop */ |
| 1311 | |
| 1312 | /*--------------------------------------------------* |
| 1313 | * Update signal for next frame. * |
| 1314 | * -> save past of speech[], wsp[] and exc[]. * |
| 1315 | *--------------------------------------------------*/ |
| 1316 | Copy(&old_speech[L_FRAME], st->old_speech, L_TOTAL - L_FRAME); |
| 1317 | Copy(&old_wsp[L_FRAME / OPL_DECIM], st->old_wsp, PIT_MAX / OPL_DECIM); |
| 1318 | Copy(&old_exc[L_FRAME], st->old_exc, PIT_MAX + L_INTERPOL); |
| 1319 | return; |
| 1320 | } |
| 1321 | |
| 1322 | /*-----------------------------------------------------* |
| 1323 | * Function synthesis() * |
| 1324 | * * |
| 1325 | * Synthesis of signal at 16kHz with HF extension. * |
| 1326 | * * |
| 1327 | *-----------------------------------------------------*/ |
| 1328 | |
| 1329 | static Word16 synthesis( |
| 1330 | Word16 Aq[], /* A(z) : quantized Az */ |
| 1331 | Word16 exc[], /* (i) : excitation at 12kHz */ |
| 1332 | Word16 Q_new, /* (i) : scaling performed on exc */ |
| 1333 | Word16 synth16k[], /* (o) : 16kHz synthesis signal */ |
| 1334 | Coder_State * st /* (i/o) : State structure */ |
| 1335 | ) |
| 1336 | { |
| 1337 | Word16 fac, tmp, exp; |
| 1338 | Word16 ener, exp_ener; |
| 1339 | Word32 L_tmp, i; |
| 1340 | |
| 1341 | Word16 synth_hi[M + L_SUBFR], synth_lo[M + L_SUBFR]; |
| 1342 | Word16 synth[L_SUBFR]; |
| 1343 | Word16 HF[L_SUBFR16k]; /* High Frequency vector */ |
| 1344 | Word16 Ap[M + 1]; |
| 1345 | |
| 1346 | Word16 HF_SP[L_SUBFR16k]; /* High Frequency vector (from original signal) */ |
| 1347 | |
| 1348 | Word16 HP_est_gain, HP_calc_gain, HP_corr_gain; |
| 1349 | Word16 dist_min, dist; |
| 1350 | Word16 HP_gain_ind = 0; |
| 1351 | Word16 gain1, gain2; |
| 1352 | Word16 weight1, weight2; |
| 1353 | |
| 1354 | /*------------------------------------------------------------* |
| 1355 | * speech synthesis * |
| 1356 | * ~~~~~~~~~~~~~~~~ * |
| 1357 | * - Find synthesis speech corresponding to exc2[]. * |
| 1358 | * - Perform fixed deemphasis and hp 50hz filtering. * |
| 1359 | * - Oversampling from 12.8kHz to 16kHz. * |
| 1360 | *------------------------------------------------------------*/ |
| 1361 | Copy(st->mem_syn_hi, synth_hi, M); |
| 1362 | Copy(st->mem_syn_lo, synth_lo, M); |
| 1363 | |
| 1364 | #ifdef ASM_OPT /* asm optimization branch */ |
| 1365 | Syn_filt_32_asm(Aq, M, exc, Q_new, synth_hi + M, synth_lo + M, L_SUBFR); |
| 1366 | #else |
| 1367 | Syn_filt_32(Aq, M, exc, Q_new, synth_hi + M, synth_lo + M, L_SUBFR); |
| 1368 | #endif |
| 1369 | |
| 1370 | Copy(synth_hi + L_SUBFR, st->mem_syn_hi, M); |
| 1371 | Copy(synth_lo + L_SUBFR, st->mem_syn_lo, M); |
| 1372 | |
| 1373 | #ifdef ASM_OPT /* asm optimization branch */ |
| 1374 | Deemph_32_asm(synth_hi + M, synth_lo + M, synth, &(st->mem_deemph)); |
| 1375 | #else |
| 1376 | Deemph_32(synth_hi + M, synth_lo + M, synth, PREEMPH_FAC, L_SUBFR, &(st->mem_deemph)); |
| 1377 | #endif |
| 1378 | |
| 1379 | HP50_12k8(synth, L_SUBFR, st->mem_sig_out); |
| 1380 | |
| 1381 | /* Original speech signal as reference for high band gain quantisation */ |
| 1382 | for (i = 0; i < L_SUBFR16k; i++) |
| 1383 | { |
| 1384 | HF_SP[i] = synth16k[i]; |
| 1385 | } |
| 1386 | |
| 1387 | /*------------------------------------------------------* |
| 1388 | * HF noise synthesis * |
| 1389 | * ~~~~~~~~~~~~~~~~~~ * |
| 1390 | * - Generate HF noise between 5.5 and 7.5 kHz. * |
| 1391 | * - Set energy of noise according to synthesis tilt. * |
| 1392 | * tilt > 0.8 ==> - 14 dB (voiced) * |
| 1393 | * tilt 0.5 ==> - 6 dB (voiced or noise) * |
| 1394 | * tilt < 0.0 ==> 0 dB (noise) * |
| 1395 | *------------------------------------------------------*/ |
| 1396 | /* generate white noise vector */ |
| 1397 | for (i = 0; i < L_SUBFR16k; i++) |
| 1398 | { |
| 1399 | HF[i] = Random(&(st->seed2))>>3; |
| 1400 | } |
| 1401 | /* energy of excitation */ |
| 1402 | #ifdef ASM_OPT /* asm optimization branch */ |
| 1403 | Scale_sig_opt(exc, L_SUBFR, -3); |
| 1404 | Q_new = Q_new - 3; |
| 1405 | ener = extract_h(Dot_product12_asm(exc, exc, L_SUBFR, &exp_ener)); |
| 1406 | #else |
| 1407 | Scale_sig(exc, L_SUBFR, -3); |
| 1408 | Q_new = Q_new - 3; |
| 1409 | ener = extract_h(Dot_product12(exc, exc, L_SUBFR, &exp_ener)); |
| 1410 | #endif |
| 1411 | |
| 1412 | exp_ener = exp_ener - (Q_new + Q_new); |
| 1413 | /* set energy of white noise to energy of excitation */ |
| 1414 | #ifdef ASM_OPT /* asm optimization branch */ |
| 1415 | tmp = extract_h(Dot_product12_asm(HF, HF, L_SUBFR16k, &exp)); |
| 1416 | #else |
| 1417 | tmp = extract_h(Dot_product12(HF, HF, L_SUBFR16k, &exp)); |
| 1418 | #endif |
| 1419 | |
| 1420 | if(tmp > ener) |
| 1421 | { |
| 1422 | tmp = (tmp >> 1); /* Be sure tmp < ener */ |
| 1423 | exp = (exp + 1); |
| 1424 | } |
| 1425 | L_tmp = L_deposit_h(div_s(tmp, ener)); /* result is normalized */ |
| 1426 | exp = (exp - exp_ener); |
| 1427 | Isqrt_n(&L_tmp, &exp); |
| 1428 | L_tmp = L_shl(L_tmp, (exp + 1)); /* L_tmp x 2, L_tmp in Q31 */ |
| 1429 | tmp = extract_h(L_tmp); /* tmp = 2 x sqrt(ener_exc/ener_hf) */ |
| 1430 | |
| 1431 | for (i = 0; i < L_SUBFR16k; i++) |
| 1432 | { |
| 1433 | HF[i] = vo_mult(HF[i], tmp); |
| 1434 | } |
| 1435 | |
| 1436 | /* find tilt of synthesis speech (tilt: 1=voiced, -1=unvoiced) */ |
| 1437 | HP400_12k8(synth, L_SUBFR, st->mem_hp400); |
| 1438 | |
| 1439 | L_tmp = 1L; |
| 1440 | for (i = 0; i < L_SUBFR; i++) |
| 1441 | L_tmp += (synth[i] * synth[i])<<1; |
| 1442 | |
| 1443 | exp = norm_l(L_tmp); |
| 1444 | ener = extract_h(L_tmp << exp); /* ener = r[0] */ |
| 1445 | |
| 1446 | L_tmp = 1L; |
| 1447 | for (i = 1; i < L_SUBFR; i++) |
| 1448 | L_tmp +=(synth[i] * synth[i - 1])<<1; |
| 1449 | |
| 1450 | tmp = extract_h(L_tmp << exp); /* tmp = r[1] */ |
| 1451 | |
| 1452 | if (tmp > 0) |
| 1453 | { |
| 1454 | fac = div_s(tmp, ener); |
| 1455 | } else |
| 1456 | { |
| 1457 | fac = 0; |
| 1458 | } |
| 1459 | |
| 1460 | /* modify energy of white noise according to synthesis tilt */ |
| 1461 | gain1 = 32767 - fac; |
| 1462 | gain2 = vo_mult(gain1, 20480); |
| 1463 | gain2 = shl(gain2, 1); |
| 1464 | |
| 1465 | if (st->vad_hist > 0) |
| 1466 | { |
| 1467 | weight1 = 0; |
| 1468 | weight2 = 32767; |
| 1469 | } else |
| 1470 | { |
| 1471 | weight1 = 32767; |
| 1472 | weight2 = 0; |
| 1473 | } |
| 1474 | tmp = vo_mult(weight1, gain1); |
| 1475 | tmp = add1(tmp, vo_mult(weight2, gain2)); |
| 1476 | |
| 1477 | if (tmp != 0) |
| 1478 | { |
| 1479 | tmp = (tmp + 1); |
| 1480 | } |
| 1481 | HP_est_gain = tmp; |
| 1482 | |
| 1483 | if(HP_est_gain < 3277) |
| 1484 | { |
| 1485 | HP_est_gain = 3277; /* 0.1 in Q15 */ |
| 1486 | } |
| 1487 | /* synthesis of noise: 4.8kHz..5.6kHz --> 6kHz..7kHz */ |
| 1488 | Weight_a(Aq, Ap, 19661, M); /* fac=0.6 */ |
| 1489 | |
| 1490 | #ifdef ASM_OPT /* asm optimization branch */ |
| 1491 | Syn_filt_asm(Ap, HF, HF, st->mem_syn_hf); |
| 1492 | /* noise High Pass filtering (1ms of delay) */ |
| 1493 | Filt_6k_7k_asm(HF, L_SUBFR16k, st->mem_hf); |
| 1494 | /* filtering of the original signal */ |
| 1495 | Filt_6k_7k_asm(HF_SP, L_SUBFR16k, st->mem_hf2); |
| 1496 | |
| 1497 | /* check the gain difference */ |
| 1498 | Scale_sig_opt(HF_SP, L_SUBFR16k, -1); |
| 1499 | ener = extract_h(Dot_product12_asm(HF_SP, HF_SP, L_SUBFR16k, &exp_ener)); |
| 1500 | /* set energy of white noise to energy of excitation */ |
| 1501 | tmp = extract_h(Dot_product12_asm(HF, HF, L_SUBFR16k, &exp)); |
| 1502 | #else |
| 1503 | Syn_filt(Ap, HF, HF, L_SUBFR16k, st->mem_syn_hf, 1); |
| 1504 | /* noise High Pass filtering (1ms of delay) */ |
| 1505 | Filt_6k_7k(HF, L_SUBFR16k, st->mem_hf); |
| 1506 | /* filtering of the original signal */ |
| 1507 | Filt_6k_7k(HF_SP, L_SUBFR16k, st->mem_hf2); |
| 1508 | /* check the gain difference */ |
| 1509 | Scale_sig(HF_SP, L_SUBFR16k, -1); |
| 1510 | ener = extract_h(Dot_product12(HF_SP, HF_SP, L_SUBFR16k, &exp_ener)); |
| 1511 | /* set energy of white noise to energy of excitation */ |
| 1512 | tmp = extract_h(Dot_product12(HF, HF, L_SUBFR16k, &exp)); |
| 1513 | #endif |
| 1514 | |
| 1515 | if (tmp > ener) |
| 1516 | { |
| 1517 | tmp = (tmp >> 1); /* Be sure tmp < ener */ |
| 1518 | exp = (exp + 1); |
| 1519 | } |
| 1520 | L_tmp = L_deposit_h(div_s(tmp, ener)); /* result is normalized */ |
| 1521 | exp = vo_sub(exp, exp_ener); |
| 1522 | Isqrt_n(&L_tmp, &exp); |
| 1523 | L_tmp = L_shl(L_tmp, exp); /* L_tmp, L_tmp in Q31 */ |
| 1524 | HP_calc_gain = extract_h(L_tmp); /* tmp = sqrt(ener_input/ener_hf) */ |
| 1525 | |
| 1526 | /* st->gain_alpha *= st->dtx_encSt->dtxHangoverCount/7 */ |
| 1527 | L_tmp = (vo_L_mult(st->dtx_encSt->dtxHangoverCount, 4681) << 15); |
| 1528 | st->gain_alpha = vo_mult(st->gain_alpha, extract_h(L_tmp)); |
| 1529 | |
| 1530 | if(st->dtx_encSt->dtxHangoverCount > 6) |
| 1531 | st->gain_alpha = 32767; |
| 1532 | HP_est_gain = HP_est_gain >> 1; /* From Q15 to Q14 */ |
| 1533 | HP_corr_gain = add1(vo_mult(HP_calc_gain, st->gain_alpha), vo_mult((32767 - st->gain_alpha), HP_est_gain)); |
| 1534 | |
| 1535 | /* Quantise the correction gain */ |
| 1536 | dist_min = 32767; |
| 1537 | for (i = 0; i < 16; i++) |
| 1538 | { |
| 1539 | dist = vo_mult((HP_corr_gain - HP_gain[i]), (HP_corr_gain - HP_gain[i])); |
| 1540 | if (dist_min > dist) |
| 1541 | { |
| 1542 | dist_min = dist; |
| 1543 | HP_gain_ind = i; |
| 1544 | } |
| 1545 | } |
| 1546 | HP_corr_gain = HP_gain[HP_gain_ind]; |
| 1547 | /* return the quantised gain index when using the highest mode, otherwise zero */ |
| 1548 | return (HP_gain_ind); |
| 1549 | } |
| 1550 | |
| 1551 | /************************************************* |
| 1552 | * |
| 1553 | * Breif: Codec main function |
| 1554 | * |
| 1555 | **************************************************/ |
| 1556 | |
| 1557 | int AMR_Enc_Encode(HAMRENC hCodec) |
| 1558 | { |
| 1559 | Word32 i; |
| 1560 | Coder_State *gData = (Coder_State*)hCodec; |
| 1561 | Word16 *signal; |
| 1562 | Word16 packed_size = 0; |
| 1563 | Word16 prms[NB_BITS_MAX]; |
| 1564 | Word16 coding_mode = 0, nb_bits, allow_dtx, mode, reset_flag; |
| 1565 | mode = gData->mode; |
| 1566 | coding_mode = gData->mode; |
| 1567 | nb_bits = nb_of_bits[mode]; |
| 1568 | signal = (Word16 *)gData->inputStream; |
| 1569 | allow_dtx = gData->allow_dtx; |
| 1570 | |
| 1571 | /* check for homing frame */ |
| 1572 | reset_flag = encoder_homing_frame_test(signal); |
| 1573 | |
| 1574 | for (i = 0; i < L_FRAME16k; i++) /* Delete the 2 LSBs (14-bit input) */ |
| 1575 | { |
| 1576 | *(signal + i) = (Word16) (*(signal + i) & 0xfffC); |
| 1577 | } |
| 1578 | |
| 1579 | coder(&coding_mode, signal, prms, &nb_bits, gData, allow_dtx); |
| 1580 | packed_size = PackBits(prms, coding_mode, mode, gData); |
| 1581 | if (reset_flag != 0) |
| 1582 | { |
| 1583 | Reset_encoder(gData, 1); |
| 1584 | } |
| 1585 | return packed_size; |
| 1586 | } |
| 1587 | |
| 1588 | /*************************************************************************** |
| 1589 | * |
| 1590 | *Brief: Codec API function --- Initialize the codec and return a codec handle |
| 1591 | * |
| 1592 | ***************************************************************************/ |
| 1593 | |
| 1594 | VO_U32 VO_API voAMRWB_Init(VO_HANDLE * phCodec, /* o: the audio codec handle */ |
| 1595 | VO_AUDIO_CODINGTYPE vType, /* i: Codec Type ID */ |
| 1596 | VO_CODEC_INIT_USERDATA * pUserData /* i: init Parameters */ |
| 1597 | ) |
| 1598 | { |
| 1599 | Coder_State *st; |
| 1600 | FrameStream *stream; |
| 1601 | #ifdef USE_DEAULT_MEM |
| 1602 | VO_MEM_OPERATOR voMemoprator; |
| 1603 | #endif |
| 1604 | VO_MEM_OPERATOR *pMemOP; |
| 1605 | int interMem = 0; |
| 1606 | |
| 1607 | if(pUserData == NULL || pUserData->memflag != VO_IMF_USERMEMOPERATOR || pUserData->memData == NULL ) |
| 1608 | { |
| 1609 | #ifdef USE_DEAULT_MEM |
| 1610 | voMemoprator.Alloc = cmnMemAlloc; |
| 1611 | voMemoprator.Copy = cmnMemCopy; |
| 1612 | voMemoprator.Free = cmnMemFree; |
| 1613 | voMemoprator.Set = cmnMemSet; |
| 1614 | voMemoprator.Check = cmnMemCheck; |
| 1615 | interMem = 1; |
| 1616 | pMemOP = &voMemoprator; |
| 1617 | #else |
| 1618 | *phCodec = NULL; |
| 1619 | return VO_ERR_INVALID_ARG; |
| 1620 | #endif |
| 1621 | } |
| 1622 | else |
| 1623 | { |
| 1624 | pMemOP = (VO_MEM_OPERATOR *)pUserData->memData; |
| 1625 | } |
| 1626 | /*-------------------------------------------------------------------------* |
| 1627 | * Memory allocation for coder state. * |
| 1628 | *-------------------------------------------------------------------------*/ |
| 1629 | if ((st = (Coder_State *)mem_malloc(pMemOP, sizeof(Coder_State), 32, VO_INDEX_ENC_AMRWB)) == NULL) |
| 1630 | { |
| 1631 | return VO_ERR_OUTOF_MEMORY; |
| 1632 | } |
| 1633 | |
| 1634 | st->vadSt = NULL; |
| 1635 | st->dtx_encSt = NULL; |
| 1636 | st->sid_update_counter = 3; |
| 1637 | st->sid_handover_debt = 0; |
| 1638 | st->prev_ft = TX_SPEECH; |
| 1639 | st->inputStream = NULL; |
| 1640 | st->inputSize = 0; |
| 1641 | |
| 1642 | /* Default setting */ |
| 1643 | st->mode = VOAMRWB_MD2385; /* bit rate 23.85kbps */ |
| 1644 | st->frameType = VOAMRWB_RFC3267; /* frame type: RFC3267 */ |
| 1645 | st->allow_dtx = 0; /* disable DTX mode */ |
| 1646 | |
| 1647 | st->outputStream = NULL; |
| 1648 | st->outputSize = 0; |
| 1649 | |
| 1650 | st->stream = (FrameStream *)mem_malloc(pMemOP, sizeof(FrameStream), 32, VO_INDEX_ENC_AMRWB); |
| 1651 | if(st->stream == NULL) |
| 1652 | return VO_ERR_OUTOF_MEMORY; |
| 1653 | |
| 1654 | st->stream->frame_ptr = (unsigned char *)mem_malloc(pMemOP, Frame_Maxsize, 32, VO_INDEX_ENC_AMRWB); |
| 1655 | if(st->stream->frame_ptr == NULL) |
| 1656 | return VO_ERR_OUTOF_MEMORY; |
| 1657 | |
| 1658 | stream = st->stream; |
| 1659 | voAWB_InitFrameBuffer(stream); |
| 1660 | |
| 1661 | wb_vad_init(&(st->vadSt), pMemOP); |
| 1662 | dtx_enc_init(&(st->dtx_encSt), isf_init, pMemOP); |
| 1663 | |
| 1664 | Reset_encoder((void *) st, 1); |
| 1665 | |
| 1666 | if(interMem) |
| 1667 | { |
| 1668 | st->voMemoprator.Alloc = cmnMemAlloc; |
| 1669 | st->voMemoprator.Copy = cmnMemCopy; |
| 1670 | st->voMemoprator.Free = cmnMemFree; |
| 1671 | st->voMemoprator.Set = cmnMemSet; |
| 1672 | st->voMemoprator.Check = cmnMemCheck; |
| 1673 | pMemOP = &st->voMemoprator; |
| 1674 | } |
| 1675 | |
| 1676 | st->pvoMemop = pMemOP; |
| 1677 | |
| 1678 | *phCodec = (void *) st; |
| 1679 | |
| 1680 | return VO_ERR_NONE; |
| 1681 | } |
| 1682 | |
| 1683 | /********************************************************************************** |
| 1684 | * |
| 1685 | * Brief: Codec API function: Input PCM data |
| 1686 | * |
| 1687 | ***********************************************************************************/ |
| 1688 | |
| 1689 | VO_U32 VO_API voAMRWB_SetInputData( |
| 1690 | VO_HANDLE hCodec, /* i/o: The codec handle which was created by Init function */ |
| 1691 | VO_CODECBUFFER * pInput /* i: The input buffer parameter */ |
| 1692 | ) |
| 1693 | { |
| 1694 | Coder_State *gData; |
| 1695 | FrameStream *stream; |
| 1696 | |
| 1697 | if(NULL == hCodec) |
| 1698 | { |
| 1699 | return VO_ERR_INVALID_ARG; |
| 1700 | } |
| 1701 | |
| 1702 | gData = (Coder_State *)hCodec; |
| 1703 | stream = gData->stream; |
| 1704 | |
| 1705 | if(NULL == pInput || NULL == pInput->Buffer || 0 > pInput->Length) |
| 1706 | { |
| 1707 | return VO_ERR_INVALID_ARG; |
| 1708 | } |
| 1709 | |
| 1710 | stream->set_ptr = pInput->Buffer; |
| 1711 | stream->set_len = pInput->Length; |
| 1712 | stream->frame_ptr = stream->frame_ptr_bk; |
| 1713 | stream->used_len = 0; |
| 1714 | |
| 1715 | return VO_ERR_NONE; |
| 1716 | } |
| 1717 | |
| 1718 | /************************************************************************************** |
| 1719 | * |
| 1720 | * Brief: Codec API function: Get the compression audio data frame by frame |
| 1721 | * |
| 1722 | ***************************************************************************************/ |
| 1723 | |
| 1724 | VO_U32 VO_API voAMRWB_GetOutputData( |
| 1725 | VO_HANDLE hCodec, /* i: The Codec Handle which was created by Init function*/ |
| 1726 | VO_CODECBUFFER * pOutput, /* o: The output audio data */ |
| 1727 | VO_AUDIO_OUTPUTINFO * pAudioFormat /* o: The encoder module filled audio format and used the input size*/ |
| 1728 | ) |
| 1729 | { |
| 1730 | Coder_State* gData = (Coder_State*)hCodec; |
| 1731 | VO_MEM_OPERATOR *pMemOP; |
| 1732 | FrameStream *stream = (FrameStream *)gData->stream; |
| 1733 | pMemOP = (VO_MEM_OPERATOR *)gData->pvoMemop; |
| 1734 | |
| 1735 | if(stream->framebuffer_len < Frame_MaxByte) /* check the work buffer len */ |
| 1736 | { |
| 1737 | stream->frame_storelen = stream->framebuffer_len; |
| 1738 | if(stream->frame_storelen) |
| 1739 | { |
| 1740 | pMemOP->Copy(VO_INDEX_ENC_AMRWB, stream->frame_ptr_bk , stream->frame_ptr , stream->frame_storelen); |
| 1741 | } |
| 1742 | if(stream->set_len > 0) |
| 1743 | { |
| 1744 | voAWB_UpdateFrameBuffer(stream, pMemOP); |
| 1745 | } |
| 1746 | if(stream->framebuffer_len < Frame_MaxByte) |
| 1747 | { |
| 1748 | if(pAudioFormat) |
| 1749 | pAudioFormat->InputUsed = stream->used_len; |
| 1750 | return VO_ERR_INPUT_BUFFER_SMALL; |
| 1751 | } |
| 1752 | } |
| 1753 | |
| 1754 | gData->inputStream = stream->frame_ptr; |
| 1755 | gData->outputStream = (unsigned short*)pOutput->Buffer; |
| 1756 | |
| 1757 | gData->outputSize = AMR_Enc_Encode(gData); /* encoder main function */ |
| 1758 | |
| 1759 | pOutput->Length = gData->outputSize; /* get the output buffer length */ |
| 1760 | stream->frame_ptr += 640; /* update the work buffer ptr */ |
| 1761 | stream->framebuffer_len -= 640; |
| 1762 | |
| 1763 | if(pAudioFormat) /* return output audio information */ |
| 1764 | { |
| 1765 | pAudioFormat->Format.Channels = 1; |
| 1766 | pAudioFormat->Format.SampleRate = 8000; |
| 1767 | pAudioFormat->Format.SampleBits = 16; |
| 1768 | pAudioFormat->InputUsed = stream->used_len; |
| 1769 | } |
| 1770 | return VO_ERR_NONE; |
| 1771 | } |
| 1772 | |
| 1773 | /************************************************************************* |
| 1774 | * |
| 1775 | * Brief: Codec API function---set the data by specified parameter ID |
| 1776 | * |
| 1777 | *************************************************************************/ |
| 1778 | |
| 1779 | |
| 1780 | VO_U32 VO_API voAMRWB_SetParam( |
| 1781 | VO_HANDLE hCodec, /* i/o: The Codec Handle which was created by Init function */ |
| 1782 | VO_S32 uParamID, /* i: The param ID */ |
| 1783 | VO_PTR pData /* i: The param value depend on the ID */ |
| 1784 | ) |
| 1785 | { |
| 1786 | Coder_State* gData = (Coder_State*)hCodec; |
| 1787 | FrameStream *stream = (FrameStream *)(gData->stream); |
| 1788 | int *lValue = (int*)pData; |
| 1789 | |
| 1790 | switch(uParamID) |
| 1791 | { |
| 1792 | /* setting AMR-WB frame type*/ |
| 1793 | case VO_PID_AMRWB_FRAMETYPE: |
| 1794 | if(*lValue < VOAMRWB_DEFAULT || *lValue > VOAMRWB_RFC3267) |
| 1795 | return VO_ERR_WRONG_PARAM_ID; |
| 1796 | gData->frameType = *lValue; |
| 1797 | break; |
| 1798 | /* setting AMR-WB bit rate */ |
| 1799 | case VO_PID_AMRWB_MODE: |
| 1800 | { |
| 1801 | if(*lValue < VOAMRWB_MD66 || *lValue > VOAMRWB_MD2385) |
| 1802 | return VO_ERR_WRONG_PARAM_ID; |
| 1803 | gData->mode = *lValue; |
| 1804 | } |
| 1805 | break; |
| 1806 | /* enable or disable DTX mode */ |
| 1807 | case VO_PID_AMRWB_DTX: |
| 1808 | gData->allow_dtx = (Word16)(*lValue); |
| 1809 | break; |
| 1810 | |
| 1811 | case VO_PID_COMMON_HEADDATA: |
| 1812 | break; |
| 1813 | /* flush the work buffer */ |
| 1814 | case VO_PID_COMMON_FLUSH: |
| 1815 | stream->set_ptr = NULL; |
| 1816 | stream->frame_storelen = 0; |
| 1817 | stream->framebuffer_len = 0; |
| 1818 | stream->set_len = 0; |
| 1819 | break; |
| 1820 | |
| 1821 | default: |
| 1822 | return VO_ERR_WRONG_PARAM_ID; |
| 1823 | } |
| 1824 | return VO_ERR_NONE; |
| 1825 | } |
| 1826 | |
| 1827 | /************************************************************************** |
| 1828 | * |
| 1829 | *Brief: Codec API function---Get the data by specified parameter ID |
| 1830 | * |
| 1831 | ***************************************************************************/ |
| 1832 | |
| 1833 | VO_U32 VO_API voAMRWB_GetParam( |
| 1834 | VO_HANDLE hCodec, /* i: The Codec Handle which was created by Init function */ |
| 1835 | VO_S32 uParamID, /* i: The param ID */ |
| 1836 | VO_PTR pData /* o: The param value depend on the ID */ |
| 1837 | ) |
| 1838 | { |
| 1839 | int temp; |
| 1840 | Coder_State* gData = (Coder_State*)hCodec; |
| 1841 | |
| 1842 | if (gData==NULL) |
| 1843 | return VO_ERR_INVALID_ARG; |
| 1844 | switch(uParamID) |
| 1845 | { |
| 1846 | /* output audio format */ |
| 1847 | case VO_PID_AMRWB_FORMAT: |
| 1848 | { |
| 1849 | VO_AUDIO_FORMAT* fmt = (VO_AUDIO_FORMAT*)pData; |
| 1850 | fmt->Channels = 1; |
| 1851 | fmt->SampleRate = 16000; |
| 1852 | fmt->SampleBits = 16; |
| 1853 | break; |
| 1854 | } |
| 1855 | /* output audio channel number */ |
| 1856 | case VO_PID_AMRWB_CHANNELS: |
| 1857 | temp = 1; |
| 1858 | pData = (void *)(&temp); |
| 1859 | break; |
| 1860 | /* output audio sample rate */ |
| 1861 | case VO_PID_AMRWB_SAMPLERATE: |
| 1862 | temp = 16000; |
| 1863 | pData = (void *)(&temp); |
| 1864 | break; |
| 1865 | /* output audio frame type */ |
| 1866 | case VO_PID_AMRWB_FRAMETYPE: |
| 1867 | temp = gData->frameType; |
| 1868 | pData = (void *)(&temp); |
| 1869 | break; |
| 1870 | /* output audio bit rate */ |
| 1871 | case VO_PID_AMRWB_MODE: |
| 1872 | temp = gData->mode; |
| 1873 | pData = (void *)(&temp); |
| 1874 | break; |
| 1875 | default: |
| 1876 | return VO_ERR_WRONG_PARAM_ID; |
| 1877 | } |
| 1878 | |
| 1879 | return VO_ERR_NONE; |
| 1880 | } |
| 1881 | |
| 1882 | /*********************************************************************************** |
| 1883 | * |
| 1884 | * Brief: Codec API function---Release the codec after all encoder operations are done |
| 1885 | * |
| 1886 | *************************************************************************************/ |
| 1887 | |
| 1888 | VO_U32 VO_API voAMRWB_Uninit(VO_HANDLE hCodec /* i/o: Codec handle pointer */ |
| 1889 | ) |
| 1890 | { |
| 1891 | Coder_State* gData = (Coder_State*)hCodec; |
| 1892 | VO_MEM_OPERATOR *pMemOP; |
| 1893 | pMemOP = gData->pvoMemop; |
| 1894 | |
| 1895 | if(hCodec) |
| 1896 | { |
| 1897 | if(gData->stream) |
| 1898 | { |
| 1899 | if(gData->stream->frame_ptr_bk) |
| 1900 | { |
| 1901 | mem_free(pMemOP, gData->stream->frame_ptr_bk, VO_INDEX_ENC_AMRWB); |
| 1902 | gData->stream->frame_ptr_bk = NULL; |
| 1903 | } |
| 1904 | mem_free(pMemOP, gData->stream, VO_INDEX_ENC_AMRWB); |
| 1905 | gData->stream = NULL; |
| 1906 | } |
| 1907 | wb_vad_exit(&(((Coder_State *) gData)->vadSt), pMemOP); |
| 1908 | dtx_enc_exit(&(((Coder_State *) gData)->dtx_encSt), pMemOP); |
| 1909 | |
| 1910 | mem_free(pMemOP, hCodec, VO_INDEX_ENC_AMRWB); |
| 1911 | hCodec = NULL; |
| 1912 | } |
| 1913 | |
| 1914 | return VO_ERR_NONE; |
| 1915 | } |
| 1916 | |
| 1917 | /******************************************************************************** |
| 1918 | * |
| 1919 | * Brief: voGetAMRWBEncAPI gets the API handle of the codec |
| 1920 | * |
| 1921 | ********************************************************************************/ |
| 1922 | |
| 1923 | VO_S32 VO_API voGetAMRWBEncAPI( |
| 1924 | VO_AUDIO_CODECAPI * pEncHandle /* i/o: Codec handle pointer */ |
| 1925 | ) |
| 1926 | { |
| 1927 | if(NULL == pEncHandle) |
| 1928 | return VO_ERR_INVALID_ARG; |
| 1929 | pEncHandle->Init = voAMRWB_Init; |
| 1930 | pEncHandle->SetInputData = voAMRWB_SetInputData; |
| 1931 | pEncHandle->GetOutputData = voAMRWB_GetOutputData; |
| 1932 | pEncHandle->SetParam = voAMRWB_SetParam; |
| 1933 | pEncHandle->GetParam = voAMRWB_GetParam; |
| 1934 | pEncHandle->Uninit = voAMRWB_Uninit; |
| 1935 | |
| 1936 | return VO_ERR_NONE; |
| 1937 | } |
| 1938 | |
| 1939 | #ifdef __cplusplus |
| 1940 | } |
| 1941 | #endif |