Home | History | Annotate | Download | only in libspeexdsp
      1 /* Copyright (C) 2006-2008 CSIRO, Jean-Marc Valin, Xiph.Org Foundation
      2 
      3    File: scal.c
      4    Shaped comb-allpass filter for channel decorrelation
      5 
      6    Redistribution and use in source and binary forms, with or without
      7    modification, are permitted provided that the following conditions are
      8    met:
      9 
     10    1. Redistributions of source code must retain the above copyright notice,
     11    this list of conditions and the following disclaimer.
     12 
     13    2. Redistributions in binary form must reproduce the above copyright
     14    notice, this list of conditions and the following disclaimer in the
     15    documentation and/or other materials provided with the distribution.
     16 
     17    3. The name of the author may not be used to endorse or promote products
     18    derived from this software without specific prior written permission.
     19 
     20    THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     21    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     22    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     23    DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
     24    INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     25    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     26    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     27    HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     28    STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
     29    ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     30    POSSIBILITY OF SUCH DAMAGE.
     31 */
     32 
     33 /*
     34 The algorithm implemented here is described in:
     35 
     36 * J.-M. Valin, Perceptually-Motivated Nonlinear Channel Decorrelation For
     37   Stereo Acoustic Echo Cancellation, Accepted for Joint Workshop on
     38   Handsfree Speech Communication and Microphone Arrays (HSCMA), 2008.
     39   http://people.xiph.org/~jm/papers/valin_hscma2008.pdf
     40 
     41 */
     42 
     43 #ifdef HAVE_CONFIG_H
     44 #include "config.h"
     45 #endif
     46 
     47 #include "speex/speex_echo.h"
     48 #include "vorbis_psy.h"
     49 #include "arch.h"
     50 #include "os_support.h"
     51 #include "smallft.h"
     52 #include <math.h>
     53 #include <stdlib.h>
     54 
     55 #ifndef M_PI
     56 #define M_PI           3.14159265358979323846  /* pi */
     57 #endif
     58 
     59 #define ALLPASS_ORDER 20
     60 
     61 struct SpeexDecorrState_ {
     62    int rate;
     63    int channels;
     64    int frame_size;
     65 #ifdef VORBIS_PSYCHO
     66    VorbisPsy *psy;
     67    struct drft_lookup lookup;
     68    float *wola_mem;
     69    float *curve;
     70 #endif
     71    float *vorbis_win;
     72    int    seed;
     73    float *y;
     74 
     75    /* Per-channel stuff */
     76    float *buff;
     77    float (*ring)[ALLPASS_ORDER];
     78    int *ringID;
     79    int *order;
     80    float *alpha;
     81 };
     82 
     83 
     84 
     85 EXPORT SpeexDecorrState *speex_decorrelate_new(int rate, int channels, int frame_size)
     86 {
     87    int i, ch;
     88    SpeexDecorrState *st = speex_alloc(sizeof(SpeexDecorrState));
     89    st->rate = rate;
     90    st->channels = channels;
     91    st->frame_size = frame_size;
     92 #ifdef VORBIS_PSYCHO
     93    st->psy = vorbis_psy_init(rate, 2*frame_size);
     94    spx_drft_init(&st->lookup, 2*frame_size);
     95    st->wola_mem = speex_alloc(frame_size*sizeof(float));
     96    st->curve = speex_alloc(frame_size*sizeof(float));
     97 #endif
     98    st->y = speex_alloc(frame_size*sizeof(float));
     99 
    100    st->buff = speex_alloc(channels*2*frame_size*sizeof(float));
    101    st->ringID = speex_alloc(channels*sizeof(int));
    102    st->order = speex_alloc(channels*sizeof(int));
    103    st->alpha = speex_alloc(channels*sizeof(float));
    104    st->ring = speex_alloc(channels*ALLPASS_ORDER*sizeof(float));
    105 
    106    /*FIXME: The +20 is there only as a kludge for ALL_PASS_OLA*/
    107    st->vorbis_win = speex_alloc((2*frame_size+20)*sizeof(float));
    108    for (i=0;i<2*frame_size;i++)
    109       st->vorbis_win[i] = sin(.5*M_PI* sin(M_PI*i/(2*frame_size))*sin(M_PI*i/(2*frame_size)) );
    110    st->seed = rand();
    111 
    112    for (ch=0;ch<channels;ch++)
    113    {
    114       for (i=0;i<ALLPASS_ORDER;i++)
    115          st->ring[ch][i] = 0;
    116       st->ringID[ch] = 0;
    117       st->alpha[ch] = 0;
    118       st->order[ch] = 10;
    119    }
    120    return st;
    121 }
    122 
    123 static float uni_rand(int *seed)
    124 {
    125    const unsigned int jflone = 0x3f800000;
    126    const unsigned int jflmsk = 0x007fffff;
    127    union {int i; float f;} ran;
    128    *seed = 1664525 * *seed + 1013904223;
    129    ran.i = jflone | (jflmsk & *seed);
    130    ran.f -= 1.5;
    131    return 2*ran.f;
    132 }
    133 
    134 static unsigned int irand(int *seed)
    135 {
    136    *seed = 1664525 * *seed + 1013904223;
    137    return ((unsigned int)*seed)>>16;
    138 }
    139 
    140 
    141 EXPORT void speex_decorrelate(SpeexDecorrState *st, const spx_int16_t *in, spx_int16_t *out, int strength)
    142 {
    143    int ch;
    144    float amount;
    145 
    146    if (strength<0)
    147       strength = 0;
    148    if (strength>100)
    149       strength = 100;
    150 
    151    amount = .01*strength;
    152    for (ch=0;ch<st->channels;ch++)
    153    {
    154       int i;
    155       int N=2*st->frame_size;
    156       float beta, beta2;
    157       float *x;
    158       float max_alpha = 0;
    159 
    160       float *buff;
    161       float *ring;
    162       int ringID;
    163       int order;
    164       float alpha;
    165 
    166       buff = st->buff+ch*2*st->frame_size;
    167       ring = st->ring[ch];
    168       ringID = st->ringID[ch];
    169       order = st->order[ch];
    170       alpha = st->alpha[ch];
    171 
    172       for (i=0;i<st->frame_size;i++)
    173          buff[i] = buff[i+st->frame_size];
    174       for (i=0;i<st->frame_size;i++)
    175          buff[i+st->frame_size] = in[i*st->channels+ch];
    176 
    177       x = buff+st->frame_size;
    178 
    179       if (amount>1)
    180          beta = 1-sqrt(.4*amount);
    181       else
    182          beta = 1-0.63246*amount;
    183       if (beta<0)
    184          beta = 0;
    185 
    186       beta2 = beta;
    187       for (i=0;i<st->frame_size;i++)
    188       {
    189          st->y[i] = alpha*(x[i-ALLPASS_ORDER+order]-beta*x[i-ALLPASS_ORDER+order-1])*st->vorbis_win[st->frame_size+i+order]
    190                + x[i-ALLPASS_ORDER]*st->vorbis_win[st->frame_size+i]
    191                - alpha*(ring[ringID]
    192                - beta*ring[ringID+1>=order?0:ringID+1]);
    193          ring[ringID++]=st->y[i];
    194          st->y[i] *= st->vorbis_win[st->frame_size+i];
    195          if (ringID>=order)
    196             ringID=0;
    197       }
    198       order = order+(irand(&st->seed)%3)-1;
    199       if (order < 5)
    200          order = 5;
    201       if (order > 10)
    202          order = 10;
    203       /*order = 5+(irand(&st->seed)%6);*/
    204       max_alpha = pow(.96+.04*(amount-1),order);
    205       if (max_alpha > .98/(1.+beta2))
    206          max_alpha = .98/(1.+beta2);
    207 
    208       alpha = alpha + .4*uni_rand(&st->seed);
    209       if (alpha > max_alpha)
    210          alpha = max_alpha;
    211       if (alpha < -max_alpha)
    212          alpha = -max_alpha;
    213       for (i=0;i<ALLPASS_ORDER;i++)
    214          ring[i] = 0;
    215       ringID = 0;
    216       for (i=0;i<st->frame_size;i++)
    217       {
    218          float tmp =  alpha*(x[i-ALLPASS_ORDER+order]-beta*x[i-ALLPASS_ORDER+order-1])*st->vorbis_win[i+order]
    219                + x[i-ALLPASS_ORDER]*st->vorbis_win[i]
    220                - alpha*(ring[ringID]
    221                - beta*ring[ringID+1>=order?0:ringID+1]);
    222          ring[ringID++]=tmp;
    223          tmp *= st->vorbis_win[i];
    224          if (ringID>=order)
    225             ringID=0;
    226          st->y[i] += tmp;
    227       }
    228 
    229 #ifdef VORBIS_PSYCHO
    230       float frame[N];
    231       float scale = 1./N;
    232       for (i=0;i<2*st->frame_size;i++)
    233          frame[i] = buff[i];
    234    //float coef = .5*0.78130;
    235       float coef = M_PI*0.075063 * 0.93763 * amount * .8 * 0.707;
    236       compute_curve(st->psy, buff, st->curve);
    237       for (i=1;i<st->frame_size;i++)
    238       {
    239          float x1,x2;
    240          float gain;
    241          do {
    242             x1 = uni_rand(&st->seed);
    243             x2 = uni_rand(&st->seed);
    244          } while (x1*x1+x2*x2 > 1.);
    245          gain = coef*sqrt(.1+st->curve[i]);
    246          frame[2*i-1] = gain*x1;
    247          frame[2*i] = gain*x2;
    248       }
    249       frame[0] = coef*uni_rand(&st->seed)*sqrt(.1+st->curve[0]);
    250       frame[2*st->frame_size-1] = coef*uni_rand(&st->seed)*sqrt(.1+st->curve[st->frame_size-1]);
    251       spx_drft_backward(&st->lookup,frame);
    252       for (i=0;i<2*st->frame_size;i++)
    253          frame[i] *= st->vorbis_win[i];
    254 #endif
    255 
    256       for (i=0;i<st->frame_size;i++)
    257       {
    258 #ifdef VORBIS_PSYCHO
    259          float tmp = st->y[i] + frame[i] + st->wola_mem[i];
    260          st->wola_mem[i] = frame[i+st->frame_size];
    261 #else
    262          float tmp = st->y[i];
    263 #endif
    264          if (tmp>32767)
    265             tmp = 32767;
    266          if (tmp < -32767)
    267             tmp = -32767;
    268          out[i*st->channels+ch] = tmp;
    269       }
    270 
    271       st->ringID[ch] = ringID;
    272       st->order[ch] = order;
    273       st->alpha[ch] = alpha;
    274 
    275    }
    276 }
    277 
    278 EXPORT void speex_decorrelate_destroy(SpeexDecorrState *st)
    279 {
    280 #ifdef VORBIS_PSYCHO
    281    vorbis_psy_destroy(st->psy);
    282    speex_free(st->wola_mem);
    283    speex_free(st->curve);
    284 #endif
    285    speex_free(st->buff);
    286    speex_free(st->ring);
    287    speex_free(st->ringID);
    288    speex_free(st->alpha);
    289    speex_free(st->vorbis_win);
    290    speex_free(st->order);
    291    speex_free(st->y);
    292    speex_free(st);
    293 }
    294