FreeCalypso > hg > efr-experiments
comparison src/dtx.c @ 0:56410792419a
src: original EFR source from ETSI
| author | Mychaela Falconia <falcon@freecalypso.org> |
|---|---|
| date | Wed, 03 Apr 2024 05:31:37 +0000 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:56410792419a |
|---|---|
| 1 /*************************************************************************** | |
| 2 * | |
| 3 * File Name: dtx.c | |
| 4 * | |
| 5 * Purpose: Contains functions for performing DTX operation and comfort | |
| 6 * noise generation. | |
| 7 * | |
| 8 * Below is a listing of all the functions appearing in the file. | |
| 9 * The functions are arranged according to their purpose. Under | |
| 10 * each heading, the ordering is hierarchical. | |
| 11 * | |
| 12 * Resetting of static variables of TX DTX: | |
| 13 * reset_tx_dtx() | |
| 14 * Resetting of static variables of RX DTX: | |
| 15 * reset_rx_dtx() | |
| 16 * | |
| 17 * TX DTX handler (called by the speech encoder): | |
| 18 * tx_dtx() | |
| 19 * RX DTX handler (called by the speech decoder): | |
| 20 * rx_dtx() | |
| 21 * Encoding of comfort noise parameters into SID frame: | |
| 22 * CN_encoding() | |
| 23 * Encoding of SID codeword into SID frame: | |
| 24 * sid_codeword_encoding() | |
| 25 * Detecting of SID codeword from a frame: | |
| 26 * sid_frame_detection() | |
| 27 * Update the LSF parameter history: | |
| 28 * update_lsf_history() | |
| 29 * Update the reference LSF parameter vector: | |
| 30 * update_lsf_p_CN() | |
| 31 * Compute the averaged LSF parameter vector: | |
| 32 * aver_lsf_history() | |
| 33 * Update the fixed codebook gain parameter history of the encoder: | |
| 34 * update_gain_code_history_tx() | |
| 35 * Update the fixed codebook gain parameter history of the decoder: | |
| 36 * update_gain_code_history_rx() | |
| 37 * Compute the unquantized fixed codebook gain: | |
| 38 * compute_CN_excitation_gain() | |
| 39 * Update the reference fixed codebook gain: | |
| 40 * update_gcode0_CN() | |
| 41 * Compute the averaged fixed codebook gain: | |
| 42 * aver_gain_code_history() | |
| 43 * Compute the comfort noise fixed codebook excitation: | |
| 44 * build_CN_code() | |
| 45 * Generate a random integer value: | |
| 46 * pseudonoise() | |
| 47 * Interpolate a comfort noise parameter value over the comfort noise | |
| 48 * update period: | |
| 49 * interpolate_CN_param() | |
| 50 * Interpolate comfort noise LSF pparameter values over the comfort | |
| 51 * noise update period: | |
| 52 * interpolate_CN_lsf() | |
| 53 * interpolate_CN_param() | |
| 54 * | |
| 55 **************************************************************************/ | |
| 56 | |
| 57 #include "typedef.h" | |
| 58 #include "basic_op.h" | |
| 59 #include "cnst.h" | |
| 60 #include "sig_proc.h" | |
| 61 #include "count.h" | |
| 62 #include "dtx.h" | |
| 63 | |
| 64 /* Inverse values of DTX hangover period and DTX hangover period + 1 */ | |
| 65 | |
| 66 #define INV_DTX_HANGOVER (0x7fff / DTX_HANGOVER) | |
| 67 #define INV_DTX_HANGOVER_P1 (0x7fff / (DTX_HANGOVER+1)) | |
| 68 | |
| 69 #define NB_PULSE 10 /* Number of pulses in fixed codebook excitation */ | |
| 70 | |
| 71 /* SID frame classification thresholds */ | |
| 72 | |
| 73 #define VALID_SID_THRESH 2 | |
| 74 #define INVALID_SID_THRESH 16 | |
| 75 | |
| 76 /* Constant DTX_ELAPSED_THRESHOLD is used as threshold for allowing | |
| 77 SID frame updating without hangover period in case when elapsed | |
| 78 time measured from previous SID update is below 24 */ | |
| 79 | |
| 80 #define DTX_ELAPSED_THRESHOLD (24 + DTX_HANGOVER - 1) | |
| 81 | |
| 82 /* Index map for encoding and detecting SID codeword */ | |
| 83 | |
| 84 static const Word16 SID_codeword_bit_idx[95] = | |
| 85 { | |
| 86 45, 46, 48, 49, 50, 51, 52, 53, 54, 55, | |
| 87 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, | |
| 88 66, 67, 68, 94, 95, 96, 98, 99, 100, 101, | |
| 89 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, | |
| 90 112, 113, 114, 115, 116, 117, 118, 148, 149, 150, | |
| 91 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, | |
| 92 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, | |
| 93 171, 196, 197, 198, 199, 200, 201, 202, 203, 204, | |
| 94 205, 206, 207, 208, 209, 212, 213, 214, 215, 216, | |
| 95 217, 218, 219, 220, 221 | |
| 96 }; | |
| 97 | |
| 98 Word16 txdtx_ctrl; /* Encoder DTX control word */ | |
| 99 Word16 rxdtx_ctrl; /* Decoder DTX control word */ | |
| 100 Word16 CN_excitation_gain; /* Unquantized fixed codebook gain */ | |
| 101 Word32 L_pn_seed_tx; /* PN generator seed (encoder) */ | |
| 102 Word32 L_pn_seed_rx; /* PN generator seed (decoder) */ | |
| 103 Word16 rx_dtx_state; /* State of comfort noise insertion period */ | |
| 104 | |
| 105 static Word16 txdtx_hangover; /* Length of hangover period (VAD=0, SP=1) */ | |
| 106 static Word16 rxdtx_aver_period;/* Length of hangover period (VAD=0, SP=1) */ | |
| 107 static Word16 txdtx_N_elapsed; /* Measured time from previous SID frame */ | |
| 108 static Word16 rxdtx_N_elapsed; /* Measured time from previous SID frame */ | |
| 109 static Word16 old_CN_mem_tx[6]; /* The most recent CN parameters are stored*/ | |
| 110 static Word16 prev_SID_frames_lost; /* Counter for lost SID frames */ | |
| 111 static Word16 buf_p_tx; /* Circular buffer pointer for gain code | |
| 112 history update in tx */ | |
| 113 static Word16 buf_p_rx; /* Circular buffer pointer for gain code | |
| 114 history update in rx */ | |
| 115 | |
| 116 Word16 lsf_old_tx[DTX_HANGOVER][M]; /* Comfort noise LSF averaging buffer */ | |
| 117 Word16 lsf_old_rx[DTX_HANGOVER][M]; /* Comfort noise LSF averaging buffer */ | |
| 118 | |
| 119 Word16 gain_code_old_tx[4 * DTX_HANGOVER]; /* Comfort noise gain averaging | |
| 120 buffer */ | |
| 121 Word16 gain_code_old_rx[4 * DTX_HANGOVER]; /* Comfort noise gain averaging | |
| 122 buffer */ | |
| 123 | |
| 124 /************************************************************************* | |
| 125 * | |
| 126 * FUNCTION NAME: reset_tx_dtx | |
| 127 * | |
| 128 * PURPOSE: Resets the static variables of the TX DTX handler to their | |
| 129 * initial values | |
| 130 * | |
| 131 *************************************************************************/ | |
| 132 | |
| 133 void reset_tx_dtx () | |
| 134 { | |
| 135 Word16 i; | |
| 136 | |
| 137 /* suppose infinitely long speech period before start */ | |
| 138 | |
| 139 txdtx_hangover = DTX_HANGOVER; | |
| 140 txdtx_N_elapsed = 0x7fff; | |
| 141 txdtx_ctrl = TX_SP_FLAG | TX_VAD_FLAG; | |
| 142 | |
| 143 for (i = 0; i < 6; i++) | |
| 144 { | |
| 145 old_CN_mem_tx[i] = 0; | |
| 146 } | |
| 147 | |
| 148 for (i = 0; i < DTX_HANGOVER; i++) | |
| 149 { | |
| 150 lsf_old_tx[i][0] = 1384; | |
| 151 lsf_old_tx[i][1] = 2077; | |
| 152 lsf_old_tx[i][2] = 3420; | |
| 153 lsf_old_tx[i][3] = 5108; | |
| 154 lsf_old_tx[i][4] = 6742; | |
| 155 lsf_old_tx[i][5] = 8122; | |
| 156 lsf_old_tx[i][6] = 9863; | |
| 157 lsf_old_tx[i][7] = 11092; | |
| 158 lsf_old_tx[i][8] = 12714; | |
| 159 lsf_old_tx[i][9] = 13701; | |
| 160 } | |
| 161 | |
| 162 for (i = 0; i < 4 * DTX_HANGOVER; i++) | |
| 163 { | |
| 164 gain_code_old_tx[i] = 0; | |
| 165 } | |
| 166 | |
| 167 L_pn_seed_tx = PN_INITIAL_SEED; | |
| 168 | |
| 169 buf_p_tx = 0; | |
| 170 return; | |
| 171 } | |
| 172 | |
| 173 /************************************************************************* | |
| 174 * | |
| 175 * FUNCTION NAME: reset_rx_dtx | |
| 176 * | |
| 177 * PURPOSE: Resets the static variables of the RX DTX handler to their | |
| 178 * initial values | |
| 179 * | |
| 180 *************************************************************************/ | |
| 181 | |
| 182 void reset_rx_dtx () | |
| 183 { | |
| 184 Word16 i; | |
| 185 | |
| 186 /* suppose infinitely long speech period before start */ | |
| 187 | |
| 188 rxdtx_aver_period = DTX_HANGOVER; | |
| 189 rxdtx_N_elapsed = 0x7fff; | |
| 190 rxdtx_ctrl = RX_SP_FLAG; | |
| 191 | |
| 192 for (i = 0; i < DTX_HANGOVER; i++) | |
| 193 { | |
| 194 lsf_old_rx[i][0] = 1384; | |
| 195 lsf_old_rx[i][1] = 2077; | |
| 196 lsf_old_rx[i][2] = 3420; | |
| 197 lsf_old_rx[i][3] = 5108; | |
| 198 lsf_old_rx[i][4] = 6742; | |
| 199 lsf_old_rx[i][5] = 8122; | |
| 200 lsf_old_rx[i][6] = 9863; | |
| 201 lsf_old_rx[i][7] = 11092; | |
| 202 lsf_old_rx[i][8] = 12714; | |
| 203 lsf_old_rx[i][9] = 13701; | |
| 204 } | |
| 205 | |
| 206 for (i = 0; i < 4 * DTX_HANGOVER; i++) | |
| 207 { | |
| 208 gain_code_old_rx[i] = 0; | |
| 209 } | |
| 210 | |
| 211 L_pn_seed_rx = PN_INITIAL_SEED; | |
| 212 rx_dtx_state = CN_INT_PERIOD - 1; | |
| 213 | |
| 214 prev_SID_frames_lost = 0; | |
| 215 buf_p_rx = 0; | |
| 216 | |
| 217 return; | |
| 218 } | |
| 219 | |
| 220 /************************************************************************* | |
| 221 * | |
| 222 * FUNCTION NAME: tx_dtx | |
| 223 * | |
| 224 * PURPOSE: DTX handler of the speech encoder. Determines when to add | |
| 225 * the hangover period to the end of the speech burst, and | |
| 226 * also determines when to use old SID parameters, and when | |
| 227 * to update the SID parameters. This function also initializes | |
| 228 * the pseudo noise generator shift register. | |
| 229 * | |
| 230 * Operation of the TX DTX handler is based on the VAD flag | |
| 231 * given as input from the speech encoder. | |
| 232 * | |
| 233 * INPUTS: VAD_flag Voice activity decision | |
| 234 * *txdtx_ctrl Old encoder DTX control word | |
| 235 * | |
| 236 * OUTPUTS: *txdtx_ctrl Updated encoder DTX control word | |
| 237 * L_pn_seed_tx Initialized pseudo noise generator shift | |
| 238 * register (global variable) | |
| 239 * | |
| 240 * RETURN VALUE: none | |
| 241 * | |
| 242 *************************************************************************/ | |
| 243 | |
| 244 void tx_dtx ( | |
| 245 Word16 VAD_flag, | |
| 246 Word16 *txdtx_ctrl | |
| 247 ) | |
| 248 { | |
| 249 | |
| 250 /* N_elapsed (frames since last SID update) is incremented. If SID | |
| 251 is updated N_elapsed is cleared later in this function */ | |
| 252 | |
| 253 txdtx_N_elapsed = add (txdtx_N_elapsed, 1); | |
| 254 | |
| 255 /* If voice activity was detected, reset hangover counter */ | |
| 256 | |
| 257 test (); | |
| 258 if (sub (VAD_flag, 1) == 0) | |
| 259 { | |
| 260 txdtx_hangover = DTX_HANGOVER; move16 (); | |
| 261 *txdtx_ctrl = TX_SP_FLAG | TX_VAD_FLAG; move16 (); logic16 (); | |
| 262 } | |
| 263 else | |
| 264 { | |
| 265 test (); | |
| 266 if (txdtx_hangover == 0) | |
| 267 { | |
| 268 /* Hangover period is over, SID should be updated */ | |
| 269 | |
| 270 txdtx_N_elapsed = 0; move16 (); | |
| 271 | |
| 272 /* Check if this is the first frame after hangover period */ | |
| 273 test (); logic16 (); | |
| 274 if ((*txdtx_ctrl & TX_HANGOVER_ACTIVE) != 0) | |
| 275 { | |
| 276 *txdtx_ctrl = TX_PREV_HANGOVER_ACTIVE | |
| 277 | TX_SID_UPDATE; move16 (); logic16 (); | |
| 278 L_pn_seed_tx = PN_INITIAL_SEED; move32 (); | |
| 279 } | |
| 280 else | |
| 281 { | |
| 282 *txdtx_ctrl = TX_SID_UPDATE; move16 (); | |
| 283 } | |
| 284 } | |
| 285 else | |
| 286 { | |
| 287 /* Hangover period is not over, update hangover counter */ | |
| 288 txdtx_hangover = sub (txdtx_hangover, 1); | |
| 289 | |
| 290 /* Check if elapsed time from last SID update is greater than | |
| 291 threshold. If not, set SP=0 (although hangover period is not | |
| 292 over) and use old SID parameters for new SID frame. | |
| 293 N_elapsed counter must be summed with hangover counter in order | |
| 294 to avoid erroneus SP=1 decision in case when N_elapsed is grown | |
| 295 bigger than threshold and hangover period is still active */ | |
| 296 | |
| 297 test (); | |
| 298 if (sub (add (txdtx_N_elapsed, txdtx_hangover), | |
| 299 DTX_ELAPSED_THRESHOLD) < 0) | |
| 300 { | |
| 301 /* old SID frame should be used */ | |
| 302 *txdtx_ctrl = TX_USE_OLD_SID; move16 (); | |
| 303 } | |
| 304 else | |
| 305 { | |
| 306 test (); logic16 (); | |
| 307 if ((*txdtx_ctrl & TX_HANGOVER_ACTIVE) != 0) | |
| 308 { | |
| 309 *txdtx_ctrl = TX_PREV_HANGOVER_ACTIVE | |
| 310 | TX_HANGOVER_ACTIVE | |
| 311 | TX_SP_FLAG; move16 (); logic16 (); logic16 (); | |
| 312 } | |
| 313 else | |
| 314 { | |
| 315 *txdtx_ctrl = TX_HANGOVER_ACTIVE | |
| 316 | TX_SP_FLAG; move16 (); logic16 (); | |
| 317 } | |
| 318 } | |
| 319 } | |
| 320 } | |
| 321 | |
| 322 return; | |
| 323 } | |
| 324 | |
| 325 /************************************************************************* | |
| 326 * | |
| 327 * FUNCTION NAME: rx_dtx | |
| 328 * | |
| 329 * PURPOSE: DTX handler of the speech decoder. Determines when to update | |
| 330 * the reference comfort noise parameters (LSF and gain) at the | |
| 331 * end of the speech burst. Also classifies the incoming frames | |
| 332 * according to SID flag and BFI flag | |
| 333 * and determines when the transmission is active during comfort | |
| 334 * noise insertion. This function also initializes the pseudo | |
| 335 * noise generator shift register. | |
| 336 * | |
| 337 * Operation of the RX DTX handler is based on measuring the | |
| 338 * lengths of speech bursts and the lengths of the pauses between | |
| 339 * speech bursts to determine when there exists a hangover period | |
| 340 * at the end of a speech burst. The idea is to keep in sync with | |
| 341 * the TX DTX handler to be able to update the reference comfort | |
| 342 * noise parameters at the same time instances. | |
| 343 * | |
| 344 * INPUTS: *rxdtx_ctrl Old decoder DTX control word | |
| 345 * TAF Time alignment flag | |
| 346 * bfi Bad frame indicator flag | |
| 347 * SID_flag Silence descriptor flag | |
| 348 * | |
| 349 * OUTPUTS: *rxdtx_ctrl Updated decoder DTX control word | |
| 350 * rx_dtx_state Updated state of comfort noise interpolation | |
| 351 * period (global variable) | |
| 352 * L_pn_seed_rx Initialized pseudo noise generator shift | |
| 353 * register (global variable) | |
| 354 * | |
| 355 * RETURN VALUE: none | |
| 356 * | |
| 357 *************************************************************************/ | |
| 358 | |
| 359 void rx_dtx ( | |
| 360 Word16 *rxdtx_ctrl, | |
| 361 Word16 TAF, | |
| 362 Word16 bfi, | |
| 363 Word16 SID_flag | |
| 364 ) | |
| 365 { | |
| 366 Word16 frame_type; | |
| 367 | |
| 368 /* Frame classification according to bfi-flag and ternary-valued | |
| 369 SID flag. The frames between SID updates (not actually trans- | |
| 370 mitted) are also classified here; they will be discarded later | |
| 371 and provided with "NO TRANSMISSION"-flag */ | |
| 372 | |
| 373 test (); test (); | |
| 374 test (); test (); | |
| 375 test (); test (); | |
| 376 if ((sub (SID_flag, 2) == 0) && (bfi == 0)) | |
| 377 { | |
| 378 frame_type = VALID_SID_FRAME; move16 (); | |
| 379 } | |
| 380 else if ((SID_flag == 0) && (bfi == 0)) | |
| 381 { | |
| 382 frame_type = GOOD_SPEECH_FRAME; move16 (); | |
| 383 } | |
| 384 else if ((SID_flag == 0) && (bfi != 0)) | |
| 385 { | |
| 386 frame_type = UNUSABLE_FRAME; move16 (); | |
| 387 } | |
| 388 else | |
| 389 { | |
| 390 frame_type = INVALID_SID_FRAME; move16 (); | |
| 391 } | |
| 392 | |
| 393 /* Update of decoder state */ | |
| 394 /* Previous frame was classified as a speech frame */ | |
| 395 test (); logic16 (); | |
| 396 if ((*rxdtx_ctrl & RX_SP_FLAG) != 0) | |
| 397 { | |
| 398 test (); test (); test (); test (); | |
| 399 if (sub (frame_type, VALID_SID_FRAME) == 0) | |
| 400 { | |
| 401 *rxdtx_ctrl = RX_FIRST_SID_UPDATE; move16 (); | |
| 402 } | |
| 403 else if (sub (frame_type, INVALID_SID_FRAME) == 0) | |
| 404 { | |
| 405 *rxdtx_ctrl = RX_FIRST_SID_UPDATE | |
| 406 | RX_INVALID_SID_FRAME; move16 (); logic16(); | |
| 407 } | |
| 408 else if (sub (frame_type, UNUSABLE_FRAME) == 0) | |
| 409 { | |
| 410 *rxdtx_ctrl = RX_SP_FLAG; move16 (); | |
| 411 } | |
| 412 else if (sub (frame_type, GOOD_SPEECH_FRAME) == 0) | |
| 413 { | |
| 414 *rxdtx_ctrl = RX_SP_FLAG; move16 (); | |
| 415 } | |
| 416 } | |
| 417 else | |
| 418 { | |
| 419 test (); test (); test (); test (); | |
| 420 if (sub (frame_type, VALID_SID_FRAME) == 0) | |
| 421 { | |
| 422 *rxdtx_ctrl = RX_CONT_SID_UPDATE; move16 (); | |
| 423 } | |
| 424 else if (sub (frame_type, INVALID_SID_FRAME) == 0) | |
| 425 { | |
| 426 *rxdtx_ctrl = RX_CONT_SID_UPDATE | |
| 427 | RX_INVALID_SID_FRAME; move16 (); logic16 (); | |
| 428 } | |
| 429 else if (sub (frame_type, UNUSABLE_FRAME) == 0) | |
| 430 { | |
| 431 *rxdtx_ctrl = RX_CNI_BFI; move16 (); | |
| 432 } | |
| 433 else if (sub (frame_type, GOOD_SPEECH_FRAME) == 0) | |
| 434 { | |
| 435 /* If the previous frame (during CNI period) was muted, | |
| 436 raise the RX_PREV_DTX_MUTING flag */ | |
| 437 test (); logic16 (); | |
| 438 if ((*rxdtx_ctrl & RX_DTX_MUTING) != 0) | |
| 439 { | |
| 440 *rxdtx_ctrl = RX_SP_FLAG | RX_FIRST_SP_FLAG | |
| 441 | RX_PREV_DTX_MUTING; move16 (); logic16 (); | |
| 442 logic16 (); | |
| 443 } | |
| 444 else | |
| 445 { | |
| 446 *rxdtx_ctrl = RX_SP_FLAG | RX_FIRST_SP_FLAG; move16 (); | |
| 447 logic16 (); | |
| 448 } | |
| 449 } | |
| 450 } | |
| 451 | |
| 452 | |
| 453 test (); logic16 (); | |
| 454 if ((*rxdtx_ctrl & RX_SP_FLAG) != 0) | |
| 455 { | |
| 456 prev_SID_frames_lost = 0; move16 (); | |
| 457 rx_dtx_state = CN_INT_PERIOD - 1; move16 (); | |
| 458 } | |
| 459 else | |
| 460 { | |
| 461 /* First SID frame */ | |
| 462 test (); logic16 (); | |
| 463 if ((*rxdtx_ctrl & RX_FIRST_SID_UPDATE) != 0) | |
| 464 { | |
| 465 prev_SID_frames_lost = 0; move16 (); | |
| 466 rx_dtx_state = CN_INT_PERIOD - 1; move16 (); | |
| 467 } | |
| 468 | |
| 469 /* SID frame detected, but not the first SID */ | |
| 470 test (); logic16 (); | |
| 471 if ((*rxdtx_ctrl & RX_CONT_SID_UPDATE) != 0) | |
| 472 { | |
| 473 prev_SID_frames_lost = 0; move16 (); | |
| 474 | |
| 475 test (); test (); | |
| 476 if (sub (frame_type, VALID_SID_FRAME) == 0) | |
| 477 { | |
| 478 rx_dtx_state = 0; move16 (); | |
| 479 } | |
| 480 else if (sub (frame_type, INVALID_SID_FRAME) == 0) | |
| 481 { | |
| 482 test (); | |
| 483 if (sub(rx_dtx_state, (CN_INT_PERIOD - 1)) < 0) | |
| 484 { | |
| 485 rx_dtx_state = add(rx_dtx_state, 1); move16 (); | |
| 486 } | |
| 487 } | |
| 488 } | |
| 489 | |
| 490 /* Bad frame received in CNI mode */ | |
| 491 test (); logic16 (); | |
| 492 if ((*rxdtx_ctrl & RX_CNI_BFI) != 0) | |
| 493 { | |
| 494 test (); | |
| 495 if (sub (rx_dtx_state, (CN_INT_PERIOD - 1)) < 0) | |
| 496 { | |
| 497 rx_dtx_state = add (rx_dtx_state, 1); move16 (); | |
| 498 } | |
| 499 | |
| 500 /* If an unusable frame is received during CNI period | |
| 501 when TAF == 1, the frame is classified as a lost | |
| 502 SID frame */ | |
| 503 test (); | |
| 504 if (sub (TAF, 1) == 0) | |
| 505 { | |
| 506 *rxdtx_ctrl = *rxdtx_ctrl | RX_LOST_SID_FRAME; | |
| 507 move16 (); logic16 (); | |
| 508 prev_SID_frames_lost = add (prev_SID_frames_lost, 1); | |
| 509 } | |
| 510 else /* No transmission occurred */ | |
| 511 { | |
| 512 *rxdtx_ctrl = *rxdtx_ctrl | RX_NO_TRANSMISSION; | |
| 513 move16 (); logic16 (); | |
| 514 } | |
| 515 | |
| 516 test (); | |
| 517 if (sub (prev_SID_frames_lost, 1) > 0) | |
| 518 { | |
| 519 *rxdtx_ctrl = *rxdtx_ctrl | RX_DTX_MUTING; | |
| 520 move16 (); logic16 (); | |
| 521 } | |
| 522 } | |
| 523 } | |
| 524 | |
| 525 /* N_elapsed (frames since last SID update) is incremented. If SID | |
| 526 is updated N_elapsed is cleared later in this function */ | |
| 527 | |
| 528 rxdtx_N_elapsed = add (rxdtx_N_elapsed, 1); | |
| 529 | |
| 530 test (); logic16 (); | |
| 531 if ((*rxdtx_ctrl & RX_SP_FLAG) != 0) | |
| 532 { | |
| 533 rxdtx_aver_period = DTX_HANGOVER; move16 (); | |
| 534 } | |
| 535 else | |
| 536 { | |
| 537 test (); test (); | |
| 538 if (sub (rxdtx_N_elapsed, DTX_ELAPSED_THRESHOLD) > 0) | |
| 539 { | |
| 540 *rxdtx_ctrl |= RX_UPD_SID_QUANT_MEM; move16 (); logic16 (); | |
| 541 rxdtx_N_elapsed = 0; move16 (); | |
| 542 rxdtx_aver_period = 0; move16 (); | |
| 543 L_pn_seed_rx = PN_INITIAL_SEED; move32 (); | |
| 544 } | |
| 545 else if (rxdtx_aver_period == 0) | |
| 546 { | |
| 547 rxdtx_N_elapsed = 0; move16 (); | |
| 548 } | |
| 549 else | |
| 550 { | |
| 551 rxdtx_aver_period = sub (rxdtx_aver_period, 1); | |
| 552 } | |
| 553 } | |
| 554 | |
| 555 return; | |
| 556 } | |
| 557 | |
| 558 /************************************************************************* | |
| 559 * | |
| 560 * FUNCTION NAME: CN_encoding | |
| 561 * | |
| 562 * PURPOSE: Encoding of the comfort noise parameters into a SID frame. | |
| 563 * Use old SID parameters if necessary. Set the parameter | |
| 564 * indices not used by comfort noise parameters to zero. | |
| 565 * | |
| 566 * INPUTS: params[0..56] Comfort noise parameter frame from the | |
| 567 * speech encoder | |
| 568 * txdtx_ctrl TX DTX handler control word | |
| 569 * | |
| 570 * OUTPUTS: params[0..56] Comfort noise encoded parameter frame | |
| 571 * | |
| 572 * RETURN VALUE: none | |
| 573 * | |
| 574 *************************************************************************/ | |
| 575 | |
| 576 void CN_encoding ( | |
| 577 Word16 params[], | |
| 578 Word16 txdtx_ctrl | |
| 579 ) | |
| 580 { | |
| 581 Word16 i; | |
| 582 | |
| 583 test (); logic16 (); | |
| 584 if ((txdtx_ctrl & TX_SID_UPDATE) != 0) | |
| 585 { | |
| 586 /* Store new CN parameters in memory to be used later as old | |
| 587 CN parameters */ | |
| 588 | |
| 589 /* LPC parameter indices */ | |
| 590 for (i = 0; i < 5; i++) | |
| 591 { | |
| 592 old_CN_mem_tx[i] = params[i]; move16 (); | |
| 593 } | |
| 594 /* Codebook index computed in last subframe */ | |
| 595 old_CN_mem_tx[5] = params[56]; move16 (); | |
| 596 } | |
| 597 test (); logic16 (); | |
| 598 if ((txdtx_ctrl & TX_USE_OLD_SID) != 0) | |
| 599 { | |
| 600 /* Use old CN parameters previously stored in memory */ | |
| 601 for (i = 0; i < 5; i++) | |
| 602 { | |
| 603 params[i] = old_CN_mem_tx[i]; move16 (); | |
| 604 } | |
| 605 params[17] = old_CN_mem_tx[5]; move16 (); | |
| 606 params[30] = old_CN_mem_tx[5]; move16 (); | |
| 607 params[43] = old_CN_mem_tx[5]; move16 (); | |
| 608 params[56] = old_CN_mem_tx[5]; move16 (); | |
| 609 } | |
| 610 /* Set all the rest of the parameters to zero (SID codeword will | |
| 611 be written later) */ | |
| 612 for (i = 0; i < 12; i++) | |
| 613 { | |
| 614 params[i + 5] = 0; move16 (); | |
| 615 params[i + 18] = 0; move16 (); | |
| 616 params[i + 31] = 0; move16 (); | |
| 617 params[i + 44] = 0; move16 (); | |
| 618 } | |
| 619 | |
| 620 return; | |
| 621 } | |
| 622 | |
| 623 /************************************************************************* | |
| 624 * | |
| 625 * FUNCTION NAME: sid_codeword_encoding | |
| 626 * | |
| 627 * PURPOSE: Encoding of the SID codeword into the SID frame. The SID | |
| 628 * codeword consists of 95 bits, all set to '1'. | |
| 629 * | |
| 630 * INPUTS: ser2[0..243] Serial-mode speech parameter frame before | |
| 631 * writing SID codeword into it | |
| 632 * | |
| 633 * OUTPUTS: ser2[0..243] Serial-mode speech parameter frame with | |
| 634 * SID codeword written into it | |
| 635 * | |
| 636 * RETURN VALUE: none | |
| 637 * | |
| 638 *************************************************************************/ | |
| 639 | |
| 640 void sid_codeword_encoding ( | |
| 641 Word16 ser2[] | |
| 642 ) | |
| 643 { | |
| 644 Word16 i; | |
| 645 | |
| 646 for (i = 0; i < 95; i++) | |
| 647 { | |
| 648 ser2[SID_codeword_bit_idx[i]] = 1; move16 (); | |
| 649 } | |
| 650 | |
| 651 return; | |
| 652 } | |
| 653 | |
| 654 /************************************************************************* | |
| 655 * | |
| 656 * FUNCTION NAME: sid_frame_detection | |
| 657 * | |
| 658 * PURPOSE: Detecting of SID codeword from a received frame. The frames | |
| 659 * are classified into three categories based on how many bit | |
| 660 * errors occur in the SID codeword: | |
| 661 * - VALID SID FRAME | |
| 662 * - INVALID SID FRAME | |
| 663 * - SPEECH FRAME | |
| 664 * | |
| 665 * INPUTS: ser2[0..243] Received serial-mode speech parameter frame | |
| 666 * | |
| 667 * OUTPUTS: none | |
| 668 * | |
| 669 * RETURN VALUE: Ternary-valued SID classification flag | |
| 670 * | |
| 671 *************************************************************************/ | |
| 672 | |
| 673 Word16 sid_frame_detection ( | |
| 674 Word16 ser2[] | |
| 675 ) | |
| 676 { | |
| 677 Word16 i, nbr_errors, sid; | |
| 678 | |
| 679 /* Search for bit errors in SID codeword */ | |
| 680 nbr_errors = 0; move16 (); | |
| 681 for (i = 0; i < 95; i++) | |
| 682 { | |
| 683 test (); | |
| 684 if (ser2[SID_codeword_bit_idx[i]] == 0) | |
| 685 { | |
| 686 nbr_errors = add (nbr_errors, 1); | |
| 687 } | |
| 688 } | |
| 689 | |
| 690 /* Frame classification */ | |
| 691 test (); test (); | |
| 692 if (sub (nbr_errors, VALID_SID_THRESH) < 0) | |
| 693 { /* Valid SID frame */ | |
| 694 sid = 2; move16 (); | |
| 695 } | |
| 696 else if (sub (nbr_errors, INVALID_SID_THRESH) < 0) | |
| 697 { /* Invalid SID frame */ | |
| 698 sid = 1; move16 (); | |
| 699 } | |
| 700 else | |
| 701 { /* Speech frame */ | |
| 702 sid = 0; move16 (); | |
| 703 } | |
| 704 | |
| 705 return sid; | |
| 706 } | |
| 707 | |
| 708 /************************************************************************* | |
| 709 * | |
| 710 * FUNCTION NAME: update_lsf_history | |
| 711 * | |
| 712 * PURPOSE: Update the LSF parameter history. The LSF parameters kept | |
| 713 * in the buffer are used later for computing the reference | |
| 714 * LSF parameter vector and the averaged LSF parameter vector. | |
| 715 * | |
| 716 * INPUTS: lsf1[0..9] LSF vector of the 1st half of the frame | |
| 717 * lsf2[0..9] LSF vector of the 2nd half of the frame | |
| 718 * lsf_old[0..DTX_HANGOVER-1][0..M-1] | |
| 719 * Old LSF history | |
| 720 * | |
| 721 * OUTPUTS: lsf_old[0..DTX_HANGOVER-1][0..M-1] | |
| 722 * Updated LSF history | |
| 723 * | |
| 724 * RETURN VALUE: none | |
| 725 * | |
| 726 *************************************************************************/ | |
| 727 | |
| 728 void update_lsf_history ( | |
| 729 Word16 lsf1[M], | |
| 730 Word16 lsf2[M], | |
| 731 Word16 lsf_old[DTX_HANGOVER][M] | |
| 732 ) | |
| 733 { | |
| 734 Word16 i, j, temp; | |
| 735 | |
| 736 /* shift LSF data to make room for LSFs from current frame */ | |
| 737 /* This can also be implemented by using circular buffering */ | |
| 738 | |
| 739 for (i = DTX_HANGOVER - 1; i > 0; i--) | |
| 740 { | |
| 741 for (j = 0; j < M; j++) | |
| 742 { | |
| 743 lsf_old[i][j] = lsf_old[i - 1][j]; move16 (); | |
| 744 } | |
| 745 } | |
| 746 | |
| 747 /* Store new LSF data to lsf_old buffer */ | |
| 748 | |
| 749 for (i = 0; i < M; i++) | |
| 750 { | |
| 751 temp = add (shr (lsf1[i], 1), shr (lsf2[i], 1)); | |
| 752 lsf_old[0][i] = temp; move16 (); | |
| 753 } | |
| 754 | |
| 755 return; | |
| 756 } | |
| 757 | |
| 758 /************************************************************************* | |
| 759 * | |
| 760 * FUNCTION NAME: update_lsf_p_CN | |
| 761 * | |
| 762 * PURPOSE: Update the reference LSF parameter vector. The reference | |
| 763 * vector is computed by averaging the quantized LSF parameter | |
| 764 * vectors which exist in the LSF parameter history. | |
| 765 * | |
| 766 * INPUTS: lsf_old[0..DTX_HANGOVER-1][0..M-1] | |
| 767 * LSF parameter history | |
| 768 * | |
| 769 * OUTPUTS: lsf_p_CN[0..9] Computed reference LSF parameter vector | |
| 770 * | |
| 771 * RETURN VALUE: none | |
| 772 * | |
| 773 *************************************************************************/ | |
| 774 | |
| 775 void update_lsf_p_CN ( | |
| 776 Word16 lsf_old[DTX_HANGOVER][M], | |
| 777 Word16 lsf_p_CN[M] | |
| 778 ) | |
| 779 { | |
| 780 Word16 i, j; | |
| 781 Word32 L_temp; | |
| 782 | |
| 783 for (j = 0; j < M; j++) | |
| 784 { | |
| 785 L_temp = L_mult (INV_DTX_HANGOVER, lsf_old[0][j]); | |
| 786 for (i = 1; i < DTX_HANGOVER; i++) | |
| 787 { | |
| 788 L_temp = L_mac (L_temp, INV_DTX_HANGOVER, lsf_old[i][j]); | |
| 789 } | |
| 790 lsf_p_CN[j] = round (L_temp); move16 (); | |
| 791 } | |
| 792 | |
| 793 return; | |
| 794 } | |
| 795 | |
| 796 /************************************************************************* | |
| 797 * | |
| 798 * FUNCTION NAME: aver_lsf_history | |
| 799 * | |
| 800 * PURPOSE: Compute the averaged LSF parameter vector. Computation is | |
| 801 * performed by averaging the LSF parameter vectors which exist | |
| 802 * in the LSF parameter history, together with the LSF | |
| 803 * parameter vectors of the current frame. | |
| 804 * | |
| 805 * INPUTS: lsf_old[0..DTX_HANGOVER-1][0..M-1] | |
| 806 * LSF parameter history | |
| 807 * lsf1[0..M-1] LSF vector of the 1st half of the frame | |
| 808 * lsf2[0..M-1] LSF vector of the 2nd half of the frame | |
| 809 * | |
| 810 * OUTPUTS: lsf_aver[0..M-1] Averaged LSF parameter vector | |
| 811 * | |
| 812 * RETURN VALUE: none | |
| 813 * | |
| 814 *************************************************************************/ | |
| 815 | |
| 816 void aver_lsf_history ( | |
| 817 Word16 lsf_old[DTX_HANGOVER][M], | |
| 818 Word16 lsf1[M], | |
| 819 Word16 lsf2[M], | |
| 820 Word16 lsf_aver[M] | |
| 821 ) | |
| 822 { | |
| 823 Word16 i, j; | |
| 824 Word32 L_temp; | |
| 825 | |
| 826 for (j = 0; j < M; j++) | |
| 827 { | |
| 828 L_temp = L_mult (0x3fff, lsf1[j]); | |
| 829 L_temp = L_mac (L_temp, 0x3fff, lsf2[j]); | |
| 830 L_temp = L_mult (INV_DTX_HANGOVER_P1, extract_h (L_temp)); | |
| 831 | |
| 832 for (i = 0; i < DTX_HANGOVER; i++) | |
| 833 { | |
| 834 L_temp = L_mac (L_temp, INV_DTX_HANGOVER_P1, lsf_old[i][j]); | |
| 835 } | |
| 836 | |
| 837 lsf_aver[j] = extract_h (L_temp); move16 (); | |
| 838 } | |
| 839 | |
| 840 return; | |
| 841 } | |
| 842 | |
| 843 /************************************************************************* | |
| 844 * | |
| 845 * FUNCTION NAME: update_gain_code_history_tx | |
| 846 * | |
| 847 * PURPOSE: Update the fixed codebook gain parameter history of the | |
| 848 * encoder. The fixed codebook gain parameters kept in the buffer | |
| 849 * are used later for computing the reference fixed codebook | |
| 850 * gain parameter value and the averaged fixed codebook gain | |
| 851 * parameter value. | |
| 852 * | |
| 853 * INPUTS: new_gain_code New fixed codebook gain value | |
| 854 * | |
| 855 * gain_code_old_tx[0..4*DTX_HANGOVER-1] | |
| 856 * Old fixed codebook gain history of encoder | |
| 857 * | |
| 858 * OUTPUTS: gain_code_old_tx[0..4*DTX_HANGOVER-1] | |
| 859 * Updated fixed codebook gain history of encoder | |
| 860 * | |
| 861 * RETURN VALUE: none | |
| 862 * | |
| 863 *************************************************************************/ | |
| 864 | |
| 865 void update_gain_code_history_tx ( | |
| 866 Word16 new_gain_code, | |
| 867 Word16 gain_code_old_tx[4 * DTX_HANGOVER] | |
| 868 ) | |
| 869 { | |
| 870 | |
| 871 /* Circular buffer */ | |
| 872 gain_code_old_tx[buf_p_tx] = new_gain_code; move16 (); | |
| 873 | |
| 874 test (); | |
| 875 if (sub (buf_p_tx, (4 * DTX_HANGOVER - 1)) == 0) | |
| 876 { | |
| 877 buf_p_tx = 0; move16 (); | |
| 878 } | |
| 879 else | |
| 880 { | |
| 881 buf_p_tx = add (buf_p_tx, 1); | |
| 882 } | |
| 883 | |
| 884 return; | |
| 885 } | |
| 886 | |
| 887 /************************************************************************* | |
| 888 * | |
| 889 * FUNCTION NAME: update_gain_code_history_rx | |
| 890 * | |
| 891 * PURPOSE: Update the fixed codebook gain parameter history of the | |
| 892 * decoder. The fixed codebook gain parameters kept in the buffer | |
| 893 * are used later for computing the reference fixed codebook | |
| 894 * gain parameter value. | |
| 895 * | |
| 896 * INPUTS: new_gain_code New fixed codebook gain value | |
| 897 * | |
| 898 * gain_code_old_tx[0..4*DTX_HANGOVER-1] | |
| 899 * Old fixed codebook gain history of decoder | |
| 900 * | |
| 901 * OUTPUTS: gain_code_old_tx[0..4*DTX_HANGOVER-1] | |
| 902 * Updated fixed codebk gain history of decoder | |
| 903 * | |
| 904 * RETURN VALUE: none | |
| 905 * | |
| 906 *************************************************************************/ | |
| 907 | |
| 908 void update_gain_code_history_rx ( | |
| 909 Word16 new_gain_code, | |
| 910 Word16 gain_code_old_rx[4 * DTX_HANGOVER] | |
| 911 ) | |
| 912 { | |
| 913 | |
| 914 /* Circular buffer */ | |
| 915 gain_code_old_rx[buf_p_rx] = new_gain_code; move16 (); | |
| 916 | |
| 917 test (); | |
| 918 if (sub (buf_p_rx, (4 * DTX_HANGOVER - 1)) == 0) | |
| 919 { | |
| 920 buf_p_rx = 0; move16 (); | |
| 921 } | |
| 922 else | |
| 923 { | |
| 924 buf_p_rx = add (buf_p_rx, 1); | |
| 925 } | |
| 926 | |
| 927 return; | |
| 928 } | |
| 929 | |
| 930 /************************************************************************* | |
| 931 * | |
| 932 * FUNCTION NAME: compute_CN_excitation_gain | |
| 933 * | |
| 934 * PURPOSE: Compute the unquantized fixed codebook gain. Computation is | |
| 935 * based on the energy of the Linear Prediction residual signal. | |
| 936 * | |
| 937 * INPUTS: res2[0..39] Linear Prediction residual signal | |
| 938 * | |
| 939 * OUTPUTS: none | |
| 940 * | |
| 941 * RETURN VALUE: Unquantized fixed codebook gain | |
| 942 * | |
| 943 *************************************************************************/ | |
| 944 | |
| 945 Word16 compute_CN_excitation_gain ( | |
| 946 Word16 res2[L_SUBFR] | |
| 947 ) | |
| 948 { | |
| 949 Word16 i, norm, norm1, temp, overfl; | |
| 950 Word32 L_temp; | |
| 951 | |
| 952 /* Compute the energy of the LP residual signal */ | |
| 953 | |
| 954 norm = 0; move16 (); | |
| 955 do | |
| 956 { | |
| 957 overfl = 0; move16 (); | |
| 958 | |
| 959 L_temp = 0L; move32 (); | |
| 960 for (i = 0; i < L_SUBFR; i++) | |
| 961 { | |
| 962 temp = shr (res2[i], norm); | |
| 963 L_temp = L_mac (L_temp, temp, temp); | |
| 964 } | |
| 965 | |
| 966 test (); | |
| 967 if (L_sub (L_temp, MAX_32) == 0) | |
| 968 { | |
| 969 norm = add (norm, 1); | |
| 970 overfl = 1; move16 (); /* Set the overflow flag */ | |
| 971 } | |
| 972 test (); | |
| 973 } | |
| 974 while (overfl != 0); | |
| 975 | |
| 976 L_temp = L_add (L_temp, 1L); /* Avoid the case of all zeros */ | |
| 977 | |
| 978 /* Take the square root of the obtained energy value (sqroot is a 2nd | |
| 979 order Taylor series approximation) */ | |
| 980 | |
| 981 norm1 = norm_l (L_temp); | |
| 982 temp = extract_h (L_shl (L_temp, norm1)); | |
| 983 L_temp = L_mult (temp, temp); | |
| 984 L_temp = L_sub (805306368L, L_shr (L_temp, 3)); | |
| 985 L_temp = L_add (L_temp, L_mult (24576, temp)); | |
| 986 | |
| 987 temp = extract_h (L_temp); | |
| 988 test (); logic16 (); | |
| 989 if ((norm1 & 0x0001) != 0) | |
| 990 { | |
| 991 temp = mult_r (temp, 23170); | |
| 992 norm1 = sub (norm1, 1); | |
| 993 } | |
| 994 /* Divide the result of sqroot operation by sqroot(10) */ | |
| 995 | |
| 996 temp = mult_r (temp, 10362); | |
| 997 | |
| 998 /* Re-scale to get the final value */ | |
| 999 | |
| 1000 norm1 = shr (norm1, 1); | |
| 1001 norm1 = sub (norm1, norm); | |
| 1002 | |
| 1003 test (); | |
| 1004 if (norm1 >= 0) | |
| 1005 { | |
| 1006 temp = shr (temp, norm1); | |
| 1007 } | |
| 1008 else | |
| 1009 { | |
| 1010 temp = shl (temp, abs_s (norm1)); | |
| 1011 } | |
| 1012 | |
| 1013 return temp; | |
| 1014 } | |
| 1015 | |
| 1016 /************************************************************************* | |
| 1017 * | |
| 1018 * FUNCTION NAME: update_gcode0_CN | |
| 1019 * | |
| 1020 * PURPOSE: Update the reference fixed codebook gain parameter value. | |
| 1021 * The reference value is computed by averaging the quantized | |
| 1022 * fixed codebook gain parameter values which exist in the | |
| 1023 * fixed codebook gain parameter history. | |
| 1024 * | |
| 1025 * INPUTS: gain_code_old[0..4*DTX_HANGOVER-1] | |
| 1026 * fixed codebook gain parameter history | |
| 1027 * | |
| 1028 * OUTPUTS: none | |
| 1029 * | |
| 1030 * RETURN VALUE: Computed reference fixed codebook gain | |
| 1031 * | |
| 1032 *************************************************************************/ | |
| 1033 | |
| 1034 Word16 update_gcode0_CN ( | |
| 1035 Word16 gain_code_old[4 * DTX_HANGOVER] | |
| 1036 ) | |
| 1037 { | |
| 1038 Word16 i, j; | |
| 1039 Word32 L_temp, L_ret; | |
| 1040 | |
| 1041 L_ret = 0L; move32 (); | |
| 1042 for (i = 0; i < DTX_HANGOVER; i++) | |
| 1043 { | |
| 1044 L_temp = L_mult (0x1fff, gain_code_old[4 * i]); | |
| 1045 for (j = 1; j < 4; j++) | |
| 1046 { | |
| 1047 L_temp = L_mac (L_temp, 0x1fff, gain_code_old[4 * i + j]); | |
| 1048 } | |
| 1049 L_ret = L_mac (L_ret, INV_DTX_HANGOVER, extract_h (L_temp)); | |
| 1050 } | |
| 1051 | |
| 1052 return extract_h (L_ret); | |
| 1053 } | |
| 1054 | |
| 1055 /************************************************************************* | |
| 1056 * | |
| 1057 * FUNCTION NAME: aver_gain_code_history | |
| 1058 * | |
| 1059 * PURPOSE: Compute the averaged fixed codebook gain parameter value. | |
| 1060 * Computation is performed by averaging the fixed codebook | |
| 1061 * gain parameter values which exist in the fixed codebook | |
| 1062 * gain parameter history, together with the fixed codebook | |
| 1063 * gain parameter value of the current subframe. | |
| 1064 * | |
| 1065 * INPUTS: CN_excitation_gain | |
| 1066 * Unquantized fixed codebook gain value | |
| 1067 * of the current subframe | |
| 1068 * gain_code_old[0..4*DTX_HANGOVER-1] | |
| 1069 * fixed codebook gain parameter history | |
| 1070 * | |
| 1071 * OUTPUTS: none | |
| 1072 * | |
| 1073 * RETURN VALUE: Averaged fixed codebook gain value | |
| 1074 * | |
| 1075 *************************************************************************/ | |
| 1076 | |
| 1077 Word16 aver_gain_code_history ( | |
| 1078 Word16 CN_excitation_gain, | |
| 1079 Word16 gain_code_old[4 * DTX_HANGOVER] | |
| 1080 ) | |
| 1081 { | |
| 1082 Word16 i; | |
| 1083 Word32 L_ret; | |
| 1084 | |
| 1085 L_ret = L_mult (0x470, CN_excitation_gain); | |
| 1086 | |
| 1087 for (i = 0; i < (4 * DTX_HANGOVER); i++) | |
| 1088 { | |
| 1089 L_ret = L_mac (L_ret, 0x470, gain_code_old[i]); | |
| 1090 } | |
| 1091 return extract_h (L_ret); | |
| 1092 } | |
| 1093 | |
| 1094 /************************************************************************* | |
| 1095 * | |
| 1096 * FUNCTION NAME: build_CN_code | |
| 1097 * | |
| 1098 * PURPOSE: Compute the comfort noise fixed codebook excitation. The | |
| 1099 * gains of the pulses are always +/-1. | |
| 1100 * | |
| 1101 * INPUTS: *seed Old CN generator shift register state | |
| 1102 * | |
| 1103 * OUTPUTS: cod[0..39] Generated comfort noise fixed codebook vector | |
| 1104 * *seed Updated CN generator shift register state | |
| 1105 * | |
| 1106 * RETURN VALUE: none | |
| 1107 * | |
| 1108 *************************************************************************/ | |
| 1109 | |
| 1110 void build_CN_code ( | |
| 1111 Word16 cod[], | |
| 1112 Word32 *seed | |
| 1113 ) | |
| 1114 { | |
| 1115 Word16 i, j, k; | |
| 1116 | |
| 1117 for (i = 0; i < L_SUBFR; i++) | |
| 1118 { | |
| 1119 cod[i] = 0; move16 (); | |
| 1120 } | |
| 1121 | |
| 1122 for (k = 0; k < NB_PULSE; k++) | |
| 1123 { | |
| 1124 i = pseudonoise (seed, 2); /* generate pulse position */ | |
| 1125 i = shr (extract_l (L_mult (i, 10)), 1); | |
| 1126 i = add (i, k); | |
| 1127 | |
| 1128 j = pseudonoise (seed, 1); /* generate sign */ | |
| 1129 | |
| 1130 test (); | |
| 1131 if (j > 0) | |
| 1132 { | |
| 1133 cod[i] = 4096; move16 (); | |
| 1134 } | |
| 1135 else | |
| 1136 { | |
| 1137 cod[i] = -4096; move16 (); | |
| 1138 } | |
| 1139 } | |
| 1140 | |
| 1141 return; | |
| 1142 } | |
| 1143 | |
| 1144 /************************************************************************* | |
| 1145 * | |
| 1146 * FUNCTION NAME: pseudonoise | |
| 1147 * | |
| 1148 * PURPOSE: Generate a random integer value to use in comfort noise | |
| 1149 * generation. The algorithm uses polynomial x^31 + x^3 + 1 | |
| 1150 * (length of PN sequence is 2^31 - 1). | |
| 1151 * | |
| 1152 * INPUTS: *shift_reg Old CN generator shift register state | |
| 1153 * | |
| 1154 * | |
| 1155 * OUTPUTS: *shift_reg Updated CN generator shift register state | |
| 1156 * | |
| 1157 * RETURN VALUE: Generated random integer value | |
| 1158 * | |
| 1159 *************************************************************************/ | |
| 1160 | |
| 1161 Word16 pseudonoise ( | |
| 1162 Word32 *shift_reg, | |
| 1163 Word16 no_bits | |
| 1164 ) | |
| 1165 { | |
| 1166 Word16 noise_bits, Sn, i; | |
| 1167 | |
| 1168 noise_bits = 0; move16 (); | |
| 1169 for (i = 0; i < no_bits; i++) | |
| 1170 { | |
| 1171 /* State n == 31 */ | |
| 1172 test (); logic32 (); | |
| 1173 if ((*shift_reg & 0x00000001L) != 0) | |
| 1174 { | |
| 1175 Sn = 1; move16 (); | |
| 1176 } | |
| 1177 else | |
| 1178 { | |
| 1179 Sn = 0; move16 (); | |
| 1180 } | |
| 1181 | |
| 1182 /* State n == 3 */ | |
| 1183 test (); logic32 (); | |
| 1184 if ((*shift_reg & 0x10000000L) != 0) | |
| 1185 { | |
| 1186 Sn = Sn ^ 1; logic16 (); | |
| 1187 } | |
| 1188 else | |
| 1189 { | |
| 1190 Sn = Sn ^ 0; logic16 (); | |
| 1191 } | |
| 1192 | |
| 1193 noise_bits = shl (noise_bits, 1); | |
| 1194 noise_bits = noise_bits | (extract_l (*shift_reg) & 1); | |
| 1195 logic16 (); logic16 (); | |
| 1196 | |
| 1197 *shift_reg = L_shr (*shift_reg, 1); move32 (); | |
| 1198 test (); logic16 (); | |
| 1199 if (Sn & 1) | |
| 1200 { | |
| 1201 *shift_reg = *shift_reg | 0x40000000L; move32 (); logic32 (); | |
| 1202 } | |
| 1203 } | |
| 1204 | |
| 1205 return noise_bits; | |
| 1206 } | |
| 1207 | |
| 1208 /************************************************************************* | |
| 1209 * | |
| 1210 * FUNCTION NAME: interpolate_CN_param | |
| 1211 * | |
| 1212 * PURPOSE: Interpolate a comfort noise parameter value over the comfort | |
| 1213 * noise update period. | |
| 1214 * | |
| 1215 * INPUTS: old_param The older parameter of the interpolation | |
| 1216 * (the endpoint the interpolation is started | |
| 1217 * from) | |
| 1218 * new_param The newer parameter of the interpolation | |
| 1219 * (the endpoint the interpolation is ended to) | |
| 1220 * rx_dtx_state State of the comfort noise insertion period | |
| 1221 * | |
| 1222 * OUTPUTS: none | |
| 1223 * | |
| 1224 * RETURN VALUE: Interpolated CN parameter value | |
| 1225 * | |
| 1226 *************************************************************************/ | |
| 1227 | |
| 1228 Word16 interpolate_CN_param ( | |
| 1229 Word16 old_param, | |
| 1230 Word16 new_param, | |
| 1231 Word16 rx_dtx_state | |
| 1232 ) | |
| 1233 { | |
| 1234 static const Word16 interp_factor[CN_INT_PERIOD] = | |
| 1235 { | |
| 1236 0x0555, 0x0aaa, 0x1000, 0x1555, 0x1aaa, 0x2000, | |
| 1237 0x2555, 0x2aaa, 0x3000, 0x3555, 0x3aaa, 0x4000, | |
| 1238 0x4555, 0x4aaa, 0x5000, 0x5555, 0x5aaa, 0x6000, | |
| 1239 0x6555, 0x6aaa, 0x7000, 0x7555, 0x7aaa, 0x7fff}; | |
| 1240 Word16 temp; | |
| 1241 Word32 L_temp; | |
| 1242 | |
| 1243 L_temp = L_mult (interp_factor[rx_dtx_state], new_param); | |
| 1244 temp = sub (0x7fff, interp_factor[rx_dtx_state]); | |
| 1245 temp = add (temp, 1); | |
| 1246 L_temp = L_mac (L_temp, temp, old_param); | |
| 1247 temp = round (L_temp); | |
| 1248 | |
| 1249 return temp; | |
| 1250 } | |
| 1251 | |
| 1252 /************************************************************************* | |
| 1253 * | |
| 1254 * FUNCTION NAME: interpolate_CN_lsf | |
| 1255 * | |
| 1256 * PURPOSE: Interpolate comfort noise LSF parameter vector over the comfort | |
| 1257 * noise update period. | |
| 1258 * | |
| 1259 * INPUTS: lsf_old_CN[0..9] | |
| 1260 * The older LSF parameter vector of the | |
| 1261 * interpolation (the endpoint the interpolation | |
| 1262 * is started from) | |
| 1263 * lsf_new_CN[0..9] | |
| 1264 * The newer LSF parameter vector of the | |
| 1265 * interpolation (the endpoint the interpolation | |
| 1266 * is ended to) | |
| 1267 * rx_dtx_state State of the comfort noise insertion period | |
| 1268 * | |
| 1269 * OUTPUTS: lsf_interp_CN[0..9] | |
| 1270 * Interpolated LSF parameter vector | |
| 1271 * | |
| 1272 * RETURN VALUE: none | |
| 1273 * | |
| 1274 *************************************************************************/ | |
| 1275 | |
| 1276 void interpolate_CN_lsf ( | |
| 1277 Word16 lsf_old_CN[M], | |
| 1278 Word16 lsf_new_CN[M], | |
| 1279 Word16 lsf_interp_CN[M], | |
| 1280 Word16 rx_dtx_state | |
| 1281 ) | |
| 1282 { | |
| 1283 Word16 i; | |
| 1284 | |
| 1285 for (i = 0; i < M; i++) | |
| 1286 { | |
| 1287 lsf_interp_CN[i] = interpolate_CN_param (lsf_old_CN[i], | |
| 1288 lsf_new_CN[i], | |
| 1289 rx_dtx_state); move16 (); | |
| 1290 } | |
| 1291 | |
| 1292 return; | |
| 1293 } |
