Line data Source code
1 : /***********************************************************************
2 : Copyright (c) 2006-2011, Skype Limited. All rights reserved.
3 : Redistribution and use in source and binary forms, with or without
4 : modification, are permitted provided that the following conditions
5 : are met:
6 : - Redistributions of source code must retain the above copyright notice,
7 : this list of conditions and the following disclaimer.
8 : - Redistributions in binary form must reproduce the above copyright
9 : notice, this list of conditions and the following disclaimer in the
10 : documentation and/or other materials provided with the distribution.
11 : - Neither the name of Internet Society, IETF or IETF Trust, nor the
12 : names of specific contributors, may be used to endorse or promote
13 : products derived from this software without specific prior written
14 : permission.
15 : THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 : AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 : IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 : ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 : LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 : CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 : SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 : INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 : CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 : ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 : POSSIBILITY OF SUCH DAMAGE.
26 : ***********************************************************************/
27 :
28 : #ifdef HAVE_CONFIG_H
29 : #include "config.h"
30 : #endif
31 :
32 : #include "SigProc_FIX.h"
33 : #include "celt_lpc.h"
34 :
35 : /*******************************************/
36 : /* LPC analysis filter */
37 : /* NB! State is kept internally and the */
38 : /* filter always starts with zero state */
39 : /* first d output samples are set to zero */
40 : /*******************************************/
41 :
42 : /* OPT: Using celt_fir() for this function should be faster, but it may cause
43 : integer overflows in intermediate values (not final results), which the
44 : current implementation silences by casting to unsigned. Enabling
45 : this should be safe in pretty much all cases, even though it is not technically
46 : C89-compliant. */
47 : #define USE_CELT_FIR 0
48 :
49 0 : void silk_LPC_analysis_filter(
50 : opus_int16 *out, /* O Output signal */
51 : const opus_int16 *in, /* I Input signal */
52 : const opus_int16 *B, /* I MA prediction coefficients, Q12 [order] */
53 : const opus_int32 len, /* I Signal length */
54 : const opus_int32 d, /* I Filter order */
55 : int arch /* I Run-time architecture */
56 : )
57 : {
58 : opus_int j;
59 : #if defined(FIXED_POINT) && USE_CELT_FIR
60 : opus_int16 num[SILK_MAX_ORDER_LPC];
61 : #else
62 : int ix;
63 : opus_int32 out32_Q12, out32;
64 : const opus_int16 *in_ptr;
65 : #endif
66 :
67 0 : silk_assert( d >= 6 );
68 0 : silk_assert( (d & 1) == 0 );
69 0 : silk_assert( d <= len );
70 :
71 : #if defined(FIXED_POINT) && USE_CELT_FIR
72 : silk_assert( d <= SILK_MAX_ORDER_LPC );
73 : for ( j = 0; j < d; j++ ) {
74 : num[ j ] = -B[ j ];
75 : }
76 : celt_fir( in + d, num, out + d, len - d, d, arch );
77 : for ( j = 0; j < d; j++ ) {
78 : out[ j ] = 0;
79 : }
80 : #else
81 : (void)arch;
82 0 : for( ix = d; ix < len; ix++ ) {
83 0 : in_ptr = &in[ ix - 1 ];
84 :
85 0 : out32_Q12 = silk_SMULBB( in_ptr[ 0 ], B[ 0 ] );
86 : /* Allowing wrap around so that two wraps can cancel each other. The rare
87 : cases where the result wraps around can only be triggered by invalid streams*/
88 0 : out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -1 ], B[ 1 ] );
89 0 : out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -2 ], B[ 2 ] );
90 0 : out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -3 ], B[ 3 ] );
91 0 : out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -4 ], B[ 4 ] );
92 0 : out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -5 ], B[ 5 ] );
93 0 : for( j = 6; j < d; j += 2 ) {
94 0 : out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -j ], B[ j ] );
95 0 : out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -j - 1 ], B[ j + 1 ] );
96 : }
97 :
98 : /* Subtract prediction */
99 0 : out32_Q12 = silk_SUB32_ovflw( silk_LSHIFT( (opus_int32)in_ptr[ 1 ], 12 ), out32_Q12 );
100 :
101 : /* Scale to Q0 */
102 0 : out32 = silk_RSHIFT_ROUND( out32_Q12, 12 );
103 :
104 : /* Saturate output */
105 0 : out[ ix ] = (opus_int16)silk_SAT16( out32 );
106 : }
107 :
108 : /* Set first d output samples to zero */
109 0 : silk_memset( out, 0, d * sizeof( opus_int16 ) );
110 : #endif
111 0 : }
|