blob: 8983121473e7a1d44dd973992939207f8dd1f23c [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 Valine2374a82013-05-25 04:25:54 -0400121 _y[i] = ROUND16(sum, SIG_SHIFT);
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500122 }
Jean-Marc Valine2374a82013-05-25 04:25:54 -0400123#else
124 celt_assert((ord&3)==0);
125 for (i=0;i<N-3;i+=4)
126 {
127 opus_val32 sum1=0;
128 opus_val32 sum2=0;
129 opus_val32 sum3=0;
130 opus_val32 sum4=0;
131 const opus_val16 *xx = x+i;
132 const opus_val16 *z = rnum;
133 opus_val16 y_0, y_1, y_2, y_3;
134 y_3=0; /* gcc doesn't realize that y_3 can't be used uninitialized */
135 y_0=*xx++;
136 y_1=*xx++;
137 y_2=*xx++;
138 for (j=0;j<ord-3;j+=4)
139 {
140 opus_val16 tmp;
141 tmp = *z++;
142 y_3=*xx++;
143 sum1 = MAC16_16(sum1,tmp,y_0);
144 sum2 = MAC16_16(sum2,tmp,y_1);
145 sum3 = MAC16_16(sum3,tmp,y_2);
146 sum4 = MAC16_16(sum4,tmp,y_3);
147 tmp=*z++;
148 y_0=*xx++;
149 sum1 = MAC16_16(sum1,tmp,y_1);
150 sum2 = MAC16_16(sum2,tmp,y_2);
151 sum3 = MAC16_16(sum3,tmp,y_3);
152 sum4 = MAC16_16(sum4,tmp,y_0);
153 tmp=*z++;
154 y_1=*xx++;
155 sum1 = MAC16_16(sum1,tmp,y_2);
156 sum2 = MAC16_16(sum2,tmp,y_3);
157 sum3 = MAC16_16(sum3,tmp,y_0);
158 sum4 = MAC16_16(sum4,tmp,y_1);
159 tmp=*z++;
160 y_2=*xx++;
161 sum1 = MAC16_16(sum1,tmp,y_3);
162 sum2 = MAC16_16(sum2,tmp,y_0);
163 sum3 = MAC16_16(sum3,tmp,y_1);
164 sum4 = MAC16_16(sum4,tmp,y_2);
165 }
166 _y[i ] = ADD16(_x[i ], ROUND16(sum1, SIG_SHIFT));
167 _y[i+1] = ADD16(_x[i+1], ROUND16(sum2, SIG_SHIFT));
168 _y[i+2] = ADD16(_x[i+2], ROUND16(sum3, SIG_SHIFT));
169 _y[i+3] = ADD16(_x[i+3], ROUND16(sum4, SIG_SHIFT));
170 }
171 for (;i<N;i++)
172 {
173 opus_val32 sum = 0;
174 for (j=0;j<ord;j++)
175 sum = MAC16_16(sum,rnum[j],x[i+j]);
176 _y[i] = ADD16(_x[i ], ROUND16(sum, SIG_SHIFT));
177 }
178#endif
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500179}
180
Jean-Marc Valin7fc2fbd2011-09-01 13:40:39 -0400181void celt_iir(const opus_val32 *x,
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400182 const opus_val16 *den,
183 opus_val32 *y,
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500184 int N,
185 int ord,
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400186 opus_val16 *mem)
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500187{
188 int i,j;
189 for (i=0;i<N;i++)
190 {
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400191 opus_val32 sum = x[i];
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500192 for (j=0;j<ord;j++)
193 {
Jean-Marc Valin74128be2010-01-01 09:33:17 -0500194 sum -= MULT16_16(den[j],mem[j]);
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500195 }
196 for (j=ord-1;j>=1;j--)
197 {
198 mem[j]=mem[j-1];
199 }
Jean-Marc Valin74128be2010-01-01 09:33:17 -0500200 mem[0] = ROUND16(sum,SIG_SHIFT);
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500201 y[i] = sum;
202 }
203}
204
205void _celt_autocorr(
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400206 const opus_val16 *x, /* in: [0...n-1] samples x */
207 opus_val32 *ac, /* out: [0...lag-1] ac values */
208 const opus_val16 *window,
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500209 int overlap,
Gregory Maxwell71d39ad2011-07-30 00:00:29 -0400210 int lag,
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500211 int n
212 )
213{
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400214 opus_val32 d;
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500215 int i;
Jean-Marc Valine8e57a32013-05-25 02:14:25 -0400216 int fastN=n-lag;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400217 VARDECL(opus_val16, xx);
Thorvald Natvigb8002a02009-12-11 13:19:09 +0100218 SAVE_STACK;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400219 ALLOC(xx, n, opus_val16);
Gregory Maxwell5d5875a2011-10-03 21:07:39 -0400220 celt_assert(n>0);
221 celt_assert(overlap>=0);
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500222 for (i=0;i<n;i++)
223 xx[i] = x[i];
224 for (i=0;i<overlap;i++)
225 {
Jean-Marc Valin0da0d912010-06-17 07:32:20 -0400226 xx[i] = MULT16_16_Q15(x[i],window[i]);
227 xx[n-i-1] = MULT16_16_Q15(x[n-i-1],window[i]);
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500228 }
Jean-Marc Valin456eab22010-06-16 22:38:57 -0400229#ifdef FIXED_POINT
230 {
Timothy B. Terriberry85ede2c2013-05-22 15:26:12 -0700231 opus_val32 ac0;
Jean-Marc Valin0da0d912010-06-17 07:32:20 -0400232 int shift;
Timothy B. Terriberry85ede2c2013-05-22 15:26:12 -0700233 ac0 = 1+n;
234 if (n&1) ac0 += SHR32(MULT16_16(xx[0],xx[0]),9);
235 for(i=(n&1);i<n;i+=2)
236 {
Jean-Marc Valine1be1922011-11-28 22:48:01 -0500237 ac0 += SHR32(MULT16_16(xx[i],xx[i]),9);
Timothy B. Terriberry85ede2c2013-05-22 15:26:12 -0700238 ac0 += SHR32(MULT16_16(xx[i+1],xx[i+1]),9);
239 }
Jean-Marc Valin0da0d912010-06-17 07:32:20 -0400240
Jean-Marc Valine1be1922011-11-28 22:48:01 -0500241 shift = celt_ilog2(ac0)-30+10;
Jean-Marc Valin0da0d912010-06-17 07:32:20 -0400242 shift = (shift+1)/2;
243 for(i=0;i<n;i++)
244 xx[i] = VSHR32(xx[i], shift);
Jean-Marc Valin456eab22010-06-16 22:38:57 -0400245 }
246#endif
Jean-Marc Valine8e57a32013-05-25 02:14:25 -0400247 pitch_xcorr(xx, xx, ac, fastN, lag+1);
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500248 while (lag>=0)
249 {
Jean-Marc Valine8e57a32013-05-25 02:14:25 -0400250 for (i = lag+fastN, d = 0; i < n; i++)
Timothy B. Terriberry85ede2c2013-05-22 15:26:12 -0700251 d = MAC16_16(d, xx[i], xx[i-lag]);
Jean-Marc Valine8e57a32013-05-25 02:14:25 -0400252 ac[lag] += d;
Jean-Marc Valin456eab22010-06-16 22:38:57 -0400253 /*printf ("%f ", ac[lag]);*/
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500254 lag--;
255 }
Jean-Marc Valin456eab22010-06-16 22:38:57 -0400256 /*printf ("\n");*/
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500257 ac[0] += 10;
Jean-Marc Valin456eab22010-06-16 22:38:57 -0400258
Thorvald Natvigb8002a02009-12-11 13:19:09 +0100259 RESTORE_STACK;
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500260}