| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 /* |  | 
| 2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |  | 
| 3  * |  | 
| 4  *  Use of this source code is governed by a BSD-style license |  | 
| 5  *  that can be found in the LICENSE file in the root of the source |  | 
| 6  *  tree. An additional intellectual property rights grant can be found |  | 
| 7  *  in the file PATENTS.  All contributing project authors may |  | 
| 8  *  be found in the AUTHORS file in the root of the source tree. |  | 
| 9  */ |  | 
| 10 |  | 
| 11 #include "webrtc_cng.h" |  | 
| 12 |  | 
| 13 #include <string.h> |  | 
| 14 #include <stdlib.h> |  | 
| 15 |  | 
| 16 #include "cng_helpfuns.h" |  | 
| 17 #include "signal_processing_library.h" |  | 
| 18 |  | 
| 19 typedef struct WebRtcCngDecoder_ { |  | 
| 20   uint32_t dec_seed; |  | 
| 21   int32_t dec_target_energy; |  | 
| 22   int32_t dec_used_energy; |  | 
| 23   int16_t dec_target_reflCoefs[WEBRTC_CNG_MAX_LPC_ORDER + 1]; |  | 
| 24   int16_t dec_used_reflCoefs[WEBRTC_CNG_MAX_LPC_ORDER + 1]; |  | 
| 25   int16_t dec_filtstate[WEBRTC_CNG_MAX_LPC_ORDER + 1]; |  | 
| 26   int16_t dec_filtstateLow[WEBRTC_CNG_MAX_LPC_ORDER + 1]; |  | 
| 27   int16_t dec_Efiltstate[WEBRTC_CNG_MAX_LPC_ORDER + 1]; |  | 
| 28   int16_t dec_EfiltstateLow[WEBRTC_CNG_MAX_LPC_ORDER + 1]; |  | 
| 29   int16_t dec_order; |  | 
| 30   int16_t dec_target_scale_factor;  /* Q29 */ |  | 
| 31   int16_t dec_used_scale_factor;  /* Q29 */ |  | 
| 32   int16_t target_scale_factor;  /* Q13 */ |  | 
| 33   int16_t errorcode; |  | 
| 34   int16_t initflag; |  | 
| 35 } WebRtcCngDecoder; |  | 
| 36 |  | 
| 37 typedef struct WebRtcCngEncoder_ { |  | 
| 38   size_t enc_nrOfCoefs; |  | 
| 39   int enc_sampfreq; |  | 
| 40   int16_t enc_interval; |  | 
| 41   int16_t enc_msSinceSID; |  | 
| 42   int32_t enc_Energy; |  | 
| 43   int16_t enc_reflCoefs[WEBRTC_CNG_MAX_LPC_ORDER + 1]; |  | 
| 44   int32_t enc_corrVector[WEBRTC_CNG_MAX_LPC_ORDER + 1]; |  | 
| 45   uint32_t enc_seed; |  | 
| 46   int16_t errorcode; |  | 
| 47   int16_t initflag; |  | 
| 48 } WebRtcCngEncoder; |  | 
| 49 |  | 
| 50 const int32_t WebRtcCng_kDbov[94] = { |  | 
| 51   1081109975,  858756178,  682134279,  541838517,  430397633,  341876992, |  | 
| 52   271562548,  215709799,  171344384,  136103682,  108110997,   85875618, |  | 
| 53   68213428,   54183852,   43039763,   34187699,   27156255,   21570980, |  | 
| 54   17134438,   13610368,   10811100,    8587562,    6821343,    5418385, |  | 
| 55   4303976,    3418770,    2715625,    2157098,    1713444,    1361037, |  | 
| 56   1081110,     858756,     682134,     541839,     430398,     341877, |  | 
| 57   271563,     215710,     171344,     136104,     108111,      85876, |  | 
| 58   68213,      54184,      43040,      34188,      27156,      21571, |  | 
| 59   17134,      13610,      10811,       8588,       6821,       5418, |  | 
| 60   4304,       3419,       2716,       2157,       1713,       1361, |  | 
| 61   1081,        859,        682,        542,        430,        342, |  | 
| 62   272,        216,        171,        136,        108,         86, |  | 
| 63   68,         54,         43,         34,         27,         22, |  | 
| 64   17,         14,         11,          9,          7,          5, |  | 
| 65   4,          3,          3,          2,          2,           1, |  | 
| 66   1,          1,          1,          1 |  | 
| 67 }; |  | 
| 68 |  | 
| 69 const int16_t WebRtcCng_kCorrWindow[WEBRTC_CNG_MAX_LPC_ORDER] = { |  | 
| 70   32702, 32636, 32570, 32505, 32439, 32374, |  | 
| 71   32309, 32244, 32179, 32114, 32049, 31985 |  | 
| 72 }; |  | 
| 73 |  | 
| 74 /**************************************************************************** |  | 
| 75  * WebRtcCng_CreateEnc/Dec(...) |  | 
| 76  * |  | 
| 77  * These functions create an instance to the specified structure |  | 
| 78  * |  | 
| 79  * Input: |  | 
| 80  *      - XXX_inst      : Pointer to created instance that should be created |  | 
| 81  * |  | 
| 82  * Return value         :  0 - Ok |  | 
| 83  *                        -1 - Error |  | 
| 84  */ |  | 
| 85 int16_t WebRtcCng_CreateEnc(CNG_enc_inst** cng_inst) { |  | 
| 86   if (cng_inst != NULL) { |  | 
| 87     *cng_inst = (CNG_enc_inst*) malloc(sizeof(WebRtcCngEncoder)); |  | 
| 88     if (*cng_inst != NULL) { |  | 
| 89       (*(WebRtcCngEncoder**) cng_inst)->errorcode = 0; |  | 
| 90       (*(WebRtcCngEncoder**) cng_inst)->initflag = 0; |  | 
| 91 |  | 
| 92       /* Needed to get the right function pointers in SPLIB. */ |  | 
| 93       WebRtcSpl_Init(); |  | 
| 94 |  | 
| 95       return 0; |  | 
| 96     } else { |  | 
| 97       /* The memory could not be allocated. */ |  | 
| 98       return -1; |  | 
| 99     } |  | 
| 100   } else { |  | 
| 101     /* The input pointer is invalid (NULL). */ |  | 
| 102     return -1; |  | 
| 103   } |  | 
| 104 } |  | 
| 105 |  | 
| 106 int16_t WebRtcCng_CreateDec(CNG_dec_inst** cng_inst) { |  | 
| 107   if (cng_inst != NULL ) { |  | 
| 108     *cng_inst = (CNG_dec_inst*) malloc(sizeof(WebRtcCngDecoder)); |  | 
| 109     if (*cng_inst != NULL ) { |  | 
| 110       (*(WebRtcCngDecoder**) cng_inst)->errorcode = 0; |  | 
| 111       (*(WebRtcCngDecoder**) cng_inst)->initflag = 0; |  | 
| 112 |  | 
| 113       /* Needed to get the right function pointers in SPLIB. */ |  | 
| 114       WebRtcSpl_Init(); |  | 
| 115 |  | 
| 116       return 0; |  | 
| 117     } else { |  | 
| 118       /* The memory could not be allocated */ |  | 
| 119       return -1; |  | 
| 120     } |  | 
| 121   } else { |  | 
| 122     /* The input pointer is invalid (NULL). */ |  | 
| 123     return -1; |  | 
| 124   } |  | 
| 125 } |  | 
| 126 |  | 
| 127 /**************************************************************************** |  | 
| 128  * WebRtcCng_InitEnc/Dec(...) |  | 
| 129  * |  | 
| 130  * This function initializes a instance |  | 
| 131  * |  | 
| 132  * Input: |  | 
| 133  *    - cng_inst      : Instance that should be initialized |  | 
| 134  * |  | 
| 135  *    - fs            : 8000 for narrowband and 16000 for wideband |  | 
| 136  *    - interval      : generate SID data every interval ms |  | 
| 137  *    - quality       : TBD |  | 
| 138  * |  | 
| 139  * Output: |  | 
| 140  *    - cng_inst      : Initialized instance |  | 
| 141  * |  | 
| 142  * Return value       :  0 - Ok |  | 
| 143  *                      -1 - Error |  | 
| 144  */ |  | 
| 145 int WebRtcCng_InitEnc(CNG_enc_inst* cng_inst, int fs, int16_t interval, |  | 
| 146                       int16_t quality) { |  | 
| 147   int i; |  | 
| 148   WebRtcCngEncoder* inst = (WebRtcCngEncoder*) cng_inst; |  | 
| 149   memset(inst, 0, sizeof(WebRtcCngEncoder)); |  | 
| 150 |  | 
| 151   /* Check LPC order */ |  | 
| 152   if (quality > WEBRTC_CNG_MAX_LPC_ORDER || quality <= 0) { |  | 
| 153     inst->errorcode = CNG_DISALLOWED_LPC_ORDER; |  | 
| 154     return -1; |  | 
| 155   } |  | 
| 156 |  | 
| 157   inst->enc_sampfreq = fs; |  | 
| 158   inst->enc_interval = interval; |  | 
| 159   inst->enc_nrOfCoefs = quality; |  | 
| 160   inst->enc_msSinceSID = 0; |  | 
| 161   inst->enc_seed = 7777;  /* For debugging only. */ |  | 
| 162   inst->enc_Energy = 0; |  | 
| 163   for (i = 0; i < (WEBRTC_CNG_MAX_LPC_ORDER + 1); i++) { |  | 
| 164     inst->enc_reflCoefs[i] = 0; |  | 
| 165     inst->enc_corrVector[i] = 0; |  | 
| 166   } |  | 
| 167   inst->initflag = 1; |  | 
| 168 |  | 
| 169   return 0; |  | 
| 170 } |  | 
| 171 |  | 
| 172 void WebRtcCng_InitDec(CNG_dec_inst* cng_inst) { |  | 
| 173   int i; |  | 
| 174 |  | 
| 175   WebRtcCngDecoder* inst = (WebRtcCngDecoder*) cng_inst; |  | 
| 176 |  | 
| 177   memset(inst, 0, sizeof(WebRtcCngDecoder)); |  | 
| 178   inst->dec_seed = 7777;  /* For debugging only. */ |  | 
| 179   inst->dec_order = 5; |  | 
| 180   inst->dec_target_scale_factor = 0; |  | 
| 181   inst->dec_used_scale_factor = 0; |  | 
| 182   for (i = 0; i < (WEBRTC_CNG_MAX_LPC_ORDER + 1); i++) { |  | 
| 183     inst->dec_filtstate[i] = 0; |  | 
| 184     inst->dec_target_reflCoefs[i] = 0; |  | 
| 185     inst->dec_used_reflCoefs[i] = 0; |  | 
| 186   } |  | 
| 187   inst->dec_target_reflCoefs[0] = 0; |  | 
| 188   inst->dec_used_reflCoefs[0] = 0; |  | 
| 189   inst->dec_used_energy = 0; |  | 
| 190   inst->initflag = 1; |  | 
| 191 } |  | 
| 192 |  | 
| 193 /**************************************************************************** |  | 
| 194  * WebRtcCng_FreeEnc/Dec(...) |  | 
| 195  * |  | 
| 196  * These functions frees the dynamic memory of a specified instance |  | 
| 197  * |  | 
| 198  * Input: |  | 
| 199  *    - cng_inst      : Pointer to created instance that should be freed |  | 
| 200  * |  | 
| 201  * Return value       :  0 - Ok |  | 
| 202  *                      -1 - Error |  | 
| 203  */ |  | 
| 204 int16_t WebRtcCng_FreeEnc(CNG_enc_inst* cng_inst) { |  | 
| 205   free(cng_inst); |  | 
| 206   return 0; |  | 
| 207 } |  | 
| 208 |  | 
| 209 int16_t WebRtcCng_FreeDec(CNG_dec_inst* cng_inst) { |  | 
| 210   free(cng_inst); |  | 
| 211   return 0; |  | 
| 212 } |  | 
| 213 |  | 
| 214 /**************************************************************************** |  | 
| 215  * WebRtcCng_Encode(...) |  | 
| 216  * |  | 
| 217  * These functions analyzes background noise |  | 
| 218  * |  | 
| 219  * Input: |  | 
| 220  *    - cng_inst      : Pointer to created instance |  | 
| 221  *    - speech        : Signal (noise) to be analyzed |  | 
| 222  *    - nrOfSamples   : Size of speech vector |  | 
| 223  *    - bytesOut      : Nr of bytes to transmit, might be 0 |  | 
| 224  * |  | 
| 225  * Return value       :  0 - Ok |  | 
| 226  *                      -1 - Error |  | 
| 227  */ |  | 
| 228 int WebRtcCng_Encode(CNG_enc_inst* cng_inst, int16_t* speech, |  | 
| 229                      size_t nrOfSamples, uint8_t* SIDdata, |  | 
| 230                      size_t* bytesOut, int16_t forceSID) { |  | 
| 231   WebRtcCngEncoder* inst = (WebRtcCngEncoder*) cng_inst; |  | 
| 232 |  | 
| 233   int16_t arCoefs[WEBRTC_CNG_MAX_LPC_ORDER + 1]; |  | 
| 234   int32_t corrVector[WEBRTC_CNG_MAX_LPC_ORDER + 1]; |  | 
| 235   int16_t refCs[WEBRTC_CNG_MAX_LPC_ORDER + 1]; |  | 
| 236   int16_t hanningW[WEBRTC_CNG_MAX_OUTSIZE_ORDER]; |  | 
| 237   int16_t ReflBeta = 19661;  /* 0.6 in q15. */ |  | 
| 238   int16_t ReflBetaComp = 13107;  /* 0.4 in q15. */ |  | 
| 239   int32_t outEnergy; |  | 
| 240   int outShifts; |  | 
| 241   size_t i; |  | 
| 242   int stab; |  | 
| 243   int acorrScale; |  | 
| 244   size_t index; |  | 
| 245   size_t ind, factor; |  | 
| 246   int32_t* bptr; |  | 
| 247   int32_t blo, bhi; |  | 
| 248   int16_t negate; |  | 
| 249   const int16_t* aptr; |  | 
| 250   int16_t speechBuf[WEBRTC_CNG_MAX_OUTSIZE_ORDER]; |  | 
| 251 |  | 
| 252   /* Check if encoder initiated. */ |  | 
| 253   if (inst->initflag != 1) { |  | 
| 254     inst->errorcode = CNG_ENCODER_NOT_INITIATED; |  | 
| 255     return -1; |  | 
| 256   } |  | 
| 257 |  | 
| 258   /* Check framesize. */ |  | 
| 259   if (nrOfSamples > WEBRTC_CNG_MAX_OUTSIZE_ORDER) { |  | 
| 260     inst->errorcode = CNG_DISALLOWED_FRAME_SIZE; |  | 
| 261     return -1; |  | 
| 262   } |  | 
| 263 |  | 
| 264   for (i = 0; i < nrOfSamples; i++) { |  | 
| 265     speechBuf[i] = speech[i]; |  | 
| 266   } |  | 
| 267 |  | 
| 268   factor = nrOfSamples; |  | 
| 269 |  | 
| 270   /* Calculate energy and a coefficients. */ |  | 
| 271   outEnergy = WebRtcSpl_Energy(speechBuf, nrOfSamples, &outShifts); |  | 
| 272   while (outShifts > 0) { |  | 
| 273     /* We can only do 5 shifts without destroying accuracy in |  | 
| 274      * division factor. */ |  | 
| 275     if (outShifts > 5) { |  | 
| 276       outEnergy <<= (outShifts - 5); |  | 
| 277       outShifts = 5; |  | 
| 278     } else { |  | 
| 279       factor /= 2; |  | 
| 280       outShifts--; |  | 
| 281     } |  | 
| 282   } |  | 
| 283   outEnergy = WebRtcSpl_DivW32W16(outEnergy, (int16_t)factor); |  | 
| 284 |  | 
| 285   if (outEnergy > 1) { |  | 
| 286     /* Create Hanning Window. */ |  | 
| 287     WebRtcSpl_GetHanningWindow(hanningW, nrOfSamples / 2); |  | 
| 288     for (i = 0; i < (nrOfSamples / 2); i++) |  | 
| 289       hanningW[nrOfSamples - i - 1] = hanningW[i]; |  | 
| 290 |  | 
| 291     WebRtcSpl_ElementwiseVectorMult(speechBuf, hanningW, speechBuf, nrOfSamples, |  | 
| 292                                     14); |  | 
| 293 |  | 
| 294     WebRtcSpl_AutoCorrelation(speechBuf, nrOfSamples, inst->enc_nrOfCoefs, |  | 
| 295                               corrVector, &acorrScale); |  | 
| 296 |  | 
| 297     if (*corrVector == 0) |  | 
| 298       *corrVector = WEBRTC_SPL_WORD16_MAX; |  | 
| 299 |  | 
| 300     /* Adds the bandwidth expansion. */ |  | 
| 301     aptr = WebRtcCng_kCorrWindow; |  | 
| 302     bptr = corrVector; |  | 
| 303 |  | 
| 304     /* (zzz) lpc16_1 = 17+1+820+2+2 = 842 (ordo2=700). */ |  | 
| 305     for (ind = 0; ind < inst->enc_nrOfCoefs; ind++) { |  | 
| 306       /* The below code multiplies the 16 b corrWindow values (Q15) with |  | 
| 307        * the 32 b corrvector (Q0) and shifts the result down 15 steps. */ |  | 
| 308       negate = *bptr < 0; |  | 
| 309       if (negate) |  | 
| 310         *bptr = -*bptr; |  | 
| 311 |  | 
| 312       blo = (int32_t) * aptr * (*bptr & 0xffff); |  | 
| 313       bhi = ((blo >> 16) & 0xffff) |  | 
| 314           + ((int32_t)(*aptr++) * ((*bptr >> 16) & 0xffff)); |  | 
| 315       blo = (blo & 0xffff) | ((bhi & 0xffff) << 16); |  | 
| 316 |  | 
| 317       *bptr = (((bhi >> 16) & 0x7fff) << 17) | ((uint32_t) blo >> 15); |  | 
| 318       if (negate) |  | 
| 319         *bptr = -*bptr; |  | 
| 320       bptr++; |  | 
| 321     } |  | 
| 322     /* End of bandwidth expansion. */ |  | 
| 323 |  | 
| 324     stab = WebRtcSpl_LevinsonDurbin(corrVector, arCoefs, refCs, |  | 
| 325                                     inst->enc_nrOfCoefs); |  | 
| 326 |  | 
| 327     if (!stab) { |  | 
| 328       /* Disregard from this frame */ |  | 
| 329       *bytesOut = 0; |  | 
| 330       return 0; |  | 
| 331     } |  | 
| 332 |  | 
| 333   } else { |  | 
| 334     for (i = 0; i < inst->enc_nrOfCoefs; i++) |  | 
| 335       refCs[i] = 0; |  | 
| 336   } |  | 
| 337 |  | 
| 338   if (forceSID) { |  | 
| 339     /* Read instantaneous values instead of averaged. */ |  | 
| 340     for (i = 0; i < inst->enc_nrOfCoefs; i++) |  | 
| 341       inst->enc_reflCoefs[i] = refCs[i]; |  | 
| 342     inst->enc_Energy = outEnergy; |  | 
| 343   } else { |  | 
| 344     /* Average history with new values. */ |  | 
| 345     for (i = 0; i < (inst->enc_nrOfCoefs); i++) { |  | 
| 346       inst->enc_reflCoefs[i] = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT( |  | 
| 347           inst->enc_reflCoefs[i], ReflBeta, 15); |  | 
| 348       inst->enc_reflCoefs[i] += (int16_t) WEBRTC_SPL_MUL_16_16_RSFT( |  | 
| 349           refCs[i], ReflBetaComp, 15); |  | 
| 350     } |  | 
| 351     inst->enc_Energy = (outEnergy >> 2) + (inst->enc_Energy >> 1) |  | 
| 352         + (inst->enc_Energy >> 2); |  | 
| 353   } |  | 
| 354 |  | 
| 355   if (inst->enc_Energy < 1) { |  | 
| 356     inst->enc_Energy = 1; |  | 
| 357   } |  | 
| 358 |  | 
| 359   if ((inst->enc_msSinceSID > (inst->enc_interval - 1)) || forceSID) { |  | 
| 360 |  | 
| 361     /* Search for best dbov value. */ |  | 
| 362     index = 0; |  | 
| 363     for (i = 1; i < 93; i++) { |  | 
| 364       /* Always round downwards. */ |  | 
| 365       if ((inst->enc_Energy - WebRtcCng_kDbov[i]) > 0) { |  | 
| 366         index = i; |  | 
| 367         break; |  | 
| 368       } |  | 
| 369     } |  | 
| 370     if ((i == 93) && (index == 0)) |  | 
| 371       index = 94; |  | 
| 372     SIDdata[0] = (uint8_t)index; |  | 
| 373 |  | 
| 374     /* Quantize coefficients with tweak for WebRtc implementation of RFC3389. */ |  | 
| 375     if (inst->enc_nrOfCoefs == WEBRTC_CNG_MAX_LPC_ORDER) { |  | 
| 376       for (i = 0; i < inst->enc_nrOfCoefs; i++) { |  | 
| 377         /* Q15 to Q7 with rounding. */ |  | 
| 378         SIDdata[i + 1] = ((inst->enc_reflCoefs[i] + 128) >> 8); |  | 
| 379       } |  | 
| 380     } else { |  | 
| 381       for (i = 0; i < inst->enc_nrOfCoefs; i++) { |  | 
| 382         /* Q15 to Q7 with rounding. */ |  | 
| 383         SIDdata[i + 1] = (127 + ((inst->enc_reflCoefs[i] + 128) >> 8)); |  | 
| 384       } |  | 
| 385     } |  | 
| 386 |  | 
| 387     inst->enc_msSinceSID = 0; |  | 
| 388     *bytesOut = inst->enc_nrOfCoefs + 1; |  | 
| 389 |  | 
| 390     inst->enc_msSinceSID += |  | 
| 391         (int16_t)((1000 * nrOfSamples) / inst->enc_sampfreq); |  | 
| 392     return (int)(inst->enc_nrOfCoefs + 1); |  | 
| 393   } else { |  | 
| 394     inst->enc_msSinceSID += |  | 
| 395         (int16_t)((1000 * nrOfSamples) / inst->enc_sampfreq); |  | 
| 396     *bytesOut = 0; |  | 
| 397     return 0; |  | 
| 398   } |  | 
| 399 } |  | 
| 400 |  | 
| 401 /**************************************************************************** |  | 
| 402  * WebRtcCng_UpdateSid(...) |  | 
| 403  * |  | 
| 404  * These functions updates the CN state, when a new SID packet arrives |  | 
| 405  * |  | 
| 406  * Input: |  | 
| 407  *    - cng_inst      : Pointer to created instance that should be freed |  | 
| 408  *    - SID           : SID packet, all headers removed |  | 
| 409  *    - length        : Length in bytes of SID packet |  | 
| 410  * |  | 
| 411  * Return value       :  0 - Ok |  | 
| 412  *                      -1 - Error |  | 
| 413  */ |  | 
| 414 int16_t WebRtcCng_UpdateSid(CNG_dec_inst* cng_inst, uint8_t* SID, |  | 
| 415                             size_t length) { |  | 
| 416 |  | 
| 417   WebRtcCngDecoder* inst = (WebRtcCngDecoder*) cng_inst; |  | 
| 418   int16_t refCs[WEBRTC_CNG_MAX_LPC_ORDER]; |  | 
| 419   int32_t targetEnergy; |  | 
| 420   int i; |  | 
| 421 |  | 
| 422   if (inst->initflag != 1) { |  | 
| 423     inst->errorcode = CNG_DECODER_NOT_INITIATED; |  | 
| 424     return -1; |  | 
| 425   } |  | 
| 426 |  | 
| 427   /* Throw away reflection coefficients of higher order than we can handle. */ |  | 
| 428   if (length > (WEBRTC_CNG_MAX_LPC_ORDER + 1)) |  | 
| 429     length = WEBRTC_CNG_MAX_LPC_ORDER + 1; |  | 
| 430 |  | 
| 431   inst->dec_order = (int16_t)length - 1; |  | 
| 432 |  | 
| 433   if (SID[0] > 93) |  | 
| 434     SID[0] = 93; |  | 
| 435   targetEnergy = WebRtcCng_kDbov[SID[0]]; |  | 
| 436   /* Take down target energy to 75%. */ |  | 
| 437   targetEnergy = targetEnergy >> 1; |  | 
| 438   targetEnergy += targetEnergy >> 2; |  | 
| 439 |  | 
| 440   inst->dec_target_energy = targetEnergy; |  | 
| 441 |  | 
| 442   /* Reconstruct coeffs with tweak for WebRtc implementation of RFC3389. */ |  | 
| 443   if (inst->dec_order == WEBRTC_CNG_MAX_LPC_ORDER) { |  | 
| 444     for (i = 0; i < (inst->dec_order); i++) { |  | 
| 445       refCs[i] = SID[i + 1] << 8; /* Q7 to Q15*/ |  | 
| 446       inst->dec_target_reflCoefs[i] = refCs[i]; |  | 
| 447     } |  | 
| 448   } else { |  | 
| 449     for (i = 0; i < (inst->dec_order); i++) { |  | 
| 450       refCs[i] = (SID[i + 1] - 127) << 8; /* Q7 to Q15. */ |  | 
| 451       inst->dec_target_reflCoefs[i] = refCs[i]; |  | 
| 452     } |  | 
| 453   } |  | 
| 454 |  | 
| 455   for (i = (inst->dec_order); i < WEBRTC_CNG_MAX_LPC_ORDER; i++) { |  | 
| 456     refCs[i] = 0; |  | 
| 457     inst->dec_target_reflCoefs[i] = refCs[i]; |  | 
| 458   } |  | 
| 459 |  | 
| 460   return 0; |  | 
| 461 } |  | 
| 462 |  | 
| 463 /**************************************************************************** |  | 
| 464  * WebRtcCng_Generate(...) |  | 
| 465  * |  | 
| 466  * These functions generates CN data when needed |  | 
| 467  * |  | 
| 468  * Input: |  | 
| 469  *    - cng_inst      : Pointer to created instance that should be freed |  | 
| 470  *    - outData       : pointer to area to write CN data |  | 
| 471  *    - nrOfSamples   : How much data to generate |  | 
| 472  * |  | 
| 473  * Return value        :  0 - Ok |  | 
| 474  *                       -1 - Error |  | 
| 475  */ |  | 
| 476 int16_t WebRtcCng_Generate(CNG_dec_inst* cng_inst, int16_t* outData, |  | 
| 477                            size_t nrOfSamples, int16_t new_period) { |  | 
| 478   WebRtcCngDecoder* inst = (WebRtcCngDecoder*) cng_inst; |  | 
| 479 |  | 
| 480   size_t i; |  | 
| 481   int16_t excitation[WEBRTC_CNG_MAX_OUTSIZE_ORDER]; |  | 
| 482   int16_t low[WEBRTC_CNG_MAX_OUTSIZE_ORDER]; |  | 
| 483   int16_t lpPoly[WEBRTC_CNG_MAX_LPC_ORDER + 1]; |  | 
| 484   int16_t ReflBetaStd = 26214;  /* 0.8 in q15. */ |  | 
| 485   int16_t ReflBetaCompStd = 6553;  /* 0.2 in q15. */ |  | 
| 486   int16_t ReflBetaNewP = 19661;  /* 0.6 in q15. */ |  | 
| 487   int16_t ReflBetaCompNewP = 13107;  /* 0.4 in q15. */ |  | 
| 488   int16_t Beta, BetaC, tmp1, tmp2, tmp3; |  | 
| 489   int32_t targetEnergy; |  | 
| 490   int16_t En; |  | 
| 491   int16_t temp16; |  | 
| 492 |  | 
| 493   if (nrOfSamples > WEBRTC_CNG_MAX_OUTSIZE_ORDER) { |  | 
| 494     inst->errorcode = CNG_DISALLOWED_FRAME_SIZE; |  | 
| 495     return -1; |  | 
| 496   } |  | 
| 497 |  | 
| 498   if (new_period) { |  | 
| 499     inst->dec_used_scale_factor = inst->dec_target_scale_factor; |  | 
| 500     Beta = ReflBetaNewP; |  | 
| 501     BetaC = ReflBetaCompNewP; |  | 
| 502   } else { |  | 
| 503     Beta = ReflBetaStd; |  | 
| 504     BetaC = ReflBetaCompStd; |  | 
| 505   } |  | 
| 506 |  | 
| 507   /* Here we use a 0.5 weighting, should possibly be modified to 0.6. */ |  | 
| 508   tmp1 = inst->dec_used_scale_factor << 2; /* Q13->Q15 */ |  | 
| 509   tmp2 = inst->dec_target_scale_factor << 2; /* Q13->Q15 */ |  | 
| 510   tmp3 = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(tmp1, Beta, 15); |  | 
| 511   tmp3 += (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(tmp2, BetaC, 15); |  | 
| 512   inst->dec_used_scale_factor = tmp3 >> 2; /* Q15->Q13 */ |  | 
| 513 |  | 
| 514   inst->dec_used_energy = inst->dec_used_energy >> 1; |  | 
| 515   inst->dec_used_energy += inst->dec_target_energy >> 1; |  | 
| 516 |  | 
| 517   /* Do the same for the reflection coeffs. */ |  | 
| 518   for (i = 0; i < WEBRTC_CNG_MAX_LPC_ORDER; i++) { |  | 
| 519     inst->dec_used_reflCoefs[i] = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT( |  | 
| 520         inst->dec_used_reflCoefs[i], Beta, 15); |  | 
| 521     inst->dec_used_reflCoefs[i] += (int16_t) WEBRTC_SPL_MUL_16_16_RSFT( |  | 
| 522         inst->dec_target_reflCoefs[i], BetaC, 15); |  | 
| 523   } |  | 
| 524 |  | 
| 525   /* Compute the polynomial coefficients. */ |  | 
| 526   WebRtcCng_K2a16(inst->dec_used_reflCoefs, WEBRTC_CNG_MAX_LPC_ORDER, lpPoly); |  | 
| 527 |  | 
| 528 |  | 
| 529   targetEnergy = inst->dec_used_energy; |  | 
| 530 |  | 
| 531   /* Calculate scaling factor based on filter energy. */ |  | 
| 532   En = 8192;  /* 1.0 in Q13. */ |  | 
| 533   for (i = 0; i < (WEBRTC_CNG_MAX_LPC_ORDER); i++) { |  | 
| 534 |  | 
| 535     /* Floating point value for reference. |  | 
| 536        E *= 1.0 - (inst->dec_used_reflCoefs[i] / 32768.0) * |  | 
| 537        (inst->dec_used_reflCoefs[i] / 32768.0); |  | 
| 538      */ |  | 
| 539 |  | 
| 540     /* Same in fixed point. */ |  | 
| 541     /* K(i).^2 in Q15. */ |  | 
| 542     temp16 = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT( |  | 
| 543         inst->dec_used_reflCoefs[i], inst->dec_used_reflCoefs[i], 15); |  | 
| 544     /* 1 - K(i).^2 in Q15. */ |  | 
| 545     temp16 = 0x7fff - temp16; |  | 
| 546     En = (int16_t) WEBRTC_SPL_MUL_16_16_RSFT(En, temp16, 15); |  | 
| 547   } |  | 
| 548 |  | 
| 549   /* float scaling= sqrt(E * inst->dec_target_energy / (1 << 24)); */ |  | 
| 550 |  | 
| 551   /* Calculate sqrt(En * target_energy / excitation energy) */ |  | 
| 552   targetEnergy = WebRtcSpl_Sqrt(inst->dec_used_energy); |  | 
| 553 |  | 
| 554   En = (int16_t) WebRtcSpl_Sqrt(En) << 6; |  | 
| 555   En = (En * 3) >> 1;  /* 1.5 estimates sqrt(2). */ |  | 
| 556   inst->dec_used_scale_factor = (int16_t)((En * targetEnergy) >> 12); |  | 
| 557 |  | 
| 558   /* Generate excitation. */ |  | 
| 559   /* Excitation energy per sample is 2.^24 - Q13 N(0,1). */ |  | 
| 560   for (i = 0; i < nrOfSamples; i++) { |  | 
| 561     excitation[i] = WebRtcSpl_RandN(&inst->dec_seed) >> 1; |  | 
| 562   } |  | 
| 563 |  | 
| 564   /* Scale to correct energy. */ |  | 
| 565   WebRtcSpl_ScaleVector(excitation, excitation, inst->dec_used_scale_factor, |  | 
| 566                         nrOfSamples, 13); |  | 
| 567 |  | 
| 568   /* |lpPoly| - Coefficients in Q12. |  | 
| 569    * |excitation| - Speech samples. |  | 
| 570    * |nst->dec_filtstate| - State preservation. |  | 
| 571    * |outData| - Filtered speech samples. */ |  | 
| 572   WebRtcSpl_FilterAR(lpPoly, WEBRTC_CNG_MAX_LPC_ORDER + 1, excitation, |  | 
| 573                      nrOfSamples, inst->dec_filtstate, WEBRTC_CNG_MAX_LPC_ORDER, |  | 
| 574                      inst->dec_filtstateLow, WEBRTC_CNG_MAX_LPC_ORDER, outData, |  | 
| 575                      low, nrOfSamples); |  | 
| 576 |  | 
| 577   return 0; |  | 
| 578 } |  | 
| 579 |  | 
| 580 /**************************************************************************** |  | 
| 581  * WebRtcCng_GetErrorCodeEnc/Dec(...) |  | 
| 582  * |  | 
| 583  * This functions can be used to check the error code of a CNG instance. When |  | 
| 584  * a function returns -1 a error code will be set for that instance. The |  | 
| 585  * function below extract the code of the last error that occured in the |  | 
| 586  * specified instance. |  | 
| 587  * |  | 
| 588  * Input: |  | 
| 589  *    - CNG_inst    : CNG enc/dec instance |  | 
| 590  * |  | 
| 591  * Return value     : Error code |  | 
| 592  */ |  | 
| 593 int16_t WebRtcCng_GetErrorCodeEnc(CNG_enc_inst* cng_inst) { |  | 
| 594   /* Typecast pointer to real structure. */ |  | 
| 595   WebRtcCngEncoder* inst = (WebRtcCngEncoder*) cng_inst; |  | 
| 596   return inst->errorcode; |  | 
| 597 } |  | 
| 598 |  | 
| 599 int16_t WebRtcCng_GetErrorCodeDec(CNG_dec_inst* cng_inst) { |  | 
| 600   /* Typecast pointer to real structure. */ |  | 
| 601   WebRtcCngDecoder* inst = (WebRtcCngDecoder*) cng_inst; |  | 
| 602   return inst->errorcode; |  | 
| 603 } |  | 
| OLD | NEW | 
|---|