1 /* 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 12 /* 13 * This file contains the resampling by two functions. 14 * The description header can be found in signal_processing_library.h 15 * 16 */ 17 18 #if defined(MIPS32_LE) 19 20 #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h" 21 22 // allpass filter coefficients. 23 static const uint16_t kResampleAllpass1[3] = {3284, 24441, 49528}; 24 static const uint16_t kResampleAllpass2[3] = {12199, 37471, 60255}; 25 26 // Multiply a 32-bit value with a 16-bit value and accumulate to another input: 27 #define MUL_ACCUM_1(a, b, c) WEBRTC_SPL_SCALEDIFF32(a, b, c) 28 #define MUL_ACCUM_2(a, b, c) WEBRTC_SPL_SCALEDIFF32(a, b, c) 29 30 // decimator 31 void WebRtcSpl_DownsampleBy2(const int16_t* in, 32 int16_t len, 33 int16_t* out, 34 int32_t* filtState) { 35 int32_t out32; 36 int16_t i, len1; 37 38 register int32_t state0 = filtState[0]; 39 register int32_t state1 = filtState[1]; 40 register int32_t state2 = filtState[2]; 41 register int32_t state3 = filtState[3]; 42 register int32_t state4 = filtState[4]; 43 register int32_t state5 = filtState[5]; 44 register int32_t state6 = filtState[6]; 45 register int32_t state7 = filtState[7]; 46 47 #if defined(MIPS_DSP_R2_LE) 48 int32_t k1Res0, k1Res1, k1Res2, k2Res0, k2Res1, k2Res2; 49 50 k1Res0= 3284; 51 k1Res1= 24441; 52 k1Res2= 49528; 53 k2Res0= 12199; 54 k2Res1= 37471; 55 k2Res2= 60255; 56 len1 = (len >> 1); 57 58 const int32_t* inw = (int32_t*)in; 59 int32_t tmp11, tmp12, tmp21, tmp22; 60 int32_t in322, in321; 61 int32_t diff1, diff2; 62 for (i = len1; i > 0; i--) { 63 __asm__ volatile ( 64 "lh %[in321], 0(%[inw]) \n\t" 65 "lh %[in322], 2(%[inw]) \n\t" 66 67 "sll %[in321], %[in321], 10 \n\t" 68 "sll %[in322], %[in322], 10 \n\t" 69 70 "addiu %[inw], %[inw], 4 \n\t" 71 72 "subu %[diff1], %[in321], %[state1] \n\t" 73 "subu %[diff2], %[in322], %[state5] \n\t" 74 75 : [in322] "=&r" (in322), [in321] "=&r" (in321), 76 [diff1] "=&r" (diff1), [diff2] "=r" (diff2), [inw] "+r" (inw) 77 : [state1] "r" (state1), [state5] "r" (state5) 78 : "memory" 79 ); 80 81 __asm__ volatile ( 82 "mult $ac0, %[diff1], %[k2Res0] \n\t" 83 "mult $ac1, %[diff2], %[k1Res0] \n\t" 84 85 "extr.w %[tmp11], $ac0, 16 \n\t" 86 "extr.w %[tmp12], $ac1, 16 \n\t" 87 88 "addu %[tmp11], %[state0], %[tmp11] \n\t" 89 "addu %[tmp12], %[state4], %[tmp12] \n\t" 90 91 "addiu %[state0], %[in321], 0 \n\t" 92 "addiu %[state4], %[in322], 0 \n\t" 93 94 "subu %[diff1], %[tmp11], %[state2] \n\t" 95 "subu %[diff2], %[tmp12], %[state6] \n\t" 96 97 "mult $ac0, %[diff1], %[k2Res1] \n\t" 98 "mult $ac1, %[diff2], %[k1Res1] \n\t" 99 100 "extr.w %[tmp21], $ac0, 16 \n\t" 101 "extr.w %[tmp22], $ac1, 16 \n\t" 102 103 "addu %[tmp21], %[state1], %[tmp21] \n\t" 104 "addu %[tmp22], %[state5], %[tmp22] \n\t" 105 106 "addiu %[state1], %[tmp11], 0 \n\t" 107 "addiu %[state5], %[tmp12], 0 \n\t" 108 : [tmp22] "=r" (tmp22), [tmp21] "=&r" (tmp21), 109 [tmp11] "=&r" (tmp11), [state0] "+r" (state0), 110 [state1] "+r" (state1), 111 [state2] "+r" (state2), 112 [state4] "+r" (state4), [tmp12] "=&r" (tmp12), 113 [state6] "+r" (state6), [state5] "+r" (state5) 114 : [k1Res1] "r" (k1Res1), [k2Res1] "r" (k2Res1), [k2Res0] "r" (k2Res0), 115 [diff2] "r" (diff2), [diff1] "r" (diff1), [in322] "r" (in322), 116 [in321] "r" (in321), [k1Res0] "r" (k1Res0) 117 : "hi", "lo", "$ac1hi", "$ac1lo" 118 ); 119 120 // upper allpass filter 121 __asm__ volatile ( 122 "subu %[diff1], %[tmp21], %[state3] \n\t" 123 "subu %[diff2], %[tmp22], %[state7] \n\t" 124 125 "mult $ac0, %[diff1], %[k2Res2] \n\t" 126 "mult $ac1, %[diff2], %[k1Res2] \n\t" 127 "extr.w %[state3], $ac0, 16 \n\t" 128 "extr.w %[state7], $ac1, 16 \n\t" 129 "addu %[state3], %[state2], %[state3] \n\t" 130 "addu %[state7], %[state6], %[state7] \n\t" 131 132 "addiu %[state2], %[tmp21], 0 \n\t" 133 "addiu %[state6], %[tmp22], 0 \n\t" 134 135 // add two allpass outputs, divide by two and round 136 "addu %[out32], %[state3], %[state7] \n\t" 137 "addiu %[out32], %[out32], 1024 \n\t" 138 "sra %[out32], %[out32], 11 \n\t" 139 : [state3] "+r" (state3), [state6] "+r" (state6), 140 [state2] "+r" (state2), [diff2] "=&r" (diff2), 141 [out32] "=r" (out32), [diff1] "=&r" (diff1), [state7] "+r" (state7) 142 : [tmp22] "r" (tmp22), [tmp21] "r" (tmp21), 143 [k1Res2] "r" (k1Res2), [k2Res2] "r" (k2Res2) 144 : "hi", "lo", "$ac1hi", "$ac1lo" 145 ); 146 147 // limit amplitude to prevent wrap-around, and write to output array 148 *out++ = WebRtcSpl_SatW32ToW16(out32); 149 } 150 #else // #if defined(MIPS_DSP_R2_LE) 151 int32_t tmp1, tmp2, diff; 152 int32_t in32; 153 len1 = (len >> 1)/4; 154 for (i = len1; i > 0; i--) { 155 // lower allpass filter 156 in32 = (int32_t)(*in++) << 10; 157 diff = in32 - state1; 158 tmp1 = MUL_ACCUM_1(kResampleAllpass2[0], diff, state0); 159 state0 = in32; 160 diff = tmp1 - state2; 161 tmp2 = MUL_ACCUM_2(kResampleAllpass2[1], diff, state1); 162 state1 = tmp1; 163 diff = tmp2 - state3; 164 state3 = MUL_ACCUM_2(kResampleAllpass2[2], diff, state2); 165 state2 = tmp2; 166 167 // upper allpass filter 168 in32 = (int32_t)(*in++) << 10; 169 diff = in32 - state5; 170 tmp1 = MUL_ACCUM_1(kResampleAllpass1[0], diff, state4); 171 state4 = in32; 172 diff = tmp1 - state6; 173 tmp2 = MUL_ACCUM_1(kResampleAllpass1[1], diff, state5); 174 state5 = tmp1; 175 diff = tmp2 - state7; 176 state7 = MUL_ACCUM_2(kResampleAllpass1[2], diff, state6); 177 state6 = tmp2; 178 179 // add two allpass outputs, divide by two and round 180 out32 = (state3 + state7 + 1024) >> 11; 181 182 // limit amplitude to prevent wrap-around, and write to output array 183 *out++ = WebRtcSpl_SatW32ToW16(out32); 184 // lower allpass filter 185 in32 = (int32_t)(*in++) << 10; 186 diff = in32 - state1; 187 tmp1 = MUL_ACCUM_1(kResampleAllpass2[0], diff, state0); 188 state0 = in32; 189 diff = tmp1 - state2; 190 tmp2 = MUL_ACCUM_2(kResampleAllpass2[1], diff, state1); 191 state1 = tmp1; 192 diff = tmp2 - state3; 193 state3 = MUL_ACCUM_2(kResampleAllpass2[2], diff, state2); 194 state2 = tmp2; 195 196 // upper allpass filter 197 in32 = (int32_t)(*in++) << 10; 198 diff = in32 - state5; 199 tmp1 = MUL_ACCUM_1(kResampleAllpass1[0], diff, state4); 200 state4 = in32; 201 diff = tmp1 - state6; 202 tmp2 = MUL_ACCUM_1(kResampleAllpass1[1], diff, state5); 203 state5 = tmp1; 204 diff = tmp2 - state7; 205 state7 = MUL_ACCUM_2(kResampleAllpass1[2], diff, state6); 206 state6 = tmp2; 207 208 // add two allpass outputs, divide by two and round 209 out32 = (state3 + state7 + 1024) >> 11; 210 211 // limit amplitude to prevent wrap-around, and write to output array 212 *out++ = WebRtcSpl_SatW32ToW16(out32); 213 // lower allpass filter 214 in32 = (int32_t)(*in++) << 10; 215 diff = in32 - state1; 216 tmp1 = MUL_ACCUM_1(kResampleAllpass2[0], diff, state0); 217 state0 = in32; 218 diff = tmp1 - state2; 219 tmp2 = MUL_ACCUM_2(kResampleAllpass2[1], diff, state1); 220 state1 = tmp1; 221 diff = tmp2 - state3; 222 state3 = MUL_ACCUM_2(kResampleAllpass2[2], diff, state2); 223 state2 = tmp2; 224 225 // upper allpass filter 226 in32 = (int32_t)(*in++) << 10; 227 diff = in32 - state5; 228 tmp1 = MUL_ACCUM_1(kResampleAllpass1[0], diff, state4); 229 state4 = in32; 230 diff = tmp1 - state6; 231 tmp2 = MUL_ACCUM_1(kResampleAllpass1[1], diff, state5); 232 state5 = tmp1; 233 diff = tmp2 - state7; 234 state7 = MUL_ACCUM_2(kResampleAllpass1[2], diff, state6); 235 state6 = tmp2; 236 237 // add two allpass outputs, divide by two and round 238 out32 = (state3 + state7 + 1024) >> 11; 239 240 // limit amplitude to prevent wrap-around, and write to output array 241 *out++ = WebRtcSpl_SatW32ToW16(out32); 242 // lower allpass filter 243 in32 = (int32_t)(*in++) << 10; 244 diff = in32 - state1; 245 tmp1 = MUL_ACCUM_1(kResampleAllpass2[0], diff, state0); 246 state0 = in32; 247 diff = tmp1 - state2; 248 tmp2 = MUL_ACCUM_2(kResampleAllpass2[1], diff, state1); 249 state1 = tmp1; 250 diff = tmp2 - state3; 251 state3 = MUL_ACCUM_2(kResampleAllpass2[2], diff, state2); 252 state2 = tmp2; 253 254 // upper allpass filter 255 in32 = (int32_t)(*in++) << 10; 256 diff = in32 - state5; 257 tmp1 = MUL_ACCUM_1(kResampleAllpass1[0], diff, state4); 258 state4 = in32; 259 diff = tmp1 - state6; 260 tmp2 = MUL_ACCUM_1(kResampleAllpass1[1], diff, state5); 261 state5 = tmp1; 262 diff = tmp2 - state7; 263 state7 = MUL_ACCUM_2(kResampleAllpass1[2], diff, state6); 264 state6 = tmp2; 265 266 // add two allpass outputs, divide by two and round 267 out32 = (state3 + state7 + 1024) >> 11; 268 269 // limit amplitude to prevent wrap-around, and write to output array 270 *out++ = WebRtcSpl_SatW32ToW16(out32); 271 } 272 #endif // #if defined(MIPS_DSP_R2_LE) 273 __asm__ volatile ( 274 "sw %[state0], 0(%[filtState]) \n\t" 275 "sw %[state1], 4(%[filtState]) \n\t" 276 "sw %[state2], 8(%[filtState]) \n\t" 277 "sw %[state3], 12(%[filtState]) \n\t" 278 "sw %[state4], 16(%[filtState]) \n\t" 279 "sw %[state5], 20(%[filtState]) \n\t" 280 "sw %[state6], 24(%[filtState]) \n\t" 281 "sw %[state7], 28(%[filtState]) \n\t" 282 : 283 : [state0] "r" (state0), [state1] "r" (state1), [state2] "r" (state2), 284 [state3] "r" (state3), [state4] "r" (state4), [state5] "r" (state5), 285 [state6] "r" (state6), [state7] "r" (state7), [filtState] "r" (filtState) 286 : "memory" 287 ); 288 } 289 290 #endif // #if defined(MIPS32_LE) 291