blob: 1b3714332da8e849737dac9a21cf86f896693570 [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
18 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
19 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20 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 Valin6c3788c2010-06-20 22:48:50 -040032#include "plc.h"
33#include "stack_alloc.h"
34#include "mathops.h"
Jean-Marc Valin3a9699e2010-06-17 00:35:26 -040035
Jean-Marc Valin6c3788c2010-06-20 22:48:50 -040036
Jean-Marc Valin456eab22010-06-16 22:38:57 -040037
38
Jean-Marc Valin7b7f0712010-06-17 20:10:02 -040039void _celt_lpc(
Jean-Marc Valinff5f7222011-07-29 18:59:12 -040040 opus_val16 *_lpc, /* out: [0...p-1] LPC coefficients */
41const opus_val32 *ac, /* in: [0...p] autocorrelation values */
Jean-Marc Valine14fe902009-12-11 00:07:31 -050042int p
43)
44{
Gregory Maxwell71d39ad2011-07-30 00:00:29 -040045 int i, j;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -040046 opus_val32 r;
47 opus_val32 error = ac[0];
Jean-Marc Valin74128be2010-01-01 09:33:17 -050048#ifdef FIXED_POINT
Jean-Marc Valinff5f7222011-07-29 18:59:12 -040049 opus_val32 lpc[LPC_ORDER];
Jean-Marc Valin74128be2010-01-01 09:33:17 -050050#else
51 float *lpc = _lpc;
52#endif
Jean-Marc Valine14fe902009-12-11 00:07:31 -050053
Jean-Marc Valin456eab22010-06-16 22:38:57 -040054 for (i = 0; i < p; i++)
55 lpc[i] = 0;
56 if (ac[0] != 0)
Jean-Marc Valine14fe902009-12-11 00:07:31 -050057 {
Jean-Marc Valin456eab22010-06-16 22:38:57 -040058 for (i = 0; i < p; i++) {
59 /* Sum up this iteration's reflection coefficient */
Jean-Marc Valinff5f7222011-07-29 18:59:12 -040060 opus_val32 rr = 0;
Jean-Marc Valin456eab22010-06-16 22:38:57 -040061 for (j = 0; j < i; j++)
62 rr += MULT32_32_Q31(lpc[j],ac[i - j]);
63 rr += SHR32(ac[i + 1],3);
Jean-Marc Valinbd82ca82010-06-17 00:11:54 -040064 r = -frac_div32(SHL32(rr,3), error);
Jean-Marc Valin456eab22010-06-16 22:38:57 -040065 /* Update LPC coefficients and total error */
66 lpc[i] = SHR32(r,3);
67 for (j = 0; j < (i+1)>>1; j++)
68 {
Jean-Marc Valinff5f7222011-07-29 18:59:12 -040069 opus_val32 tmp1, tmp2;
Jean-Marc Valin456eab22010-06-16 22:38:57 -040070 tmp1 = lpc[j];
71 tmp2 = lpc[i-1-j];
72 lpc[j] = tmp1 + MULT32_32_Q31(r,tmp2);
73 lpc[i-1-j] = tmp2 + MULT32_32_Q31(r,tmp1);
74 }
75
76 error = error - MULT32_32_Q31(MULT32_32_Q31(r,r),error);
Jean-Marc Valinbd82ca82010-06-17 00:11:54 -040077 /* Bail out once we get 30 dB gain */
78#ifdef FIXED_POINT
79 if (error<SHR32(ac[0],10))
Jean-Marc Valin456eab22010-06-16 22:38:57 -040080 break;
Jean-Marc Valinbd82ca82010-06-17 00:11:54 -040081#else
Gregory Maxwell60c316b2010-11-04 20:14:19 -040082 if (error<.001f*ac[0])
Jean-Marc Valinbd82ca82010-06-17 00:11:54 -040083 break;
84#endif
Jean-Marc Valine14fe902009-12-11 00:07:31 -050085 }
Jean-Marc Valine14fe902009-12-11 00:07:31 -050086 }
Jean-Marc Valin303b3b62009-12-30 22:40:24 -050087#ifdef FIXED_POINT
88 for (i=0;i<p;i++)
Jean-Marc Valin456eab22010-06-16 22:38:57 -040089 _lpc[i] = ROUND16(lpc[i],16);
Jean-Marc Valin303b3b62009-12-30 22:40:24 -050090#endif
Jean-Marc Valine14fe902009-12-11 00:07:31 -050091}
92
Jean-Marc Valinff5f7222011-07-29 18:59:12 -040093void fir(const opus_val16 *x,
94 const opus_val16 *num,
95 opus_val16 *y,
Jean-Marc Valine14fe902009-12-11 00:07:31 -050096 int N,
97 int ord,
Jean-Marc Valinff5f7222011-07-29 18:59:12 -040098 opus_val16 *mem)
Jean-Marc Valine14fe902009-12-11 00:07:31 -050099{
100 int i,j;
101
102 for (i=0;i<N;i++)
103 {
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400104 opus_val32 sum = SHL32(EXTEND32(x[i]), SIG_SHIFT);
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500105 for (j=0;j<ord;j++)
106 {
Jean-Marc Valin74128be2010-01-01 09:33:17 -0500107 sum += MULT16_16(num[j],mem[j]);
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500108 }
109 for (j=ord-1;j>=1;j--)
110 {
111 mem[j]=mem[j-1];
112 }
113 mem[0] = x[i];
Jean-Marc Valin74128be2010-01-01 09:33:17 -0500114 y[i] = ROUND16(sum, SIG_SHIFT);
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500115 }
116}
117
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400118void iir(const opus_val32 *x,
119 const opus_val16 *den,
120 opus_val32 *y,
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500121 int N,
122 int ord,
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400123 opus_val16 *mem)
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500124{
125 int i,j;
126 for (i=0;i<N;i++)
127 {
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400128 opus_val32 sum = x[i];
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500129 for (j=0;j<ord;j++)
130 {
Jean-Marc Valin74128be2010-01-01 09:33:17 -0500131 sum -= MULT16_16(den[j],mem[j]);
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500132 }
133 for (j=ord-1;j>=1;j--)
134 {
135 mem[j]=mem[j-1];
136 }
Jean-Marc Valin74128be2010-01-01 09:33:17 -0500137 mem[0] = ROUND16(sum,SIG_SHIFT);
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500138 y[i] = sum;
139 }
140}
141
142void _celt_autocorr(
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400143 const opus_val16 *x, /* in: [0...n-1] samples x */
144 opus_val32 *ac, /* out: [0...lag-1] ac values */
145 const opus_val16 *window,
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500146 int overlap,
Gregory Maxwell71d39ad2011-07-30 00:00:29 -0400147 int lag,
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500148 int n
149 )
150{
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400151 opus_val32 d;
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500152 int i;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400153 VARDECL(opus_val16, xx);
Thorvald Natvigb8002a02009-12-11 13:19:09 +0100154 SAVE_STACK;
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400155 ALLOC(xx, n, opus_val16);
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500156 for (i=0;i<n;i++)
157 xx[i] = x[i];
158 for (i=0;i<overlap;i++)
159 {
Jean-Marc Valin0da0d912010-06-17 07:32:20 -0400160 xx[i] = MULT16_16_Q15(x[i],window[i]);
161 xx[n-i-1] = MULT16_16_Q15(x[n-i-1],window[i]);
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500162 }
Jean-Marc Valin456eab22010-06-16 22:38:57 -0400163#ifdef FIXED_POINT
164 {
Jean-Marc Valinff5f7222011-07-29 18:59:12 -0400165 opus_val32 ac0=0;
Jean-Marc Valin0da0d912010-06-17 07:32:20 -0400166 int shift;
Jean-Marc Valin456eab22010-06-16 22:38:57 -0400167 for(i=0;i<n;i++)
Jean-Marc Valin0da0d912010-06-17 07:32:20 -0400168 ac0 += SHR32(MULT16_16(xx[i],xx[i]),8);
169 ac0 += 1+n;
170
Jean-Marc Valin1ad93cf2010-11-06 22:02:32 -0400171 shift = celt_ilog2(ac0)-30+9;
Jean-Marc Valin0da0d912010-06-17 07:32:20 -0400172 shift = (shift+1)/2;
173 for(i=0;i<n;i++)
174 xx[i] = VSHR32(xx[i], shift);
Jean-Marc Valin456eab22010-06-16 22:38:57 -0400175 }
176#endif
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500177 while (lag>=0)
178 {
Gregory Maxwell71d39ad2011-07-30 00:00:29 -0400179 for (i = lag, d = 0; i < n; i++)
Jean-Marc Valin0da0d912010-06-17 07:32:20 -0400180 d += xx[i] * xx[i-lag];
181 ac[lag] = d;
Jean-Marc Valin456eab22010-06-16 22:38:57 -0400182 /*printf ("%f ", ac[lag]);*/
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500183 lag--;
184 }
Jean-Marc Valin456eab22010-06-16 22:38:57 -0400185 /*printf ("\n");*/
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500186 ac[0] += 10;
Jean-Marc Valin456eab22010-06-16 22:38:57 -0400187
Thorvald Natvigb8002a02009-12-11 13:19:09 +0100188 RESTORE_STACK;
Jean-Marc Valine14fe902009-12-11 00:07:31 -0500189}