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