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 1127fe999a8fe09ea7a39318e00262b30e38caa83ckma@webrtc.org#include <assert.h> 12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 1327fe999a8fe09ea7a39318e00262b30e38caa83ckma@webrtc.org#include "webrtc/modules/audio_coding/codecs/isac/fix/source/codec.h" 14b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 15b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Autocorrelation function in fixed point. 16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// NOTE! Different from SPLIB-version in how it scales the signal. 17fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgint WebRtcIsacfix_AutocorrC(int32_t* __restrict r, 18fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org const int16_t* __restrict x, 19fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org int16_t N, 20fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org int16_t order, 21fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org int16_t* __restrict scale) { 22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int i = 0; 23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int j = 0; 24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int16_t scaling = 0; 25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int32_t sum = 0; 26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org uint32_t temp = 0; 27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int64_t prod = 0; 28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 2927fe999a8fe09ea7a39318e00262b30e38caa83ckma@webrtc.org // The ARM assembly code assumptoins. 3027fe999a8fe09ea7a39318e00262b30e38caa83ckma@webrtc.org assert(N % 4 == 0); 3127fe999a8fe09ea7a39318e00262b30e38caa83ckma@webrtc.org assert(N >= 8); 3227fe999a8fe09ea7a39318e00262b30e38caa83ckma@webrtc.org 33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Calculate r[0]. 34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (i = 0; i < N; i++) { 35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org prod += WEBRTC_SPL_MUL_16_16(x[i], x[i]); 36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Calculate scaling (the value of shifting). 39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org temp = (uint32_t)(prod >> 31); 40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if(temp == 0) { 41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org scaling = 0; 42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else { 43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org scaling = 32 - WebRtcSpl_NormU32(temp); 44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org r[0] = (int32_t)(prod >> scaling); 46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Perform the actual correlation calculation. 48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (i = 1; i < order + 1; i++) { 49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org prod = 0; 50b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (j = 0; j < N - i; j++) { 51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org prod += WEBRTC_SPL_MUL_16_16(x[j], x[i + j]); 52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org sum = (int32_t)(prod >> scaling); 54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org r[i] = sum; 55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *scale = scaling; 58b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return(order + 1); 60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 62fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgstatic const int32_t kApUpperQ15[ALLPASSSECTIONS] = { 1137, 12537 }; 63fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgstatic const int32_t kApLowerQ15[ALLPASSSECTIONS] = { 5059, 24379 }; 64b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 65b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 66fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgstatic void AllpassFilterForDec32(int16_t *InOut16, //Q0 67fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org const int32_t *APSectionFactors, //Q15 68fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org int16_t lengthInOut, 69fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org int32_t *FilterState) //Q16 70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int n, j; 72fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org int32_t a, b; 73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (j=0; j<ALLPASSSECTIONS; j++) { 75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (n=0;n<lengthInOut;n+=2){ 76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org a = WEBRTC_SPL_MUL_16_32_RSFT16(InOut16[n], APSectionFactors[j]); //Q0*Q31=Q31 shifted 16 gives Q15 77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org a = WEBRTC_SPL_LSHIFT_W32(a, 1); // Q15 -> Q16 78347671c843ed5c93d25bf1a23f9295d35ce3df4abjornv@webrtc.org b = WebRtcSpl_AddSatW32(a, FilterState[j]); //Q16+Q16=Q16 79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org a = WEBRTC_SPL_MUL_16_32_RSFT16( 80fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org (int16_t) WEBRTC_SPL_RSHIFT_W32(b, 16), 81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org -APSectionFactors[j]); //Q0*Q31=Q31 shifted 16 gives Q15 82347671c843ed5c93d25bf1a23f9295d35ce3df4abjornv@webrtc.org FilterState[j] = WebRtcSpl_AddSatW32( 83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org WEBRTC_SPL_LSHIFT_W32(a,1), 84fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org WEBRTC_SPL_LSHIFT_W32((uint32_t)InOut16[n], 16)); // Q15<<1 + Q0<<16 = Q16 + Q16 = Q16 85fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org InOut16[n] = (int16_t) WEBRTC_SPL_RSHIFT_W32(b, 16); //Save as Q0 86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 93fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.orgvoid WebRtcIsacfix_DecimateAllpass32(const int16_t *in, 94fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org int32_t *state_in, /* array of size: 2*ALLPASSSECTIONS+1 */ 95fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org int16_t N, /* number of input samples */ 96fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org int16_t *out) /* array of size N/2 */ 97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int n; 99fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org int16_t data_vec[PITCH_FRAME_LEN]; 100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org /* copy input */ 102fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org memcpy(data_vec+1, in, WEBRTC_SPL_MUL_16_16(sizeof(int16_t), (N-1))); 103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 105fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org data_vec[0] = (int16_t) WEBRTC_SPL_RSHIFT_W32(state_in[WEBRTC_SPL_MUL_16_16(2, ALLPASSSECTIONS)],16); //the z^(-1) state 106fbda0fcf2f9e82c82bcaac138f44d4e5144f6e0dpbos@webrtc.org state_in[WEBRTC_SPL_MUL_16_16(2, ALLPASSSECTIONS)] = WEBRTC_SPL_LSHIFT_W32((uint32_t)in[N-1],16); 107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org AllpassFilterForDec32(data_vec+1, kApUpperQ15, N, state_in); 111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org AllpassFilterForDec32(data_vec, kApLowerQ15, N, state_in+ALLPASSSECTIONS); 112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (n=0;n<N/2;n++) { 114347671c843ed5c93d25bf1a23f9295d35ce3df4abjornv@webrtc.org out[n] = WebRtcSpl_AddSatW16(data_vec[WEBRTC_SPL_MUL_16_16(2, n)], 115347671c843ed5c93d25bf1a23f9295d35ce3df4abjornv@webrtc.org data_vec[WEBRTC_SPL_MUL_16_16(2, n) + 1]); 116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 118