198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project/* Copyright (C) 2006-2008 CSIRO, Jean-Marc Valin, Xiph.Org Foundation
298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   File: scal.c
498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   Shaped comb-allpass filter for channel decorrelation
598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   Redistribution and use in source and binary forms, with or without
798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   modification, are permitted provided that the following conditions are
898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   met:
998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
1098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   1. Redistributions of source code must retain the above copyright notice,
1198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   this list of conditions and the following disclaimer.
1298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
1398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   2. Redistributions in binary form must reproduce the above copyright
1498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   notice, this list of conditions and the following disclaimer in the
1598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   documentation and/or other materials provided with the distribution.
1698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
1798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   3. The name of the author may not be used to endorse or promote products
1898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   derived from this software without specific prior written permission.
1998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
2098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
2498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
2898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
2998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   POSSIBILITY OF SUCH DAMAGE.
3198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project*/
3298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
3398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project/*
3498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectThe algorithm implemented here is described in:
3598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
3698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project* J.-M. Valin, Perceptually-Motivated Nonlinear Channel Decorrelation For
3798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project  Stereo Acoustic Echo Cancellation, Accepted for Joint Workshop on
3898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project  Hands­free Speech Communication and Microphone Arrays (HSCMA), 2008.
3998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project  http://people.xiph.org/~jm/papers/valin_hscma2008.pdf
4098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
4198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project*/
4298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
4398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef HAVE_CONFIG_H
4498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "config.h"
4598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
4698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
4798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "speex/speex_echo.h"
4898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "vorbis_psy.h"
4998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "arch.h"
5098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "os_support.h"
5198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include "smallft.h"
5298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include <math.h>
5398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#include <stdlib.h>
5498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
5598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#define ALLPASS_ORDER 20
5698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
5798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstruct SpeexDecorrState_ {
5898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int rate;
5998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int channels;
6098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int frame_size;
6198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef VORBIS_PSYCHO
6298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   VorbisPsy *psy;
6398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   struct drft_lookup lookup;
6498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   float *wola_mem;
6598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   float *curve;
6698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
6798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   float *vorbis_win;
6898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int    seed;
6998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   float *y;
7098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
7198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /* Per-channel stuff */
7298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   float *buff;
7398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   float (*ring)[ALLPASS_ORDER];
7498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int *ringID;
7598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int *order;
7698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   float *alpha;
7798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project};
7898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
7998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
8098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
8198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT SpeexDecorrState *speex_decorrelate_new(int rate, int channels, int frame_size)
8298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
8398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int i, ch;
8498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   SpeexDecorrState *st = speex_alloc(sizeof(SpeexDecorrState));
8598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->rate = rate;
8698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->channels = channels;
8798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->frame_size = frame_size;
8898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef VORBIS_PSYCHO
8998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->psy = vorbis_psy_init(rate, 2*frame_size);
9098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   spx_drft_init(&st->lookup, 2*frame_size);
9198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->wola_mem = speex_alloc(frame_size*sizeof(float));
9298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->curve = speex_alloc(frame_size*sizeof(float));
9398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
9498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->y = speex_alloc(frame_size*sizeof(float));
9598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
9698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->buff = speex_alloc(channels*2*frame_size*sizeof(float));
9798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->ringID = speex_alloc(channels*sizeof(int));
9898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->order = speex_alloc(channels*sizeof(int));
9998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->alpha = speex_alloc(channels*sizeof(float));
10098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->ring = speex_alloc(channels*ALLPASS_ORDER*sizeof(float));
10198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
10298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   /*FIXME: The +20 is there only as a kludge for ALL_PASS_OLA*/
10398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->vorbis_win = speex_alloc((2*frame_size+20)*sizeof(float));
10498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (i=0;i<2*frame_size;i++)
10598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->vorbis_win[i] = sin(.5*M_PI* sin(M_PI*i/(2*frame_size))*sin(M_PI*i/(2*frame_size)) );
10698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   st->seed = rand();
10798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
10898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (ch=0;ch<channels;ch++)
10998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
11098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (i=0;i<ALLPASS_ORDER;i++)
11198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->ring[ch][i] = 0;
11298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->ringID[ch] = 0;
11398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->alpha[ch] = 0;
11498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->order[ch] = 10;
11598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
11698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   return st;
11798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
11898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
11998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic float uni_rand(int *seed)
12098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
12198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   const unsigned int jflone = 0x3f800000;
12298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   const unsigned int jflmsk = 0x007fffff;
12398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   union {int i; float f;} ran;
12498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   *seed = 1664525 * *seed + 1013904223;
12598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   ran.i = jflone | (jflmsk & *seed);
12698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   ran.f -= 1.5;
12798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   return 2*ran.f;
12898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
12998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
13098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Projectstatic unsigned int irand(int *seed)
13198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
13298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   *seed = 1664525 * *seed + 1013904223;
13398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   return ((unsigned int)*seed)>>16;
13498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
13598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
13698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
13798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT void speex_decorrelate(SpeexDecorrState *st, const spx_int16_t *in, spx_int16_t *out, int strength)
13898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
13998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   int ch;
14098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   float amount;
14198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
14298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (strength<0)
14398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      strength = 0;
14498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   if (strength>100)
14598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      strength = 100;
14698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
14798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   amount = .01*strength;
14898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   for (ch=0;ch<st->channels;ch++)
14998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   {
15098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      int i;
15198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      int N=2*st->frame_size;
15298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      float beta, beta2;
15398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      float *x;
15498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      float max_alpha = 0;
15598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
15698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      float *buff;
15798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      float *ring;
15898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      int ringID;
15998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      int order;
16098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      float alpha;
16198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
16298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      buff = st->buff+ch*2*st->frame_size;
16398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      ring = st->ring[ch];
16498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      ringID = st->ringID[ch];
16598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      order = st->order[ch];
16698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      alpha = st->alpha[ch];
16798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
16898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (i=0;i<st->frame_size;i++)
16998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         buff[i] = buff[i+st->frame_size];
17098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (i=0;i<st->frame_size;i++)
17198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         buff[i+st->frame_size] = in[i*st->channels+ch];
17298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
17398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      x = buff+st->frame_size;
17498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      beta = 1.-.3*amount*amount;
17598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (amount>1)
17698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         beta = 1-sqrt(.4*amount);
17798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      else
17898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         beta = 1-0.63246*amount;
17998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (beta<0)
18098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         beta = 0;
18198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
18298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      beta2 = beta;
18398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (i=0;i<st->frame_size;i++)
18498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
18598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->y[i] = alpha*(x[i-ALLPASS_ORDER+order]-beta*x[i-ALLPASS_ORDER+order-1])*st->vorbis_win[st->frame_size+i+order]
18698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project               + x[i-ALLPASS_ORDER]*st->vorbis_win[st->frame_size+i]
18798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project               - alpha*(ring[ringID]
18898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project               - beta*ring[ringID+1>=order?0:ringID+1]);
18998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         ring[ringID++]=st->y[i];
19098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->y[i] *= st->vorbis_win[st->frame_size+i];
19198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         if (ringID>=order)
19298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project            ringID=0;
19398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      }
19498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      order = order+(irand(&st->seed)%3)-1;
19598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (order < 5)
19698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         order = 5;
19798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (order > 10)
19898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         order = 10;
19998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      /*order = 5+(irand(&st->seed)%6);*/
20098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      max_alpha = pow(.96+.04*(amount-1),order);
20198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (max_alpha > .98/(1.+beta2))
20298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         max_alpha = .98/(1.+beta2);
20398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
20498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      alpha = alpha + .4*uni_rand(&st->seed);
20598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (alpha > max_alpha)
20698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         alpha = max_alpha;
20798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      if (alpha < -max_alpha)
20898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         alpha = -max_alpha;
20998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (i=0;i<ALLPASS_ORDER;i++)
21098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         ring[i] = 0;
21198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      ringID = 0;
21298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (i=0;i<st->frame_size;i++)
21398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
21498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         float tmp =  alpha*(x[i-ALLPASS_ORDER+order]-beta*x[i-ALLPASS_ORDER+order-1])*st->vorbis_win[i+order]
21598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project               + x[i-ALLPASS_ORDER]*st->vorbis_win[i]
21698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project               - alpha*(ring[ringID]
21798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project               - beta*ring[ringID+1>=order?0:ringID+1]);
21898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         ring[ringID++]=tmp;
21998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         tmp *= st->vorbis_win[i];
22098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         if (ringID>=order)
22198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project            ringID=0;
22298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->y[i] += tmp;
22398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      }
22498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
22598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef VORBIS_PSYCHO
22698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      float frame[N];
22798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      float scale = 1./N;
22898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (i=0;i<2*st->frame_size;i++)
22998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         frame[i] = buff[i];
23098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   //float coef = .5*0.78130;
23198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      float coef = M_PI*0.075063 * 0.93763 * amount * .8 * 0.707;
23298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      compute_curve(st->psy, buff, st->curve);
23398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (i=1;i<st->frame_size;i++)
23498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
23598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         float x1,x2;
23698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         float gain;
23798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         do {
23898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project            x1 = uni_rand(&st->seed);
23998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project            x2 = uni_rand(&st->seed);
24098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         } while (x1*x1+x2*x2 > 1.);
24198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         gain = coef*sqrt(.1+st->curve[i]);
24298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         frame[2*i-1] = gain*x1;
24398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         frame[2*i] = gain*x2;
24498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      }
24598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      frame[0] = coef*uni_rand(&st->seed)*sqrt(.1+st->curve[0]);
24698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      frame[2*st->frame_size-1] = coef*uni_rand(&st->seed)*sqrt(.1+st->curve[st->frame_size-1]);
24798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      spx_drft_backward(&st->lookup,frame);
24898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (i=0;i<2*st->frame_size;i++)
24998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         frame[i] *= st->vorbis_win[i];
25098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
25198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
25298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      for (i=0;i<st->frame_size;i++)
25398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      {
25498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef VORBIS_PSYCHO
25598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         float tmp = st->y[i] + frame[i] + st->wola_mem[i];
25698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         st->wola_mem[i] = frame[i+st->frame_size];
25798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#else
25898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         float tmp = st->y[i];
25998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
26098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         if (tmp>32767)
26198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project            tmp = 32767;
26298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         if (tmp < -32767)
26398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project            tmp = -32767;
26498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project         out[i*st->channels+ch] = tmp;
26598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      }
26698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
26798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->ringID[ch] = ringID;
26898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->order[ch] = order;
26998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project      st->alpha[ch] = alpha;
27098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
27198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   }
27298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
27398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project
27498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source ProjectEXPORT void speex_decorrelate_destroy(SpeexDecorrState *st)
27598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project{
27698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#ifdef VORBIS_PSYCHO
27798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   vorbis_psy_destroy(st->psy);
27898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_free(st->wola_mem);
27998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_free(st->curve);
28098913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project#endif
28198913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_free(st->buff);
28298913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_free(st->ring);
28398913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_free(st->ringID);
28498913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_free(st->alpha);
28598913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_free(st->vorbis_win);
28698913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_free(st->order);
28798913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_free(st->y);
28898913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project   speex_free(st);
28998913fed6520d8849fb2e246be943e04474aefaThe Android Open Source Project}
290