Fixes the case of PLC before receiving any valid packet
[opus.git] / silk / silk_A2NLSF.c
1 /***********************************************************************\r
2 Copyright (c) 2006-2011, Skype Limited. All rights reserved. \r
3 Redistribution and use in source and binary forms, with or without \r
4 modification, (subject to the limitations in the disclaimer below) \r
5 are permitted provided that the following conditions are met:\r
6 - Redistributions of source code must retain the above copyright notice,\r
7 this list of conditions and the following disclaimer.\r
8 - Redistributions in binary form must reproduce the above copyright \r
9 notice, this list of conditions and the following disclaimer in the \r
10 documentation and/or other materials provided with the distribution.\r
11 - Neither the name of Skype Limited, nor the names of specific \r
12 contributors, may be used to endorse or promote products derived from \r
13 this software without specific prior written permission.\r
14 NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED \r
15 BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND \r
16 CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,\r
17 BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND \r
18 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE \r
19 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, \r
20 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\r
21 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF \r
22 USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON \r
23 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT \r
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE \r
25 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
26 ***********************************************************************/\r
27 \r
28 /* Conversion between prediction filter coefficients and NLSFs  */\r
29 /* Requires the order to be an even number                      */\r
30 /* A piecewise linear approximation maps LSF <-> cos(LSF)       */\r
31 /* Therefore the result is not accurate NLSFs, but the two      */\r
32 /* functions are accurate inverses of each other                */\r
33 \r
34 #include "silk_SigProc_FIX.h"\r
35 #include "silk_tables.h"\r
36 \r
37 /* Number of binary divisions, when not in low complexity mode */\r
38 #define BIN_DIV_STEPS_A2NLSF_FIX      3 /* must be no higher than 16 - log2( LSF_COS_TAB_SZ_FIX ) */\r
39 #define QPoly                        16\r
40 #define MAX_ITERATIONS_A2NLSF_FIX    30\r
41 \r
42 /* Flag for using 2x as many cosine sampling points, reduces the risk of missing a root */\r
43 #define OVERSAMPLE_COSINE_TABLE       0\r
44 \r
45 /* Helper function for A2NLSF(..)                    */\r
46 /* Transforms polynomials from cos(n*f) to cos(f)^n  */\r
47 SKP_INLINE void silk_A2NLSF_trans_poly(\r
48     SKP_int32        *p,    /* I/O    Polynomial                                */\r
49     const SKP_int    dd     /* I      Polynomial order (= filter order / 2 )    */\r
50 )\r
51 {\r
52     SKP_int k, n;\r
53     \r
54     for( k = 2; k <= dd; k++ ) {\r
55         for( n = dd; n > k; n-- ) {\r
56             p[ n - 2 ] -= p[ n ];\r
57         }\r
58         p[ k - 2 ] -= SKP_LSHIFT( p[ k ], 1 );\r
59     }\r
60 }    \r
61 /* Helper function for A2NLSF(..)                    */\r
62 /* Polynomial evaluation                             */\r
63 SKP_INLINE SKP_int32 silk_A2NLSF_eval_poly(    /* return the polynomial evaluation, in QPoly */\r
64     SKP_int32        *p,    /* I    Polynomial, QPoly        */\r
65     const SKP_int32   x,    /* I    Evaluation point, Q12    */\r
66     const SKP_int    dd     /* I    Order                    */\r
67 )\r
68 {\r
69     SKP_int   n;\r
70     SKP_int32 x_Q16, y32;\r
71 \r
72     y32 = p[ dd ];                                    /* QPoly */\r
73     x_Q16 = SKP_LSHIFT( x, 4 );\r
74     for( n = dd - 1; n >= 0; n-- ) {\r
75         y32 = SKP_SMLAWW( p[ n ], y32, x_Q16 );       /* QPoly */\r
76     }\r
77     return y32;\r
78 }\r
79 \r
80 SKP_INLINE void silk_A2NLSF_init(\r
81      const SKP_int32    *a_Q16,\r
82      SKP_int32          *P, \r
83      SKP_int32          *Q, \r
84      const SKP_int      dd\r
85\r
86 {\r
87     SKP_int k;\r
88 \r
89     /* Convert filter coefs to even and odd polynomials */\r
90     P[dd] = SKP_LSHIFT( 1, QPoly );\r
91     Q[dd] = SKP_LSHIFT( 1, QPoly );\r
92     for( k = 0; k < dd; k++ ) {\r
93 #if( QPoly < 16 )\r
94         P[ k ] = SKP_RSHIFT_ROUND( -a_Q16[ dd - k - 1 ] - a_Q16[ dd + k ], 16 - QPoly ); /* QPoly */\r
95         Q[ k ] = SKP_RSHIFT_ROUND( -a_Q16[ dd - k - 1 ] + a_Q16[ dd + k ], 16 - QPoly ); /* QPoly */\r
96 #elif( Qpoly == 16 )\r
97         P[ k ] = -a_Q16[ dd - k - 1 ] - a_Q16[ dd + k ]; // QPoly\r
98         Q[ k ] = -a_Q16[ dd - k - 1 ] + a_Q16[ dd + k ]; // QPoly\r
99 #else\r
100         P[ k ] = SKP_LSHIFT( -a_Q16[ dd - k - 1 ] - a_Q16[ dd + k ], QPoly - 16 ); /* QPoly */\r
101         Q[ k ] = SKP_LSHIFT( -a_Q16[ dd - k - 1 ] + a_Q16[ dd + k ], QPoly - 16 ); /* QPoly */\r
102 #endif\r
103     }\r
104 \r
105     /* Divide out zeros as we have that for even filter orders, */\r
106     /* z =  1 is always a root in Q, and                        */\r
107     /* z = -1 is always a root in P                             */\r
108     for( k = dd; k > 0; k-- ) {\r
109         P[ k - 1 ] -= P[ k ]; \r
110         Q[ k - 1 ] += Q[ k ]; \r
111     }\r
112 \r
113     /* Transform polynomials from cos(n*f) to cos(f)^n */\r
114     silk_A2NLSF_trans_poly( P, dd );\r
115     silk_A2NLSF_trans_poly( Q, dd );\r
116 }\r
117 \r
118 /* Compute Normalized Line Spectral Frequencies (NLSFs) from whitening filter coefficients        */\r
119 /* If not all roots are found, the a_Q16 coefficients are bandwidth expanded until convergence.    */\r
120 void silk_A2NLSF(\r
121     SKP_int16        *NLSF,                 /* O    Normalized Line Spectral Frequencies, Q15 (0 - (2^15-1)), [d]    */\r
122     SKP_int32        *a_Q16,                /* I/O  Monic whitening filter coefficients in Q16 [d]                   */\r
123     const SKP_int    d                      /* I    Filter order (must be even)                                      */\r
124 )\r
125 {\r
126     SKP_int      i, k, m, dd, root_ix, ffrac;\r
127     SKP_int32 xlo, xhi, xmid;\r
128     SKP_int32 ylo, yhi, ymid;\r
129     SKP_int32 nom, den;\r
130     SKP_int32 P[ SILK_MAX_ORDER_LPC / 2 + 1 ];\r
131     SKP_int32 Q[ SILK_MAX_ORDER_LPC / 2 + 1 ];\r
132     SKP_int32 *PQ[ 2 ];\r
133     SKP_int32 *p;\r
134 \r
135     /* Store pointers to array */\r
136     PQ[ 0 ] = P;\r
137     PQ[ 1 ] = Q;\r
138 \r
139     dd = SKP_RSHIFT( d, 1 );\r
140 \r
141     silk_A2NLSF_init( a_Q16, P, Q, dd );\r
142 \r
143     /* Find roots, alternating between P and Q */\r
144     p = P;    /* Pointer to polynomial */\r
145     \r
146     xlo = silk_LSFCosTab_FIX_Q12[ 0 ]; // Q12\r
147     ylo = silk_A2NLSF_eval_poly( p, xlo, dd );\r
148 \r
149     if( ylo < 0 ) {\r
150         /* Set the first NLSF to zero and move on to the next */\r
151         NLSF[ 0 ] = 0;\r
152         p = Q;                      /* Pointer to polynomial */\r
153         ylo = silk_A2NLSF_eval_poly( p, xlo, dd );\r
154         root_ix = 1;                /* Index of current root */\r
155     } else {\r
156         root_ix = 0;                /* Index of current root */\r
157     }\r
158     k = 1;                          /* Loop counter */\r
159     i = 0;                          /* Counter for bandwidth expansions applied */\r
160     while( 1 ) {\r
161         /* Evaluate polynomial */\r
162 #if OVERSAMPLE_COSINE_TABLE\r
163         xhi = silk_LSFCosTab_FIX_Q12[   k       >> 1 ] +\r
164           ( ( silk_LSFCosTab_FIX_Q12[ ( k + 1 ) >> 1 ] - \r
165               silk_LSFCosTab_FIX_Q12[   k       >> 1 ] ) >> 1 );    /* Q12 */\r
166 #else\r
167         xhi = silk_LSFCosTab_FIX_Q12[ k ]; /* Q12 */\r
168 #endif\r
169         yhi = silk_A2NLSF_eval_poly( p, xhi, dd );\r
170         \r
171         /* Detect zero crossing */\r
172         if( ( ylo <= 0 && yhi >= 0 ) || ( ylo >= 0 && yhi <= 0 ) ) {\r
173             /* Binary division */\r
174 #if OVERSAMPLE_COSINE_TABLE\r
175             ffrac = -128;\r
176 #else\r
177             ffrac = -256;\r
178 #endif\r
179             for( m = 0; m < BIN_DIV_STEPS_A2NLSF_FIX; m++ ) {\r
180                 /* Evaluate polynomial */\r
181                 xmid = SKP_RSHIFT_ROUND( xlo + xhi, 1 );\r
182                 ymid = silk_A2NLSF_eval_poly( p, xmid, dd );\r
183 \r
184                 /* Detect zero crossing */\r
185                 if( ( ylo <= 0 && ymid >= 0 ) || ( ylo >= 0 && ymid <= 0 ) ) {\r
186                     /* Reduce frequency */\r
187                     xhi = xmid;\r
188                     yhi = ymid;\r
189                 } else {\r
190                     /* Increase frequency */\r
191                     xlo = xmid;\r
192                     ylo = ymid;\r
193 #if OVERSAMPLE_COSINE_TABLE\r
194                     ffrac = SKP_ADD_RSHIFT( ffrac,  64, m );\r
195 #else\r
196                     ffrac = SKP_ADD_RSHIFT( ffrac, 128, m );\r
197 #endif\r
198                 }\r
199             }\r
200             \r
201             /* Interpolate */\r
202             if( SKP_abs( ylo ) < 65536 ) {\r
203                 /* Avoid dividing by zero */\r
204                 den = ylo - yhi;\r
205                 nom = SKP_LSHIFT( ylo, 8 - BIN_DIV_STEPS_A2NLSF_FIX ) + SKP_RSHIFT( den, 1 );\r
206                 if( den != 0 ) {\r
207                     ffrac += SKP_DIV32( nom, den );\r
208                 }\r
209             } else {\r
210                 /* No risk of dividing by zero because abs(ylo - yhi) >= abs(ylo) >= 65536 */\r
211                 ffrac += SKP_DIV32( ylo, SKP_RSHIFT( ylo - yhi, 8 - BIN_DIV_STEPS_A2NLSF_FIX ) );\r
212             }\r
213 #if OVERSAMPLE_COSINE_TABLE\r
214             NLSF[ root_ix ] = (SKP_int16)SKP_min_32( SKP_LSHIFT( (SKP_int32)k, 7 ) + ffrac, SKP_int16_MAX ); \r
215 #else\r
216             NLSF[ root_ix ] = (SKP_int16)SKP_min_32( SKP_LSHIFT( (SKP_int32)k, 8 ) + ffrac, SKP_int16_MAX ); \r
217 #endif\r
218 \r
219             SKP_assert( NLSF[ root_ix ] >=     0 );\r
220             SKP_assert( NLSF[ root_ix ] <= 32767 );\r
221 \r
222             root_ix++;        /* Next root */\r
223             if( root_ix >= d ) {\r
224                 /* Found all roots */\r
225                 break;\r
226             }\r
227             /* Alternate pointer to polynomial */\r
228             p = PQ[ root_ix & 1 ];\r
229             \r
230             /* Evaluate polynomial */\r
231 #if OVERSAMPLE_COSINE_TABLE\r
232             xlo = silk_LSFCosTab_FIX_Q12[ ( k - 1 ) >> 1 ] +\r
233               ( ( silk_LSFCosTab_FIX_Q12[   k       >> 1 ] - \r
234                   silk_LSFCosTab_FIX_Q12[ ( k - 1 ) >> 1 ] ) >> 1 ); // Q12\r
235 #else\r
236             xlo = silk_LSFCosTab_FIX_Q12[ k - 1 ]; // Q12\r
237 #endif\r
238             ylo = SKP_LSHIFT( 1 - ( root_ix & 2 ), 12 );\r
239         } else {\r
240             /* Increment loop counter */\r
241             k++;\r
242             xlo    = xhi;\r
243             ylo    = yhi;\r
244             \r
245 #if OVERSAMPLE_COSINE_TABLE\r
246             if( k > 2 * LSF_COS_TAB_SZ_FIX ) {\r
247 #else\r
248             if( k > LSF_COS_TAB_SZ_FIX ) {\r
249 #endif\r
250                 i++;\r
251                 if( i > MAX_ITERATIONS_A2NLSF_FIX ) {\r
252                     /* Set NLSFs to white spectrum and exit */\r
253                     NLSF[ 0 ] = (SKP_int16)SKP_DIV32_16( 1 << 15, d + 1 );\r
254                     for( k = 1; k < d; k++ ) {\r
255                         NLSF[ k ] = (SKP_int16)SKP_SMULBB( k + 1, NLSF[ 0 ] );\r
256                     }\r
257                     return;\r
258                 }\r
259 \r
260                 /* Error: Apply progressively more bandwidth expansion and run again */\r
261                 silk_bwexpander_32( a_Q16, d, 65536 - SKP_SMULBB( 10 + i, i ) ); // 10_Q16 = 0.00015\r
262 \r
263                 silk_A2NLSF_init( a_Q16, P, Q, dd );\r
264                 p = P;                            /* Pointer to polynomial */\r
265                 xlo = silk_LSFCosTab_FIX_Q12[ 0 ]; // Q12\r
266                 ylo = silk_A2NLSF_eval_poly( p, xlo, dd );\r
267                 if( ylo < 0 ) {\r
268                     /* Set the first NLSF to zero and move on to the next */\r
269                     NLSF[ 0 ] = 0;\r
270                     p = Q;                        /* Pointer to polynomial */\r
271                     ylo = silk_A2NLSF_eval_poly( p, xlo, dd );\r
272                     root_ix = 1;                  /* Index of current root */\r
273                 } else {\r
274                     root_ix = 0;                  /* Index of current root */\r
275                 }\r
276                 k = 1;                            /* Reset loop counter */\r
277             }\r
278         }\r
279     }\r
280 }\r