1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* Copyright (C) 2002-2006 Jean-Marc Valin 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com File: ltp.c 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com Long-Term Prediction functions 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com Redistribution and use in source and binary forms, with or without 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com modification, are permitted provided that the following conditions 7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com are met: 8b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org 9b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org - Redistributions of source code must retain the above copyright 10b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org notice, this list of conditions and the following disclaimer. 11b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org 12b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org - Redistributions in binary form must reproduce the above copyright 13b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org notice, this list of conditions and the following disclaimer in the 142f3dc9dc4c970bd066be329a842a791d91f524e2reed@google.com documentation and/or other materials provided with the distribution. 152f3dc9dc4c970bd066be329a842a791d91f524e2reed@google.com 16ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com - Neither the name of the Xiph.org Foundation nor the names of its 172f3dc9dc4c970bd066be329a842a791d91f524e2reed@google.com contributors may be used to endorse or promote products derived from 182f3dc9dc4c970bd066be329a842a791d91f524e2reed@google.com this software without specific prior written permission. 192f3dc9dc4c970bd066be329a842a791d91f524e2reed@google.com 202f3dc9dc4c970bd066be329a842a791d91f524e2reed@google.com THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 212f3dc9dc4c970bd066be329a842a791d91f524e2reed@google.com ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 232f3dc9dc4c970bd066be329a842a791d91f524e2reed@google.com A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR 24ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 252880df2609eba09b555ca37be04b6ad89290c765Tom Hudson EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 262f3dc9dc4c970bd066be329a842a791d91f524e2reed@google.com PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 272f3dc9dc4c970bd066be329a842a791d91f524e2reed@google.com PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 292f3dc9dc4c970bd066be329a842a791d91f524e2reed@google.com NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 302f3dc9dc4c970bd066be329a842a791d91f524e2reed@google.com SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 312f3dc9dc4c970bd066be329a842a791d91f524e2reed@google.com*/ 322f3dc9dc4c970bd066be329a842a791d91f524e2reed@google.com 332f3dc9dc4c970bd066be329a842a791d91f524e2reed@google.com#ifdef HAVE_CONFIG_H 342f3dc9dc4c970bd066be329a842a791d91f524e2reed@google.com#include "config.h" 352f3dc9dc4c970bd066be329a842a791d91f524e2reed@google.com#endif 362f3dc9dc4c970bd066be329a842a791d91f524e2reed@google.com 372f3dc9dc4c970bd066be329a842a791d91f524e2reed@google.com#include <math.h> 38a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org#include "ltp.h" 39a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org#include "stack_alloc.h" 40ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com#include "filters.h" 41a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org#include <speex/speex_bits.h> 42a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org#include "math_approx.h" 43a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org#include "os_support.h" 44ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com 45a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org#ifndef NULL 46a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org#define NULL 0 47a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org#endif 48a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org 49a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org 50a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org#ifdef _USE_SSE 51a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org#include "ltp_sse.h" 52a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org#elif defined (ARM4_ASM) || defined(ARM5E_ASM) 53a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org#include "ltp_arm4.h" 54a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org#elif defined (BFIN_ASM) 55a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org#include "ltp_bfin.h" 56a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org#endif 57a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org 58a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org#ifndef OVERRIDE_INNER_PROD 59a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.orgspx_word32_t inner_prod(const spx_word16_t *x, const spx_word16_t *y, int len) 60a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org{ 61261b8e2ca1cf22303ad95267f0bdc6e87e1bbe70reed@google.com spx_word32_t sum=0; 62a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org len >>= 2; 63a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org while(len--) 64ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com { 65a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org spx_word32_t part=0; 66261b8e2ca1cf22303ad95267f0bdc6e87e1bbe70reed@google.com part = MAC16_16(part,*x++,*y++); 67a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org part = MAC16_16(part,*x++,*y++); 68a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org part = MAC16_16(part,*x++,*y++); 69ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com part = MAC16_16(part,*x++,*y++); 70a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org /* HINT: If you had a 40-bit accumulator, you could shift only at the end */ 71261b8e2ca1cf22303ad95267f0bdc6e87e1bbe70reed@google.com sum = ADD32(sum,SHR32(part,6)); 72a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org } 73a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org return sum; 74ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com} 75a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org#endif 76261b8e2ca1cf22303ad95267f0bdc6e87e1bbe70reed@google.com 77a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org#ifndef OVERRIDE_PITCH_XCORR 78a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org#if 0 /* HINT: Enable this for machines with enough registers (i.e. not x86) */ 79ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.comvoid pitch_xcorr(const spx_word16_t *_x, const spx_word16_t *_y, spx_word32_t *corr, int len, int nb_pitch, char *stack) 80a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org{ 81261b8e2ca1cf22303ad95267f0bdc6e87e1bbe70reed@google.com int i,j; 82a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org for (i=0;i<nb_pitch;i+=4) 83a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org { 84ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com /* Compute correlation*/ 85a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org /*corr[nb_pitch-1-i]=inner_prod(x, _y+i, len);*/ 86a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org spx_word32_t sum1=0; 87b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org spx_word32_t sum2=0; 88b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org spx_word32_t sum3=0; 89dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org spx_word32_t sum4=0; 90dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org const spx_word16_t *y = _y+i; 91dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org const spx_word16_t *x = _x; 92dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org spx_word16_t y0, y1, y2, y3; 93dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org /*y0=y[0];y1=y[1];y2=y[2];y3=y[3];*/ 94dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org y0=*y++; 95dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org y1=*y++; 96dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org y2=*y++; 97dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org y3=*y++; 98dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org for (j=0;j<len;j+=4) 99dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org { 100dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org spx_word32_t part1; 101dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org spx_word32_t part2; 102dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org spx_word32_t part3; 103dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org spx_word32_t part4; 104dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org part1 = MULT16_16(*x,y0); 105dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org part2 = MULT16_16(*x,y1); 106b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org part3 = MULT16_16(*x,y2); 107dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org part4 = MULT16_16(*x,y3); 108b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org x++; 109dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org y0=*y++; 110dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org part1 = MAC16_16(part1,*x,y1); 111dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org part2 = MAC16_16(part2,*x,y2); 112dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org part3 = MAC16_16(part3,*x,y3); 113dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org part4 = MAC16_16(part4,*x,y0); 114dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org x++; 115dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org y1=*y++; 116dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org part1 = MAC16_16(part1,*x,y2); 117dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org part2 = MAC16_16(part2,*x,y3); 118dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org part3 = MAC16_16(part3,*x,y0); 119dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org part4 = MAC16_16(part4,*x,y1); 120dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org x++; 121dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org y2=*y++; 122dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org part1 = MAC16_16(part1,*x,y3); 123dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org part2 = MAC16_16(part2,*x,y0); 124dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org part3 = MAC16_16(part3,*x,y1); 125dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org part4 = MAC16_16(part4,*x,y2); 126dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org x++; 127dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org y3=*y++; 128dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org 129dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org sum1 = ADD32(sum1,SHR32(part1,6)); 130dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org sum2 = ADD32(sum2,SHR32(part2,6)); 131dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org sum3 = ADD32(sum3,SHR32(part3,6)); 132dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org sum4 = ADD32(sum4,SHR32(part4,6)); 133dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org } 134b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org corr[nb_pitch-1-i]=sum1; 135b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org corr[nb_pitch-2-i]=sum2; 136b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org corr[nb_pitch-3-i]=sum3; 137b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org corr[nb_pitch-4-i]=sum4; 138dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org } 139dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org 140dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org} 141dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org#else 142dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.orgvoid pitch_xcorr(const spx_word16_t *_x, const spx_word16_t *_y, spx_word32_t *corr, int len, int nb_pitch, char *stack) 143dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org{ 144dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org int i; 145dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org for (i=0;i<nb_pitch;i++) 146dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org { 147dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org /* Compute correlation*/ 148dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org corr[nb_pitch-1-i]=inner_prod(_x, _y+i, len); 149dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org } 150dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org 151dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org} 152dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org#endif 153dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org#endif 154dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org 155dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org#ifndef OVERRIDE_COMPUTE_PITCH_ERROR 156dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.orgstatic inline spx_word32_t compute_pitch_error(spx_word16_t *C, spx_word16_t *g, spx_word16_t pitch_control) 157dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org{ 158dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org spx_word32_t sum = 0; 159b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org sum = ADD32(sum,MULT16_16(MULT16_16_16(g[0],pitch_control),C[0])); 160b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org sum = ADD32(sum,MULT16_16(MULT16_16_16(g[1],pitch_control),C[1])); 161b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org sum = ADD32(sum,MULT16_16(MULT16_16_16(g[2],pitch_control),C[2])); 162b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org sum = SUB32(sum,MULT16_16(MULT16_16_16(g[0],g[1]),C[3])); 163b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org sum = SUB32(sum,MULT16_16(MULT16_16_16(g[2],g[1]),C[4])); 164b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org sum = SUB32(sum,MULT16_16(MULT16_16_16(g[2],g[0]),C[5])); 165b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org sum = SUB32(sum,MULT16_16(MULT16_16_16(g[0],g[0]),C[6])); 166a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org sum = SUB32(sum,MULT16_16(MULT16_16_16(g[1],g[1]),C[7])); 167a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org sum = SUB32(sum,MULT16_16(MULT16_16_16(g[2],g[2]),C[8])); 168b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org return sum; 169b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org} 170b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org#endif 171b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org 172b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org#ifndef OVERRIDE_OPEN_LOOP_NBEST_PITCH 173b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.orgvoid open_loop_nbest_pitch(spx_word16_t *sw, int start, int end, int len, int *pitch, spx_word16_t *gain, int N, char *stack) 174b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org{ 175b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org int i,j,k; 176b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org VARDECL(spx_word32_t *best_score); 177b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org VARDECL(spx_word32_t *best_ener); 178b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org spx_word32_t e0; 179b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org VARDECL(spx_word32_t *corr); 180b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org#ifdef FIXED_POINT 181b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org /* In fixed-point, we need only one (temporary) array of 32-bit values and two (corr16, ener16) 182b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org arrays for (normalized) 16-bit values */ 183b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org VARDECL(spx_word16_t *corr16); 184b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org VARDECL(spx_word16_t *ener16); 185b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org spx_word32_t *energy; 186b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org int cshift=0, eshift=0; 187b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org int scaledown = 0; 188b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org ALLOC(corr16, end-start+1, spx_word16_t); 189b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org ALLOC(ener16, end-start+1, spx_word16_t); 190b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org ALLOC(corr, end-start+1, spx_word32_t); 191b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org energy = corr; 192b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org#else 193b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org /* In floating-point, we need to float arrays and no normalized copies */ 194b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org VARDECL(spx_word32_t *energy); 195b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org spx_word16_t *corr16; 196b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org spx_word16_t *ener16; 197b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org ALLOC(energy, end-start+2, spx_word32_t); 198b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org ALLOC(corr, end-start+1, spx_word32_t); 199b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org corr16 = corr; 200a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org ener16 = energy; 201a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org#endif 202a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org 203a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org ALLOC(best_score, N, spx_word32_t); 204a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org ALLOC(best_ener, N, spx_word32_t); 205a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org for (i=0;i<N;i++) 206a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org { 207a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org best_score[i]=-1; 208a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org best_ener[i]=0; 209b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org pitch[i]=start; 210b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org } 211b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org 212dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org#ifdef FIXED_POINT 213dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org for (i=-end;i<len;i++) 214dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org { 215dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org if (ABS16(sw[i])>16383) 216dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org { 217dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org scaledown=1; 218dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org break; 219dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org } 220b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org } 221b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org /* If the weighted input is close to saturation, then we scale it down */ 222b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org if (scaledown) 223b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org { 224b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org for (i=-end;i<len;i++) 225b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org { 226b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org sw[i]=SHR16(sw[i],1); 227b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org } 228b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org } 229b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org#endif 230b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org energy[0]=inner_prod(sw-start, sw-start, len); 231b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org e0=inner_prod(sw, sw, len); 232b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org for (i=start;i<end;i++) 233b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org { 234b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org /* Update energy for next pitch*/ 235b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org energy[i-start+1] = SUB32(ADD32(energy[i-start],SHR32(MULT16_16(sw[-i-1],sw[-i-1]),6)), SHR32(MULT16_16(sw[-i+len-1],sw[-i+len-1]),6)); 236b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org if (energy[i-start+1] < 0) 237b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org energy[i-start+1] = 0; 238b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org } 239ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com 240b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org#ifdef FIXED_POINT 241b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org eshift = normalize16(energy, ener16, 32766, end-start+1); 242b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org#endif 243b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org 244b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org /* In fixed-point, this actually overrites the energy array (aliased to corr) */ 245b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org pitch_xcorr(sw, sw-end, corr, len, end-start+1, stack); 246b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org 247b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org#ifdef FIXED_POINT 248b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org /* Normalize to 180 so we can square it and it still fits in 16 bits */ 249b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org cshift = normalize16(corr, corr16, 180, end-start+1); 250b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org /* If we scaled weighted input down, we need to scale it up again (OK, so we've just lost the LSB, who cares?) */ 251a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org if (scaledown) 252a8282ef8f9e63e60c5665af0cdfc8fdd11c089f6mike@reedtribe.org { 253b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org for (i=-end;i<len;i++) 254b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org { 255b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org sw[i]=SHL16(sw[i],1); 256b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org } 257b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org } 258b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org#endif 259b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org 260b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org /* Search for the best pitch prediction gain */ 261b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org for (i=start;i<=end;i++) 262b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org { 263b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org spx_word16_t tmp = MULT16_16_16(corr16[i-start],corr16[i-start]); 264b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org /* Instead of dividing the tmp by the energy, we multiply on the other side */ 2652880df2609eba09b555ca37be04b6ad89290c765Tom Hudson if (MULT16_16(tmp,best_ener[N-1])>MULT16_16(best_score[N-1],ADD16(1,ener16[i-start]))) 266b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org { 267b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org /* We can safely put it last and then check */ 268b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org best_score[N-1]=tmp; 269b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org best_ener[N-1]=ener16[i-start]+1; 270b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org pitch[N-1]=i; 271b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org /* Check if it comes in front of others */ 2721d5aaa8ef65f312508e41ec458d4a6457f9cd39ereed@google.com for (j=0;j<N-1;j++) 273b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org { 274b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org if (MULT16_16(tmp,best_ener[j])>MULT16_16(best_score[j],ADD16(1,ener16[i-start]))) 275b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org { 276b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org for (k=N-1;k>j;k--) 277b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org { 278b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org best_score[k]=best_score[k-1]; 279b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org best_ener[k]=best_ener[k-1]; 280b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org pitch[k]=pitch[k-1]; 281b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org } 282b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org best_score[j]=tmp; 283b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org best_ener[j]=ener16[i-start]+1; 284dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org pitch[j]=i; 285dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org break; 286dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org } 287dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org } 288dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org } 289dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org } 290dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org 291dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org /* Compute open-loop gain if necessary */ 2922880df2609eba09b555ca37be04b6ad89290c765Tom Hudson if (gain) 293dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org { 294ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com for (j=0;j<N;j++) 295b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org { 296b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org spx_word16_t g; 297b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org i=pitch[j]; 298b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org g = DIV32(SHL32(EXTEND32(corr16[i-start]),cshift), 10+SHR32(MULT16_16(spx_sqrt(e0),spx_sqrt(SHL32(EXTEND32(ener16[i-start]),eshift))),6)); 299b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org /* FIXME: g = max(g,corr/energy) */ 300b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org if (g<0) 301b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org g = 0; 302b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org gain[j]=g; 303b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org } 304b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org } 305b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org 306b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org 307b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org} 308b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org#endif 309b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org 310b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org#ifndef OVERRIDE_PITCH_GAIN_SEARCH_3TAP_VQ 311b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.orgstatic int pitch_gain_search_3tap_vq( 3122f3dc9dc4c970bd066be329a842a791d91f524e2reed@google.com const signed char *gain_cdbk, 3132f3dc9dc4c970bd066be329a842a791d91f524e2reed@google.com int gain_cdbk_size, 314b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org spx_word16_t *C16, 315dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org spx_word16_t max_gain 316b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org) 317b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org{ 318b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org const signed char *ptr=gain_cdbk; 319b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org int best_cdbk=0; 320b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org spx_word32_t best_sum=-VERY_LARGE32; 321b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org spx_word32_t sum=0; 322b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org spx_word16_t g[3]; 323b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org spx_word16_t pitch_control=64; 324dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org spx_word16_t gain_sum; 325dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org int i; 326dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org 327dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org for (i=0;i<gain_cdbk_size;i++) { 328dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org 329dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org ptr = gain_cdbk+4*i; 330dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org g[0]=ADD16((spx_word16_t)ptr[0],32); 331dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org g[1]=ADD16((spx_word16_t)ptr[1],32); 332dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org g[2]=ADD16((spx_word16_t)ptr[2],32); 333dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org gain_sum = (spx_word16_t)ptr[3]; 334dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org 335dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org sum = compute_pitch_error(C16, g, pitch_control); 336dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org 337b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org if (sum>best_sum && gain_sum<=max_gain) { 338b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org best_sum=sum; 339b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org best_cdbk=i; 340b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org } 341dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org } 342dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org 343dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org return best_cdbk; 344dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org} 345dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org#endif 346dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.org 3472880df2609eba09b555ca37be04b6ad89290c765Tom Hudson/** Finds the best quantized 3-tap pitch predictor by analysis by synthesis */ 348dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.orgstatic spx_word32_t pitch_gain_search_3tap( 349b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.orgconst spx_word16_t target[], /* Target vector */ 350b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.orgconst spx_coef_t ak[], /* LPCs for this subframe */ 351b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.orgconst spx_coef_t awk1[], /* Weighted LPCs #1 for this subframe */ 352b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.orgconst spx_coef_t awk2[], /* Weighted LPCs #2 for this subframe */ 353b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.orgspx_sig_t exc[], /* Excitation */ 354b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.orgconst signed char *gain_cdbk, 355b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.orgint gain_cdbk_size, 356b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.orgint pitch, /* Pitch value */ 357dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.orgint p, /* Number of LPC coeffs */ 358dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.orgint nsf, /* Number of samples in subframe */ 359dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.orgSpeexBits *bits, 360dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.orgchar *stack, 361dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.orgconst spx_word16_t *exc2, 362dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.orgconst spx_word16_t *r, 363dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.orgspx_word16_t *new_target, 364dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.orgint *cdbk_index, 365dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.orgint plc_tuning, 366dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.orgspx_word32_t cumul_gain, 367dd0cd34067d103ace7c6739405cb7885d8ad3fb2mike@reedtribe.orgint scaledown 3682880df2609eba09b555ca37be04b6ad89290c765Tom Hudson) 369b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org{ 370b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org int i,j; 371b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org VARDECL(spx_word16_t *tmp1); 372b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org VARDECL(spx_word16_t *e); 373b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org spx_word16_t *x[3]; 374b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org spx_word32_t corr[3]; 375b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org spx_word32_t A[3][3]; 376b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org spx_word16_t gain[3]; 377b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org spx_word32_t err; 378b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org spx_word16_t max_gain=128; 379b7d956df4665e06f3ae98cb696cef7c04452ab8emike@reedtribe.org int best_cdbk=0; 380 381 ALLOC(tmp1, 3*nsf, spx_word16_t); 382 ALLOC(e, nsf, spx_word16_t); 383 384 if (cumul_gain > 262144) 385 max_gain = 31; 386 387 x[0]=tmp1; 388 x[1]=tmp1+nsf; 389 x[2]=tmp1+2*nsf; 390 391 for (j=0;j<nsf;j++) 392 new_target[j] = target[j]; 393 394 { 395 VARDECL(spx_mem_t *mm); 396 int pp=pitch-1; 397 ALLOC(mm, p, spx_mem_t); 398 for (j=0;j<nsf;j++) 399 { 400 if (j-pp<0) 401 e[j]=exc2[j-pp]; 402 else if (j-pp-pitch<0) 403 e[j]=exc2[j-pp-pitch]; 404 else 405 e[j]=0; 406 } 407#ifdef FIXED_POINT 408 /* Scale target and excitation down if needed (avoiding overflow) */ 409 if (scaledown) 410 { 411 for (j=0;j<nsf;j++) 412 e[j] = SHR16(e[j],1); 413 for (j=0;j<nsf;j++) 414 new_target[j] = SHR16(new_target[j],1); 415 } 416#endif 417 for (j=0;j<p;j++) 418 mm[j] = 0; 419 iir_mem16(e, ak, e, nsf, p, mm, stack); 420 for (j=0;j<p;j++) 421 mm[j] = 0; 422 filter_mem16(e, awk1, awk2, e, nsf, p, mm, stack); 423 for (j=0;j<nsf;j++) 424 x[2][j] = e[j]; 425 } 426 for (i=1;i>=0;i--) 427 { 428 spx_word16_t e0=exc2[-pitch-1+i]; 429#ifdef FIXED_POINT 430 /* Scale excitation down if needed (avoiding overflow) */ 431 if (scaledown) 432 e0 = SHR16(e0,1); 433#endif 434 x[i][0]=MULT16_16_Q14(r[0], e0); 435 for (j=0;j<nsf-1;j++) 436 x[i][j+1]=ADD32(x[i+1][j],MULT16_16_P14(r[j+1], e0)); 437 } 438 439 for (i=0;i<3;i++) 440 corr[i]=inner_prod(x[i],new_target,nsf); 441 for (i=0;i<3;i++) 442 for (j=0;j<=i;j++) 443 A[i][j]=A[j][i]=inner_prod(x[i],x[j],nsf); 444 445 { 446 spx_word32_t C[9]; 447#ifdef FIXED_POINT 448 spx_word16_t C16[9]; 449#else 450 spx_word16_t *C16=C; 451#endif 452 C[0]=corr[2]; 453 C[1]=corr[1]; 454 C[2]=corr[0]; 455 C[3]=A[1][2]; 456 C[4]=A[0][1]; 457 C[5]=A[0][2]; 458 C[6]=A[2][2]; 459 C[7]=A[1][1]; 460 C[8]=A[0][0]; 461 462 /*plc_tuning *= 2;*/ 463 if (plc_tuning<2) 464 plc_tuning=2; 465 if (plc_tuning>30) 466 plc_tuning=30; 467#ifdef FIXED_POINT 468 C[0] = SHL32(C[0],1); 469 C[1] = SHL32(C[1],1); 470 C[2] = SHL32(C[2],1); 471 C[3] = SHL32(C[3],1); 472 C[4] = SHL32(C[4],1); 473 C[5] = SHL32(C[5],1); 474 C[6] = MAC16_32_Q15(C[6],MULT16_16_16(plc_tuning,655),C[6]); 475 C[7] = MAC16_32_Q15(C[7],MULT16_16_16(plc_tuning,655),C[7]); 476 C[8] = MAC16_32_Q15(C[8],MULT16_16_16(plc_tuning,655),C[8]); 477 normalize16(C, C16, 32767, 9); 478#else 479 C[6]*=.5*(1+.02*plc_tuning); 480 C[7]*=.5*(1+.02*plc_tuning); 481 C[8]*=.5*(1+.02*plc_tuning); 482#endif 483 484 best_cdbk = pitch_gain_search_3tap_vq(gain_cdbk, gain_cdbk_size, C16, max_gain); 485 486#ifdef FIXED_POINT 487 gain[0] = ADD16(32,(spx_word16_t)gain_cdbk[best_cdbk*4]); 488 gain[1] = ADD16(32,(spx_word16_t)gain_cdbk[best_cdbk*4+1]); 489 gain[2] = ADD16(32,(spx_word16_t)gain_cdbk[best_cdbk*4+2]); 490 /*printf ("%d %d %d %d\n",gain[0],gain[1],gain[2], best_cdbk);*/ 491#else 492 gain[0] = 0.015625*gain_cdbk[best_cdbk*4] + .5; 493 gain[1] = 0.015625*gain_cdbk[best_cdbk*4+1]+ .5; 494 gain[2] = 0.015625*gain_cdbk[best_cdbk*4+2]+ .5; 495#endif 496 *cdbk_index=best_cdbk; 497 } 498 499 SPEEX_MEMSET(exc, 0, nsf); 500 for (i=0;i<3;i++) 501 { 502 int j; 503 int tmp1, tmp3; 504 int pp=pitch+1-i; 505 tmp1=nsf; 506 if (tmp1>pp) 507 tmp1=pp; 508 for (j=0;j<tmp1;j++) 509 exc[j]=MAC16_16(exc[j],SHL16(gain[2-i],7),exc2[j-pp]); 510 tmp3=nsf; 511 if (tmp3>pp+pitch) 512 tmp3=pp+pitch; 513 for (j=tmp1;j<tmp3;j++) 514 exc[j]=MAC16_16(exc[j],SHL16(gain[2-i],7),exc2[j-pp-pitch]); 515 } 516 for (i=0;i<nsf;i++) 517 { 518 spx_word32_t tmp = ADD32(ADD32(MULT16_16(gain[0],x[2][i]),MULT16_16(gain[1],x[1][i])), 519 MULT16_16(gain[2],x[0][i])); 520 new_target[i] = SUB16(new_target[i], EXTRACT16(PSHR32(tmp,6))); 521 } 522 err = inner_prod(new_target, new_target, nsf); 523 524 return err; 525} 526 527/** Finds the best quantized 3-tap pitch predictor by analysis by synthesis */ 528int pitch_search_3tap( 529spx_word16_t target[], /* Target vector */ 530spx_word16_t *sw, 531spx_coef_t ak[], /* LPCs for this subframe */ 532spx_coef_t awk1[], /* Weighted LPCs #1 for this subframe */ 533spx_coef_t awk2[], /* Weighted LPCs #2 for this subframe */ 534spx_sig_t exc[], /* Excitation */ 535const void *par, 536int start, /* Smallest pitch value allowed */ 537int end, /* Largest pitch value allowed */ 538spx_word16_t pitch_coef, /* Voicing (pitch) coefficient */ 539int p, /* Number of LPC coeffs */ 540int nsf, /* Number of samples in subframe */ 541SpeexBits *bits, 542char *stack, 543spx_word16_t *exc2, 544spx_word16_t *r, 545int complexity, 546int cdbk_offset, 547int plc_tuning, 548spx_word32_t *cumul_gain 549) 550{ 551 int i; 552 int cdbk_index, pitch=0, best_gain_index=0; 553 VARDECL(spx_sig_t *best_exc); 554 VARDECL(spx_word16_t *new_target); 555 VARDECL(spx_word16_t *best_target); 556 int best_pitch=0; 557 spx_word32_t err, best_err=-1; 558 int N; 559 const ltp_params *params; 560 const signed char *gain_cdbk; 561 int gain_cdbk_size; 562 int scaledown=0; 563 564 VARDECL(int *nbest); 565 566 params = (const ltp_params*) par; 567 gain_cdbk_size = 1<<params->gain_bits; 568 gain_cdbk = params->gain_cdbk + 4*gain_cdbk_size*cdbk_offset; 569 570 N=complexity; 571 if (N>10) 572 N=10; 573 if (N<1) 574 N=1; 575 576 ALLOC(nbest, N, int); 577 params = (const ltp_params*) par; 578 579 if (end<start) 580 { 581 speex_bits_pack(bits, 0, params->pitch_bits); 582 speex_bits_pack(bits, 0, params->gain_bits); 583 SPEEX_MEMSET(exc, 0, nsf); 584 return start; 585 } 586 587#ifdef FIXED_POINT 588 /* Check if we need to scale everything down in the pitch search to avoid overflows */ 589 for (i=0;i<nsf;i++) 590 { 591 if (ABS16(target[i])>16383) 592 { 593 scaledown=1; 594 break; 595 } 596 } 597 for (i=-end;i<nsf;i++) 598 { 599 if (ABS16(exc2[i])>16383) 600 { 601 scaledown=1; 602 break; 603 } 604 } 605#endif 606 if (N>end-start+1) 607 N=end-start+1; 608 if (end != start) 609 open_loop_nbest_pitch(sw, start, end, nsf, nbest, NULL, N, stack); 610 else 611 nbest[0] = start; 612 613 ALLOC(best_exc, nsf, spx_sig_t); 614 ALLOC(new_target, nsf, spx_word16_t); 615 ALLOC(best_target, nsf, spx_word16_t); 616 617 for (i=0;i<N;i++) 618 { 619 pitch=nbest[i]; 620 SPEEX_MEMSET(exc, 0, nsf); 621 err=pitch_gain_search_3tap(target, ak, awk1, awk2, exc, gain_cdbk, gain_cdbk_size, pitch, p, nsf, 622 bits, stack, exc2, r, new_target, &cdbk_index, plc_tuning, *cumul_gain, scaledown); 623 if (err<best_err || best_err<0) 624 { 625 SPEEX_COPY(best_exc, exc, nsf); 626 SPEEX_COPY(best_target, new_target, nsf); 627 best_err=err; 628 best_pitch=pitch; 629 best_gain_index=cdbk_index; 630 } 631 } 632 /*printf ("pitch: %d %d\n", best_pitch, best_gain_index);*/ 633 speex_bits_pack(bits, best_pitch-start, params->pitch_bits); 634 speex_bits_pack(bits, best_gain_index, params->gain_bits); 635#ifdef FIXED_POINT 636 *cumul_gain = MULT16_32_Q13(SHL16(params->gain_cdbk[4*best_gain_index+3],8), MAX32(1024,*cumul_gain)); 637#else 638 *cumul_gain = 0.03125*MAX32(1024,*cumul_gain)*params->gain_cdbk[4*best_gain_index+3]; 639#endif 640 /*printf ("%f\n", cumul_gain);*/ 641 /*printf ("encode pitch: %d %d\n", best_pitch, best_gain_index);*/ 642 SPEEX_COPY(exc, best_exc, nsf); 643 SPEEX_COPY(target, best_target, nsf); 644#ifdef FIXED_POINT 645 /* Scale target back up if needed */ 646 if (scaledown) 647 { 648 for (i=0;i<nsf;i++) 649 target[i]=SHL16(target[i],1); 650 } 651#endif 652 return pitch; 653} 654 655void pitch_unquant_3tap( 656spx_word16_t exc[], /* Input excitation */ 657spx_word32_t exc_out[], /* Output excitation */ 658int start, /* Smallest pitch value allowed */ 659int end, /* Largest pitch value allowed */ 660spx_word16_t pitch_coef, /* Voicing (pitch) coefficient */ 661const void *par, 662int nsf, /* Number of samples in subframe */ 663int *pitch_val, 664spx_word16_t *gain_val, 665SpeexBits *bits, 666char *stack, 667int count_lost, 668int subframe_offset, 669spx_word16_t last_pitch_gain, 670int cdbk_offset 671) 672{ 673 int i; 674 int pitch; 675 int gain_index; 676 spx_word16_t gain[3]; 677 const signed char *gain_cdbk; 678 int gain_cdbk_size; 679 const ltp_params *params; 680 681 params = (const ltp_params*) par; 682 gain_cdbk_size = 1<<params->gain_bits; 683 gain_cdbk = params->gain_cdbk + 4*gain_cdbk_size*cdbk_offset; 684 685 pitch = speex_bits_unpack_unsigned(bits, params->pitch_bits); 686 pitch += start; 687 gain_index = speex_bits_unpack_unsigned(bits, params->gain_bits); 688 /*printf ("decode pitch: %d %d\n", pitch, gain_index);*/ 689#ifdef FIXED_POINT 690 gain[0] = ADD16(32,(spx_word16_t)gain_cdbk[gain_index*4]); 691 gain[1] = ADD16(32,(spx_word16_t)gain_cdbk[gain_index*4+1]); 692 gain[2] = ADD16(32,(spx_word16_t)gain_cdbk[gain_index*4+2]); 693#else 694 gain[0] = 0.015625*gain_cdbk[gain_index*4]+.5; 695 gain[1] = 0.015625*gain_cdbk[gain_index*4+1]+.5; 696 gain[2] = 0.015625*gain_cdbk[gain_index*4+2]+.5; 697#endif 698 699 if (count_lost && pitch > subframe_offset) 700 { 701 spx_word16_t gain_sum; 702 if (1) { 703#ifdef FIXED_POINT 704 spx_word16_t tmp = count_lost < 4 ? last_pitch_gain : SHR16(last_pitch_gain,1); 705 if (tmp>62) 706 tmp=62; 707#else 708 spx_word16_t tmp = count_lost < 4 ? last_pitch_gain : 0.5 * last_pitch_gain; 709 if (tmp>.95) 710 tmp=.95; 711#endif 712 gain_sum = gain_3tap_to_1tap(gain); 713 714 if (gain_sum > tmp) 715 { 716 spx_word16_t fact = DIV32_16(SHL32(EXTEND32(tmp),14),gain_sum); 717 for (i=0;i<3;i++) 718 gain[i]=MULT16_16_Q14(fact,gain[i]); 719 } 720 721 } 722 723 } 724 725 *pitch_val = pitch; 726 gain_val[0]=gain[0]; 727 gain_val[1]=gain[1]; 728 gain_val[2]=gain[2]; 729 gain[0] = SHL16(gain[0],7); 730 gain[1] = SHL16(gain[1],7); 731 gain[2] = SHL16(gain[2],7); 732 SPEEX_MEMSET(exc_out, 0, nsf); 733 for (i=0;i<3;i++) 734 { 735 int j; 736 int tmp1, tmp3; 737 int pp=pitch+1-i; 738 tmp1=nsf; 739 if (tmp1>pp) 740 tmp1=pp; 741 for (j=0;j<tmp1;j++) 742 exc_out[j]=MAC16_16(exc_out[j],gain[2-i],exc[j-pp]); 743 tmp3=nsf; 744 if (tmp3>pp+pitch) 745 tmp3=pp+pitch; 746 for (j=tmp1;j<tmp3;j++) 747 exc_out[j]=MAC16_16(exc_out[j],gain[2-i],exc[j-pp-pitch]); 748 } 749 /*for (i=0;i<nsf;i++) 750 exc[i]=PSHR32(exc32[i],13);*/ 751} 752 753 754/** Forced pitch delay and gain */ 755int forced_pitch_quant( 756spx_word16_t target[], /* Target vector */ 757spx_word16_t *sw, 758spx_coef_t ak[], /* LPCs for this subframe */ 759spx_coef_t awk1[], /* Weighted LPCs #1 for this subframe */ 760spx_coef_t awk2[], /* Weighted LPCs #2 for this subframe */ 761spx_sig_t exc[], /* Excitation */ 762const void *par, 763int start, /* Smallest pitch value allowed */ 764int end, /* Largest pitch value allowed */ 765spx_word16_t pitch_coef, /* Voicing (pitch) coefficient */ 766int p, /* Number of LPC coeffs */ 767int nsf, /* Number of samples in subframe */ 768SpeexBits *bits, 769char *stack, 770spx_word16_t *exc2, 771spx_word16_t *r, 772int complexity, 773int cdbk_offset, 774int plc_tuning, 775spx_word32_t *cumul_gain 776) 777{ 778 int i; 779 VARDECL(spx_word16_t *res); 780 ALLOC(res, nsf, spx_word16_t); 781#ifdef FIXED_POINT 782 if (pitch_coef>63) 783 pitch_coef=63; 784#else 785 if (pitch_coef>.99) 786 pitch_coef=.99; 787#endif 788 for (i=0;i<nsf&&i<start;i++) 789 { 790 exc[i]=MULT16_16(SHL16(pitch_coef, 7),exc2[i-start]); 791 } 792 for (;i<nsf;i++) 793 { 794 exc[i]=MULT16_32_Q15(SHL16(pitch_coef, 9),exc[i-start]); 795 } 796 for (i=0;i<nsf;i++) 797 res[i] = EXTRACT16(PSHR32(exc[i], SIG_SHIFT-1)); 798 syn_percep_zero16(res, ak, awk1, awk2, res, nsf, p, stack); 799 for (i=0;i<nsf;i++) 800 target[i]=EXTRACT16(SATURATE(SUB32(EXTEND32(target[i]),EXTEND32(res[i])),32700)); 801 return start; 802} 803 804/** Unquantize forced pitch delay and gain */ 805void forced_pitch_unquant( 806spx_word16_t exc[], /* Input excitation */ 807spx_word32_t exc_out[], /* Output excitation */ 808int start, /* Smallest pitch value allowed */ 809int end, /* Largest pitch value allowed */ 810spx_word16_t pitch_coef, /* Voicing (pitch) coefficient */ 811const void *par, 812int nsf, /* Number of samples in subframe */ 813int *pitch_val, 814spx_word16_t *gain_val, 815SpeexBits *bits, 816char *stack, 817int count_lost, 818int subframe_offset, 819spx_word16_t last_pitch_gain, 820int cdbk_offset 821) 822{ 823 int i; 824#ifdef FIXED_POINT 825 if (pitch_coef>63) 826 pitch_coef=63; 827#else 828 if (pitch_coef>.99) 829 pitch_coef=.99; 830#endif 831 for (i=0;i<nsf;i++) 832 { 833 exc_out[i]=MULT16_16(exc[i-start],SHL16(pitch_coef,7)); 834 exc[i] = EXTRACT16(PSHR32(exc_out[i],13)); 835 } 836 *pitch_val = start; 837 gain_val[0]=gain_val[2]=0; 838 gain_val[1] = pitch_coef; 839} 840