| /* |
| * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| |
| /* |
| * This file contains the resampling by two functions. |
| * The description header can be found in signal_processing_library.h |
| * |
| */ |
| |
| #include "signal_processing_library.h" |
| |
| // allpass filter coefficients. |
| static const WebRtc_UWord16 kResampleAllpass1[3] = {3284, 24441, 49528}; |
| static const WebRtc_UWord16 kResampleAllpass2[3] = {12199, 37471, 60255}; |
| |
| // decimator |
| void WebRtcSpl_DownsampleBy2(const WebRtc_Word16* in, const WebRtc_Word16 len, |
| WebRtc_Word16* out, WebRtc_Word32* filtState) |
| { |
| const WebRtc_Word16 *inptr; |
| WebRtc_Word16 *outptr; |
| WebRtc_Word32 *state; |
| WebRtc_Word32 tmp1, tmp2, diff, in32, out32; |
| WebRtc_Word16 i; |
| |
| // local versions of pointers to input and output arrays |
| inptr = in; // input array |
| outptr = out; // output array (of length len/2) |
| state = filtState; // filter state array; length = 8 |
| |
| register WebRtc_Word32 state0 = state[0]; |
| register WebRtc_Word32 state1 = state[1]; |
| register WebRtc_Word32 state2 = state[2]; |
| register WebRtc_Word32 state3 = state[3]; |
| register WebRtc_Word32 state4 = state[4]; |
| register WebRtc_Word32 state5 = state[5]; |
| register WebRtc_Word32 state6 = state[6]; |
| register WebRtc_Word32 state7 = state[7]; |
| |
| for (i = (len >> 1); i > 0; i--) |
| { |
| // lower allpass filter |
| in32 = (WebRtc_Word32)(*inptr++) << 10; |
| diff = in32 - state1; |
| tmp1 = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass2[0], diff, state0 ); |
| state0 = in32; |
| diff = tmp1 - state2; |
| tmp2 = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass2[1], diff, state1 ); |
| state1 = tmp1; |
| diff = tmp2 - state3; |
| state3 = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass2[2], diff, state2 ); |
| state2 = tmp2; |
| |
| // upper allpass filter |
| in32 = (WebRtc_Word32)(*inptr++) << 10; |
| diff = in32 - state5; |
| tmp1 = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass1[0], diff, state4 ); |
| state4 = in32; |
| diff = tmp1 - state6; |
| tmp2 = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass1[1], diff, state5 ); |
| state5 = tmp1; |
| diff = tmp2 - state7; |
| state7 = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass1[2], diff, state6 ); |
| state6 = tmp2; |
| |
| // add two allpass outputs, divide by two and round |
| out32 = (state3 + state7 + 1024) >> 11; |
| |
| // limit amplitude to prevent wrap-around, and write to output array |
| #ifdef WEBRTC_ARCH_ARM_V7A |
| __asm__("ssat %r0, #16, %r1" : "=r"(*outptr) : "r"(out32)); |
| outptr++; |
| #else |
| if (out32 > 32767) |
| *outptr++ = 32767; |
| else if (out32 < -32768) |
| *outptr++ = -32768; |
| else |
| *outptr++ = (WebRtc_Word16)out32; |
| #endif |
| } |
| |
| state[0]=state0; |
| state[1]=state1; |
| state[2]=state2; |
| state[3]=state3; |
| state[4]=state4; |
| state[5]=state5; |
| state[6]=state6; |
| state[7]=state7; |
| } |
| |
| void WebRtcSpl_UpsampleBy2(const WebRtc_Word16* in, WebRtc_Word16 len, WebRtc_Word16* out, |
| WebRtc_Word32* filtState) |
| { |
| const WebRtc_Word16 *inptr; |
| WebRtc_Word16 *outptr; |
| WebRtc_Word32 *state; |
| WebRtc_Word32 tmp1, tmp2, diff, in32, out32; |
| WebRtc_Word16 i; |
| |
| // local versions of pointers to input and output arrays |
| inptr = in; // input array |
| outptr = out; // output array (of length len*2) |
| state = filtState; // filter state array; length = 8 |
| |
| register WebRtc_Word32 state0 = state[0]; |
| register WebRtc_Word32 state1 = state[1]; |
| register WebRtc_Word32 state2 = state[2]; |
| register WebRtc_Word32 state3 = state[3]; |
| register WebRtc_Word32 state4 = state[4]; |
| register WebRtc_Word32 state5 = state[5]; |
| register WebRtc_Word32 state6 = state[6]; |
| register WebRtc_Word32 state7 = state[7]; |
| |
| for (i = len; i > 0; i--) |
| { |
| // lower allpass filter |
| in32 = (WebRtc_Word32)(*inptr++) << 10; |
| diff = in32 - state1; |
| tmp1 = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass1[0], diff, state0 ); |
| state0 = in32; |
| diff = tmp1 - state2; |
| tmp2 = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass1[1], diff, state1 ); |
| state1 = tmp1; |
| diff = tmp2 - state3; |
| state3 = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass1[2], diff, state2 ); |
| state2 = tmp2; |
| |
| // round; limit amplitude to prevent wrap-around; write to output array |
| out32 = (state3 + 512) >> 10; |
| #ifdef WEBRTC_ARCH_ARM_V7A |
| __asm__("ssat %r0, #16, %r1":"=r"(*outptr): "r"(out32)); |
| outptr++; |
| #else |
| if (out32 > 32767) |
| *outptr++ = 32767; |
| else if (out32 < -32768) |
| *outptr++ = -32768; |
| else |
| *outptr++ = (WebRtc_Word16)out32; |
| #endif |
| |
| // upper allpass filter |
| diff = in32 - state5; |
| tmp1 = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass2[0], diff, state4 ); |
| state4 = in32; |
| diff = tmp1 - state6; |
| tmp2 = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass2[1], diff, state5 ); |
| state5 = tmp1; |
| diff = tmp2 - state7; |
| state7 = WEBRTC_SPL_SCALEDIFF32( kResampleAllpass2[2], diff, state6 ); |
| state6 = tmp2; |
| |
| // round; limit amplitude to prevent wrap-around; write to output array |
| out32 = (state7 + 512) >> 10; |
| #ifdef WEBRTC_ARCH_ARM_V7A |
| __asm__("ssat %r0, #16, %r1":"=r"(*outptr): "r"(out32)); |
| outptr++; |
| #else |
| if (out32 > 32767) |
| *outptr++ = 32767; |
| else if (out32 < -32768) |
| *outptr++ = -32768; |
| else |
| *outptr++ = (WebRtc_Word16)out32; |
| #endif |
| } |
| state[0]=state0; |
| state[1]=state1; |
| state[2]=state2; |
| state[3]=state3; |
| state[4]=state4; |
| state[5]=state5; |
| state[6]=state6; |
| state[7]=state7; |
| |
| } |