15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/***********************************************************************
25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)Copyright (c) 2006-2011, Skype Limited. All rights reserved.
35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)Redistribution and use in source and binary forms, with or without
45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)modification, are permitted provided that the following conditions
55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)are met:
65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)- Redistributions of source code must retain the above copyright notice,
75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)this list of conditions and the following disclaimer.
85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)- Redistributions in binary form must reproduce the above copyright
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinotice, this list of conditions and the following disclaimer in the
105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)documentation and/or other materials provided with the distribution.
115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)- Neither the name of Internet Society, IETF or IETF Trust, nor the
125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)names of specific contributors, may be used to endorse or promote
135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)products derived from this software without specific prior written
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)permission.
155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)POSSIBILITY OF SUCH DAMAGE.
265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)***********************************************************************/
275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#ifdef HAVE_CONFIG_H
295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "config.h"
305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/*
335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Elliptic/Cauer filters designed with 0.1 dB passband ripple,
345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    80 dB minimum stopband attenuation, and
355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    [0.95 : 0.15 : 0.35] normalized cut off frequencies.
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci*/
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "main.h"
395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/* Helper function, interpolates the filter taps */
415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static OPUS_INLINE void silk_LP_interpolate_filter_taps(
425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    opus_int32           B_Q28[ TRANSITION_NB ],
435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    opus_int32           A_Q28[ TRANSITION_NA ],
445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const opus_int       ind,
455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const opus_int32     fac_Q16
465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles))
475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles){
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    opus_int nb, na;
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if( ind < TRANSITION_INT_NUM - 1 ) {
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        if( fac_Q16 > 0 ) {
525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            if( fac_Q16 < 32768 ) { /* fac_Q16 is in range of a 16-bit int */
535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                /* Piece-wise linear interpolation of B and A */
545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                for( nb = 0; nb < TRANSITION_NB; nb++ ) {
555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                    B_Q28[ nb ] = silk_SMLAWB(
565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        silk_Transition_LP_B_Q28[ ind     ][ nb ],
575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        silk_Transition_LP_B_Q28[ ind + 1 ][ nb ] -
58                        silk_Transition_LP_B_Q28[ ind     ][ nb ],
59                        fac_Q16 );
60                }
61                for( na = 0; na < TRANSITION_NA; na++ ) {
62                    A_Q28[ na ] = silk_SMLAWB(
63                        silk_Transition_LP_A_Q28[ ind     ][ na ],
64                        silk_Transition_LP_A_Q28[ ind + 1 ][ na ] -
65                        silk_Transition_LP_A_Q28[ ind     ][ na ],
66                        fac_Q16 );
67                }
68            } else { /* ( fac_Q16 - ( 1 << 16 ) ) is in range of a 16-bit int */
69                silk_assert( fac_Q16 - ( 1 << 16 ) == silk_SAT16( fac_Q16 - ( 1 << 16 ) ) );
70                /* Piece-wise linear interpolation of B and A */
71                for( nb = 0; nb < TRANSITION_NB; nb++ ) {
72                    B_Q28[ nb ] = silk_SMLAWB(
73                        silk_Transition_LP_B_Q28[ ind + 1 ][ nb ],
74                        silk_Transition_LP_B_Q28[ ind + 1 ][ nb ] -
75                        silk_Transition_LP_B_Q28[ ind     ][ nb ],
76                        fac_Q16 - ( (opus_int32)1 << 16 ) );
77                }
78                for( na = 0; na < TRANSITION_NA; na++ ) {
79                    A_Q28[ na ] = silk_SMLAWB(
80                        silk_Transition_LP_A_Q28[ ind + 1 ][ na ],
81                        silk_Transition_LP_A_Q28[ ind + 1 ][ na ] -
82                        silk_Transition_LP_A_Q28[ ind     ][ na ],
83                        fac_Q16 - ( (opus_int32)1 << 16 ) );
84                }
85            }
86        } else {
87            silk_memcpy( B_Q28, silk_Transition_LP_B_Q28[ ind ], TRANSITION_NB * sizeof( opus_int32 ) );
88            silk_memcpy( A_Q28, silk_Transition_LP_A_Q28[ ind ], TRANSITION_NA * sizeof( opus_int32 ) );
89        }
90    } else {
91        silk_memcpy( B_Q28, silk_Transition_LP_B_Q28[ TRANSITION_INT_NUM - 1 ], TRANSITION_NB * sizeof( opus_int32 ) );
92        silk_memcpy( A_Q28, silk_Transition_LP_A_Q28[ TRANSITION_INT_NUM - 1 ], TRANSITION_NA * sizeof( opus_int32 ) );
93    }
94}
95
96/* Low-pass filter with variable cutoff frequency based on  */
97/* piece-wise linear interpolation between elliptic filters */
98/* Start by setting psEncC->mode <> 0;                      */
99/* Deactivate by setting psEncC->mode = 0;                  */
100void silk_LP_variable_cutoff(
101    silk_LP_state               *psLP,                          /* I/O  LP filter state                             */
102    opus_int16                  *frame,                         /* I/O  Low-pass filtered output signal             */
103    const opus_int              frame_length                    /* I    Frame length                                */
104)
105{
106    opus_int32   B_Q28[ TRANSITION_NB ], A_Q28[ TRANSITION_NA ], fac_Q16 = 0;
107    opus_int     ind = 0;
108
109    silk_assert( psLP->transition_frame_no >= 0 && psLP->transition_frame_no <= TRANSITION_FRAMES );
110
111    /* Run filter if needed */
112    if( psLP->mode != 0 ) {
113        /* Calculate index and interpolation factor for interpolation */
114#if( TRANSITION_INT_STEPS == 64 )
115        fac_Q16 = silk_LSHIFT( TRANSITION_FRAMES - psLP->transition_frame_no, 16 - 6 );
116#else
117        fac_Q16 = silk_DIV32_16( silk_LSHIFT( TRANSITION_FRAMES - psLP->transition_frame_no, 16 ), TRANSITION_FRAMES );
118#endif
119        ind      = silk_RSHIFT( fac_Q16, 16 );
120        fac_Q16 -= silk_LSHIFT( ind, 16 );
121
122        silk_assert( ind >= 0 );
123        silk_assert( ind < TRANSITION_INT_NUM );
124
125        /* Interpolate filter coefficients */
126        silk_LP_interpolate_filter_taps( B_Q28, A_Q28, ind, fac_Q16 );
127
128        /* Update transition frame number for next frame */
129        psLP->transition_frame_no = silk_LIMIT( psLP->transition_frame_no + psLP->mode, 0, TRANSITION_FRAMES );
130
131        /* ARMA low-pass filtering */
132        silk_assert( TRANSITION_NB == 3 && TRANSITION_NA == 2 );
133        silk_biquad_alt( frame, B_Q28, A_Q28, psLP->In_LP_State, frame, frame_length, 1);
134    }
135}
136