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