blob: 783e42b35617e492624132ad811a209b8a3d4b5e [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
Jean-Marc Valinae00e602012-04-20 16:31:04 -04004modification, are permitted provided that the following conditions
5are met:
Gregory Maxwellae231142011-07-30 08:18:48 -04006- 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.
Ralph Gilesf2446c22013-09-16 14:40:04 -070011- Neither the name of Internet Society, IETF or IETF Trust, nor the
Jean-Marc Valinae00e602012-04-20 16:31:04 -040012names of specific contributors, may be used to endorse or promote
13products derived from this software without specific prior written
14permission.
Timothy B. Terriberry80ad3832013-05-19 18:00:39 -070015THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
Jean-Marc Valinae00e602012-04-20 16:31:04 -040016AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25POSSIBILITY OF SUCH DAMAGE.
Gregory Maxwellae231142011-07-30 08:18:48 -040026***********************************************************************/
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"
Timothy B. Terriberryc152d602013-05-08 10:32:37 -070034#include "stack_alloc.h"
Gregory Maxwellae231142011-07-30 08:18:48 -040035
Gregory Maxwell7830cf12013-10-17 15:56:52 -070036static OPUS_INLINE opus_int16 *silk_resampler_private_down_FIR_INTERPOL(
Ralph Giles5f6e4722012-03-19 17:10:13 -070037 opus_int16 *out,
38 opus_int32 *buf,
39 const opus_int16 *FIR_Coefs,
Koen Vosbf75c8e2011-12-13 14:47:31 -050040 opus_int FIR_Order,
41 opus_int FIR_Fracs,
Ralph Giles5f6e4722012-03-19 17:10:13 -070042 opus_int32 max_index_Q16,
Koen Vosacc7a6c2011-10-28 19:44:26 -040043 opus_int32 index_increment_Q16
44)
45{
Gregory Maxwellae231142011-07-30 08:18:48 -040046 opus_int32 index_Q16, res_Q6;
47 opus_int32 *buf_ptr;
Gregory Maxwellae231142011-07-30 08:18:48 -040048 opus_int32 interpol_ind;
49 const opus_int16 *interpol_ptr;
Koen Vosacc7a6c2011-10-28 19:44:26 -040050
Koen Vosbf75c8e2011-12-13 14:47:31 -050051 switch( FIR_Order ) {
52 case RESAMPLER_DOWN_ORDER_FIR0:
53 for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) {
54 /* Integer part gives pointer to buffered input */
55 buf_ptr = buf + silk_RSHIFT( index_Q16, 16 );
Gregory Maxwellae231142011-07-30 08:18:48 -040056
Koen Vosbf75c8e2011-12-13 14:47:31 -050057 /* Fractional part gives interpolation coefficients */
58 interpol_ind = silk_SMULWB( index_Q16 & 0xFFFF, FIR_Fracs );
Gregory Maxwellae231142011-07-30 08:18:48 -040059
Koen Vosbf75c8e2011-12-13 14:47:31 -050060 /* Inner product */
61 interpol_ptr = &FIR_Coefs[ RESAMPLER_DOWN_ORDER_FIR0 / 2 * interpol_ind ];
62 res_Q6 = silk_SMULWB( buf_ptr[ 0 ], interpol_ptr[ 0 ] );
63 res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 1 ], interpol_ptr[ 1 ] );
64 res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 2 ], interpol_ptr[ 2 ] );
65 res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 3 ], interpol_ptr[ 3 ] );
66 res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 4 ], interpol_ptr[ 4 ] );
67 res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 5 ], interpol_ptr[ 5 ] );
68 res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 6 ], interpol_ptr[ 6 ] );
69 res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 7 ], interpol_ptr[ 7 ] );
70 res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 8 ], interpol_ptr[ 8 ] );
71 interpol_ptr = &FIR_Coefs[ RESAMPLER_DOWN_ORDER_FIR0 / 2 * ( FIR_Fracs - 1 - interpol_ind ) ];
72 res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 17 ], interpol_ptr[ 0 ] );
73 res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 16 ], interpol_ptr[ 1 ] );
74 res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 15 ], interpol_ptr[ 2 ] );
75 res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 14 ], interpol_ptr[ 3 ] );
76 res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 13 ], interpol_ptr[ 4 ] );
77 res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 12 ], interpol_ptr[ 5 ] );
78 res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 11 ], interpol_ptr[ 6 ] );
79 res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 10 ], interpol_ptr[ 7 ] );
80 res_Q6 = silk_SMLAWB( res_Q6, buf_ptr[ 9 ], interpol_ptr[ 8 ] );
Gregory Maxwellae231142011-07-30 08:18:48 -040081
Koen Vosbf75c8e2011-12-13 14:47:31 -050082 /* Scale down, saturate and store in output array */
83 *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) );
84 }
85 break;
86 case RESAMPLER_DOWN_ORDER_FIR1:
87 for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) {
88 /* Integer part gives pointer to buffered input */
89 buf_ptr = buf + silk_RSHIFT( index_Q16, 16 );
90
91 /* Inner product */
92 res_Q6 = silk_SMULWB( silk_ADD32( buf_ptr[ 0 ], buf_ptr[ 23 ] ), FIR_Coefs[ 0 ] );
93 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 1 ], buf_ptr[ 22 ] ), FIR_Coefs[ 1 ] );
94 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 2 ], buf_ptr[ 21 ] ), FIR_Coefs[ 2 ] );
95 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 3 ], buf_ptr[ 20 ] ), FIR_Coefs[ 3 ] );
96 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 4 ], buf_ptr[ 19 ] ), FIR_Coefs[ 4 ] );
97 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 5 ], buf_ptr[ 18 ] ), FIR_Coefs[ 5 ] );
98 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 6 ], buf_ptr[ 17 ] ), FIR_Coefs[ 6 ] );
99 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 7 ], buf_ptr[ 16 ] ), FIR_Coefs[ 7 ] );
100 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 8 ], buf_ptr[ 15 ] ), FIR_Coefs[ 8 ] );
101 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 9 ], buf_ptr[ 14 ] ), FIR_Coefs[ 9 ] );
102 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 10 ], buf_ptr[ 13 ] ), FIR_Coefs[ 10 ] );
103 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 11 ], buf_ptr[ 12 ] ), FIR_Coefs[ 11 ] );
104
105 /* Scale down, saturate and store in output array */
106 *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) );
107 }
108 break;
109 case RESAMPLER_DOWN_ORDER_FIR2:
110 for( index_Q16 = 0; index_Q16 < max_index_Q16; index_Q16 += index_increment_Q16 ) {
111 /* Integer part gives pointer to buffered input */
112 buf_ptr = buf + silk_RSHIFT( index_Q16, 16 );
113
114 /* Inner product */
115 res_Q6 = silk_SMULWB( silk_ADD32( buf_ptr[ 0 ], buf_ptr[ 35 ] ), FIR_Coefs[ 0 ] );
116 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 1 ], buf_ptr[ 34 ] ), FIR_Coefs[ 1 ] );
117 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 2 ], buf_ptr[ 33 ] ), FIR_Coefs[ 2 ] );
118 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 3 ], buf_ptr[ 32 ] ), FIR_Coefs[ 3 ] );
119 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 4 ], buf_ptr[ 31 ] ), FIR_Coefs[ 4 ] );
120 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 5 ], buf_ptr[ 30 ] ), FIR_Coefs[ 5 ] );
121 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 6 ], buf_ptr[ 29 ] ), FIR_Coefs[ 6 ] );
122 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 7 ], buf_ptr[ 28 ] ), FIR_Coefs[ 7 ] );
123 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 8 ], buf_ptr[ 27 ] ), FIR_Coefs[ 8 ] );
124 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 9 ], buf_ptr[ 26 ] ), FIR_Coefs[ 9 ] );
125 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 10 ], buf_ptr[ 25 ] ), FIR_Coefs[ 10 ] );
126 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 11 ], buf_ptr[ 24 ] ), FIR_Coefs[ 11 ] );
127 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 12 ], buf_ptr[ 23 ] ), FIR_Coefs[ 12 ] );
128 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 13 ], buf_ptr[ 22 ] ), FIR_Coefs[ 13 ] );
129 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 14 ], buf_ptr[ 21 ] ), FIR_Coefs[ 14 ] );
130 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 15 ], buf_ptr[ 20 ] ), FIR_Coefs[ 15 ] );
131 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 16 ], buf_ptr[ 19 ] ), FIR_Coefs[ 16 ] );
132 res_Q6 = silk_SMLAWB( res_Q6, silk_ADD32( buf_ptr[ 17 ], buf_ptr[ 18 ] ), FIR_Coefs[ 17 ] );
133
134 /* Scale down, saturate and store in output array */
135 *out++ = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( res_Q6, 6 ) );
136 }
137 break;
138 default:
139 silk_assert( 0 );
Gregory Maxwellae231142011-07-30 08:18:48 -0400140 }
141 return out;
142}
143
Koen Vosbf75c8e2011-12-13 14:47:31 -0500144/* Resample with a 2nd order AR filter followed by FIR interpolation */
Gregory Maxwellae231142011-07-30 08:18:48 -0400145void silk_resampler_private_down_FIR(
Koen Vosacc7a6c2011-10-28 19:44:26 -0400146 void *SS, /* I/O Resampler state */
147 opus_int16 out[], /* O Output signal */
148 const opus_int16 in[], /* I Input signal */
149 opus_int32 inLen /* I Number of input samples */
Gregory Maxwellae231142011-07-30 08:18:48 -0400150)
151{
152 silk_resampler_state_struct *S = (silk_resampler_state_struct *)SS;
153 opus_int32 nSamplesIn;
154 opus_int32 max_index_Q16, index_increment_Q16;
Timothy B. Terriberryc152d602013-05-08 10:32:37 -0700155 VARDECL( opus_int32, buf );
Gregory Maxwellae231142011-07-30 08:18:48 -0400156 const opus_int16 *FIR_Coefs;
Timothy B. Terriberryc152d602013-05-08 10:32:37 -0700157 SAVE_STACK;
158
159 ALLOC( buf, S->batchSize + S->FIR_Order, opus_int32 );
Gregory Maxwellae231142011-07-30 08:18:48 -0400160
161 /* Copy buffered samples to start of buffer */
Timothy B. Terriberrydc585792013-05-08 10:25:52 -0700162 silk_memcpy( buf, S->sFIR.i32, S->FIR_Order * sizeof( opus_int32 ) );
Gregory Maxwellae231142011-07-30 08:18:48 -0400163
164 FIR_Coefs = &S->Coefs[ 2 ];
165
166 /* Iterate over blocks of frameSizeIn input samples */
167 index_increment_Q16 = S->invRatio_Q16;
168 while( 1 ) {
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -0700169 nSamplesIn = silk_min( inLen, S->batchSize );
Gregory Maxwellae231142011-07-30 08:18:48 -0400170
Koen Vosbf75c8e2011-12-13 14:47:31 -0500171 /* Second-order AR filter (output in Q8) */
172 silk_resampler_private_AR2( S->sIIR, &buf[ S->FIR_Order ], in, S->Coefs, nSamplesIn );
Gregory Maxwellae231142011-07-30 08:18:48 -0400173
Jean-Marc Valinfb3a4372011-09-16 00:58:26 -0700174 max_index_Q16 = silk_LSHIFT32( nSamplesIn, 16 );
Gregory Maxwellae231142011-07-30 08:18:48 -0400175
176 /* Interpolate filtered signal */
Ralph Giles5f6e4722012-03-19 17:10:13 -0700177 out = silk_resampler_private_down_FIR_INTERPOL( out, buf, FIR_Coefs, S->FIR_Order,
Koen Vosbf75c8e2011-12-13 14:47:31 -0500178 S->FIR_Fracs, max_index_Q16, index_increment_Q16 );
Gregory Maxwellae231142011-07-30 08:18:48 -0400179
Koen Vosbf75c8e2011-12-13 14:47:31 -0500180 in += nSamplesIn;
181 inLen -= nSamplesIn;
Gregory Maxwellae231142011-07-30 08:18:48 -0400182
Koen Vosbf75c8e2011-12-13 14:47:31 -0500183 if( inLen > 1 ) {
Gregory Maxwellae231142011-07-30 08:18:48 -0400184 /* More iterations to do; copy last part of filtered signal to beginning of buffer */
Koen Vosbf75c8e2011-12-13 14:47:31 -0500185 silk_memcpy( buf, &buf[ nSamplesIn ], S->FIR_Order * sizeof( opus_int32 ) );
Gregory Maxwellae231142011-07-30 08:18:48 -0400186 } else {
187 break;
188 }
189 }
190
191 /* Copy last part of filtered signal to the state for the next call */
Timothy B. Terriberrydc585792013-05-08 10:25:52 -0700192 silk_memcpy( S->sFIR.i32, &buf[ nSamplesIn ], S->FIR_Order * sizeof( opus_int32 ) );
Timothy B. Terriberryc152d602013-05-08 10:32:37 -0700193 RESTORE_STACK;
Gregory Maxwellae231142011-07-30 08:18:48 -0400194}