blob: fa29d626eaf661acab399b674424a29c792425c5 [file] [log] [blame]
Jean-Marc Valin6c3788c2010-06-20 22:48:50 -04001/* Copyright (c) 2009-2010 Xiph.Org Foundation
2 Written by Jean-Marc Valin */
3/*
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
Jean-Marc Valine14fe902009-12-11 00:07:31 -05007
Jean-Marc Valin6c3788c2010-06-20 22:48:50 -04008 - Redistributions of source code must retain the above copyright
9 notice, this list of conditions and the following disclaimer.
10
11 - Redistributions in binary form must reproduce the above copyright
12 notice, this list of conditions and the following disclaimer in the
13 documentation and/or other materials provided with the distribution.
14
Jean-Marc Valin6c3788c2010-06-20 22:48:50 -040015 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Jean-Marc Valincb05e7c2012-04-20 16:40:24 -040018 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
19 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
Jean-Marc Valin6c3788c2010-06-20 22:48:50 -040020 EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*/
27
28#ifdef HAVE_CONFIG_H
29#include "config.h"
Jean-Marc Valind69c1cb2009-12-28 00:34:29 -050030#endif
Jean-Marc Valine14fe902009-12-11 00:07:31 -050031
Jean-Marc Valin2779df72011-10-04 13:26:53 -040032#include "celt_lpc.h"
Jean-Marc Valin6c3788c2010-06-20 22:48:50 -040033#include "stack_alloc.h"
34#include "mathops.h"
Jean-Marc Valine8e57a32013-05-25 02:14:25 -040035#include "pitch.h"
Jean-Marc Valin3a9699e2010-06-17 00:35:26 -040036
Jean-Marc Valin7b7f0712010-06-17 20:10:02 -040037void _celt_lpc(
Jean-Marc Valinff5f7222011-07-29 18:59:12 -040038 opus_val16 *_lpc, /* out: [0...p-1] LPC coefficients */
39const opus_val32 *ac, /* in: [0...p] autocorrelation values */
Jean-Marc Valine14fe902009-12-11 00:07:31 -050040int p
41)
42{
Gregory Maxwell71d39ad2011-07-30 00:00:29 -040043 int i, j;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -040044 opus_val32 r;
45 opus_val32 error = ac[0];
Jean-Marc Valin74128be2010-01-01 09:33:17 -050046#ifdef FIXED_POINT
Jean-Marc Valinff5f7222011-07-29 18:59:12 -040047 opus_val32 lpc[LPC_ORDER];
Jean-Marc Valin74128be2010-01-01 09:33:17 -050048#else
49 float *lpc = _lpc;
50#endif
Jean-Marc Valine14fe902009-12-11 00:07:31 -050051
Jean-Marc Valin456eab22010-06-16 22:38:57 -040052 for (i = 0; i < p; i++)
53 lpc[i] = 0;
54 if (ac[0] != 0)
Jean-Marc Valine14fe902009-12-11 00:07:31 -050055 {
Jean-Marc Valin456eab22010-06-16 22:38:57 -040056 for (i = 0; i < p; i++) {
57 /* Sum up this iteration's reflection coefficient */
Jean-Marc Valinff5f7222011-07-29 18:59:12 -040058 opus_val32 rr = 0;
Jean-Marc Valin456eab22010-06-16 22:38:57 -040059 for (j = 0; j < i; j++)
60 rr += MULT32_32_Q31(lpc[j],ac[i - j]);
61 rr += SHR32(ac[i + 1],3);
Jean-Marc Valinbd82ca82010-06-17 00:11:54 -040062 r = -frac_div32(SHL32(rr,3), error);
Jean-Marc Valin456eab22010-06-16 22:38:57 -040063 /* Update LPC coefficients and total error */
64 lpc[i] = SHR32(r,3);
65 for (j = 0; j < (i+1)>>1; j++)
66 {
Jean-Marc Valinff5f7222011-07-29 18:59:12 -040067 opus_val32 tmp1, tmp2;
Jean-Marc Valin456eab22010-06-16 22:38:57 -040068 tmp1 = lpc[j];
69 tmp2 = lpc[i-1-j];
70 lpc[j] = tmp1 + MULT32_32_Q31(r,tmp2);
71 lpc[i-1-j] = tmp2 + MULT32_32_Q31(r,tmp1);
72 }
73
74 error = error - MULT32_32_Q31(MULT32_32_Q31(r,r),error);
Jean-Marc Valinbd82ca82010-06-17 00:11:54 -040075 /* Bail out once we get 30 dB gain */
76#ifdef FIXED_POINT
77 if (error<SHR32(ac[0],10))
Jean-Marc Valin456eab22010-06-16 22:38:57 -040078 break;
Jean-Marc Valinbd82ca82010-06-17 00:11:54 -040079#else
Gregory Maxwell60c316b2010-11-04 20:14:19 -040080 if (error<.001f*ac[0])
Jean-Marc Valinbd82ca82010-06-17 00:11:54 -040081 break;
82#endif
Jean-Marc Valine14fe902009-12-11 00:07:31 -050083 }
Jean-Marc Valine14fe902009-12-11 00:07:31 -050084 }
Jean-Marc Valin303b3b62009-12-30 22:40:24 -050085#ifdef FIXED_POINT
86 for (i=0;i<p;i++)
Jean-Marc Valin456eab22010-06-16 22:38:57 -040087 _lpc[i] = ROUND16(lpc[i],16);
Jean-Marc Valin303b3b62009-12-30 22:40:24 -050088#endif
Jean-Marc Valine14fe902009-12-11 00:07:31 -050089}
90
Jean-Marc Valine2374a82013-05-25 04:25:54 -040091void celt_fir(const opus_val16 *_x,
Jean-Marc Valinff5f7222011-07-29 18:59:12 -040092 const opus_val16 *num,
Jean-Marc Valine2374a82013-05-25 04:25:54 -040093 opus_val16 *_y,
Jean-Marc Valine14fe902009-12-11 00:07:31 -050094 int N,
95 int ord,
Jean-Marc Valinff5f7222011-07-29 18:59:12 -040096 opus_val16 *mem)
Jean-Marc Valine14fe902009-12-11 00:07:31 -050097{
98 int i,j;
Jean-Marc Valine2374a82013-05-25 04:25:54 -040099 VARDECL(opus_val16, rnum);
100 VARDECL(opus_val16, x);
101 SAVE_STACK;
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500102
Jean-Marc Valine2374a82013-05-25 04:25:54 -0400103 ALLOC(rnum, ord, opus_val16);
104 ALLOC(x, N+ord, opus_val16);
105 for(i=0;i<ord;i++)
106 rnum[i] = num[ord-i-1];
107 for(i=0;i<ord;i++)
108 x[i] = mem[ord-i-1];
109 for (i=0;i<N;i++)
110 x[i+ord]=_x[i];
111 for(i=0;i<ord;i++)
112 mem[i] = _x[N-i-1];
113#ifdef SMALL_FOOTPRINT
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500114 for (i=0;i<N;i++)
115 {
Jean-Marc Valine2374a82013-05-25 04:25:54 -0400116 opus_val32 sum = SHL32(EXTEND32(_x[i]), SIG_SHIFT);
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500117 for (j=0;j<ord;j++)
118 {
Jean-Marc Valine2374a82013-05-25 04:25:54 -0400119 sum = MAC16_16(sum,rnum[j],x[i+j]);
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500120 }
Jean-Marc Valin02fed472013-08-29 15:29:02 -0400121 _y[i] = SATURATE16(PSHR32(sum, SIG_SHIFT));
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500122 }
Jean-Marc Valine2374a82013-05-25 04:25:54 -0400123#else
Jean-Marc Valine2374a82013-05-25 04:25:54 -0400124 for (i=0;i<N-3;i+=4)
125 {
Jean-Marc Valin068cbd82013-05-26 20:08:35 -0400126 opus_val32 sum[4]={0,0,0,0};
127 xcorr_kernel(rnum, x+i, sum, ord);
Jean-Marc Valin02fed472013-08-29 15:29:02 -0400128 _y[i ] = SATURATE16(ADD32(EXTEND32(_x[i ]), PSHR32(sum[0], SIG_SHIFT)));
129 _y[i+1] = SATURATE16(ADD32(EXTEND32(_x[i+1]), PSHR32(sum[1], SIG_SHIFT)));
130 _y[i+2] = SATURATE16(ADD32(EXTEND32(_x[i+2]), PSHR32(sum[2], SIG_SHIFT)));
131 _y[i+3] = SATURATE16(ADD32(EXTEND32(_x[i+3]), PSHR32(sum[3], SIG_SHIFT)));
Jean-Marc Valine2374a82013-05-25 04:25:54 -0400132 }
133 for (;i<N;i++)
134 {
135 opus_val32 sum = 0;
136 for (j=0;j<ord;j++)
137 sum = MAC16_16(sum,rnum[j],x[i+j]);
Jean-Marc Valin02fed472013-08-29 15:29:02 -0400138 _y[i] = SATURATE16(ADD32(EXTEND32(_x[i]), PSHR32(sum, SIG_SHIFT)));
Jean-Marc Valine2374a82013-05-25 04:25:54 -0400139 }
140#endif
Jean-Marc Valin0fa5fa82013-05-25 18:50:01 -0400141 RESTORE_STACK;
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500142}
143
Jean-Marc Valin531cf592013-05-25 07:41:55 -0400144void celt_iir(const opus_val32 *_x,
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400145 const opus_val16 *den,
Jean-Marc Valin531cf592013-05-25 07:41:55 -0400146 opus_val32 *_y,
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500147 int N,
148 int ord,
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400149 opus_val16 *mem)
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500150{
Jean-Marc Valin531cf592013-05-25 07:41:55 -0400151#ifdef SMALL_FOOTPRINT
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500152 int i,j;
153 for (i=0;i<N;i++)
154 {
Jean-Marc Valin531cf592013-05-25 07:41:55 -0400155 opus_val32 sum = _x[i];
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500156 for (j=0;j<ord;j++)
157 {
Jean-Marc Valin74128be2010-01-01 09:33:17 -0500158 sum -= MULT16_16(den[j],mem[j]);
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500159 }
160 for (j=ord-1;j>=1;j--)
161 {
162 mem[j]=mem[j-1];
163 }
Jean-Marc Valin74128be2010-01-01 09:33:17 -0500164 mem[0] = ROUND16(sum,SIG_SHIFT);
Jean-Marc Valin531cf592013-05-25 07:41:55 -0400165 _y[i] = sum;
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500166 }
Jean-Marc Valin531cf592013-05-25 07:41:55 -0400167#else
168 int i,j;
169 VARDECL(opus_val16, rden);
170 VARDECL(opus_val16, y);
171 SAVE_STACK;
172
173 celt_assert((ord&3)==0);
174 ALLOC(rden, ord, opus_val16);
175 ALLOC(y, N+ord, opus_val16);
176 for(i=0;i<ord;i++)
177 rden[i] = den[ord-i-1];
178 for(i=0;i<ord;i++)
179 y[i] = -mem[ord-i-1];
180 for(;i<N+ord;i++)
181 y[i]=0;
182 for (i=0;i<N-3;i+=4)
183 {
Jean-Marc Valin068cbd82013-05-26 20:08:35 -0400184 /* Unroll by 4 as if it were an FIR filter */
Jean-Marc Valin0fed0742013-05-26 20:29:44 -0400185 opus_val32 sum[4];
186 sum[0]=_x[i];
187 sum[1]=_x[i+1];
188 sum[2]=_x[i+2];
189 sum[3]=_x[i+3];
Jean-Marc Valin068cbd82013-05-26 20:08:35 -0400190 xcorr_kernel(rden, y+i, sum, ord);
Jean-Marc Valin531cf592013-05-25 07:41:55 -0400191
Jean-Marc Valin068cbd82013-05-26 20:08:35 -0400192 /* Patch up the result to compensate for the fact that this is an IIR */
193 y[i+ord ] = -ROUND16(sum[0],SIG_SHIFT);
194 _y[i ] = sum[0];
195 sum[1] = MAC16_16(sum[1], y[i+ord ], den[0]);
196 y[i+ord+1] = -ROUND16(sum[1],SIG_SHIFT);
197 _y[i+1] = sum[1];
198 sum[2] = MAC16_16(sum[2], y[i+ord+1], den[0]);
199 sum[2] = MAC16_16(sum[2], y[i+ord ], den[1]);
200 y[i+ord+2] = -ROUND16(sum[2],SIG_SHIFT);
201 _y[i+2] = sum[2];
202
203 sum[3] = MAC16_16(sum[3], y[i+ord+2], den[0]);
204 sum[3] = MAC16_16(sum[3], y[i+ord+1], den[1]);
205 sum[3] = MAC16_16(sum[3], y[i+ord ], den[2]);
206 y[i+ord+3] = -ROUND16(sum[3],SIG_SHIFT);
207 _y[i+3] = sum[3];
Jean-Marc Valin531cf592013-05-25 07:41:55 -0400208 }
209 for (;i<N;i++)
210 {
211 opus_val32 sum = _x[i];
212 for (j=0;j<ord;j++)
213 sum -= MULT16_16(rden[j],y[i+j]);
214 y[i+ord] = ROUND16(sum,SIG_SHIFT);
215 _y[i] = sum;
216 }
217 for(i=0;i<ord;i++)
218 mem[i] = _y[N-i-1];
Jean-Marc Valin0fa5fa82013-05-25 18:50:01 -0400219 RESTORE_STACK;
John Ridgese50e8082013-06-06 23:12:57 -0400220#endif
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500221}
222
Jean-Marc Valin6a7ee7f2013-08-28 17:55:34 -0400223int _celt_autocorr(
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400224 const opus_val16 *x, /* in: [0...n-1] samples x */
225 opus_val32 *ac, /* out: [0...lag-1] ac values */
226 const opus_val16 *window,
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500227 int overlap,
Gregory Maxwell71d39ad2011-07-30 00:00:29 -0400228 int lag,
Timothy B. Terriberry39386e02013-11-18 13:30:13 -0500229 int n,
230 int arch
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500231 )
232{
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400233 opus_val32 d;
Jean-Marc Valin6a7ee7f2013-08-28 17:55:34 -0400234 int i, k;
Jean-Marc Valine8e57a32013-05-25 02:14:25 -0400235 int fastN=n-lag;
Jean-Marc Valin6a7ee7f2013-08-28 17:55:34 -0400236 int shift;
237 const opus_val16 *xptr;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400238 VARDECL(opus_val16, xx);
Thorvald Natvigb8002a02009-12-11 13:19:09 +0100239 SAVE_STACK;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400240 ALLOC(xx, n, opus_val16);
Gregory Maxwell5d5875a2011-10-03 21:07:39 -0400241 celt_assert(n>0);
242 celt_assert(overlap>=0);
Jean-Marc Valin6a7ee7f2013-08-28 17:55:34 -0400243 if (overlap == 0)
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500244 {
Jean-Marc Valin6a7ee7f2013-08-28 17:55:34 -0400245 xptr = x;
246 } else {
247 for (i=0;i<n;i++)
248 xx[i] = x[i];
249 for (i=0;i<overlap;i++)
250 {
251 xx[i] = MULT16_16_Q15(x[i],window[i]);
252 xx[n-i-1] = MULT16_16_Q15(x[n-i-1],window[i]);
253 }
254 xptr = xx;
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500255 }
Jean-Marc Valin6a7ee7f2013-08-28 17:55:34 -0400256 shift=0;
Jean-Marc Valin456eab22010-06-16 22:38:57 -0400257#ifdef FIXED_POINT
258 {
Timothy B. Terriberry85ede2c2013-05-22 15:26:12 -0700259 opus_val32 ac0;
Jean-Marc Valin6a7ee7f2013-08-28 17:55:34 -0400260 ac0 = 1+(n<<7);
261 if (n&1) ac0 += SHR32(MULT16_16(xptr[0],xptr[0]),9);
Timothy B. Terriberry85ede2c2013-05-22 15:26:12 -0700262 for(i=(n&1);i<n;i+=2)
263 {
Jean-Marc Valin6a7ee7f2013-08-28 17:55:34 -0400264 ac0 += SHR32(MULT16_16(xptr[i],xptr[i]),9);
265 ac0 += SHR32(MULT16_16(xptr[i+1],xptr[i+1]),9);
Timothy B. Terriberry85ede2c2013-05-22 15:26:12 -0700266 }
Jean-Marc Valin0da0d912010-06-17 07:32:20 -0400267
Jean-Marc Valine1be1922011-11-28 22:48:01 -0500268 shift = celt_ilog2(ac0)-30+10;
Jean-Marc Valin6a7ee7f2013-08-28 17:55:34 -0400269 shift = (shift)/2;
270 if (shift>0)
271 {
272 for(i=0;i<n;i++)
273 xx[i] = PSHR32(xptr[i], shift);
274 xptr = xx;
275 } else
276 shift = 0;
Jean-Marc Valin456eab22010-06-16 22:38:57 -0400277 }
278#endif
Timothy B. Terriberry39386e02013-11-18 13:30:13 -0500279 celt_pitch_xcorr(xptr, xptr, ac, fastN, lag+1, arch);
Jean-Marc Valin6a7ee7f2013-08-28 17:55:34 -0400280 for (k=0;k<=lag;k++)
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500281 {
Jean-Marc Valin6a7ee7f2013-08-28 17:55:34 -0400282 for (i = k+fastN, d = 0; i < n; i++)
283 d = MAC16_16(d, xptr[i], xptr[i-k]);
284 ac[k] += d;
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500285 }
Jean-Marc Valin6a7ee7f2013-08-28 17:55:34 -0400286#ifdef FIXED_POINT
287 shift = 2*shift;
288 if (shift<=0)
289 ac[0] += SHL32((opus_int32)1, -shift);
290 if (ac[0] < 268435456)
291 {
292 int shift2 = 29 - EC_ILOG(ac[0]);
293 for (i=0;i<=lag;i++)
294 ac[i] = SHL32(ac[i], shift2);
295 shift -= shift2;
296 } else if (ac[0] >= 536870912)
297 {
298 int shift2=1;
299 if (ac[0] >= 1073741824)
300 shift2++;
301 for (i=0;i<=lag;i++)
302 ac[i] = SHR32(ac[i], shift2);
303 shift += shift2;
304 }
305#endif
Jean-Marc Valin456eab22010-06-16 22:38:57 -0400306
Thorvald Natvigb8002a02009-12-11 13:19:09 +0100307 RESTORE_STACK;
Jean-Marc Valin6a7ee7f2013-08-28 17:55:34 -0400308 return shift;
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500309}