1470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* 2173538faa35c01e1b861767212a79c02a9253dd7kma@webrtc.org * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * 4470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * Use of this source code is governed by a BSD-style license 5470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * that can be found in the LICENSE file in the root of the source 6470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * tree. An additional intellectual property rights grant can be found 7470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * in the file PATENTS. All contributing project authors may 8470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * be found in the AUTHORS file in the root of the source tree. 9470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com */ 10470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 11470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* 12470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * lpc_masking_model.c 13470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * 14470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * LPC analysis and filtering functions 15470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * 16470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com */ 17470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 182d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org#include "lpc_masking_model.h" 19173538faa35c01e1b861767212a79c02a9253dd7kma@webrtc.org 202d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org#include <limits.h> /* For LLONG_MAX and LLONG_MIN. */ 21470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "codec.h" 22470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "entropy_coding.h" 23470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com#include "settings.h" 24470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 25470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* The conversion is implemented by the step-down algorithm */ 26470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.comvoid WebRtcSpl_AToK_JSK( 270946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t *a16, /* Q11 */ 280946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t useOrder, 290946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t *k16 /* Q15 */ 30470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com ) 31470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 32470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com int m, k; 330946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int32_t tmp32[MAX_AR_MODEL_ORDER]; 340946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int32_t tmp32b; 350946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int32_t tmp_inv_denum32; 360946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t tmp_inv_denum16; 37470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 383ea35fdb1b3bc50e98b0fee03d274dce76fbdd55bjornv@webrtc.org k16[useOrder-1] = a16[useOrder] << 4; // Q11<<4 => Q15 39470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 40470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for (m=useOrder-1; m>0; m--) { 41bc2bb34419021fb3be4f87eb062cf0a9ed52675abjornv@webrtc.org // (1 - k^2) in Q30 42bc2bb34419021fb3be4f87eb062cf0a9ed52675abjornv@webrtc.org tmp_inv_denum32 = 1073741823 - k16[m] * k16[m]; 43a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org tmp_inv_denum16 = (int16_t)(tmp_inv_denum32 >> 15); // (1 - k^2) in Q15. 44470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 45470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for (k=1; k<=m; k++) { 46d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker tmp32b = (a16[k] << 16) - ((k16[m] * a16[m - k + 1]) << 1); 47470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 48470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmp32[k] = WebRtcSpl_DivW32W16(tmp32b, tmp_inv_denum16); //Q27/Q15 = Q12 49470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 50470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 51470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for (k=1; k<m; k++) { 52a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org a16[k] = (int16_t)(tmp32[k] >> 1); // Q12>>1 => Q11 53470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 54470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 55470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmp32[m] = WEBRTC_SPL_SAT(4092, tmp32[m], -4092); 56d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker k16[m - 1] = (int16_t)(tmp32[m] << 3); // Q12<<3 => Q15 57470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 58470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 59470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return; 60470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 61470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 62470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 63470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 64470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 65470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 660946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgint16_t WebRtcSpl_LevinsonW32_JSK( 670946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int32_t *R, /* (i) Autocorrelation of length >= order+1 */ 680946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t *A, /* (o) A[0..order] LPC coefficients (Q11) */ 690946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t *K, /* (o) K[0...order-1] Reflection coefficients (Q15) */ 700946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t order /* (i) filter order */ 71470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com ) { 720946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t i, j; 730946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t R_hi[LEVINSON_MAX_ORDER+1], R_low[LEVINSON_MAX_ORDER+1]; 74470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Aurocorr coefficients in high precision */ 750946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t A_hi[LEVINSON_MAX_ORDER+1], A_low[LEVINSON_MAX_ORDER+1]; 76470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* LPC coefficients in high precicion */ 770946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t A_upd_hi[LEVINSON_MAX_ORDER+1], A_upd_low[LEVINSON_MAX_ORDER+1]; 78470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* LPC coefficients for next iteration */ 790946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t K_hi, K_low; /* reflection coefficient in high precision */ 800946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t Alpha_hi, Alpha_low, Alpha_exp; /* Prediction gain Alpha in high precision 81470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com and with scale factor */ 820946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t tmp_hi, tmp_low; 830946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int32_t temp1W32, temp2W32, temp3W32; 840946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t norm; 85470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 86470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Normalize the autocorrelation R[0]...R[order+1] */ 87470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 88470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com norm = WebRtcSpl_NormW32(R[0]); 89470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 90470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for (i=order;i>=0;i--) { 91d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker temp1W32 = R[i] << norm; 92470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Put R in hi and low format */ 93a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org R_hi[i] = (int16_t)(temp1W32 >> 16); 94a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org R_low[i] = (int16_t)((temp1W32 - ((int32_t)R_hi[i] << 16)) >> 1); 95470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 96470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 97470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* K = A[1] = -R[1] / R[0] */ 98470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 99d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker temp2W32 = (R_hi[1] << 16) + (R_low[1] << 1); /* R[1] in Q31 */ 100470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com temp3W32 = WEBRTC_SPL_ABS_W32(temp2W32); /* abs R[1] */ 101470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com temp1W32 = WebRtcSpl_DivW32HiLow(temp3W32, R_hi[0], R_low[0]); /* abs(R[1])/R[0] in Q31 */ 102470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Put back the sign on R[1] */ 103470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (temp2W32 > 0) { 104470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com temp1W32 = -temp1W32; 105470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 106470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 107470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Put K in hi and low format */ 108a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org K_hi = (int16_t)(temp1W32 >> 16); 109a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org K_low = (int16_t)((temp1W32 - ((int32_t)K_hi << 16)) >> 1); 110470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 111470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Store first reflection coefficient */ 112470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com K[0] = K_hi; 113470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 114a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org temp1W32 >>= 4; /* A[1] in Q27. */ 115470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 116470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Put A[1] in hi and low format */ 117a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org A_hi[1] = (int16_t)(temp1W32 >> 16); 118a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org A_low[1] = (int16_t)((temp1W32 - ((int32_t)A_hi[1] << 16)) >> 1); 119470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 120470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Alpha = R[0] * (1-K^2) */ 121470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 122a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org temp1W32 = (((K_hi * K_low) >> 14) + K_hi * K_hi) << 1; /* = k^2 in Q31 */ 123470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 124470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com temp1W32 = WEBRTC_SPL_ABS_W32(temp1W32); /* Guard against <0 */ 1250946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org temp1W32 = (int32_t)0x7fffffffL - temp1W32; /* temp1W32 = (1 - K[0]*K[0]) in Q31 */ 126470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 127470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Store temp1W32 = 1 - K[0]*K[0] on hi and low format */ 128a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org tmp_hi = (int16_t)(temp1W32 >> 16); 129a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org tmp_low = (int16_t)((temp1W32 - ((int32_t)tmp_hi << 16)) >> 1); 130470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 131470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Calculate Alpha in Q31 */ 132a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org temp1W32 = (R_hi[0] * tmp_hi + ((R_hi[0] * tmp_low) >> 15) + 133a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org ((R_low[0] * tmp_hi) >> 15)) << 1; 134470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 135470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Normalize Alpha and put it in hi and low format */ 136470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 137470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com Alpha_exp = WebRtcSpl_NormW32(temp1W32); 138d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker temp1W32 <<= Alpha_exp; 139a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org Alpha_hi = (int16_t)(temp1W32 >> 16); 140a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org Alpha_low = (int16_t)((temp1W32 - ((int32_t)Alpha_hi<< 16)) >> 1); 141470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 142470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Perform the iterative calculations in the 143470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com Levinson Durbin algorithm */ 144470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 145470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for (i=2; i<=order; i++) 146470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 147470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 148470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* ---- 149470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com \ 150a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org temp1W32 = R[i] + > R[j]*A[i-j] 151470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com / 152470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com ---- 153470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com j=1..i-1 154470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com */ 155470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 156470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com temp1W32 = 0; 157470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 158470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for(j=1; j<i; j++) { 159470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* temp1W32 is in Q31 */ 160a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org temp1W32 += ((R_hi[j] * A_hi[i - j]) << 1) + 161a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org ((((R_hi[j] * A_low[i - j]) >> 15) + 162a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org ((R_low[j] * A_hi[i - j]) >> 15)) << 1); 163470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 164470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 165d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker temp1W32 <<= 4; 166d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker temp1W32 += (R_hi[i] << 16) + (R_low[i] << 1); 167470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 168470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* K = -temp1W32 / Alpha */ 169470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com temp2W32 = WEBRTC_SPL_ABS_W32(temp1W32); /* abs(temp1W32) */ 170470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com temp3W32 = WebRtcSpl_DivW32HiLow(temp2W32, Alpha_hi, Alpha_low); /* abs(temp1W32)/Alpha */ 171470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 172470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Put the sign of temp1W32 back again */ 173470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (temp1W32 > 0) { 174470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com temp3W32 = -temp3W32; 175470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 176470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 177470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Use the Alpha shifts from earlier to denormalize */ 178470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com norm = WebRtcSpl_NormW32(temp3W32); 179470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if ((Alpha_exp <= norm)||(temp3W32==0)) { 180d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker temp3W32 <<= Alpha_exp; 181470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } else { 182470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (temp3W32 > 0) 183470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1840946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org temp3W32 = (int32_t)0x7fffffffL; 185470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } else 186470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 1870946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org temp3W32 = (int32_t)0x80000000L; 188470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 189470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 190470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 191470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Put K on hi and low format */ 192a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org K_hi = (int16_t)(temp3W32 >> 16); 193a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org K_low = (int16_t)((temp3W32 - ((int32_t)K_hi << 16)) >> 1); 194470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 195470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Store Reflection coefficient in Q15 */ 196470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com K[i-1] = K_hi; 197470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 198470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Test for unstable filter. If unstable return 0 and let the 199470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com user decide what to do in that case 200470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com */ 201470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2020946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org if ((int32_t)WEBRTC_SPL_ABS_W16(K_hi) > (int32_t)32740) { 203470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return(-i); /* Unstable filter */ 204470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 205470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 206470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* 207470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com Compute updated LPC coefficient: Anew[i] 208470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com Anew[j]= A[j] + K*A[i-j] for j=1..i-1 209470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com Anew[i]= K 210470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com */ 211470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 212470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for(j=1; j<i; j++) 213470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 214d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker temp1W32 = (A_hi[j] << 16) + (A_low[j] << 1); // temp1W32 = A[j] in Q27 215470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 216a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org temp1W32 += (K_hi * A_hi[i - j] + ((K_hi * A_low[i - j]) >> 15) + 217a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org ((K_low * A_hi[i - j]) >> 15)) << 1; // temp1W32 += K*A[i-j] in Q27. 218470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 219470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Put Anew in hi and low format */ 220a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org A_upd_hi[j] = (int16_t)(temp1W32 >> 16); 221a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org A_upd_low[j] = (int16_t)((temp1W32 - ((int32_t)A_upd_hi[j] << 16)) >> 1); 222470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 223470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 224a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org temp3W32 >>= 4; /* temp3W32 = K in Q27 (Convert from Q31 to Q27) */ 225470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 226470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Store Anew in hi and low format */ 227a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org A_upd_hi[i] = (int16_t)(temp3W32 >> 16); 228a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org A_upd_low[i] = (int16_t)((temp3W32 - ((int32_t)A_upd_hi[i] << 16)) >> 1); 229470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 230470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Alpha = Alpha * (1-K^2) */ 231470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 232a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org temp1W32 = (((K_hi * K_low) >> 14) + K_hi * K_hi) << 1; /* K*K in Q31 */ 233470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 234470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com temp1W32 = WEBRTC_SPL_ABS_W32(temp1W32); /* Guard against <0 */ 2350946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org temp1W32 = (int32_t)0x7fffffffL - temp1W32; /* 1 - K*K in Q31 */ 236470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 237470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Convert 1- K^2 in hi and low format */ 238a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org tmp_hi = (int16_t)(temp1W32 >> 16); 239a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org tmp_low = (int16_t)((temp1W32 - ((int32_t)tmp_hi << 16)) >> 1); 240470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 241470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Calculate Alpha = Alpha * (1-K^2) in Q31 */ 242a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org temp1W32 = (Alpha_hi * tmp_hi + ((Alpha_hi * tmp_low) >> 15) + 243a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org ((Alpha_low * tmp_hi) >> 15)) << 1; 244470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 245470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Normalize Alpha and store it on hi and low format */ 246470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 247470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com norm = WebRtcSpl_NormW32(temp1W32); 248d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker temp1W32 <<= norm; 249470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 250a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org Alpha_hi = (int16_t)(temp1W32 >> 16); 251a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org Alpha_low = (int16_t)((temp1W32 - ((int32_t)Alpha_hi << 16)) >> 1); 252470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 253470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Update the total nomalization of Alpha */ 254470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com Alpha_exp = Alpha_exp + norm; 255470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 256470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Update A[] */ 257470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 258470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for(j=1; j<=i; j++) 259470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 260470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com A_hi[j] =A_upd_hi[j]; 261470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com A_low[j] =A_upd_low[j]; 262470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 263470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 264470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 265470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* 266470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com Set A[0] to 1.0 and store the A[i] i=1...order in Q12 267470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com (Convert from Q27 and use rounding) 268470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com */ 269470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 270470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com A[0] = 2048; 271470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 272470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for(i=1; i<=order; i++) { 273470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* temp1W32 in Q27 */ 274d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker temp1W32 = (A_hi[i] << 16) + (A_low[i] << 1); 275470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Round and store upper word */ 276a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org A[i] = (int16_t)((temp1W32 + 32768) >> 16); 277470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 278470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com return(1); /* Stable filters */ 279470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 280470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 281470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 282470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 283470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 284470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 285470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* window */ 286470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* Matlab generation of floating point code: 287470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * t = (1:256)/257; r = 1-(1-t).^.45; w = sin(r*pi).^3; w = w/sum(w); plot((1:256)/8, w); grid; 288470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * for k=1:16, fprintf(1, '%.8f, ', w(k*16 + (-15:0))); fprintf(1, '\n'); end 289470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com * All values are multiplyed with 2^21 in fixed point code. 290470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com */ 2910946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgstatic const int16_t kWindowAutocorr[WINLEN] = { 292470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 5, 6, 293470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 8, 10, 12, 14, 17, 20, 24, 28, 33, 38, 43, 49, 294470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 56, 63, 71, 79, 88, 98, 108, 119, 131, 143, 157, 171, 295470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 186, 202, 219, 237, 256, 275, 296, 318, 341, 365, 390, 416, 296470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 444, 472, 502, 533, 566, 600, 635, 671, 709, 748, 789, 831, 297470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 875, 920, 967, 1015, 1065, 1116, 1170, 1224, 1281, 1339, 1399, 1461, 298470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1525, 1590, 1657, 1726, 1797, 1870, 1945, 2021, 2100, 2181, 2263, 2348, 299470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 2434, 2523, 2614, 2706, 2801, 2898, 2997, 3099, 3202, 3307, 3415, 3525, 300470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3637, 3751, 3867, 3986, 4106, 4229, 4354, 4481, 4611, 4742, 4876, 5012, 301470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 5150, 5291, 5433, 5578, 5725, 5874, 6025, 6178, 6333, 6490, 6650, 6811, 302470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 6974, 7140, 7307, 7476, 7647, 7820, 7995, 8171, 8349, 8529, 8711, 8894, 303470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 9079, 9265, 9453, 9642, 9833, 10024, 10217, 10412, 10607, 10803, 11000, 11199, 304470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 11398, 11597, 11797, 11998, 12200, 12401, 12603, 12805, 13008, 13210, 13412, 13614, 305470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 13815, 14016, 14216, 14416, 14615, 14813, 15009, 15205, 15399, 15591, 15782, 15971, 306470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 16157, 16342, 16524, 16704, 16881, 17056, 17227, 17395, 17559, 17720, 17877, 18030, 307470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 18179, 18323, 18462, 18597, 18727, 18851, 18970, 19082, 19189, 19290, 19384, 19471, 308470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 19551, 19623, 19689, 19746, 19795, 19835, 19867, 19890, 19904, 19908, 19902, 19886, 309470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 19860, 19823, 19775, 19715, 19644, 19561, 19465, 19357, 19237, 19102, 18955, 18793, 310470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 18618, 18428, 18223, 18004, 17769, 17518, 17252, 16970, 16672, 16357, 16025, 15677, 311470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 15311, 14929, 14529, 14111, 13677, 13225, 12755, 12268, 11764, 11243, 10706, 10152, 312470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 9583, 8998, 8399, 7787, 7162, 6527, 5883, 5231, 4576, 3919, 3265, 2620, 313470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 1990, 1386, 825, 333 314470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}; 315470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 316470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 317470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* By using a hearing threshold level in dB of -28 dB (higher value gives more noise), 318470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com the H_T_H (in float) can be calculated as: 319470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com H_T_H = pow(10.0, 0.05 * (-28.0)) = 0.039810717055350 320470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com In Q19, H_T_H becomes round(0.039810717055350*2^19) ~= 20872, i.e. 321470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com H_T_H = 20872/524288.0, and H_T_HQ19 = 20872; 322470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com*/ 323470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 324470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 325470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com/* The bandwidth expansion vectors are created from: 326470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com kPolyVecLo=[0.900000,0.810000,0.729000,0.656100,0.590490,0.531441,0.478297,0.430467,0.387420,0.348678,0.313811,0.282430]; 327470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com kPolyVecHi=[0.800000,0.640000,0.512000,0.409600,0.327680,0.262144]; 328470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com round(kPolyVecLo*32768) 329470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com round(kPolyVecHi*32768) 330470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com*/ 3310946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgstatic const int16_t kPolyVecLo[12] = { 332470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 29491, 26542, 23888, 21499, 19349, 17414, 15673, 14106, 12695, 11425, 10283, 9255 333470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}; 3340946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgstatic const int16_t kPolyVecHi[6] = { 335470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 26214, 20972, 16777, 13422, 10737, 8590 336470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com}; 337470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3380946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgstatic __inline int32_t log2_Q8_LPC( uint32_t x ) { 339470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3403ea35fdb1b3bc50e98b0fee03d274dce76fbdd55bjornv@webrtc.org int32_t zeros; 3410946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t frac; 342470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 343470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com zeros=WebRtcSpl_NormU32(x); 344a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org frac = (int16_t)(((x << zeros) & 0x7FFFFFFF) >> 23); 345470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 346470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* log2(x) */ 3473ea35fdb1b3bc50e98b0fee03d274dce76fbdd55bjornv@webrtc.org return ((31 - zeros) << 8) + frac; 348470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 349470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3500946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgstatic const int16_t kMulPitchGain = -25; /* 200/256 in Q5 */ 3510946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgstatic const int16_t kChngFactor = 3523; /* log10(2)*10/4*0.4/1.4=log10(2)/1.4= 0.2150 in Q14 */ 3520946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgstatic const int16_t kExp2 = 11819; /* 1/log(2) */ 353173538faa35c01e1b861767212a79c02a9253dd7kma@webrtc.orgconst int kShiftLowerBand = 11; /* Shift value for lower band in Q domain. */ 354173538faa35c01e1b861767212a79c02a9253dd7kma@webrtc.orgconst int kShiftHigherBand = 12; /* Shift value for higher band in Q domain. */ 355470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 3560946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgvoid WebRtcIsacfix_GetVars(const int16_t *input, const int16_t *pitchGains_Q12, 3570946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org uint32_t *oldEnergy, int16_t *varscale) 358470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 359470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com int k; 3600946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org uint32_t nrgQ[4]; 3610946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t nrgQlog[4]; 3620946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t tmp16, chng1, chng2, chng3, chng4, tmp, chngQ, oldNrgQlog, pgQ, pg3; 3630946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int32_t expPg32; 3640946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t expPg, divVal; 3650946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t tmp16_1, tmp16_2; 366470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 367470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Calculate energies of first and second frame halfs */ 368470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com nrgQ[0]=0; 369470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for (k = QLOOKAHEAD/2; k < (FRAMESAMPLES/4 + QLOOKAHEAD) / 2; k++) { 370bc2bb34419021fb3be4f87eb062cf0a9ed52675abjornv@webrtc.org nrgQ[0] += (uint32_t)(input[k] * input[k]); 371470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 372470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com nrgQ[1]=0; 373470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for ( ; k < (FRAMESAMPLES/2 + QLOOKAHEAD) / 2; k++) { 374bc2bb34419021fb3be4f87eb062cf0a9ed52675abjornv@webrtc.org nrgQ[1] += (uint32_t)(input[k] * input[k]); 375470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 376470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com nrgQ[2]=0; 377bc2bb34419021fb3be4f87eb062cf0a9ed52675abjornv@webrtc.org for ( ; k < (FRAMESAMPLES * 3 / 4 + QLOOKAHEAD) / 2; k++) { 378bc2bb34419021fb3be4f87eb062cf0a9ed52675abjornv@webrtc.org nrgQ[2] += (uint32_t)(input[k] * input[k]); 379470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 380470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com nrgQ[3]=0; 381470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for ( ; k < (FRAMESAMPLES + QLOOKAHEAD) / 2; k++) { 382bc2bb34419021fb3be4f87eb062cf0a9ed52675abjornv@webrtc.org nrgQ[3] += (uint32_t)(input[k] * input[k]); 383470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 384470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 385470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for ( k=0; k<4; k++) { 3860946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org nrgQlog[k] = (int16_t)log2_Q8_LPC(nrgQ[k]); /* log2(nrgQ) */ 387470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 3880946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org oldNrgQlog = (int16_t)log2_Q8_LPC(*oldEnergy); 389470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 390470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Calculate average level change */ 391470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com chng1 = WEBRTC_SPL_ABS_W16(nrgQlog[3]-nrgQlog[2]); 392470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com chng2 = WEBRTC_SPL_ABS_W16(nrgQlog[2]-nrgQlog[1]); 393470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com chng3 = WEBRTC_SPL_ABS_W16(nrgQlog[1]-nrgQlog[0]); 394470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com chng4 = WEBRTC_SPL_ABS_W16(nrgQlog[0]-oldNrgQlog); 395470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmp = chng1+chng2+chng3+chng4; 396f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker chngQ = (int16_t)(tmp * kChngFactor >> 10); /* Q12 */ 397470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com chngQ += 2926; /* + 1.0/1.4 in Q12 */ 398470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 399470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Find average pitch gain */ 400470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com pgQ = 0; 401470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for (k=0; k<4; k++) 402470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 403470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com pgQ += pitchGains_Q12[k]; 404470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 405470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 406f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker pg3 = (int16_t)(pgQ * pgQ >> 11); // pgQ in Q(12+2)=Q14. Q14*Q14>>11 => Q17 407f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker pg3 = (int16_t)(pgQ * pg3 >> 13); /* Q14*Q17>>13 =>Q18 */ 408f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker /* kMulPitchGain = -25 = -200 in Q-3. */ 409f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker pg3 = (int16_t)(pg3 * kMulPitchGain >> 5); // Q10 4100946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org tmp16=(int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(kExp2,pg3,13);/* Q13*Q10>>13 => Q10*/ 411470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (tmp16<0) { 412470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmp16_2 = (0x0400 | (tmp16 & 0x03FF)); 413f71785cd3b282ad7d584d746ba5b19833a11692bbjornv@webrtc.org tmp16_1 = ((uint16_t)(tmp16 ^ 0xFFFF) >> 10) - 3; /* Gives result in Q14 */ 414470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (tmp16_1<0) 4153ea35fdb1b3bc50e98b0fee03d274dce76fbdd55bjornv@webrtc.org expPg = -(tmp16_2 << -tmp16_1); 416470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com else 417f71785cd3b282ad7d584d746ba5b19833a11692bbjornv@webrtc.org expPg = -(tmp16_2 >> tmp16_1); 418470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } else 4190946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org expPg = (int16_t) -16384; /* 1 in Q14, since 2^0=1 */ 420470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 4213ea35fdb1b3bc50e98b0fee03d274dce76fbdd55bjornv@webrtc.org expPg32 = (int32_t)expPg << 8; /* Q22 */ 422470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com divVal = WebRtcSpl_DivW32W16ResW16(expPg32, chngQ); /* Q22/Q12=Q10 */ 423470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 4240946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org tmp16=(int16_t)WEBRTC_SPL_MUL_16_16_RSFT_WITH_ROUND(kExp2,divVal,13);/* Q13*Q10>>13 => Q10*/ 425470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (tmp16<0) { 426470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmp16_2 = (0x0400 | (tmp16 & 0x03FF)); 427f71785cd3b282ad7d584d746ba5b19833a11692bbjornv@webrtc.org tmp16_1 = ((uint16_t)(tmp16 ^ 0xFFFF) >> 10) - 3; /* Gives result in Q14 */ 428470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (tmp16_1<0) 4293ea35fdb1b3bc50e98b0fee03d274dce76fbdd55bjornv@webrtc.org expPg = tmp16_2 << -tmp16_1; 430470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com else 431f71785cd3b282ad7d584d746ba5b19833a11692bbjornv@webrtc.org expPg = tmp16_2 >> tmp16_1; 432470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } else 4330946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org expPg = (int16_t) 16384; /* 1 in Q14, since 2^0=1 */ 434470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 435470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *varscale = expPg-1; 436470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *oldEnergy = nrgQ[3]; 437470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 438470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 439470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 440470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 4410946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgstatic __inline int16_t exp2_Q10_T(int16_t x) { // Both in and out in Q10 442470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 4430946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t tmp16_1, tmp16_2; 444470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 4450946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org tmp16_2=(int16_t)(0x0400|(x&0x03FF)); 446f71785cd3b282ad7d584d746ba5b19833a11692bbjornv@webrtc.org tmp16_1 = -(x >> 10); 447470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if(tmp16_1>0) 448f71785cd3b282ad7d584d746ba5b19833a11692bbjornv@webrtc.org return tmp16_2 >> tmp16_1; 449470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com else 4503ea35fdb1b3bc50e98b0fee03d274dce76fbdd55bjornv@webrtc.org return tmp16_2 << -tmp16_1; 451470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 452470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 453470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 454e8482f0e9ff1e9733719f58b4dd6c5d6d776a93akma@webrtc.org 455e8482f0e9ff1e9733719f58b4dd6c5d6d776a93akma@webrtc.org// Declare function pointers. 456e8482f0e9ff1e9733719f58b4dd6c5d6d776a93akma@webrtc.orgAutocorrFix WebRtcIsacfix_AutocorrFix; 457e8482f0e9ff1e9733719f58b4dd6c5d6d776a93akma@webrtc.orgCalculateResidualEnergy WebRtcIsacfix_CalculateResidualEnergy; 458e8482f0e9ff1e9733719f58b4dd6c5d6d776a93akma@webrtc.org 459173538faa35c01e1b861767212a79c02a9253dd7kma@webrtc.org/* This routine calculates the residual energy for LPC. 460173538faa35c01e1b861767212a79c02a9253dd7kma@webrtc.org * Formula as shown in comments inside. 461173538faa35c01e1b861767212a79c02a9253dd7kma@webrtc.org */ 462a15ea4965ef07f6aa074339f206383028e3b8898kma@webrtc.orgint32_t WebRtcIsacfix_CalculateResidualEnergyC(int lpc_order, 463a15ea4965ef07f6aa074339f206383028e3b8898kma@webrtc.org int32_t q_val_corr, 464a15ea4965ef07f6aa074339f206383028e3b8898kma@webrtc.org int q_val_polynomial, 465a15ea4965ef07f6aa074339f206383028e3b8898kma@webrtc.org int16_t* a_polynomial, 466a15ea4965ef07f6aa074339f206383028e3b8898kma@webrtc.org int32_t* corr_coeffs, 467a15ea4965ef07f6aa074339f206383028e3b8898kma@webrtc.org int* q_val_residual_energy) { 4682d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org int i = 0, j = 0; 4692d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org int shift_internal = 0, shift_norm = 0; 4702d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org int32_t tmp32 = 0, word32_high = 0, word32_low = 0, residual_energy = 0; 4712d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org int64_t sum64 = 0, sum64_tmp = 0; 4722d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org 4732d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org for (i = 0; i <= lpc_order; i++) { 4742d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org for (j = i; j <= lpc_order; j++) { 4752d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org /* For the case of i == 0: residual_energy += 4762d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org * a_polynomial[j] * corr_coeffs[i] * a_polynomial[j - i]; 4772d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org * For the case of i != 0: residual_energy += 4782d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org * a_polynomial[j] * corr_coeffs[i] * a_polynomial[j - i] * 2; 479173538faa35c01e1b861767212a79c02a9253dd7kma@webrtc.org */ 480173538faa35c01e1b861767212a79c02a9253dd7kma@webrtc.org 481bc2bb34419021fb3be4f87eb062cf0a9ed52675abjornv@webrtc.org tmp32 = a_polynomial[j] * a_polynomial[j - i]; 4822d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org /* tmp32 in Q(q_val_polynomial * 2). */ 4832d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org if (i != 0) { 484173538faa35c01e1b861767212a79c02a9253dd7kma@webrtc.org tmp32 <<= 1; 485173538faa35c01e1b861767212a79c02a9253dd7kma@webrtc.org } 4862d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org sum64_tmp = (int64_t)tmp32 * (int64_t)corr_coeffs[i]; 4872d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org sum64_tmp >>= shift_internal; 4882d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org 4892d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org /* Test overflow and sum the result. */ 4902d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org if(((sum64_tmp > 0 && sum64 > 0) && (LLONG_MAX - sum64 < sum64_tmp)) || 4912d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org ((sum64_tmp < 0 && sum64 < 0) && (LLONG_MIN - sum64 > sum64_tmp))) { 4922d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org /* Shift right for overflow. */ 4932d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org shift_internal += 1; 4942d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org sum64 >>= 1; 4952d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org sum64 += sum64_tmp >> 1; 4962d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org } else { 4972d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org sum64 += sum64_tmp; 498173538faa35c01e1b861767212a79c02a9253dd7kma@webrtc.org } 4992d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org } 5002d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org } 501173538faa35c01e1b861767212a79c02a9253dd7kma@webrtc.org 5022d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org word32_high = (int32_t)(sum64 >> 32); 5032d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org word32_low = (int32_t)sum64; 5042d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org 5052d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org // Calculate the value of shifting (shift_norm) for the 64-bit sum. 5062d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org if(word32_high != 0) { 5072d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org shift_norm = 32 - WebRtcSpl_NormW32(word32_high); 5082d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org residual_energy = (int32_t)(sum64 >> shift_norm); 5092d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org } else { 510620a2563d0798eb0fac486814f9166c298d45b20kma@webrtc.org if((word32_low & 0x80000000) != 0) { 5112d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org shift_norm = 1; 512620a2563d0798eb0fac486814f9166c298d45b20kma@webrtc.org residual_energy = (uint32_t)word32_low >> 1; 5132d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org } else { 5142d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org shift_norm = WebRtcSpl_NormW32(word32_low); 5152d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org residual_energy = word32_low << shift_norm; 5162d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org shift_norm = -shift_norm; 517173538faa35c01e1b861767212a79c02a9253dd7kma@webrtc.org } 518173538faa35c01e1b861767212a79c02a9253dd7kma@webrtc.org } 5192d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org 5202d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org /* Q(q_val_polynomial * 2) * Q(q_val_corr) >> shift_internal >> shift_norm 5212d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org * = Q(q_val_corr - shift_internal - shift_norm + q_val_polynomial * 2) 5222d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org */ 5232d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org *q_val_residual_energy = q_val_corr - shift_internal - shift_norm 5242d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org + q_val_polynomial * 2; 5252d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org 526173538faa35c01e1b861767212a79c02a9253dd7kma@webrtc.org return residual_energy; 527173538faa35c01e1b861767212a79c02a9253dd7kma@webrtc.org} 528173538faa35c01e1b861767212a79c02a9253dd7kma@webrtc.org 5290946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.orgvoid WebRtcIsacfix_GetLpcCoef(int16_t *inLoQ0, 5300946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t *inHiQ0, 531470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com MaskFiltstr_enc *maskdata, 5320946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t snrQ10, 5330946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org const int16_t *pitchGains_Q12, 5340946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int32_t *gain_lo_hiQ17, 5350946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t *lo_coeffQ15, 5360946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t *hi_coeffQ15) 537470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com{ 538173538faa35c01e1b861767212a79c02a9253dd7kma@webrtc.org int k, n, ii; 539173538faa35c01e1b861767212a79c02a9253dd7kma@webrtc.org int pos1, pos2; 540173538faa35c01e1b861767212a79c02a9253dd7kma@webrtc.org int sh_lo, sh_hi, sh, ssh, shMem; 5410946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t varscaleQ14; 542470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 5430946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t tmpQQlo, tmpQQhi; 5440946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int32_t tmp32; 5450946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t tmp16,tmp16b; 546470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 5470946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t polyHI[ORDERHI+1]; 5480946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t rcQ15_lo[ORDERLO], rcQ15_hi[ORDERHI]; 549470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 550470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 5510946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t DataLoQ6[WINLEN], DataHiQ6[WINLEN]; 5520946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int32_t corrloQQ[ORDERLO+2]; 5530946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int32_t corrhiQQ[ORDERHI+1]; 5540946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int32_t corrlo2QQ[ORDERLO+1]; 5550946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t scale; 5560946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t QdomLO, QdomHI, newQdomHI, newQdomLO; 557470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 5580946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int32_t res_nrgQQ; 5590946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int32_t sqrt_nrg; 560470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 561470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* less-noise-at-low-frequencies factor */ 5620946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t aaQ14; 563470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 564470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Multiplication with 1/sqrt(12) ~= 0.28901734104046 can be done by convertion to 565470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com Q15, i.e. round(0.28901734104046*32768) = 9471, and use 9471/32768.0 ~= 0.289032 566470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com */ 5670946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t snrq; 568173538faa35c01e1b861767212a79c02a9253dd7kma@webrtc.org int shft; 569470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 5700946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t tmp16a; 5710946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int32_t tmp32a, tmp32b, tmp32c; 572470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 5730946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t a_LOQ11[ORDERLO+1]; 5740946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t k_vecloQ15[ORDERLO]; 5750946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t a_HIQ12[ORDERHI+1]; 5760946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t k_vechiQ15[ORDERHI]; 577470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 5780946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t stab; 579470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 580470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com snrq=snrQ10; 581470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 582470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* SNR= C * 2 ^ (D * snrq) ; C=0.289, D=0.05*log2(10)=0.166 (~=172 in Q10)*/ 583f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker tmp16 = (int16_t)(snrq * 172 >> 10); // Q10 584470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmp16b = exp2_Q10_T(tmp16); // Q10 585f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker snrq = (int16_t)(tmp16b * 285 >> 10); // Q10 586470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 587470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* change quallevel depending on pitch gains and level fluctuations */ 588470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WebRtcIsacfix_GetVars(inLoQ0, pitchGains_Q12, &(maskdata->OldEnergy), &varscaleQ14); 589470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 590470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* less-noise-at-low-frequencies factor */ 591470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Calculation of 0.35 * (0.5 + 0.5 * varscale) in fixpoint: 592470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com With 0.35 in Q16 (0.35 ~= 22938/65536.0 = 0.3500061) and varscaleQ14 in Q14, 593470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com we get Q16*Q14>>16 = Q14 594470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com */ 595a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org aaQ14 = (int16_t)((22938 * (8192 + (varscaleQ14 >> 1)) + 32768) >> 16); 596470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 597470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Calculate tmp = (1.0 + aa*aa); in Q12 */ 598f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker tmp16 = (int16_t)(aaQ14 * aaQ14 >> 15); // Q14*Q14>>15 = Q13 599f71785cd3b282ad7d584d746ba5b19833a11692bbjornv@webrtc.org tmpQQlo = 4096 + (tmp16 >> 1); // Q12 + Q13>>1 = Q12. 600470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 601470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Calculate tmp = (1.0+aa) * (1.0+aa); */ 602f71785cd3b282ad7d584d746ba5b19833a11692bbjornv@webrtc.org tmp16 = 8192 + (aaQ14 >> 1); // 1+a in Q13. 603f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker tmpQQhi = (int16_t)(tmp16 * tmp16 >> 14); // Q13*Q13>>14 = Q12 604470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 605470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* replace data in buffer by new look-ahead data */ 606470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for (pos1 = 0; pos1 < QLOOKAHEAD; pos1++) { 607470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com maskdata->DataBufferLoQ0[pos1 + WINLEN - QLOOKAHEAD] = inLoQ0[pos1]; 608470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 609470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 610470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for (k = 0; k < SUBFRAMES; k++) { 611470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 612470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Update input buffer and multiply signal with window */ 613470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for (pos1 = 0; pos1 < WINLEN - UPDATE/2; pos1++) { 614470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com maskdata->DataBufferLoQ0[pos1] = maskdata->DataBufferLoQ0[pos1 + UPDATE/2]; 615470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com maskdata->DataBufferHiQ0[pos1] = maskdata->DataBufferHiQ0[pos1 + UPDATE/2]; 616f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker DataLoQ6[pos1] = (int16_t)(maskdata->DataBufferLoQ0[pos1] * 617f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker kWindowAutocorr[pos1] >> 15); // Q0*Q21>>15 = Q6 618f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker DataHiQ6[pos1] = (int16_t)(maskdata->DataBufferHiQ0[pos1] * 619f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker kWindowAutocorr[pos1] >> 15); // Q0*Q21>>15 = Q6 620470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 621bc2bb34419021fb3be4f87eb062cf0a9ed52675abjornv@webrtc.org pos2 = (int16_t)(k * UPDATE / 2); 622470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for (n = 0; n < UPDATE/2; n++, pos1++) { 623470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com maskdata->DataBufferLoQ0[pos1] = inLoQ0[QLOOKAHEAD + pos2]; 624470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com maskdata->DataBufferHiQ0[pos1] = inHiQ0[pos2++]; 625f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker DataLoQ6[pos1] = (int16_t)(maskdata->DataBufferLoQ0[pos1] * 626f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker kWindowAutocorr[pos1] >> 15); // Q0*Q21>>15 = Q6 627f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker DataHiQ6[pos1] = (int16_t)(maskdata->DataBufferHiQ0[pos1] * 628f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker kWindowAutocorr[pos1] >> 15); // Q0*Q21>>15 = Q6 629470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 630470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 631470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Get correlation coefficients */ 632470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* The highest absolute value measured inside DataLo in the test set 633470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com For DataHi, corresponding value was 160. 634470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 635470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com This means that it should be possible to represent the input values 636470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com to WebRtcSpl_AutoCorrelation() as Q6 values (since 307*2^6 = 637470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 19648). Of course, Q0 will also work, but due to the low energy in 638470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com DataLo and DataHi, the outputted autocorrelation will be more accurate 639470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com and mimic the floating point code better, by being in an high as possible 640470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com Q-domain. 641470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com */ 642470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 643470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WebRtcIsacfix_AutocorrFix(corrloQQ,DataLoQ6,WINLEN, ORDERLO+1, &scale); 644470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com QdomLO = 12-scale; // QdomLO is the Q-domain of corrloQQ 645470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com sh_lo = WebRtcSpl_NormW32(corrloQQ[0]); 646470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com QdomLO += sh_lo; 647470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for (ii=0; ii<ORDERLO+2; ii++) { 648d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker corrloQQ[ii] <<= sh_lo; 649470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 650470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* It is investigated whether it was possible to use 16 bits for the 651470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 32-bit vector corrloQQ, but it didn't work. */ 652470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 653470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WebRtcIsacfix_AutocorrFix(corrhiQQ,DataHiQ6,WINLEN, ORDERHI, &scale); 654470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 655470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com QdomHI = 12-scale; // QdomHI is the Q-domain of corrhiQQ 656470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com sh_hi = WebRtcSpl_NormW32(corrhiQQ[0]); 657470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com QdomHI += sh_hi; 658470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for (ii=0; ii<ORDERHI+1; ii++) { 659d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker corrhiQQ[ii] <<= sh_hi; 660470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 661470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 662470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* less noise for lower frequencies, by filtering/scaling autocorrelation sequences */ 663470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 664470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Calculate corrlo2[0] = tmpQQlo * corrlo[0] - 2.0*tmpQQlo * corrlo[1];*/ 665a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org // |corrlo2QQ| in Q(QdomLO-5). 666a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org corrlo2QQ[0] = (WEBRTC_SPL_MUL_16_32_RSFT16(tmpQQlo, corrloQQ[0]) >> 1) - 667a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org (WEBRTC_SPL_MUL_16_32_RSFT16(aaQ14, corrloQQ[1]) >> 2); 668470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 669470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Calculate corrlo2[n] = tmpQQlo * corrlo[n] - tmpQQlo * (corrlo[n-1] + corrlo[n+1]);*/ 670470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for (n = 1; n <= ORDERLO; n++) { 671470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 672a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org tmp32 = (corrloQQ[n - 1] >> 1) + (corrloQQ[n + 1] >> 1); // Q(QdomLO-1). 673a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org corrlo2QQ[n] = (WEBRTC_SPL_MUL_16_32_RSFT16(tmpQQlo, corrloQQ[n]) >> 1) - 674a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org (WEBRTC_SPL_MUL_16_32_RSFT16(aaQ14, tmp32) >> 2); 675470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 676470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com QdomLO -= 5; 677470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 678470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Calculate corrhi[n] = tmpQQhi * corrhi[n]; */ 679470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for (n = 0; n <= ORDERHI; n++) { 680470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com corrhiQQ[n] = WEBRTC_SPL_MUL_16_32_RSFT16(tmpQQhi, corrhiQQ[n]); // Q(12+QdomHI-16) = Q(QdomHI-4) 681470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 682470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com QdomHI -= 4; 683470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 684470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* add white noise floor */ 685470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* corrlo2QQ is in Q(QdomLO) and corrhiQQ is in Q(QdomHI) */ 686470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Calculate corrlo2[0] += 9.5367431640625e-7; and 687470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com corrhi[0] += 9.5367431640625e-7, where the constant is 1/2^20 */ 688470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 6890946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org tmp32 = WEBRTC_SPL_SHIFT_W32((int32_t) 1, QdomLO-20); 690470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com corrlo2QQ[0] += tmp32; 6910946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org tmp32 = WEBRTC_SPL_SHIFT_W32((int32_t) 1, QdomHI-20); 692470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com corrhiQQ[0] += tmp32; 693470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 694470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* corrlo2QQ is in Q(QdomLO) and corrhiQQ is in Q(QdomHI) before the following 695470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com code segment, where we want to make sure we get a 1-bit margin */ 696470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for (n = 0; n <= ORDERLO; n++) { 697a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org corrlo2QQ[n] >>= 1; // Make sure we have a 1-bit margin. 698470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 699470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com QdomLO -= 1; // Now, corrlo2QQ is in Q(QdomLO), with a 1-bit margin 700470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 701470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for (n = 0; n <= ORDERHI; n++) { 702a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org corrhiQQ[n] >>= 1; // Make sure we have a 1-bit margin. 703470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 704470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com QdomHI -= 1; // Now, corrhiQQ is in Q(QdomHI), with a 1-bit margin 705470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 706470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 707470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com newQdomLO = QdomLO; 708470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 709470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for (n = 0; n <= ORDERLO; n++) { 7100946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int32_t tmp, tmpB, tmpCorr; 7110946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t alpha=328; //0.01 in Q15 7120946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t beta=324; //(1-0.01)*0.01=0.0099 in Q15 7130946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t gamma=32440; //(1-0.01)=0.99 in Q15 714470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 715470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (maskdata->CorrBufLoQQ[n] != 0) { 716470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com shMem=WebRtcSpl_NormW32(maskdata->CorrBufLoQQ[n]); 717470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com sh = QdomLO - maskdata->CorrBufLoQdom[n]; 718470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (sh<=shMem) { 719470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufLoQQ[n], sh); // Get CorrBufLoQQ to same domain as corrlo2 720470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmp = WEBRTC_SPL_MUL_16_32_RSFT15(alpha, tmp); 721470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } else if ((sh-shMem)<7){ 722470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufLoQQ[n], shMem); // Shift up CorrBufLoQQ as much as possible 7233ea35fdb1b3bc50e98b0fee03d274dce76fbdd55bjornv@webrtc.org // Shift |alpha| the number of times required to get |tmp| in QdomLO. 7243ea35fdb1b3bc50e98b0fee03d274dce76fbdd55bjornv@webrtc.org tmp = WEBRTC_SPL_MUL_16_32_RSFT15(alpha << (sh - shMem), tmp); 725470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } else { 726470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufLoQQ[n], shMem); // Shift up CorrBufHiQQ as much as possible 7273ea35fdb1b3bc50e98b0fee03d274dce76fbdd55bjornv@webrtc.org // Shift |alpha| as much as possible without overflow the number of 7283ea35fdb1b3bc50e98b0fee03d274dce76fbdd55bjornv@webrtc.org // times required to get |tmp| in QdomLO. 7293ea35fdb1b3bc50e98b0fee03d274dce76fbdd55bjornv@webrtc.org tmp = WEBRTC_SPL_MUL_16_32_RSFT15(alpha << 6, tmp); 730a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org tmpCorr = corrloQQ[n] >> (sh - shMem - 6); 731470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmp = tmp + tmpCorr; 732470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com maskdata->CorrBufLoQQ[n] = tmp; 733470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com newQdomLO = QdomLO-(sh-shMem-6); 734470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com maskdata->CorrBufLoQdom[n] = newQdomLO; 735470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 736470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } else 737470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmp = 0; 738470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 739470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmp = tmp + corrlo2QQ[n]; 740470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 741470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com maskdata->CorrBufLoQQ[n] = tmp; 742470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com maskdata->CorrBufLoQdom[n] = QdomLO; 743470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 744470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmp=WEBRTC_SPL_MUL_16_32_RSFT15(beta, tmp); 745470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmpB=WEBRTC_SPL_MUL_16_32_RSFT15(gamma, corrlo2QQ[n]); 746470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com corrlo2QQ[n] = tmp + tmpB; 747470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 748470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if( newQdomLO!=QdomLO) { 749470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for (n = 0; n <= ORDERLO; n++) { 750470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (maskdata->CorrBufLoQdom[n] != newQdomLO) 751a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org corrloQQ[n] >>= maskdata->CorrBufLoQdom[n] - newQdomLO; 752470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 753470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com QdomLO = newQdomLO; 754470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 755470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 756470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 757470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com newQdomHI = QdomHI; 758470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 759470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for (n = 0; n <= ORDERHI; n++) { 7600946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int32_t tmp, tmpB, tmpCorr; 7610946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t alpha=328; //0.01 in Q15 7620946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t beta=324; //(1-0.01)*0.01=0.0099 in Q15 7630946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org int16_t gamma=32440; //(1-0.01)=0.99 in Q1 764470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (maskdata->CorrBufHiQQ[n] != 0) { 765470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com shMem=WebRtcSpl_NormW32(maskdata->CorrBufHiQQ[n]); 766470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com sh = QdomHI - maskdata->CorrBufHiQdom[n]; 767470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (sh<=shMem) { 768470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufHiQQ[n], sh); // Get CorrBufHiQQ to same domain as corrhi 769470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmp = WEBRTC_SPL_MUL_16_32_RSFT15(alpha, tmp); 770470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmpCorr = corrhiQQ[n]; 771470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmp = tmp + tmpCorr; 772470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com maskdata->CorrBufHiQQ[n] = tmp; 773470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com maskdata->CorrBufHiQdom[n] = QdomHI; 774470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } else if ((sh-shMem)<7) { 775470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufHiQQ[n], shMem); // Shift up CorrBufHiQQ as much as possible 7763ea35fdb1b3bc50e98b0fee03d274dce76fbdd55bjornv@webrtc.org // Shift |alpha| the number of times required to get |tmp| in QdomHI. 7773ea35fdb1b3bc50e98b0fee03d274dce76fbdd55bjornv@webrtc.org tmp = WEBRTC_SPL_MUL_16_32_RSFT15(alpha << (sh - shMem), tmp); 778470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmpCorr = corrhiQQ[n]; 779470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmp = tmp + tmpCorr; 780470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com maskdata->CorrBufHiQQ[n] = tmp; 781470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com maskdata->CorrBufHiQdom[n] = QdomHI; 782470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } else { 783470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmp = WEBRTC_SPL_SHIFT_W32(maskdata->CorrBufHiQQ[n], shMem); // Shift up CorrBufHiQQ as much as possible 7843ea35fdb1b3bc50e98b0fee03d274dce76fbdd55bjornv@webrtc.org // Shift |alpha| as much as possible without overflow the number of 7853ea35fdb1b3bc50e98b0fee03d274dce76fbdd55bjornv@webrtc.org // times required to get |tmp| in QdomHI. 7863ea35fdb1b3bc50e98b0fee03d274dce76fbdd55bjornv@webrtc.org tmp = WEBRTC_SPL_MUL_16_32_RSFT15(alpha << 6, tmp); 787a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org tmpCorr = corrhiQQ[n] >> (sh - shMem - 6); 788470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmp = tmp + tmpCorr; 789470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com maskdata->CorrBufHiQQ[n] = tmp; 790470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com newQdomHI = QdomHI-(sh-shMem-6); 791470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com maskdata->CorrBufHiQdom[n] = newQdomHI; 792470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 793470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } else { 794470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmp = corrhiQQ[n]; 795470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmpCorr = tmp; 796470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com maskdata->CorrBufHiQQ[n] = tmp; 797470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com maskdata->CorrBufHiQdom[n] = QdomHI; 798470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 799470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 800470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmp=WEBRTC_SPL_MUL_16_32_RSFT15(beta, tmp); 801470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmpB=WEBRTC_SPL_MUL_16_32_RSFT15(gamma, tmpCorr); 802470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com corrhiQQ[n] = tmp + tmpB; 803470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 804470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 805470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if( newQdomHI!=QdomHI) { 806470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for (n = 0; n <= ORDERHI; n++) { 807470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (maskdata->CorrBufHiQdom[n] != newQdomHI) 808a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org corrhiQQ[n] >>= maskdata->CorrBufHiQdom[n] - newQdomHI; 809470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 810470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com QdomHI = newQdomHI; 811470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 812470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 813470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com stab=WebRtcSpl_LevinsonW32_JSK(corrlo2QQ, a_LOQ11, k_vecloQ15, ORDERLO); 814470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 815470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (stab<0) { // If unstable use lower order 816470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com a_LOQ11[0]=2048; 817470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for (n = 1; n <= ORDERLO; n++) { 818470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com a_LOQ11[n]=0; 819470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 820470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 821470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com stab=WebRtcSpl_LevinsonW32_JSK(corrlo2QQ, a_LOQ11, k_vecloQ15, 8); 822470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 823470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 824470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 825470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WebRtcSpl_LevinsonDurbin(corrhiQQ, a_HIQ12, k_vechiQ15, ORDERHI); 826470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 827470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* bandwidth expansion */ 828470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for (n = 1; n <= ORDERLO; n++) { 829bc2bb34419021fb3be4f87eb062cf0a9ed52675abjornv@webrtc.org a_LOQ11[n] = (int16_t)((kPolyVecLo[n - 1] * a_LOQ11[n] + (1 << 14)) >> 830bc2bb34419021fb3be4f87eb062cf0a9ed52675abjornv@webrtc.org 15); 831470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 832470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 833470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 834470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com polyHI[0] = a_HIQ12[0]; 835470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for (n = 1; n <= ORDERHI; n++) { 836bc2bb34419021fb3be4f87eb062cf0a9ed52675abjornv@webrtc.org a_HIQ12[n] = (int16_t)(((int32_t)(kPolyVecHi[n - 1] * a_HIQ12[n]) + 837bc2bb34419021fb3be4f87eb062cf0a9ed52675abjornv@webrtc.org (1 << 14)) >> 15); 838470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com polyHI[n] = a_HIQ12[n]; 839470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 840470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 841470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Normalize the corrlo2 vector */ 842470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com sh = WebRtcSpl_NormW32(corrlo2QQ[0]); 843470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for (n = 0; n <= ORDERLO; n++) { 844d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker corrlo2QQ[n] <<= sh; 845470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 846470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com QdomLO += sh; /* Now, corrlo2QQ is still in Q(QdomLO) */ 847470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 848470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 849470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* residual energy */ 850470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 851470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com sh_lo = 31; 8522d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org res_nrgQQ = WebRtcIsacfix_CalculateResidualEnergy(ORDERLO, QdomLO, 8532d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org kShiftLowerBand, a_LOQ11, corrlo2QQ, &sh_lo); 854470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 855173538faa35c01e1b861767212a79c02a9253dd7kma@webrtc.org /* Convert to reflection coefficients */ 856470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WebRtcSpl_AToK_JSK(a_LOQ11, ORDERLO, rcQ15_lo); 857470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 858470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (sh_lo & 0x0001) { 859a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org res_nrgQQ >>= 1; 860470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com sh_lo-=1; 861470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 862470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 863470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 864470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if( res_nrgQQ > 0 ) 865470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 866470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com sqrt_nrg=WebRtcSpl_Sqrt(res_nrgQQ); 867470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 868470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* add hearing threshold and compute the gain */ 869470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* lo_coeff = varscale * S_N_R / (sqrt_nrg + varscale * H_T_H); */ 870470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 871f71785cd3b282ad7d584d746ba5b19833a11692bbjornv@webrtc.org tmp32a = varscaleQ14 >> 1; // H_T_HQ19=65536 (16-17=-1) 872f71785cd3b282ad7d584d746ba5b19833a11692bbjornv@webrtc.org ssh = sh_lo >> 1; // sqrt_nrg is in Qssh. 873470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com sh = ssh - 14; 874470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmp32b = WEBRTC_SPL_SHIFT_W32(tmp32a, sh); // Q14->Qssh 875470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmp32c = sqrt_nrg + tmp32b; // Qssh (denominator) 876f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker tmp32a = varscaleQ14 * snrq; // Q24 (numerator) 877470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 878470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com sh = WebRtcSpl_NormW32(tmp32c); 879470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com shft = 16 - sh; 8800946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org tmp16a = (int16_t) WEBRTC_SPL_SHIFT_W32(tmp32c, -shft); // Q(ssh-shft) (denominator) 881470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 882470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmp32b = WebRtcSpl_DivW32W16(tmp32a, tmp16a); // Q(24-ssh+shft) 883470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com sh = ssh-shft-7; 884470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *gain_lo_hiQ17 = WEBRTC_SPL_SHIFT_W32(tmp32b, sh); // Gains in Q17 885470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 886470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com else 887470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 888d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker *gain_lo_hiQ17 = 100; // Gains in Q17 889470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 890470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com gain_lo_hiQ17++; 891470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 892470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* copy coefficients to output array */ 893470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for (n = 0; n < ORDERLO; n++) { 8940946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org *lo_coeffQ15 = (int16_t) (rcQ15_lo[n]); 895470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com lo_coeffQ15++; 896470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 897470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* residual energy */ 898470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com sh_hi = 31; 8992d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org res_nrgQQ = WebRtcIsacfix_CalculateResidualEnergy(ORDERHI, QdomHI, 9002d4c4ae55388d98350683b7b53b0f1273d65bff6kma@webrtc.org kShiftHigherBand, a_HIQ12, corrhiQQ, &sh_hi); 901470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 902470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* Convert to reflection coefficients */ 903470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com WebRtcSpl_LpcToReflCoef(polyHI, ORDERHI, rcQ15_hi); 904470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 905470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if (sh_hi & 0x0001) { 906a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org res_nrgQQ >>= 1; 907470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com sh_hi-=1; 908470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 909470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 910470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 911470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com if( res_nrgQQ > 0 ) 912470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 913470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com sqrt_nrg=WebRtcSpl_Sqrt(res_nrgQQ); 914470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 915470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 916470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* add hearing threshold and compute the gain */ 917470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* hi_coeff = varscale * S_N_R / (sqrt_nrg + varscale * H_T_H); */ 918470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 919a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org tmp32a = varscaleQ14 >> 1; // H_T_HQ19=65536 (16-17=-1) 920470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 921a296725d0eea443b6cb181262069433866e2849fbjornv@webrtc.org ssh = sh_hi >> 1; // |sqrt_nrg| is in Qssh. 922470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com sh = ssh - 14; 923470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmp32b = WEBRTC_SPL_SHIFT_W32(tmp32a, sh); // Q14->Qssh 924470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmp32c = sqrt_nrg + tmp32b; // Qssh (denominator) 925f2822edf611ff187eab61abccd9edb2edac4ba64Bjorn Volcker tmp32a = varscaleQ14 * snrq; // Q24 (numerator) 926470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 927470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com sh = WebRtcSpl_NormW32(tmp32c); 928470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com shft = 16 - sh; 9290946a56023d821e0deca04029bb016ae1f23aa82pbos@webrtc.org tmp16a = (int16_t) WEBRTC_SPL_SHIFT_W32(tmp32c, -shft); // Q(ssh-shft) (denominator) 930470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 931470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com tmp32b = WebRtcSpl_DivW32W16(tmp32a, tmp16a); // Q(24-ssh+shft) 932470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com sh = ssh-shft-7; 933470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *gain_lo_hiQ17 = WEBRTC_SPL_SHIFT_W32(tmp32b, sh); // Gains in Q17 934470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 935470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com else 936470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com { 937d4e75016a3836c3aab992afff6bfd8d5e3862aacBjorn Volcker *gain_lo_hiQ17 = 100; // Gains in Q17 938470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 939470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com gain_lo_hiQ17++; 940470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 941470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com 942470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com /* copy coefficients to output array */ 943470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com for (n = 0; n < ORDERHI; n++) { 944470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com *hi_coeffQ15 = rcQ15_hi[n]; 945470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com hi_coeffQ15++; 946470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 947470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com } 948470e71d3649f6cac4688e83819640b012b5d38bbniklase@google.com} 949