198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project/* Copyright (C) 2002-2006 Jean-Marc Valin
298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   File: ltp.c
398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   Long-Term Prediction functions
498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   Redistribution and use in source and binary forms, with or without
698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   modification, are permitted provided that the following conditions
798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   are met:
898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   - Redistributions of source code must retain the above copyright
1098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   notice, this list of conditions and the following disclaimer.
1198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
1298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   - Redistributions in binary form must reproduce the above copyright
1398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   notice, this list of conditions and the following disclaimer in the
1498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   documentation and/or other materials provided with the distribution.
1598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
1698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   - Neither the name of the Xiph.org Foundation nor the names of its
1798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   contributors may be used to endorse or promote products derived from
1898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   this software without specific prior written permission.
1998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
2098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
2498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
2898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
2998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project*/
3298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
3398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef HAVE_CONFIG_H
3498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "config.h"
3598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
3698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
3798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include <math.h>
3898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "ltp.h"
3998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "stack_alloc.h"
4098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "filters.h"
4198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include <speex/speex_bits.h>
4298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "math_approx.h"
4398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "os_support.h"
4498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
4598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifndef NULL
4698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define NULL 0
4798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
4898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
4998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
5098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef _USE_SSE
5198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "ltp_sse.h"
5298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#elif defined (ARM4_ASM) || defined(ARM5E_ASM)
5398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "ltp_arm4.h"
5498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#elif defined (BFIN_ASM)
5598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "ltp_bfin.h"
5698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
5798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
5898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifndef OVERRIDE_INNER_PROD
5998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_word32_t inner_prod(const spx_word16_t *x, const spx_word16_t *y, int len)
6098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
6198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word32_t sum=0;
6298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   len >>= 2;
6398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   while(len--)
6498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
6598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      spx_word32_t part=0;
6698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      part = MAC16_16(part,*x++,*y++);
6798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      part = MAC16_16(part,*x++,*y++);
6898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      part = MAC16_16(part,*x++,*y++);
6998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      part = MAC16_16(part,*x++,*y++);
7098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /* HINT: If you had a 40-bit accumulator, you could shift only at the end */
7198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      sum = ADD32(sum,SHR32(part,6));
7298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
7398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   return sum;
7498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
7598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
7698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
7798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifndef OVERRIDE_PITCH_XCORR
7898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#if 0 /* HINT: Enable this for machines with enough registers (i.e. not x86) */
7998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectvoid pitch_xcorr(const spx_word16_t *_x, const spx_word16_t *_y, spx_word32_t *corr, int len, int nb_pitch, char *stack)
8098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
8198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int i,j;
8298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<nb_pitch;i+=4)
8398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
8498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /* Compute correlation*/
8598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /*corr[nb_pitch-1-i]=inner_prod(x, _y+i, len);*/
8698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      spx_word32_t sum1=0;
8798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      spx_word32_t sum2=0;
8898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      spx_word32_t sum3=0;
8998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      spx_word32_t sum4=0;
9098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      const spx_word16_t *y = _y+i;
9198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      const spx_word16_t *x = _x;
9298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      spx_word16_t y0, y1, y2, y3;
9398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /*y0=y[0];y1=y[1];y2=y[2];y3=y[3];*/
9498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      y0=*y++;
9598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      y1=*y++;
9698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      y2=*y++;
9798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      y3=*y++;
9898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (j=0;j<len;j+=4)
9998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
10098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         spx_word32_t part1;
10198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         spx_word32_t part2;
10298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         spx_word32_t part3;
10398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         spx_word32_t part4;
10498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         part1 = MULT16_16(*x,y0);
10598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         part2 = MULT16_16(*x,y1);
10698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         part3 = MULT16_16(*x,y2);
10798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         part4 = MULT16_16(*x,y3);
10898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         x++;
10998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         y0=*y++;
11098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         part1 = MAC16_16(part1,*x,y1);
11198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         part2 = MAC16_16(part2,*x,y2);
11298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         part3 = MAC16_16(part3,*x,y3);
11398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         part4 = MAC16_16(part4,*x,y0);
11498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         x++;
11598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         y1=*y++;
11698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         part1 = MAC16_16(part1,*x,y2);
11798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         part2 = MAC16_16(part2,*x,y3);
11898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         part3 = MAC16_16(part3,*x,y0);
11998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         part4 = MAC16_16(part4,*x,y1);
12098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         x++;
12198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         y2=*y++;
12298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         part1 = MAC16_16(part1,*x,y3);
12398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         part2 = MAC16_16(part2,*x,y0);
12498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         part3 = MAC16_16(part3,*x,y1);
12598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         part4 = MAC16_16(part4,*x,y2);
12698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         x++;
12798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         y3=*y++;
12898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
12998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         sum1 = ADD32(sum1,SHR32(part1,6));
13098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         sum2 = ADD32(sum2,SHR32(part2,6));
13198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         sum3 = ADD32(sum3,SHR32(part3,6));
13298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         sum4 = ADD32(sum4,SHR32(part4,6));
13398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      }
13498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      corr[nb_pitch-1-i]=sum1;
13598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      corr[nb_pitch-2-i]=sum2;
13698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      corr[nb_pitch-3-i]=sum3;
13798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      corr[nb_pitch-4-i]=sum4;
13898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
13998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
14098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
14198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else
14298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectvoid pitch_xcorr(const spx_word16_t *_x, const spx_word16_t *_y, spx_word32_t *corr, int len, int nb_pitch, char *stack)
14398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
14498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int i;
14598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<nb_pitch;i++)
14698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
14798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /* Compute correlation*/
14898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      corr[nb_pitch-1-i]=inner_prod(_x, _y+i, len);
14998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
15098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
15198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
15298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
15398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
15498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
15598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifndef OVERRIDE_COMPUTE_PITCH_ERROR
15698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic inline spx_word32_t compute_pitch_error(spx_word16_t *C, spx_word16_t *g, spx_word16_t pitch_control)
15798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
15898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word32_t sum = 0;
15998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   sum = ADD32(sum,MULT16_16(MULT16_16_16(g[0],pitch_control),C[0]));
16098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   sum = ADD32(sum,MULT16_16(MULT16_16_16(g[1],pitch_control),C[1]));
16198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   sum = ADD32(sum,MULT16_16(MULT16_16_16(g[2],pitch_control),C[2]));
16298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   sum = SUB32(sum,MULT16_16(MULT16_16_16(g[0],g[1]),C[3]));
16398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   sum = SUB32(sum,MULT16_16(MULT16_16_16(g[2],g[1]),C[4]));
16498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   sum = SUB32(sum,MULT16_16(MULT16_16_16(g[2],g[0]),C[5]));
16598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   sum = SUB32(sum,MULT16_16(MULT16_16_16(g[0],g[0]),C[6]));
16698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   sum = SUB32(sum,MULT16_16(MULT16_16_16(g[1],g[1]),C[7]));
16798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   sum = SUB32(sum,MULT16_16(MULT16_16_16(g[2],g[2]),C[8]));
16898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   return sum;
16998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
17098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
17198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
17298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifndef OVERRIDE_OPEN_LOOP_NBEST_PITCH
17398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectvoid open_loop_nbest_pitch(spx_word16_t *sw, int start, int end, int len, int *pitch, spx_word16_t *gain, int N, char *stack)
17498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
17598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int i,j,k;
17698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   VARDECL(spx_word32_t *best_score);
17798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   VARDECL(spx_word32_t *best_ener);
17898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word32_t e0;
17998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   VARDECL(spx_word32_t *corr);
18098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT
18198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* In fixed-point, we need only one (temporary) array of 32-bit values and two (corr16, ener16)
18298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      arrays for (normalized) 16-bit values */
18398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   VARDECL(spx_word16_t *corr16);
18498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   VARDECL(spx_word16_t *ener16);
18598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word32_t *energy;
18698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int cshift=0, eshift=0;
18798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int scaledown = 0;
18898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   ALLOC(corr16, end-start+1, spx_word16_t);
18998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   ALLOC(ener16, end-start+1, spx_word16_t);
19098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   ALLOC(corr, end-start+1, spx_word32_t);
19198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   energy = corr;
19298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else
19398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* In floating-point, we need to float arrays and no normalized copies */
19498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   VARDECL(spx_word32_t *energy);
19598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word16_t *corr16;
19698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word16_t *ener16;
19798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   ALLOC(energy, end-start+2, spx_word32_t);
19898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   ALLOC(corr, end-start+1, spx_word32_t);
19998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   corr16 = corr;
20098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   ener16 = energy;
20198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
20298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
20398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   ALLOC(best_score, N, spx_word32_t);
20498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   ALLOC(best_ener, N, spx_word32_t);
20598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<N;i++)
20698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
20798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project        best_score[i]=-1;
20898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project        best_ener[i]=0;
20998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project        pitch[i]=start;
21098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
21198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
21298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT
21398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=-end;i<len;i++)
21498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
21598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (ABS16(sw[i])>16383)
21698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
21798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         scaledown=1;
21898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         break;
21998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      }
22098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
22198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* If the weighted input is close to saturation, then we scale it down */
22298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (scaledown)
22398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
22498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (i=-end;i<len;i++)
22598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
22698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         sw[i]=SHR16(sw[i],1);
22798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      }
22898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
22998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
23098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   energy[0]=inner_prod(sw-start, sw-start, len);
23198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   e0=inner_prod(sw, sw, len);
23298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=start;i<end;i++)
23398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
23498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /* Update energy for next pitch*/
23598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      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));
23698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (energy[i-start+1] < 0)
23798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         energy[i-start+1] = 0;
23898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
23998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
24098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT
24198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   eshift = normalize16(energy, ener16, 32766, end-start+1);
24298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
24398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
24498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* In fixed-point, this actually overrites the energy array (aliased to corr) */
24598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   pitch_xcorr(sw, sw-end, corr, len, end-start+1, stack);
24698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
24798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT
24898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* Normalize to 180 so we can square it and it still fits in 16 bits */
24998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   cshift = normalize16(corr, corr16, 180, end-start+1);
25098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* If we scaled weighted input down, we need to scale it up again (OK, so we've just lost the LSB, who cares?) */
25198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (scaledown)
25298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
25398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (i=-end;i<len;i++)
25498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
25598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         sw[i]=SHL16(sw[i],1);
25698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      }
25798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
25898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
25998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
26098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* Search for the best pitch prediction gain */
26198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=start;i<=end;i++)
26298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
26398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      spx_word16_t tmp = MULT16_16_16(corr16[i-start],corr16[i-start]);
26498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /* Instead of dividing the tmp by the energy, we multiply on the other side */
26598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (MULT16_16(tmp,best_ener[N-1])>MULT16_16(best_score[N-1],ADD16(1,ener16[i-start])))
26698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
26798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         /* We can safely put it last and then check */
26898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         best_score[N-1]=tmp;
26998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         best_ener[N-1]=ener16[i-start]+1;
27098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         pitch[N-1]=i;
27198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         /* Check if it comes in front of others */
27298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         for (j=0;j<N-1;j++)
27398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         {
27498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project            if (MULT16_16(tmp,best_ener[j])>MULT16_16(best_score[j],ADD16(1,ener16[i-start])))
27598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project            {
27698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project               for (k=N-1;k>j;k--)
27798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project               {
27898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project                  best_score[k]=best_score[k-1];
27998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project                  best_ener[k]=best_ener[k-1];
28098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project                  pitch[k]=pitch[k-1];
28198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project               }
28298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project               best_score[j]=tmp;
28398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project               best_ener[j]=ener16[i-start]+1;
28498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project               pitch[j]=i;
28598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project               break;
28698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project            }
28798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         }
28898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      }
28998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
29098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
29198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* Compute open-loop gain if necessary */
29298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (gain)
29398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
29498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (j=0;j<N;j++)
29598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
29698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         spx_word16_t g;
29798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         i=pitch[j];
29898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         g = DIV32(SHL32(EXTEND32(corr16[i-start]),cshift), 10+SHR32(MULT16_16(spx_sqrt(e0),spx_sqrt(SHL32(EXTEND32(ener16[i-start]),eshift))),6));
29998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         /* FIXME: g = max(g,corr/energy) */
30098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         if (g<0)
30198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project            g = 0;
30298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         gain[j]=g;
30398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      }
30498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
30598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
30698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
30798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
30898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
30998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
31098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifndef OVERRIDE_PITCH_GAIN_SEARCH_3TAP_VQ
31198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic int pitch_gain_search_3tap_vq(
31298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project  const signed char *gain_cdbk,
31398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project  int                gain_cdbk_size,
31498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project  spx_word16_t      *C16,
31598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project  spx_word16_t       max_gain
31698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project)
31798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
31898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project  const signed char *ptr=gain_cdbk;
31998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project  int                best_cdbk=0;
32098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project  spx_word32_t       best_sum=-VERY_LARGE32;
32198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project  spx_word32_t       sum=0;
32298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project  spx_word16_t       g[3];
32398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project  spx_word16_t       pitch_control=64;
32498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project  spx_word16_t       gain_sum;
32598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project  int                i;
32698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
32798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project  for (i=0;i<gain_cdbk_size;i++) {
32898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
32998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project    ptr = gain_cdbk+4*i;
33098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project    g[0]=ADD16((spx_word16_t)ptr[0],32);
33198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project    g[1]=ADD16((spx_word16_t)ptr[1],32);
33298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project    g[2]=ADD16((spx_word16_t)ptr[2],32);
33398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project    gain_sum = (spx_word16_t)ptr[3];
33498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
33598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project    sum = compute_pitch_error(C16, g, pitch_control);
33698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
33798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project    if (sum>best_sum && gain_sum<=max_gain) {
33898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      best_sum=sum;
33998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      best_cdbk=i;
34098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project    }
34198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project  }
34298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
34398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project  return best_cdbk;
34498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
34598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
34698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
34798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project/** Finds the best quantized 3-tap pitch predictor by analysis by synthesis */
34898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic spx_word32_t pitch_gain_search_3tap(
34998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectconst spx_word16_t target[],       /* Target vector */
35098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectconst spx_coef_t ak[],          /* LPCs for this subframe */
35198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectconst spx_coef_t awk1[],        /* Weighted LPCs #1 for this subframe */
35298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectconst spx_coef_t awk2[],        /* Weighted LPCs #2 for this subframe */
35398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_sig_t exc[],                /* Excitation */
35498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectconst signed char *gain_cdbk,
35598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint gain_cdbk_size,
35698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint   pitch,                    /* Pitch value */
35798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint   p,                        /* Number of LPC coeffs */
35898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint   nsf,                      /* Number of samples in subframe */
35998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectSpeexBits *bits,
36098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectchar *stack,
36198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectconst spx_word16_t *exc2,
36298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectconst spx_word16_t *r,
36398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_word16_t *new_target,
36498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint  *cdbk_index,
36598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint plc_tuning,
36698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_word32_t cumul_gain,
36798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint scaledown
36898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project)
36998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
37098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int i,j;
37198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   VARDECL(spx_word16_t *tmp1);
37298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   VARDECL(spx_word16_t *e);
37398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word16_t *x[3];
37498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word32_t corr[3];
37598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word32_t A[3][3];
37698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word16_t gain[3];
37798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word32_t err;
37898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word16_t max_gain=128;
37998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int          best_cdbk=0;
38098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
38198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   ALLOC(tmp1, 3*nsf, spx_word16_t);
38298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   ALLOC(e, nsf, spx_word16_t);
38398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
38498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (cumul_gain > 262144)
38598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      max_gain = 31;
38698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
38798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   x[0]=tmp1;
38898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   x[1]=tmp1+nsf;
38998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   x[2]=tmp1+2*nsf;
39098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
39198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (j=0;j<nsf;j++)
39298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      new_target[j] = target[j];
39398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
39498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
39598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      VARDECL(spx_mem_t *mm);
39698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      int pp=pitch-1;
39798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      ALLOC(mm, p, spx_mem_t);
39898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (j=0;j<nsf;j++)
39998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
40098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         if (j-pp<0)
40198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project            e[j]=exc2[j-pp];
40298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         else if (j-pp-pitch<0)
40398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project            e[j]=exc2[j-pp-pitch];
40498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         else
40598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project            e[j]=0;
40698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      }
40798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT
40898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /* Scale target and excitation down if needed (avoiding overflow) */
40998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (scaledown)
41098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
41198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         for (j=0;j<nsf;j++)
41298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project            e[j] = SHR16(e[j],1);
41398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         for (j=0;j<nsf;j++)
41498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project            new_target[j] = SHR16(new_target[j],1);
41598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      }
41698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
41798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (j=0;j<p;j++)
41898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         mm[j] = 0;
41998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      iir_mem16(e, ak, e, nsf, p, mm, stack);
42098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (j=0;j<p;j++)
42198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         mm[j] = 0;
42298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      filter_mem16(e, awk1, awk2, e, nsf, p, mm, stack);
42398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (j=0;j<nsf;j++)
42498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         x[2][j] = e[j];
42598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
42698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=1;i>=0;i--)
42798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
42898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      spx_word16_t e0=exc2[-pitch-1+i];
42998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT
43098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /* Scale excitation down if needed (avoiding overflow) */
43198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (scaledown)
43298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         e0 = SHR16(e0,1);
43398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
43498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      x[i][0]=MULT16_16_Q14(r[0], e0);
43598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (j=0;j<nsf-1;j++)
43698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         x[i][j+1]=ADD32(x[i+1][j],MULT16_16_P14(r[j+1], e0));
43798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
43898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
43998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<3;i++)
44098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      corr[i]=inner_prod(x[i],new_target,nsf);
44198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<3;i++)
44298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (j=0;j<=i;j++)
44398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         A[i][j]=A[j][i]=inner_prod(x[i],x[j],nsf);
44498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
44598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
44698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      spx_word32_t C[9];
44798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT
44898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      spx_word16_t C16[9];
44998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else
45098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      spx_word16_t *C16=C;
45198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
45298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      C[0]=corr[2];
45398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      C[1]=corr[1];
45498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      C[2]=corr[0];
45598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      C[3]=A[1][2];
45698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      C[4]=A[0][1];
45798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      C[5]=A[0][2];
45898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      C[6]=A[2][2];
45998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      C[7]=A[1][1];
46098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      C[8]=A[0][0];
46198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
46298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /*plc_tuning *= 2;*/
46398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (plc_tuning<2)
46498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         plc_tuning=2;
46598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (plc_tuning>30)
46698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         plc_tuning=30;
46798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT
46898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      C[0] = SHL32(C[0],1);
46998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      C[1] = SHL32(C[1],1);
47098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      C[2] = SHL32(C[2],1);
47198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      C[3] = SHL32(C[3],1);
47298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      C[4] = SHL32(C[4],1);
47398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      C[5] = SHL32(C[5],1);
47498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      C[6] = MAC16_32_Q15(C[6],MULT16_16_16(plc_tuning,655),C[6]);
47598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      C[7] = MAC16_32_Q15(C[7],MULT16_16_16(plc_tuning,655),C[7]);
47698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      C[8] = MAC16_32_Q15(C[8],MULT16_16_16(plc_tuning,655),C[8]);
47798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      normalize16(C, C16, 32767, 9);
47898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else
47998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      C[6]*=.5*(1+.02*plc_tuning);
48098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      C[7]*=.5*(1+.02*plc_tuning);
48198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      C[8]*=.5*(1+.02*plc_tuning);
48298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
48398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
48498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      best_cdbk = pitch_gain_search_3tap_vq(gain_cdbk, gain_cdbk_size, C16, max_gain);
48598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
48698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT
48798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      gain[0] = ADD16(32,(spx_word16_t)gain_cdbk[best_cdbk*4]);
48898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      gain[1] = ADD16(32,(spx_word16_t)gain_cdbk[best_cdbk*4+1]);
48998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      gain[2] = ADD16(32,(spx_word16_t)gain_cdbk[best_cdbk*4+2]);
49098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /*printf ("%d %d %d %d\n",gain[0],gain[1],gain[2], best_cdbk);*/
49198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else
49298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      gain[0] = 0.015625*gain_cdbk[best_cdbk*4]  + .5;
49398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      gain[1] = 0.015625*gain_cdbk[best_cdbk*4+1]+ .5;
49498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      gain[2] = 0.015625*gain_cdbk[best_cdbk*4+2]+ .5;
49598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
49698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      *cdbk_index=best_cdbk;
49798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
49898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
49998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   SPEEX_MEMSET(exc, 0, nsf);
50098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<3;i++)
50198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
50298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      int j;
50398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      int tmp1, tmp3;
50498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      int pp=pitch+1-i;
50598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      tmp1=nsf;
50698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (tmp1>pp)
50798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         tmp1=pp;
50898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (j=0;j<tmp1;j++)
50998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         exc[j]=MAC16_16(exc[j],SHL16(gain[2-i],7),exc2[j-pp]);
51098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      tmp3=nsf;
51198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (tmp3>pp+pitch)
51298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         tmp3=pp+pitch;
51398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (j=tmp1;j<tmp3;j++)
51498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         exc[j]=MAC16_16(exc[j],SHL16(gain[2-i],7),exc2[j-pp-pitch]);
51598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
51698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<nsf;i++)
51798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
51898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      spx_word32_t tmp = ADD32(ADD32(MULT16_16(gain[0],x[2][i]),MULT16_16(gain[1],x[1][i])),
51998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project                            MULT16_16(gain[2],x[0][i]));
52098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      new_target[i] = SUB16(new_target[i], EXTRACT16(PSHR32(tmp,6)));
52198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
52298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   err = inner_prod(new_target, new_target, nsf);
52398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
52498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   return err;
52598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
52698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
52798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project/** Finds the best quantized 3-tap pitch predictor by analysis by synthesis */
52898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint pitch_search_3tap(
52998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_word16_t target[],                 /* Target vector */
53098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_word16_t *sw,
53198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_coef_t ak[],                     /* LPCs for this subframe */
53298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_coef_t awk1[],                   /* Weighted LPCs #1 for this subframe */
53398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_coef_t awk2[],                   /* Weighted LPCs #2 for this subframe */
53498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_sig_t exc[],                    /* Excitation */
53598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectconst void *par,
53698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint   start,                    /* Smallest pitch value allowed */
53798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint   end,                      /* Largest pitch value allowed */
53898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_word16_t pitch_coef,               /* Voicing (pitch) coefficient */
53998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint   p,                        /* Number of LPC coeffs */
54098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint   nsf,                      /* Number of samples in subframe */
54198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectSpeexBits *bits,
54298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectchar *stack,
54398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_word16_t *exc2,
54498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_word16_t *r,
54598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint complexity,
54698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint cdbk_offset,
54798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint plc_tuning,
54898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_word32_t *cumul_gain
54998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project)
55098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
55198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int i;
55298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int cdbk_index, pitch=0, best_gain_index=0;
55398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   VARDECL(spx_sig_t *best_exc);
55498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   VARDECL(spx_word16_t *new_target);
55598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   VARDECL(spx_word16_t *best_target);
55698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int best_pitch=0;
55798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word32_t err, best_err=-1;
55898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int N;
55998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   const ltp_params *params;
56098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   const signed char *gain_cdbk;
56198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int   gain_cdbk_size;
56298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int scaledown=0;
56398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
56498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   VARDECL(int *nbest);
56598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
56698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   params = (const ltp_params*) par;
56798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   gain_cdbk_size = 1<<params->gain_bits;
56898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   gain_cdbk = params->gain_cdbk + 4*gain_cdbk_size*cdbk_offset;
56998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
57098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   N=complexity;
57198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (N>10)
57298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      N=10;
57398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (N<1)
57498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      N=1;
57598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
57698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   ALLOC(nbest, N, int);
57798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   params = (const ltp_params*) par;
57898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
57998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (end<start)
58098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
58198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      speex_bits_pack(bits, 0, params->pitch_bits);
58298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      speex_bits_pack(bits, 0, params->gain_bits);
58398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      SPEEX_MEMSET(exc, 0, nsf);
58498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      return start;
58598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
58698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
58798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT
58898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* Check if we need to scale everything down in the pitch search to avoid overflows */
58998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<nsf;i++)
59098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
59198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (ABS16(target[i])>16383)
59298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
59398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         scaledown=1;
59498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         break;
59598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      }
59698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
59798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=-end;i<nsf;i++)
59898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
59998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (ABS16(exc2[i])>16383)
60098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
60198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         scaledown=1;
60298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         break;
60398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      }
60498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
60598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
60698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (N>end-start+1)
60798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      N=end-start+1;
60898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (end != start)
60998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      open_loop_nbest_pitch(sw, start, end, nsf, nbest, NULL, N, stack);
61098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   else
61198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      nbest[0] = start;
61298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
61398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   ALLOC(best_exc, nsf, spx_sig_t);
61498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   ALLOC(new_target, nsf, spx_word16_t);
61598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   ALLOC(best_target, nsf, spx_word16_t);
61698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
61798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<N;i++)
61898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
61998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      pitch=nbest[i];
62098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      SPEEX_MEMSET(exc, 0, nsf);
62198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      err=pitch_gain_search_3tap(target, ak, awk1, awk2, exc, gain_cdbk, gain_cdbk_size, pitch, p, nsf,
62298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project                                 bits, stack, exc2, r, new_target, &cdbk_index, plc_tuning, *cumul_gain, scaledown);
62398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (err<best_err || best_err<0)
62498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
62598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         SPEEX_COPY(best_exc, exc, nsf);
62698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         SPEEX_COPY(best_target, new_target, nsf);
62798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         best_err=err;
62898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         best_pitch=pitch;
62998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         best_gain_index=cdbk_index;
63098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      }
63198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
63298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /*printf ("pitch: %d %d\n", best_pitch, best_gain_index);*/
63398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_bits_pack(bits, best_pitch-start, params->pitch_bits);
63498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_bits_pack(bits, best_gain_index, params->gain_bits);
63598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT
63698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   *cumul_gain = MULT16_32_Q13(SHL16(params->gain_cdbk[4*best_gain_index+3],8), MAX32(1024,*cumul_gain));
63798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else
63898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   *cumul_gain = 0.03125*MAX32(1024,*cumul_gain)*params->gain_cdbk[4*best_gain_index+3];
63998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
64098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /*printf ("%f\n", cumul_gain);*/
64198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /*printf ("encode pitch: %d %d\n", best_pitch, best_gain_index);*/
64298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   SPEEX_COPY(exc, best_exc, nsf);
64398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   SPEEX_COPY(target, best_target, nsf);
64498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT
64598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* Scale target back up if needed */
64698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (scaledown)
64798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
64898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (i=0;i<nsf;i++)
64998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         target[i]=SHL16(target[i],1);
65098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
65198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
65298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   return pitch;
65398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
65498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
65598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectvoid pitch_unquant_3tap(
65698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_word16_t exc[],             /* Input excitation */
65798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_word32_t exc_out[],         /* Output excitation */
65898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint   start,                    /* Smallest pitch value allowed */
65998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint   end,                      /* Largest pitch value allowed */
66098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_word16_t pitch_coef,        /* Voicing (pitch) coefficient */
66198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectconst void *par,
66298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint   nsf,                      /* Number of samples in subframe */
66398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint *pitch_val,
66498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_word16_t *gain_val,
66598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectSpeexBits *bits,
66698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectchar *stack,
66798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint count_lost,
66898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint subframe_offset,
66998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_word16_t last_pitch_gain,
67098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint cdbk_offset
67198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project)
67298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
67398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int i;
67498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int pitch;
67598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int gain_index;
67698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_word16_t gain[3];
67798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   const signed char *gain_cdbk;
67898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int gain_cdbk_size;
67998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   const ltp_params *params;
68098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
68198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   params = (const ltp_params*) par;
68298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   gain_cdbk_size = 1<<params->gain_bits;
68398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   gain_cdbk = params->gain_cdbk + 4*gain_cdbk_size*cdbk_offset;
68498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
68598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   pitch = speex_bits_unpack_unsigned(bits, params->pitch_bits);
68698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   pitch += start;
68798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   gain_index = speex_bits_unpack_unsigned(bits, params->gain_bits);
68898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /*printf ("decode pitch: %d %d\n", pitch, gain_index);*/
68998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT
69098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   gain[0] = ADD16(32,(spx_word16_t)gain_cdbk[gain_index*4]);
69198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   gain[1] = ADD16(32,(spx_word16_t)gain_cdbk[gain_index*4+1]);
69298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   gain[2] = ADD16(32,(spx_word16_t)gain_cdbk[gain_index*4+2]);
69398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else
69498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   gain[0] = 0.015625*gain_cdbk[gain_index*4]+.5;
69598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   gain[1] = 0.015625*gain_cdbk[gain_index*4+1]+.5;
69698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   gain[2] = 0.015625*gain_cdbk[gain_index*4+2]+.5;
69798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
69898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
69998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (count_lost && pitch > subframe_offset)
70098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
70198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      spx_word16_t gain_sum;
70298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (1) {
70398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT
70498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         spx_word16_t tmp = count_lost < 4 ? last_pitch_gain : SHR16(last_pitch_gain,1);
70598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         if (tmp>62)
70698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project            tmp=62;
70798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else
70898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         spx_word16_t tmp = count_lost < 4 ? last_pitch_gain : 0.5 * last_pitch_gain;
70998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         if (tmp>.95)
71098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project            tmp=.95;
71198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
71298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         gain_sum = gain_3tap_to_1tap(gain);
71398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
71498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         if (gain_sum > tmp)
71598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         {
71698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project            spx_word16_t fact = DIV32_16(SHL32(EXTEND32(tmp),14),gain_sum);
71798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project            for (i=0;i<3;i++)
71898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project               gain[i]=MULT16_16_Q14(fact,gain[i]);
71998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         }
72098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
72198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      }
72298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
72398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
72498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
72598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   *pitch_val = pitch;
72698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   gain_val[0]=gain[0];
72798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   gain_val[1]=gain[1];
72898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   gain_val[2]=gain[2];
72998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   gain[0] = SHL16(gain[0],7);
73098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   gain[1] = SHL16(gain[1],7);
73198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   gain[2] = SHL16(gain[2],7);
73298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   SPEEX_MEMSET(exc_out, 0, nsf);
73398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<3;i++)
73498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
73598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      int j;
73698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      int tmp1, tmp3;
73798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      int pp=pitch+1-i;
73898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      tmp1=nsf;
73998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (tmp1>pp)
74098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         tmp1=pp;
74198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (j=0;j<tmp1;j++)
74298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         exc_out[j]=MAC16_16(exc_out[j],gain[2-i],exc[j-pp]);
74398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      tmp3=nsf;
74498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (tmp3>pp+pitch)
74598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         tmp3=pp+pitch;
74698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (j=tmp1;j<tmp3;j++)
74798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         exc_out[j]=MAC16_16(exc_out[j],gain[2-i],exc[j-pp-pitch]);
74898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
74998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /*for (i=0;i<nsf;i++)
75098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   exc[i]=PSHR32(exc32[i],13);*/
75198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
75298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
75398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
75498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project/** Forced pitch delay and gain */
75598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint forced_pitch_quant(
75698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_word16_t target[],                 /* Target vector */
75798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_word16_t *sw,
75898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_coef_t ak[],                     /* LPCs for this subframe */
75998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_coef_t awk1[],                   /* Weighted LPCs #1 for this subframe */
76098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_coef_t awk2[],                   /* Weighted LPCs #2 for this subframe */
76198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_sig_t exc[],                    /* Excitation */
76298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectconst void *par,
76398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint   start,                    /* Smallest pitch value allowed */
76498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint   end,                      /* Largest pitch value allowed */
76598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_word16_t pitch_coef,               /* Voicing (pitch) coefficient */
76698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint   p,                        /* Number of LPC coeffs */
76798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint   nsf,                      /* Number of samples in subframe */
76898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectSpeexBits *bits,
76998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectchar *stack,
77098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_word16_t *exc2,
77198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_word16_t *r,
77298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint complexity,
77398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint cdbk_offset,
77498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint plc_tuning,
77598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_word32_t *cumul_gain
77698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project)
77798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
77898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int i;
77998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   VARDECL(spx_word16_t *res);
78098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   ALLOC(res, nsf, spx_word16_t);
78198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT
78298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (pitch_coef>63)
78398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      pitch_coef=63;
78498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else
78598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (pitch_coef>.99)
78698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      pitch_coef=.99;
78798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
78898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<nsf&&i<start;i++)
78998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
79098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      exc[i]=MULT16_16(SHL16(pitch_coef, 7),exc2[i-start]);
79198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
79298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (;i<nsf;i++)
79398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
79498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      exc[i]=MULT16_32_Q15(SHL16(pitch_coef, 9),exc[i-start]);
79598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
79698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<nsf;i++)
79798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      res[i] = EXTRACT16(PSHR32(exc[i], SIG_SHIFT-1));
79898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   syn_percep_zero16(res, ak, awk1, awk2, res, nsf, p, stack);
79998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<nsf;i++)
80098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      target[i]=EXTRACT16(SATURATE(SUB32(EXTEND32(target[i]),EXTEND32(res[i])),32700));
80198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   return start;
80298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
80398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
80498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project/** Unquantize forced pitch delay and gain */
80598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectvoid forced_pitch_unquant(
80698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_word16_t exc[],             /* Input excitation */
80798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_word32_t exc_out[],         /* Output excitation */
80898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint   start,                    /* Smallest pitch value allowed */
80998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint   end,                      /* Largest pitch value allowed */
81098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_word16_t pitch_coef,        /* Voicing (pitch) coefficient */
81198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectconst void *par,
81298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint   nsf,                      /* Number of samples in subframe */
81398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint *pitch_val,
81498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_word16_t *gain_val,
81598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectSpeexBits *bits,
81698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectchar *stack,
81798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint count_lost,
81898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint subframe_offset,
81998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectspx_word16_t last_pitch_gain,
82098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectint cdbk_offset
82198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project)
82298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
82398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int i;
82498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef FIXED_POINT
82598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (pitch_coef>63)
82698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      pitch_coef=63;
82798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else
82898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (pitch_coef>.99)
82998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      pitch_coef=.99;
83098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
83198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<nsf;i++)
83298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
83398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      exc_out[i]=MULT16_16(exc[i-start],SHL16(pitch_coef,7));
83498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      exc[i] = EXTRACT16(PSHR32(exc_out[i],13));
83598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
83698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   *pitch_val = start;
83798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   gain_val[0]=gain_val[2]=0;
83898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   gain_val[1] = pitch_coef;
83998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
840