blob: c6abfd22d73967e229b473d262dfe9c0a4e1e5d6 [file] [log] [blame]
The Android Open Source Project98913fe2009-03-15 16:47:32 -07001/* 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/*
34The 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 HandsĀ­free 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#define ALLPASS_ORDER 20
56
57struct SpeexDecorrState_ {
58 int rate;
59 int channels;
60 int frame_size;
61#ifdef VORBIS_PSYCHO
62 VorbisPsy *psy;
63 struct drft_lookup lookup;
64 float *wola_mem;
65 float *curve;
66#endif
67 float *vorbis_win;
68 int seed;
69 float *y;
70
71 /* Per-channel stuff */
72 float *buff;
73 float (*ring)[ALLPASS_ORDER];
74 int *ringID;
75 int *order;
76 float *alpha;
77};
78
79
80
81EXPORT SpeexDecorrState *speex_decorrelate_new(int rate, int channels, int frame_size)
82{
83 int i, ch;
84 SpeexDecorrState *st = speex_alloc(sizeof(SpeexDecorrState));
85 st->rate = rate;
86 st->channels = channels;
87 st->frame_size = frame_size;
88#ifdef VORBIS_PSYCHO
89 st->psy = vorbis_psy_init(rate, 2*frame_size);
90 spx_drft_init(&st->lookup, 2*frame_size);
91 st->wola_mem = speex_alloc(frame_size*sizeof(float));
92 st->curve = speex_alloc(frame_size*sizeof(float));
93#endif
94 st->y = speex_alloc(frame_size*sizeof(float));
95
96 st->buff = speex_alloc(channels*2*frame_size*sizeof(float));
97 st->ringID = speex_alloc(channels*sizeof(int));
98 st->order = speex_alloc(channels*sizeof(int));
99 st->alpha = speex_alloc(channels*sizeof(float));
100 st->ring = speex_alloc(channels*ALLPASS_ORDER*sizeof(float));
101
102 /*FIXME: The +20 is there only as a kludge for ALL_PASS_OLA*/
103 st->vorbis_win = speex_alloc((2*frame_size+20)*sizeof(float));
104 for (i=0;i<2*frame_size;i++)
105 st->vorbis_win[i] = sin(.5*M_PI* sin(M_PI*i/(2*frame_size))*sin(M_PI*i/(2*frame_size)) );
106 st->seed = rand();
107
108 for (ch=0;ch<channels;ch++)
109 {
110 for (i=0;i<ALLPASS_ORDER;i++)
111 st->ring[ch][i] = 0;
112 st->ringID[ch] = 0;
113 st->alpha[ch] = 0;
114 st->order[ch] = 10;
115 }
116 return st;
117}
118
119static float uni_rand(int *seed)
120{
121 const unsigned int jflone = 0x3f800000;
122 const unsigned int jflmsk = 0x007fffff;
123 union {int i; float f;} ran;
124 *seed = 1664525 * *seed + 1013904223;
125 ran.i = jflone | (jflmsk & *seed);
126 ran.f -= 1.5;
127 return 2*ran.f;
128}
129
130static unsigned int irand(int *seed)
131{
132 *seed = 1664525 * *seed + 1013904223;
133 return ((unsigned int)*seed)>>16;
134}
135
136
137EXPORT void speex_decorrelate(SpeexDecorrState *st, const spx_int16_t *in, spx_int16_t *out, int strength)
138{
139 int ch;
140 float amount;
141
142 if (strength<0)
143 strength = 0;
144 if (strength>100)
145 strength = 100;
146
147 amount = .01*strength;
148 for (ch=0;ch<st->channels;ch++)
149 {
150 int i;
151 int N=2*st->frame_size;
152 float beta, beta2;
153 float *x;
154 float max_alpha = 0;
155
156 float *buff;
157 float *ring;
158 int ringID;
159 int order;
160 float alpha;
161
162 buff = st->buff+ch*2*st->frame_size;
163 ring = st->ring[ch];
164 ringID = st->ringID[ch];
165 order = st->order[ch];
166 alpha = st->alpha[ch];
167
168 for (i=0;i<st->frame_size;i++)
169 buff[i] = buff[i+st->frame_size];
170 for (i=0;i<st->frame_size;i++)
171 buff[i+st->frame_size] = in[i*st->channels+ch];
172
173 x = buff+st->frame_size;
174 beta = 1.-.3*amount*amount;
175 if (amount>1)
176 beta = 1-sqrt(.4*amount);
177 else
178 beta = 1-0.63246*amount;
179 if (beta<0)
180 beta = 0;
181
182 beta2 = beta;
183 for (i=0;i<st->frame_size;i++)
184 {
185 st->y[i] = alpha*(x[i-ALLPASS_ORDER+order]-beta*x[i-ALLPASS_ORDER+order-1])*st->vorbis_win[st->frame_size+i+order]
186 + x[i-ALLPASS_ORDER]*st->vorbis_win[st->frame_size+i]
187 - alpha*(ring[ringID]
188 - beta*ring[ringID+1>=order?0:ringID+1]);
189 ring[ringID++]=st->y[i];
190 st->y[i] *= st->vorbis_win[st->frame_size+i];
191 if (ringID>=order)
192 ringID=0;
193 }
194 order = order+(irand(&st->seed)%3)-1;
195 if (order < 5)
196 order = 5;
197 if (order > 10)
198 order = 10;
199 /*order = 5+(irand(&st->seed)%6);*/
200 max_alpha = pow(.96+.04*(amount-1),order);
201 if (max_alpha > .98/(1.+beta2))
202 max_alpha = .98/(1.+beta2);
203
204 alpha = alpha + .4*uni_rand(&st->seed);
205 if (alpha > max_alpha)
206 alpha = max_alpha;
207 if (alpha < -max_alpha)
208 alpha = -max_alpha;
209 for (i=0;i<ALLPASS_ORDER;i++)
210 ring[i] = 0;
211 ringID = 0;
212 for (i=0;i<st->frame_size;i++)
213 {
214 float tmp = alpha*(x[i-ALLPASS_ORDER+order]-beta*x[i-ALLPASS_ORDER+order-1])*st->vorbis_win[i+order]
215 + x[i-ALLPASS_ORDER]*st->vorbis_win[i]
216 - alpha*(ring[ringID]
217 - beta*ring[ringID+1>=order?0:ringID+1]);
218 ring[ringID++]=tmp;
219 tmp *= st->vorbis_win[i];
220 if (ringID>=order)
221 ringID=0;
222 st->y[i] += tmp;
223 }
224
225#ifdef VORBIS_PSYCHO
226 float frame[N];
227 float scale = 1./N;
228 for (i=0;i<2*st->frame_size;i++)
229 frame[i] = buff[i];
230 //float coef = .5*0.78130;
231 float coef = M_PI*0.075063 * 0.93763 * amount * .8 * 0.707;
232 compute_curve(st->psy, buff, st->curve);
233 for (i=1;i<st->frame_size;i++)
234 {
235 float x1,x2;
236 float gain;
237 do {
238 x1 = uni_rand(&st->seed);
239 x2 = uni_rand(&st->seed);
240 } while (x1*x1+x2*x2 > 1.);
241 gain = coef*sqrt(.1+st->curve[i]);
242 frame[2*i-1] = gain*x1;
243 frame[2*i] = gain*x2;
244 }
245 frame[0] = coef*uni_rand(&st->seed)*sqrt(.1+st->curve[0]);
246 frame[2*st->frame_size-1] = coef*uni_rand(&st->seed)*sqrt(.1+st->curve[st->frame_size-1]);
247 spx_drft_backward(&st->lookup,frame);
248 for (i=0;i<2*st->frame_size;i++)
249 frame[i] *= st->vorbis_win[i];
250#endif
251
252 for (i=0;i<st->frame_size;i++)
253 {
254#ifdef VORBIS_PSYCHO
255 float tmp = st->y[i] + frame[i] + st->wola_mem[i];
256 st->wola_mem[i] = frame[i+st->frame_size];
257#else
258 float tmp = st->y[i];
259#endif
260 if (tmp>32767)
261 tmp = 32767;
262 if (tmp < -32767)
263 tmp = -32767;
264 out[i*st->channels+ch] = tmp;
265 }
266
267 st->ringID[ch] = ringID;
268 st->order[ch] = order;
269 st->alpha[ch] = alpha;
270
271 }
272}
273
274EXPORT void speex_decorrelate_destroy(SpeexDecorrState *st)
275{
276#ifdef VORBIS_PSYCHO
277 vorbis_psy_destroy(st->psy);
278 speex_free(st->wola_mem);
279 speex_free(st->curve);
280#endif
281 speex_free(st->buff);
282 speex_free(st->ring);
283 speex_free(st->ringID);
284 speex_free(st->alpha);
285 speex_free(st->vorbis_win);
286 speex_free(st->order);
287 speex_free(st->y);
288 speex_free(st);
289}