|
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 "resampler_private.h" |
|
34 #include "stack_alloc.h" |
|
35 |
|
36 static OPUS_INLINE opus_int16 *silk_resampler_private_IIR_FIR_INTERPOL( |
|
37 opus_int16 *out, |
|
38 opus_int16 *buf, |
|
39 opus_int32 max_index_Q16, |
|
40 opus_int32 index_increment_Q16 |
|
41 ) |
|
42 { |
|
43 opus_int32 index_Q16, res_Q15; |
|
44 opus_int16 *buf_ptr; |
|
45 opus_int32 table_index; |
|
46 |
|
47 /* Interpolate upsampled signal and store in output array */ |
|
48 for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) { |
|
49 table_index = silk_SMULWB( index_Q16 & 0xFFFF, 12 ); |
|
50 buf_ptr = &buf[ index_Q16 >> 16 ]; |
|
51 |
|
52 res_Q15 = silk_SMULBB( buf_ptr[ 0 ], silk_resampler_frac_FIR_12[ table_index ][ 0 ] ); |
|
53 res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 1 ], silk_resampler_frac_FIR_12[ table_index ][ 1 ] ); |
|
54 res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 2 ], silk_resampler_frac_FIR_12[ table_index ][ 2 ] ); |
|
55 res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 3 ], silk_resampler_frac_FIR_12[ table_index ][ 3 ] ); |
|
56 res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 4 ], silk_resampler_frac_FIR_12[ 11 - table_index ][ 3 ] ); |
|
57 res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 5 ], silk_resampler_frac_FIR_12[ 11 - table_index ][ 2 ] ); |
|
58 res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 6 ], silk_resampler_frac_FIR_12[ 11 - table_index ][ 1 ] ); |
|
59 res_Q15 = silk_SMLABB( res_Q15, buf_ptr[ 7 ], silk_resampler_frac_FIR_12[ 11 - table_index ][ 0 ] ); |
|
60 *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q15, 15 ) ); |
|
61 } |
|
62 return out; |
|
63 } |
|
64 /* Upsample using a combination of allpass-based 2x upsampling and FIR interpolation */ |
|
65 void silk_resampler_private_IIR_FIR( |
|
66 void *SS, /* I/O Resampler state */ |
|
67 opus_int16 out[], /* O Output signal */ |
|
68 const opus_int16 in[], /* I Input signal */ |
|
69 opus_int32 inLen /* I Number of input samples */ |
|
70 ) |
|
71 { |
|
72 silk_resampler_state_struct *S = (silk_resampler_state_struct *)SS; |
|
73 opus_int32 nSamplesIn; |
|
74 opus_int32 max_index_Q16, index_increment_Q16; |
|
75 VARDECL( opus_int16, buf ); |
|
76 SAVE_STACK; |
|
77 |
|
78 ALLOC( buf, 2 * S->batchSize + RESAMPLER_ORDER_FIR_12, opus_int16 ); |
|
79 |
|
80 /* Copy buffered samples to start of buffer */ |
|
81 silk_memcpy( buf, S->sFIR.i16, RESAMPLER_ORDER_FIR_12 * sizeof( opus_int16 ) ); |
|
82 |
|
83 /* Iterate over blocks of frameSizeIn input samples */ |
|
84 index_increment_Q16 = S->invRatio_Q16; |
|
85 while( 1 ) { |
|
86 nSamplesIn = silk_min( inLen, S->batchSize ); |
|
87 |
|
88 /* Upsample 2x */ |
|
89 silk_resampler_private_up2_HQ( S->sIIR, &buf[ RESAMPLER_ORDER_FIR_12 ], in, nSamplesIn ); |
|
90 |
|
91 max_index_Q16 = silk_LSHIFT32( nSamplesIn, 16 + 1 ); /* + 1 because 2x upsampling */ |
|
92 out = silk_resampler_private_IIR_FIR_INTERPOL( out, buf, max_index_Q16, index_increment_Q16 ); |
|
93 in += nSamplesIn; |
|
94 inLen -= nSamplesIn; |
|
95 |
|
96 if( inLen > 0 ) { |
|
97 /* More iterations to do; copy last part of filtered signal to beginning of buffer */ |
|
98 silk_memcpy( buf, &buf[ nSamplesIn << 1 ], RESAMPLER_ORDER_FIR_12 * sizeof( opus_int16 ) ); |
|
99 } else { |
|
100 break; |
|
101 } |
|
102 } |
|
103 |
|
104 /* Copy last part of filtered signal to the state for the next call */ |
|
105 silk_memcpy( S->sFIR.i16, &buf[ nSamplesIn << 1 ], RESAMPLER_ORDER_FIR_12 * sizeof( opus_int16 ) ); |
|
106 RESTORE_STACK; |
|
107 } |