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