Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /*********************************************************************** |
michael@0 | 2 | Copyright (c) 2006-2011, Skype Limited. All rights reserved. |
michael@0 | 3 | Redistribution and use in source and binary forms, with or without |
michael@0 | 4 | modification, are permitted provided that the following conditions |
michael@0 | 5 | are met: |
michael@0 | 6 | - Redistributions of source code must retain the above copyright notice, |
michael@0 | 7 | this list of conditions and the following disclaimer. |
michael@0 | 8 | - Redistributions in binary form must reproduce the above copyright |
michael@0 | 9 | notice, this list of conditions and the following disclaimer in the |
michael@0 | 10 | documentation and/or other materials provided with the distribution. |
michael@0 | 11 | - Neither the name of Internet Society, IETF or IETF Trust, nor the |
michael@0 | 12 | names of specific contributors, may be used to endorse or promote |
michael@0 | 13 | products derived from this software without specific prior written |
michael@0 | 14 | permission. |
michael@0 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
michael@0 | 16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
michael@0 | 17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
michael@0 | 18 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
michael@0 | 19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
michael@0 | 20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
michael@0 | 21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
michael@0 | 22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
michael@0 | 23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
michael@0 | 24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
michael@0 | 25 | POSSIBILITY OF SUCH DAMAGE. |
michael@0 | 26 | ***********************************************************************/ |
michael@0 | 27 | |
michael@0 | 28 | #ifdef HAVE_CONFIG_H |
michael@0 | 29 | #include "config.h" |
michael@0 | 30 | #endif |
michael@0 | 31 | |
michael@0 | 32 | /* |
michael@0 | 33 | * Matrix of resampling methods used: |
michael@0 | 34 | * Fs_out (kHz) |
michael@0 | 35 | * 8 12 16 24 48 |
michael@0 | 36 | * |
michael@0 | 37 | * 8 C UF U UF UF |
michael@0 | 38 | * 12 AF C UF U UF |
michael@0 | 39 | * Fs_in (kHz) 16 D AF C UF UF |
michael@0 | 40 | * 24 AF D AF C U |
michael@0 | 41 | * 48 AF AF AF D C |
michael@0 | 42 | * |
michael@0 | 43 | * C -> Copy (no resampling) |
michael@0 | 44 | * D -> Allpass-based 2x downsampling |
michael@0 | 45 | * U -> Allpass-based 2x upsampling |
michael@0 | 46 | * UF -> Allpass-based 2x upsampling followed by FIR interpolation |
michael@0 | 47 | * AF -> AR2 filter followed by FIR interpolation |
michael@0 | 48 | */ |
michael@0 | 49 | |
michael@0 | 50 | #include "resampler_private.h" |
michael@0 | 51 | |
michael@0 | 52 | /* Tables with delay compensation values to equalize total delay for different modes */ |
michael@0 | 53 | static const opus_int8 delay_matrix_enc[ 5 ][ 3 ] = { |
michael@0 | 54 | /* in \ out 8 12 16 */ |
michael@0 | 55 | /* 8 */ { 6, 0, 3 }, |
michael@0 | 56 | /* 12 */ { 0, 7, 3 }, |
michael@0 | 57 | /* 16 */ { 0, 1, 10 }, |
michael@0 | 58 | /* 24 */ { 0, 2, 6 }, |
michael@0 | 59 | /* 48 */ { 18, 10, 12 } |
michael@0 | 60 | }; |
michael@0 | 61 | |
michael@0 | 62 | static const opus_int8 delay_matrix_dec[ 3 ][ 5 ] = { |
michael@0 | 63 | /* in \ out 8 12 16 24 48 */ |
michael@0 | 64 | /* 8 */ { 4, 0, 2, 0, 0 }, |
michael@0 | 65 | /* 12 */ { 0, 9, 4, 7, 4 }, |
michael@0 | 66 | /* 16 */ { 0, 3, 12, 7, 7 } |
michael@0 | 67 | }; |
michael@0 | 68 | |
michael@0 | 69 | /* Simple way to make [8000, 12000, 16000, 24000, 48000] to [0, 1, 2, 3, 4] */ |
michael@0 | 70 | #define rateID(R) ( ( ( ((R)>>12) - ((R)>16000) ) >> ((R)>24000) ) - 1 ) |
michael@0 | 71 | |
michael@0 | 72 | #define USE_silk_resampler_copy (0) |
michael@0 | 73 | #define USE_silk_resampler_private_up2_HQ_wrapper (1) |
michael@0 | 74 | #define USE_silk_resampler_private_IIR_FIR (2) |
michael@0 | 75 | #define USE_silk_resampler_private_down_FIR (3) |
michael@0 | 76 | |
michael@0 | 77 | /* Initialize/reset the resampler state for a given pair of input/output sampling rates */ |
michael@0 | 78 | opus_int silk_resampler_init( |
michael@0 | 79 | silk_resampler_state_struct *S, /* I/O Resampler state */ |
michael@0 | 80 | opus_int32 Fs_Hz_in, /* I Input sampling rate (Hz) */ |
michael@0 | 81 | opus_int32 Fs_Hz_out, /* I Output sampling rate (Hz) */ |
michael@0 | 82 | opus_int forEnc /* I If 1: encoder; if 0: decoder */ |
michael@0 | 83 | ) |
michael@0 | 84 | { |
michael@0 | 85 | opus_int up2x; |
michael@0 | 86 | |
michael@0 | 87 | /* Clear state */ |
michael@0 | 88 | silk_memset( S, 0, sizeof( silk_resampler_state_struct ) ); |
michael@0 | 89 | |
michael@0 | 90 | /* Input checking */ |
michael@0 | 91 | if( forEnc ) { |
michael@0 | 92 | if( ( Fs_Hz_in != 8000 && Fs_Hz_in != 12000 && Fs_Hz_in != 16000 && Fs_Hz_in != 24000 && Fs_Hz_in != 48000 ) || |
michael@0 | 93 | ( Fs_Hz_out != 8000 && Fs_Hz_out != 12000 && Fs_Hz_out != 16000 ) ) { |
michael@0 | 94 | silk_assert( 0 ); |
michael@0 | 95 | return -1; |
michael@0 | 96 | } |
michael@0 | 97 | S->inputDelay = delay_matrix_enc[ rateID( Fs_Hz_in ) ][ rateID( Fs_Hz_out ) ]; |
michael@0 | 98 | } else { |
michael@0 | 99 | if( ( Fs_Hz_in != 8000 && Fs_Hz_in != 12000 && Fs_Hz_in != 16000 ) || |
michael@0 | 100 | ( Fs_Hz_out != 8000 && Fs_Hz_out != 12000 && Fs_Hz_out != 16000 && Fs_Hz_out != 24000 && Fs_Hz_out != 48000 ) ) { |
michael@0 | 101 | silk_assert( 0 ); |
michael@0 | 102 | return -1; |
michael@0 | 103 | } |
michael@0 | 104 | S->inputDelay = delay_matrix_dec[ rateID( Fs_Hz_in ) ][ rateID( Fs_Hz_out ) ]; |
michael@0 | 105 | } |
michael@0 | 106 | |
michael@0 | 107 | S->Fs_in_kHz = silk_DIV32_16( Fs_Hz_in, 1000 ); |
michael@0 | 108 | S->Fs_out_kHz = silk_DIV32_16( Fs_Hz_out, 1000 ); |
michael@0 | 109 | |
michael@0 | 110 | /* Number of samples processed per batch */ |
michael@0 | 111 | S->batchSize = S->Fs_in_kHz * RESAMPLER_MAX_BATCH_SIZE_MS; |
michael@0 | 112 | |
michael@0 | 113 | /* Find resampler with the right sampling ratio */ |
michael@0 | 114 | up2x = 0; |
michael@0 | 115 | if( Fs_Hz_out > Fs_Hz_in ) { |
michael@0 | 116 | /* Upsample */ |
michael@0 | 117 | if( Fs_Hz_out == silk_MUL( Fs_Hz_in, 2 ) ) { /* Fs_out : Fs_in = 2 : 1 */ |
michael@0 | 118 | /* Special case: directly use 2x upsampler */ |
michael@0 | 119 | S->resampler_function = USE_silk_resampler_private_up2_HQ_wrapper; |
michael@0 | 120 | } else { |
michael@0 | 121 | /* Default resampler */ |
michael@0 | 122 | S->resampler_function = USE_silk_resampler_private_IIR_FIR; |
michael@0 | 123 | up2x = 1; |
michael@0 | 124 | } |
michael@0 | 125 | } else if ( Fs_Hz_out < Fs_Hz_in ) { |
michael@0 | 126 | /* Downsample */ |
michael@0 | 127 | S->resampler_function = USE_silk_resampler_private_down_FIR; |
michael@0 | 128 | if( silk_MUL( Fs_Hz_out, 4 ) == silk_MUL( Fs_Hz_in, 3 ) ) { /* Fs_out : Fs_in = 3 : 4 */ |
michael@0 | 129 | S->FIR_Fracs = 3; |
michael@0 | 130 | S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR0; |
michael@0 | 131 | S->Coefs = silk_Resampler_3_4_COEFS; |
michael@0 | 132 | } else if( silk_MUL( Fs_Hz_out, 3 ) == silk_MUL( Fs_Hz_in, 2 ) ) { /* Fs_out : Fs_in = 2 : 3 */ |
michael@0 | 133 | S->FIR_Fracs = 2; |
michael@0 | 134 | S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR0; |
michael@0 | 135 | S->Coefs = silk_Resampler_2_3_COEFS; |
michael@0 | 136 | } else if( silk_MUL( Fs_Hz_out, 2 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 2 */ |
michael@0 | 137 | S->FIR_Fracs = 1; |
michael@0 | 138 | S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR1; |
michael@0 | 139 | S->Coefs = silk_Resampler_1_2_COEFS; |
michael@0 | 140 | } else if( silk_MUL( Fs_Hz_out, 3 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 3 */ |
michael@0 | 141 | S->FIR_Fracs = 1; |
michael@0 | 142 | S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR2; |
michael@0 | 143 | S->Coefs = silk_Resampler_1_3_COEFS; |
michael@0 | 144 | } else if( silk_MUL( Fs_Hz_out, 4 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 4 */ |
michael@0 | 145 | S->FIR_Fracs = 1; |
michael@0 | 146 | S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR2; |
michael@0 | 147 | S->Coefs = silk_Resampler_1_4_COEFS; |
michael@0 | 148 | } else if( silk_MUL( Fs_Hz_out, 6 ) == Fs_Hz_in ) { /* Fs_out : Fs_in = 1 : 6 */ |
michael@0 | 149 | S->FIR_Fracs = 1; |
michael@0 | 150 | S->FIR_Order = RESAMPLER_DOWN_ORDER_FIR2; |
michael@0 | 151 | S->Coefs = silk_Resampler_1_6_COEFS; |
michael@0 | 152 | } else { |
michael@0 | 153 | /* None available */ |
michael@0 | 154 | silk_assert( 0 ); |
michael@0 | 155 | return -1; |
michael@0 | 156 | } |
michael@0 | 157 | } else { |
michael@0 | 158 | /* Input and output sampling rates are equal: copy */ |
michael@0 | 159 | S->resampler_function = USE_silk_resampler_copy; |
michael@0 | 160 | } |
michael@0 | 161 | |
michael@0 | 162 | /* Ratio of input/output samples */ |
michael@0 | 163 | S->invRatio_Q16 = silk_LSHIFT32( silk_DIV32( silk_LSHIFT32( Fs_Hz_in, 14 + up2x ), Fs_Hz_out ), 2 ); |
michael@0 | 164 | /* Make sure the ratio is rounded up */ |
michael@0 | 165 | while( silk_SMULWW( S->invRatio_Q16, Fs_Hz_out ) < silk_LSHIFT32( Fs_Hz_in, up2x ) ) { |
michael@0 | 166 | S->invRatio_Q16++; |
michael@0 | 167 | } |
michael@0 | 168 | |
michael@0 | 169 | return 0; |
michael@0 | 170 | } |
michael@0 | 171 | |
michael@0 | 172 | /* Resampler: convert from one sampling rate to another */ |
michael@0 | 173 | /* Input and output sampling rate are at most 48000 Hz */ |
michael@0 | 174 | opus_int silk_resampler( |
michael@0 | 175 | silk_resampler_state_struct *S, /* I/O Resampler state */ |
michael@0 | 176 | opus_int16 out[], /* O Output signal */ |
michael@0 | 177 | const opus_int16 in[], /* I Input signal */ |
michael@0 | 178 | opus_int32 inLen /* I Number of input samples */ |
michael@0 | 179 | ) |
michael@0 | 180 | { |
michael@0 | 181 | opus_int nSamples; |
michael@0 | 182 | |
michael@0 | 183 | /* Need at least 1 ms of input data */ |
michael@0 | 184 | silk_assert( inLen >= S->Fs_in_kHz ); |
michael@0 | 185 | /* Delay can't exceed the 1 ms of buffering */ |
michael@0 | 186 | silk_assert( S->inputDelay <= S->Fs_in_kHz ); |
michael@0 | 187 | |
michael@0 | 188 | nSamples = S->Fs_in_kHz - S->inputDelay; |
michael@0 | 189 | |
michael@0 | 190 | /* Copy to delay buffer */ |
michael@0 | 191 | silk_memcpy( &S->delayBuf[ S->inputDelay ], in, nSamples * sizeof( opus_int16 ) ); |
michael@0 | 192 | |
michael@0 | 193 | switch( S->resampler_function ) { |
michael@0 | 194 | case USE_silk_resampler_private_up2_HQ_wrapper: |
michael@0 | 195 | silk_resampler_private_up2_HQ_wrapper( S, out, S->delayBuf, S->Fs_in_kHz ); |
michael@0 | 196 | silk_resampler_private_up2_HQ_wrapper( S, &out[ S->Fs_out_kHz ], &in[ nSamples ], inLen - S->Fs_in_kHz ); |
michael@0 | 197 | break; |
michael@0 | 198 | case USE_silk_resampler_private_IIR_FIR: |
michael@0 | 199 | silk_resampler_private_IIR_FIR( S, out, S->delayBuf, S->Fs_in_kHz ); |
michael@0 | 200 | silk_resampler_private_IIR_FIR( S, &out[ S->Fs_out_kHz ], &in[ nSamples ], inLen - S->Fs_in_kHz ); |
michael@0 | 201 | break; |
michael@0 | 202 | case USE_silk_resampler_private_down_FIR: |
michael@0 | 203 | silk_resampler_private_down_FIR( S, out, S->delayBuf, S->Fs_in_kHz ); |
michael@0 | 204 | silk_resampler_private_down_FIR( S, &out[ S->Fs_out_kHz ], &in[ nSamples ], inLen - S->Fs_in_kHz ); |
michael@0 | 205 | break; |
michael@0 | 206 | default: |
michael@0 | 207 | silk_memcpy( out, S->delayBuf, S->Fs_in_kHz * sizeof( opus_int16 ) ); |
michael@0 | 208 | silk_memcpy( &out[ S->Fs_out_kHz ], &in[ nSamples ], ( inLen - S->Fs_in_kHz ) * sizeof( opus_int16 ) ); |
michael@0 | 209 | } |
michael@0 | 210 | |
michael@0 | 211 | /* Copy to delay buffer */ |
michael@0 | 212 | silk_memcpy( S->delayBuf, &in[ inLen - S->inputDelay ], S->inputDelay * sizeof( opus_int16 ) ); |
michael@0 | 213 | |
michael@0 | 214 | return 0; |
michael@0 | 215 | } |