1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* 2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Use of this source code is governed by a BSD-style license 5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * that can be found in the LICENSE file in the root of the source 6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * tree. An additional intellectual property rights grant can be found 7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * in the file PATENTS. All contributing project authors may 8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */ 10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 11b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* 13b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * This file contains the function WebRtcSpl_LevinsonDurbin(). 14b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * The description header can be found in signal_processing_library.h 15b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */ 17b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 18f24ac5923cbe5e806fac59a0d15e32567553ce8epbos@webrtc.org#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h" 19b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#define SPL_LEVINSON_MAXORDER 20 21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 22c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.orgint16_t WebRtcSpl_LevinsonDurbin(int32_t *R, int16_t *A, int16_t *K, 23c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org int16_t order) 24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 25c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org int16_t i, j; 26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Auto-correlation coefficients in high precision 27c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org int16_t R_hi[SPL_LEVINSON_MAXORDER + 1], R_low[SPL_LEVINSON_MAXORDER + 1]; 28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // LPC coefficients in high precision 29c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org int16_t A_hi[SPL_LEVINSON_MAXORDER + 1], A_low[SPL_LEVINSON_MAXORDER + 1]; 30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // LPC coefficients for next iteration 31c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org int16_t A_upd_hi[SPL_LEVINSON_MAXORDER + 1], A_upd_low[SPL_LEVINSON_MAXORDER + 1]; 32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Reflection coefficient in high precision 33c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org int16_t K_hi, K_low; 34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Prediction gain Alpha in high precision and with scale factor 35c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org int16_t Alpha_hi, Alpha_low, Alpha_exp; 36c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org int16_t tmp_hi, tmp_low; 37c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org int32_t temp1W32, temp2W32, temp3W32; 38c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org int16_t norm; 39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Normalize the autocorrelation R[0]...R[order+1] 41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org norm = WebRtcSpl_NormW32(R[0]); 43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (i = order; i >= 0; i--) 45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org temp1W32 = WEBRTC_SPL_LSHIFT_W32(R[i], norm); 47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Put R in hi and low format 48c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org R_hi[i] = (int16_t)WEBRTC_SPL_RSHIFT_W32(temp1W32, 16); 49c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org R_low[i] = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp1W32 50c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org - WEBRTC_SPL_LSHIFT_W32((int32_t)R_hi[i], 16)), 1); 51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // K = A[1] = -R[1] / R[0] 54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 55c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org temp2W32 = WEBRTC_SPL_LSHIFT_W32((int32_t)R_hi[1],16) 56c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org + WEBRTC_SPL_LSHIFT_W32((int32_t)R_low[1],1); // R[1] in Q31 57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org temp3W32 = WEBRTC_SPL_ABS_W32(temp2W32); // abs R[1] 58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org temp1W32 = WebRtcSpl_DivW32HiLow(temp3W32, R_hi[0], R_low[0]); // abs(R[1])/R[0] in Q31 59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Put back the sign on R[1] 60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (temp2W32 > 0) 61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org temp1W32 = -temp1W32; 63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Put K in hi and low format 66c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org K_hi = (int16_t)WEBRTC_SPL_RSHIFT_W32(temp1W32, 16); 67c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org K_low = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp1W32 68c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org - WEBRTC_SPL_LSHIFT_W32((int32_t)K_hi, 16)), 1); 69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Store first reflection coefficient 71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org K[0] = K_hi; 72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org temp1W32 = WEBRTC_SPL_RSHIFT_W32(temp1W32, 4); // A[1] in Q27 74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Put A[1] in hi and low format 76c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org A_hi[1] = (int16_t)WEBRTC_SPL_RSHIFT_W32(temp1W32, 16); 77c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org A_low[1] = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp1W32 78c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org - WEBRTC_SPL_LSHIFT_W32((int32_t)A_hi[1], 16)), 1); 79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Alpha = R[0] * (1-K^2) 81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org temp1W32 = (((WEBRTC_SPL_MUL_16_16(K_hi, K_low) >> 14) + WEBRTC_SPL_MUL_16_16(K_hi, K_hi)) 83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org << 1); // temp1W32 = k^2 in Q31 84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org temp1W32 = WEBRTC_SPL_ABS_W32(temp1W32); // Guard against <0 86c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org temp1W32 = (int32_t)0x7fffffffL - temp1W32; // temp1W32 = (1 - K[0]*K[0]) in Q31 87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Store temp1W32 = 1 - K[0]*K[0] on hi and low format 89c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org tmp_hi = (int16_t)WEBRTC_SPL_RSHIFT_W32(temp1W32, 16); 90c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org tmp_low = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp1W32 91c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org - WEBRTC_SPL_LSHIFT_W32((int32_t)tmp_hi, 16)), 1); 92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Calculate Alpha in Q31 94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org temp1W32 = ((WEBRTC_SPL_MUL_16_16(R_hi[0], tmp_hi) 95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org + (WEBRTC_SPL_MUL_16_16(R_hi[0], tmp_low) >> 15) 96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org + (WEBRTC_SPL_MUL_16_16(R_low[0], tmp_hi) >> 15)) << 1); 97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Normalize Alpha and put it in hi and low format 99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Alpha_exp = WebRtcSpl_NormW32(temp1W32); 101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org temp1W32 = WEBRTC_SPL_LSHIFT_W32(temp1W32, Alpha_exp); 102c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org Alpha_hi = (int16_t)WEBRTC_SPL_RSHIFT_W32(temp1W32, 16); 103c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org Alpha_low = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp1W32 104c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org - WEBRTC_SPL_LSHIFT_W32((int32_t)Alpha_hi, 16)), 1); 105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Perform the iterative calculations in the Levinson-Durbin algorithm 107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (i = 2; i <= order; i++) 109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org /* ---- 111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org temp1W32 = R[i] + > R[j]*A[i-j] 112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org / 113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org ---- 114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org j=1..i-1 115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */ 116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org temp1W32 = 0; 118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (j = 1; j < i; j++) 120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // temp1W32 is in Q31 122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org temp1W32 += ((WEBRTC_SPL_MUL_16_16(R_hi[j], A_hi[i-j]) << 1) 123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org + (((WEBRTC_SPL_MUL_16_16(R_hi[j], A_low[i-j]) >> 15) 124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org + (WEBRTC_SPL_MUL_16_16(R_low[j], A_hi[i-j]) >> 15)) << 1)); 125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org temp1W32 = WEBRTC_SPL_LSHIFT_W32(temp1W32, 4); 128c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org temp1W32 += (WEBRTC_SPL_LSHIFT_W32((int32_t)R_hi[i], 16) 129c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org + WEBRTC_SPL_LSHIFT_W32((int32_t)R_low[i], 1)); 130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // K = -temp1W32 / Alpha 132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org temp2W32 = WEBRTC_SPL_ABS_W32(temp1W32); // abs(temp1W32) 133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org temp3W32 = WebRtcSpl_DivW32HiLow(temp2W32, Alpha_hi, Alpha_low); // abs(temp1W32)/Alpha 134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Put the sign of temp1W32 back again 136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (temp1W32 > 0) 137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org temp3W32 = -temp3W32; 139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Use the Alpha shifts from earlier to de-normalize 142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org norm = WebRtcSpl_NormW32(temp3W32); 143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if ((Alpha_exp <= norm) || (temp3W32 == 0)) 144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org temp3W32 = WEBRTC_SPL_LSHIFT_W32(temp3W32, Alpha_exp); 146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else 147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (temp3W32 > 0) 149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 150c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org temp3W32 = (int32_t)0x7fffffffL; 151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else 152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 153c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org temp3W32 = (int32_t)0x80000000L; 154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Put K on hi and low format 158c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org K_hi = (int16_t)WEBRTC_SPL_RSHIFT_W32(temp3W32, 16); 159c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org K_low = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp3W32 160c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org - WEBRTC_SPL_LSHIFT_W32((int32_t)K_hi, 16)), 1); 161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Store Reflection coefficient in Q15 163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org K[i - 1] = K_hi; 164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Test for unstable filter. 166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // If unstable return 0 and let the user decide what to do in that case 167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 168c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org if ((int32_t)WEBRTC_SPL_ABS_W16(K_hi) > (int32_t)32750) 169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; // Unstable filter 171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org /* 174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Compute updated LPC coefficient: Anew[i] 175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Anew[j]= A[j] + K*A[i-j] for j=1..i-1 176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Anew[i]= K 177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */ 178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (j = 1; j < i; j++) 180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // temp1W32 = A[j] in Q27 182c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org temp1W32 = WEBRTC_SPL_LSHIFT_W32((int32_t)A_hi[j],16) 183c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org + WEBRTC_SPL_LSHIFT_W32((int32_t)A_low[j],1); 184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // temp1W32 += K*A[i-j] in Q27 186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org temp1W32 += ((WEBRTC_SPL_MUL_16_16(K_hi, A_hi[i-j]) 187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org + (WEBRTC_SPL_MUL_16_16(K_hi, A_low[i-j]) >> 15) 188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org + (WEBRTC_SPL_MUL_16_16(K_low, A_hi[i-j]) >> 15)) << 1); 189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 190b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Put Anew in hi and low format 191c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org A_upd_hi[j] = (int16_t)WEBRTC_SPL_RSHIFT_W32(temp1W32, 16); 192c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org A_upd_low[j] = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp1W32 193c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org - WEBRTC_SPL_LSHIFT_W32((int32_t)A_upd_hi[j], 16)), 1); 194b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 196b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // temp3W32 = K in Q27 (Convert from Q31 to Q27) 197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org temp3W32 = WEBRTC_SPL_RSHIFT_W32(temp3W32, 4); 198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 199b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Store Anew in hi and low format 200c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org A_upd_hi[i] = (int16_t)WEBRTC_SPL_RSHIFT_W32(temp3W32, 16); 201c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org A_upd_low[i] = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp3W32 202c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org - WEBRTC_SPL_LSHIFT_W32((int32_t)A_upd_hi[i], 16)), 1); 203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Alpha = Alpha * (1-K^2) 205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org temp1W32 = (((WEBRTC_SPL_MUL_16_16(K_hi, K_low) >> 14) 207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org + WEBRTC_SPL_MUL_16_16(K_hi, K_hi)) << 1); // K*K in Q31 208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org temp1W32 = WEBRTC_SPL_ABS_W32(temp1W32); // Guard against <0 210c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org temp1W32 = (int32_t)0x7fffffffL - temp1W32; // 1 - K*K in Q31 211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Convert 1- K^2 in hi and low format 213c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org tmp_hi = (int16_t)WEBRTC_SPL_RSHIFT_W32(temp1W32, 16); 214c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org tmp_low = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp1W32 215c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org - WEBRTC_SPL_LSHIFT_W32((int32_t)tmp_hi, 16)), 1); 216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Calculate Alpha = Alpha * (1-K^2) in Q31 218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org temp1W32 = ((WEBRTC_SPL_MUL_16_16(Alpha_hi, tmp_hi) 219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org + (WEBRTC_SPL_MUL_16_16(Alpha_hi, tmp_low) >> 15) 220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org + (WEBRTC_SPL_MUL_16_16(Alpha_low, tmp_hi) >> 15)) << 1); 221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Normalize Alpha and store it on hi and low format 223b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 224b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org norm = WebRtcSpl_NormW32(temp1W32); 225b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org temp1W32 = WEBRTC_SPL_LSHIFT_W32(temp1W32, norm); 226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 227c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org Alpha_hi = (int16_t)WEBRTC_SPL_RSHIFT_W32(temp1W32, 16); 228c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org Alpha_low = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp1W32 229c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org - WEBRTC_SPL_LSHIFT_W32((int32_t)Alpha_hi, 16)), 1); 230b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 231b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Update the total normalization of Alpha 232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Alpha_exp = Alpha_exp + norm; 233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Update A[] 235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (j = 1; j <= i; j++) 237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org A_hi[j] = A_upd_hi[j]; 239b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org A_low[j] = A_upd_low[j]; 240b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 241b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 242b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 243b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org /* 244b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org Set A[0] to 1.0 and store the A[i] i=1...order in Q12 245b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (Convert from Q27 and use rounding) 246b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */ 247b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 248b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org A[0] = 4096; 249b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 250b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (i = 1; i <= order; i++) 251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // temp1W32 in Q27 253c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org temp1W32 = WEBRTC_SPL_LSHIFT_W32((int32_t)A_hi[i], 16) 254c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org + WEBRTC_SPL_LSHIFT_W32((int32_t)A_low[i], 1); 255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Round and store upper word 256c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org A[i] = (int16_t)WEBRTC_SPL_RSHIFT_W32((temp1W32<<1)+(int32_t)32768, 16); 257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 258b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 1; // Stable filters 259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 260