blob: 028a200e3d843188d20b7f20793b77e2c2c95910 [file] [log] [blame]
Gregory Maxwellae231142011-07-30 08:18:48 -04001/***********************************************************************
2Copyright (c) 2006-2011, Skype Limited. All rights reserved.
3Redistribution and use in source and binary forms, with or without
4modification, (subject to the limitations in the disclaimer below)
5are permitted provided that the following conditions are met:
6- Redistributions of source code must retain the above copyright notice,
7this list of conditions and the following disclaimer.
8- Redistributions in binary form must reproduce the above copyright
9notice, this list of conditions and the following disclaimer in the
10documentation and/or other materials provided with the distribution.
11- Neither the name of Skype Limited, nor the names of specific
12contributors, may be used to endorse or promote products derived from
13this software without specific prior written permission.
14NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
15BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
16CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
17BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
18FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
22USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
23ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26***********************************************************************/
27
Jean-Marc Valin5a484122011-08-15 10:49:53 -040028#ifdef HAVE_CONFIG_H
29#include "config.h"
30#endif
31
Jean-Marc Valin1c2f5632011-09-16 01:16:53 -070032#include "SigProc_FIX.h"
33#include "resampler_private.h"
Gregory Maxwellae231142011-07-30 08:18:48 -040034
Jean-Marc Valin4dc0b392011-08-15 11:24:37 -040035static inline opus_int16 *silk_resampler_private_down_FIR_INTERPOL0(
Gregory Maxwellae231142011-07-30 08:18:48 -040036 opus_int16 *out, opus_int32 *buf2, const opus_int16 *FIR_Coefs, opus_int32 max_index_Q16, opus_int32 index_increment_Q16){
37
38 opus_int32 index_Q16, res_Q6;
39 opus_int32 *buf_ptr;
40 for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) {
41 /* Integer part gives pointer to buffered input */
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -070042 buf_ptr = buf2 + silk_RSHIFT( index_Q16, 16 );
Gregory Maxwellae231142011-07-30 08:18:48 -040043
44 /* Inner product */
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -070045 res_Q6 = silk_SMULWB( silk_ADD32( buf_ptr[ 0 ], buf_ptr[ 15 ] ), FIR_Coefs[ 0 ] );
46 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 1 ], buf_ptr[ 14 ] ), FIR_Coefs[ 1 ] );
47 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 2 ], buf_ptr[ 13 ] ), FIR_Coefs[ 2 ] );
48 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 3 ], buf_ptr[ 12 ] ), FIR_Coefs[ 3 ] );
49 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 4 ], buf_ptr[ 11 ] ), FIR_Coefs[ 4 ] );
50 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 5 ], buf_ptr[ 10 ] ), FIR_Coefs[ 5 ] );
51 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 6 ], buf_ptr[ 9 ] ), FIR_Coefs[ 6 ] );
52 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 7 ], buf_ptr[ 8 ] ), FIR_Coefs[ 7 ] );
Gregory Maxwellae231142011-07-30 08:18:48 -040053
54 /* Scale down, saturate and store in output array */
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -070055 *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) );
Gregory Maxwellae231142011-07-30 08:18:48 -040056 }
57 return out;
58}
59
Jean-Marc Valin4dc0b392011-08-15 11:24:37 -040060static inline opus_int16 *silk_resampler_private_down_FIR_INTERPOL1(
Gregory Maxwellae231142011-07-30 08:18:48 -040061 opus_int16 *out, opus_int32 *buf2, const opus_int16 *FIR_Coefs, opus_int32 max_index_Q16, opus_int32 index_increment_Q16, opus_int32 FIR_Fracs){
62
63 opus_int32 index_Q16, res_Q6;
64 opus_int32 *buf_ptr;
65 opus_int32 interpol_ind;
66 const opus_int16 *interpol_ptr;
67 for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) {
68 /* Integer part gives pointer to buffered input */
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -070069 buf_ptr = buf2 + silk_RSHIFT( index_Q16, 16 );
Gregory Maxwellae231142011-07-30 08:18:48 -040070
71 /* Fractional part gives interpolation coefficients */
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -070072 interpol_ind = silk_SMULWB( index_Q16 & 0xFFFF, FIR_Fracs );
Gregory Maxwellae231142011-07-30 08:18:48 -040073
74 /* Inner product */
75 interpol_ptr = &FIR_Coefs[ RESAMPLER_DOWN_ORDER_FIR / 2 * interpol_ind ];
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -070076 res_Q6 = silk_SMULWB( buf_ptr[ 0 ], interpol_ptr[ 0 ] );
77 res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 1 ], interpol_ptr[ 1 ] );
78 res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 2 ], interpol_ptr[ 2 ] );
79 res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 3 ], interpol_ptr[ 3 ] );
80 res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 4 ], interpol_ptr[ 4 ] );
81 res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 5 ], interpol_ptr[ 5 ] );
82 res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 6 ], interpol_ptr[ 6 ] );
83 res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 7 ], interpol_ptr[ 7 ] );
Gregory Maxwellae231142011-07-30 08:18:48 -040084 interpol_ptr = &FIR_Coefs[ RESAMPLER_DOWN_ORDER_FIR / 2 * ( FIR_Fracs - 1 - interpol_ind ) ];
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -070085 res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 15 ], interpol_ptr[ 0 ] );
86 res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 14 ], interpol_ptr[ 1 ] );
87 res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 13 ], interpol_ptr[ 2 ] );
88 res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 12 ], interpol_ptr[ 3 ] );
89 res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 11 ], interpol_ptr[ 4 ] );
90 res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 10 ], interpol_ptr[ 5 ] );
91 res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 9 ], interpol_ptr[ 6 ] );
92 res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 8 ], interpol_ptr[ 7 ] );
Gregory Maxwellae231142011-07-30 08:18:48 -040093
94 /* Scale down, saturate and store in output array */
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -070095 *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) );
Gregory Maxwellae231142011-07-30 08:18:48 -040096 }
97 return out;
98}
99
100
101/* Resample with a 2x downsampler (optional), a 2nd order AR filter followed by FIR interpolation */
102void silk_resampler_private_down_FIR(
103 void *SS, /* I/O: Resampler state */
104 opus_int16 out[], /* O: Output signal */
105 const opus_int16 in[], /* I: Input signal */
106 opus_int32 inLen /* I: Number of input samples */
107)
108{
109 silk_resampler_state_struct *S = (silk_resampler_state_struct *)SS;
110 opus_int32 nSamplesIn;
111 opus_int32 max_index_Q16, index_increment_Q16;
112 opus_int16 buf1[ RESAMPLER_MAX_BATCH_SIZE_IN / 2 ];
113 opus_int32 buf2[ RESAMPLER_MAX_BATCH_SIZE_IN + RESAMPLER_DOWN_ORDER_FIR ];
114 const opus_int16 *FIR_Coefs;
115
116 /* Copy buffered samples to start of buffer */
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -0700117 silk_memcpy( buf2, S->sFIR, RESAMPLER_DOWN_ORDER_FIR * sizeof( opus_int32 ) );
Gregory Maxwellae231142011-07-30 08:18:48 -0400118
119 FIR_Coefs = &S->Coefs[ 2 ];
120
121 /* Iterate over blocks of frameSizeIn input samples */
122 index_increment_Q16 = S->invRatio_Q16;
123 while( 1 ) {
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -0700124 nSamplesIn = silk_min( inLen, S->batchSize );
Gregory Maxwellae231142011-07-30 08:18:48 -0400125
126 if( S->input2x == 1 ) {
127 /* Downsample 2x */
128 silk_resampler_down2( S->sDown2, buf1, in, nSamplesIn );
129
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -0700130 nSamplesIn = silk_RSHIFT32( nSamplesIn, 1 );
Gregory Maxwellae231142011-07-30 08:18:48 -0400131
132 /* Second-order AR filter (output in Q8) */
133 silk_resampler_private_AR2( S->sIIR, &buf2[ RESAMPLER_DOWN_ORDER_FIR ], buf1, S->Coefs, nSamplesIn );
134 } else {
135 /* Second-order AR filter (output in Q8) */
136 silk_resampler_private_AR2( S->sIIR, &buf2[ RESAMPLER_DOWN_ORDER_FIR ], in, S->Coefs, nSamplesIn );
137 }
138
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -0700139 max_index_Q16 = silk_LSHIFT32( nSamplesIn, 16 );
Gregory Maxwellae231142011-07-30 08:18:48 -0400140
141 /* Interpolate filtered signal */
142 if( S->FIR_Fracs == 1 ) {
143 out = silk_resampler_private_down_FIR_INTERPOL0(out, buf2, FIR_Coefs, max_index_Q16, index_increment_Q16);
144 } else {
145 out = silk_resampler_private_down_FIR_INTERPOL1(out, buf2, FIR_Coefs, max_index_Q16, index_increment_Q16, S->FIR_Fracs);
146 }
147
148 in += nSamplesIn << S->input2x;
149 inLen -= nSamplesIn << S->input2x;
150
151 if( inLen > S->input2x ) {
152 /* More iterations to do; copy last part of filtered signal to beginning of buffer */
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -0700153 silk_memcpy( buf2, &buf2[ nSamplesIn ], RESAMPLER_DOWN_ORDER_FIR * sizeof( opus_int32 ) );
Gregory Maxwellae231142011-07-30 08:18:48 -0400154 } else {
155 break;
156 }
157 }
158
159 /* Copy last part of filtered signal to the state for the next call */
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -0700160 silk_memcpy( S->sFIR, &buf2[ nSamplesIn ], RESAMPLER_DOWN_ORDER_FIR * sizeof( opus_int32 ) );
Gregory Maxwellae231142011-07-30 08:18:48 -0400161}
162