1
/* Copyright (C) 2006-2008 CSIRO, Jean-Marc Valin, Xiph.Org Foundation
4
Shaped comb-allpass filter for channel decorrelation
6
Redistribution and use in source and binary forms, with or without
7
modification, are permitted provided that the following conditions are
10
1. Redistributions of source code must retain the above copyright notice,
11
this list of conditions and the following disclaimer.
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.
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.
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.
34
The algorithm implemented here is described in:
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
47
#include "speex/speex_echo.h"
48
#include "vorbis_psy.h"
50
#include "os_support.h"
55
#define ALLPASS_ORDER 20
57
struct SpeexDecorrState_ {
63
struct drft_lookup lookup;
71
/* Per-channel stuff */
73
float (*ring)[ALLPASS_ORDER];
81
EXPORT SpeexDecorrState *speex_decorrelate_new(int rate, int channels, int frame_size)
84
SpeexDecorrState *st = speex_alloc(sizeof(SpeexDecorrState));
86
st->channels = channels;
87
st->frame_size = frame_size;
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));
94
st->y = speex_alloc(frame_size*sizeof(float));
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));
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)) );
108
for (ch=0;ch<channels;ch++)
110
for (i=0;i<ALLPASS_ORDER;i++)
119
static float uni_rand(int *seed)
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);
130
static unsigned int irand(int *seed)
132
*seed = 1664525 * *seed + 1013904223;
133
return ((unsigned int)*seed)>>16;
137
EXPORT void speex_decorrelate(SpeexDecorrState *st, const spx_int16_t *in, spx_int16_t *out, int strength)
147
amount = .01*strength;
148
for (ch=0;ch<st->channels;ch++)
151
int N=2*st->frame_size;
162
buff = st->buff+ch*2*st->frame_size;
164
ringID = st->ringID[ch];
165
order = st->order[ch];
166
alpha = st->alpha[ch];
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];
173
x = buff+st->frame_size;
174
beta = 1.-.3*amount*amount;
176
beta = 1-sqrt(.4*amount);
178
beta = 1-0.63246*amount;
183
for (i=0;i<st->frame_size;i++)
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];
194
order = order+(irand(&st->seed)%3)-1;
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);
204
alpha = alpha + .4*uni_rand(&st->seed);
205
if (alpha > max_alpha)
207
if (alpha < -max_alpha)
209
for (i=0;i<ALLPASS_ORDER;i++)
212
for (i=0;i<st->frame_size;i++)
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]);
219
tmp *= st->vorbis_win[i];
228
for (i=0;i<2*st->frame_size;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++)
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;
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];
252
for (i=0;i<st->frame_size;i++)
255
float tmp = st->y[i] + frame[i] + st->wola_mem[i];
256
st->wola_mem[i] = frame[i+st->frame_size];
258
float tmp = st->y[i];
264
out[i*st->channels+ch] = tmp;
267
st->ringID[ch] = ringID;
268
st->order[ch] = order;
269
st->alpha[ch] = alpha;
274
EXPORT void speex_decorrelate_destroy(SpeexDecorrState *st)
277
vorbis_psy_destroy(st->psy);
278
speex_free(st->wola_mem);
279
speex_free(st->curve);
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);