1c55a96383497a772a307b346368133960b02ad03Eric Laurent/* 2c55a96383497a772a307b346368133960b02ad03Eric Laurent * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3c55a96383497a772a307b346368133960b02ad03Eric Laurent * 4c55a96383497a772a307b346368133960b02ad03Eric Laurent * Use of this source code is governed by a BSD-style license 5c55a96383497a772a307b346368133960b02ad03Eric Laurent * that can be found in the LICENSE file in the root of the source 6c55a96383497a772a307b346368133960b02ad03Eric Laurent * tree. An additional intellectual property rights grant can be found 7c55a96383497a772a307b346368133960b02ad03Eric Laurent * in the file PATENTS. All contributing project authors may 8c55a96383497a772a307b346368133960b02ad03Eric Laurent * be found in the AUTHORS file in the root of the source tree. 9c55a96383497a772a307b346368133960b02ad03Eric Laurent */ 10c55a96383497a772a307b346368133960b02ad03Eric Laurent 11c55a96383497a772a307b346368133960b02ad03Eric Laurent 12c55a96383497a772a307b346368133960b02ad03Eric Laurent/* 13c55a96383497a772a307b346368133960b02ad03Eric Laurent * This file contains the resampling by two functions. 14c55a96383497a772a307b346368133960b02ad03Eric Laurent * The description header can be found in signal_processing_library.h 15c55a96383497a772a307b346368133960b02ad03Eric Laurent * 16c55a96383497a772a307b346368133960b02ad03Eric Laurent */ 17c55a96383497a772a307b346368133960b02ad03Eric Laurent 18c55a96383497a772a307b346368133960b02ad03Eric Laurent#include "signal_processing_library.h" 19c55a96383497a772a307b346368133960b02ad03Eric Laurent 20c55a96383497a772a307b346368133960b02ad03Eric Laurent#ifdef WEBRTC_ARCH_ARM_V7A 21c55a96383497a772a307b346368133960b02ad03Eric Laurent 22c55a96383497a772a307b346368133960b02ad03Eric Laurent// allpass filter coefficients. 23c55a96383497a772a307b346368133960b02ad03Eric Laurentstatic const WebRtc_UWord32 kResampleAllpass1[3] = {3284, 24441, 49528 << 15}; 24c55a96383497a772a307b346368133960b02ad03Eric Laurentstatic const WebRtc_UWord32 kResampleAllpass2[3] = 25c55a96383497a772a307b346368133960b02ad03Eric Laurent {12199, 37471 << 15, 60255 << 15}; 26c55a96383497a772a307b346368133960b02ad03Eric Laurent 27c55a96383497a772a307b346368133960b02ad03Eric Laurent// Multiply two 32-bit values and accumulate to another input value. 28c55a96383497a772a307b346368133960b02ad03Eric Laurent// Return: state + ((diff * tbl_value) >> 16) 29c55a96383497a772a307b346368133960b02ad03Eric Laurent 30c55a96383497a772a307b346368133960b02ad03Eric Laurentstatic __inline WebRtc_Word32 MUL_ACCUM_1(WebRtc_Word32 tbl_value, 31c55a96383497a772a307b346368133960b02ad03Eric Laurent WebRtc_Word32 diff, 32c55a96383497a772a307b346368133960b02ad03Eric Laurent WebRtc_Word32 state) { 33c55a96383497a772a307b346368133960b02ad03Eric Laurent WebRtc_Word32 result; 34c55a96383497a772a307b346368133960b02ad03Eric Laurent __asm__("smlawb %r0, %r1, %r2, %r3": "=r"(result): "r"(diff), 35c55a96383497a772a307b346368133960b02ad03Eric Laurent "r"(tbl_value), "r"(state)); 36c55a96383497a772a307b346368133960b02ad03Eric Laurent return result; 37c55a96383497a772a307b346368133960b02ad03Eric Laurent} 38c55a96383497a772a307b346368133960b02ad03Eric Laurent 39c55a96383497a772a307b346368133960b02ad03Eric Laurent// Multiply two 32-bit values and accumulate to another input value. 40c55a96383497a772a307b346368133960b02ad03Eric Laurent// Return: Return: state + (((diff << 1) * tbl_value) >> 32) 41c55a96383497a772a307b346368133960b02ad03Eric Laurent// 42c55a96383497a772a307b346368133960b02ad03Eric Laurent// The reason to introduce this function is that, in case we can't use smlawb 43c55a96383497a772a307b346368133960b02ad03Eric Laurent// instruction (in MUL_ACCUM_1) due to input value range, we can still use 44c55a96383497a772a307b346368133960b02ad03Eric Laurent// smmla to save some cycles. 45c55a96383497a772a307b346368133960b02ad03Eric Laurent 46c55a96383497a772a307b346368133960b02ad03Eric Laurentstatic __inline WebRtc_Word32 MUL_ACCUM_2(WebRtc_Word32 tbl_value, 47c55a96383497a772a307b346368133960b02ad03Eric Laurent WebRtc_Word32 diff, 48c55a96383497a772a307b346368133960b02ad03Eric Laurent WebRtc_Word32 state) { 49c55a96383497a772a307b346368133960b02ad03Eric Laurent WebRtc_Word32 result; 50c55a96383497a772a307b346368133960b02ad03Eric Laurent __asm__("smmla %r0, %r1, %r2, %r3": "=r"(result): "r"(diff << 1), 51c55a96383497a772a307b346368133960b02ad03Eric Laurent "r"(tbl_value), "r"(state)); 52c55a96383497a772a307b346368133960b02ad03Eric Laurent return result; 53c55a96383497a772a307b346368133960b02ad03Eric Laurent} 54c55a96383497a772a307b346368133960b02ad03Eric Laurent 55c55a96383497a772a307b346368133960b02ad03Eric Laurent#else 56c55a96383497a772a307b346368133960b02ad03Eric Laurent 57c55a96383497a772a307b346368133960b02ad03Eric Laurent// allpass filter coefficients. 58c55a96383497a772a307b346368133960b02ad03Eric Laurentstatic const WebRtc_UWord16 kResampleAllpass1[3] = {3284, 24441, 49528}; 59c55a96383497a772a307b346368133960b02ad03Eric Laurentstatic const WebRtc_UWord16 kResampleAllpass2[3] = {12199, 37471, 60255}; 60c55a96383497a772a307b346368133960b02ad03Eric Laurent 61c55a96383497a772a307b346368133960b02ad03Eric Laurent// Multiply a 32-bit value with a 16-bit value and accumulate to another input: 62c55a96383497a772a307b346368133960b02ad03Eric Laurent#define MUL_ACCUM_1(a, b, c) WEBRTC_SPL_SCALEDIFF32(a, b, c) 63c55a96383497a772a307b346368133960b02ad03Eric Laurent#define MUL_ACCUM_2(a, b, c) WEBRTC_SPL_SCALEDIFF32(a, b, c) 64c55a96383497a772a307b346368133960b02ad03Eric Laurent 65c55a96383497a772a307b346368133960b02ad03Eric Laurent#endif // WEBRTC_ARCH_ARM_V7A 66c55a96383497a772a307b346368133960b02ad03Eric Laurent 67c55a96383497a772a307b346368133960b02ad03Eric Laurent 68c55a96383497a772a307b346368133960b02ad03Eric Laurent// decimator 69c55a96383497a772a307b346368133960b02ad03Eric Laurentvoid WebRtcSpl_DownsampleBy2(const WebRtc_Word16* in, const WebRtc_Word16 len, 70c55a96383497a772a307b346368133960b02ad03Eric Laurent WebRtc_Word16* out, WebRtc_Word32* filtState) { 71c55a96383497a772a307b346368133960b02ad03Eric Laurent WebRtc_Word32 tmp1, tmp2, diff, in32, out32; 72c55a96383497a772a307b346368133960b02ad03Eric Laurent WebRtc_Word16 i; 73c55a96383497a772a307b346368133960b02ad03Eric Laurent 74c55a96383497a772a307b346368133960b02ad03Eric Laurent register WebRtc_Word32 state0 = filtState[0]; 75c55a96383497a772a307b346368133960b02ad03Eric Laurent register WebRtc_Word32 state1 = filtState[1]; 76c55a96383497a772a307b346368133960b02ad03Eric Laurent register WebRtc_Word32 state2 = filtState[2]; 77c55a96383497a772a307b346368133960b02ad03Eric Laurent register WebRtc_Word32 state3 = filtState[3]; 78c55a96383497a772a307b346368133960b02ad03Eric Laurent register WebRtc_Word32 state4 = filtState[4]; 79c55a96383497a772a307b346368133960b02ad03Eric Laurent register WebRtc_Word32 state5 = filtState[5]; 80c55a96383497a772a307b346368133960b02ad03Eric Laurent register WebRtc_Word32 state6 = filtState[6]; 81c55a96383497a772a307b346368133960b02ad03Eric Laurent register WebRtc_Word32 state7 = filtState[7]; 82c55a96383497a772a307b346368133960b02ad03Eric Laurent 83c55a96383497a772a307b346368133960b02ad03Eric Laurent for (i = (len >> 1); i > 0; i--) { 84c55a96383497a772a307b346368133960b02ad03Eric Laurent // lower allpass filter 85c55a96383497a772a307b346368133960b02ad03Eric Laurent in32 = (WebRtc_Word32)(*in++) << 10; 86c55a96383497a772a307b346368133960b02ad03Eric Laurent diff = in32 - state1; 87c55a96383497a772a307b346368133960b02ad03Eric Laurent tmp1 = MUL_ACCUM_1(kResampleAllpass2[0], diff, state0); 88c55a96383497a772a307b346368133960b02ad03Eric Laurent state0 = in32; 89c55a96383497a772a307b346368133960b02ad03Eric Laurent diff = tmp1 - state2; 90c55a96383497a772a307b346368133960b02ad03Eric Laurent tmp2 = MUL_ACCUM_2(kResampleAllpass2[1], diff, state1); 91c55a96383497a772a307b346368133960b02ad03Eric Laurent state1 = tmp1; 92c55a96383497a772a307b346368133960b02ad03Eric Laurent diff = tmp2 - state3; 93c55a96383497a772a307b346368133960b02ad03Eric Laurent state3 = MUL_ACCUM_2(kResampleAllpass2[2], diff, state2); 94c55a96383497a772a307b346368133960b02ad03Eric Laurent state2 = tmp2; 95c55a96383497a772a307b346368133960b02ad03Eric Laurent 96c55a96383497a772a307b346368133960b02ad03Eric Laurent // upper allpass filter 97c55a96383497a772a307b346368133960b02ad03Eric Laurent in32 = (WebRtc_Word32)(*in++) << 10; 98c55a96383497a772a307b346368133960b02ad03Eric Laurent diff = in32 - state5; 99c55a96383497a772a307b346368133960b02ad03Eric Laurent tmp1 = MUL_ACCUM_1(kResampleAllpass1[0], diff, state4); 100c55a96383497a772a307b346368133960b02ad03Eric Laurent state4 = in32; 101c55a96383497a772a307b346368133960b02ad03Eric Laurent diff = tmp1 - state6; 102c55a96383497a772a307b346368133960b02ad03Eric Laurent tmp2 = MUL_ACCUM_1(kResampleAllpass1[1], diff, state5); 103c55a96383497a772a307b346368133960b02ad03Eric Laurent state5 = tmp1; 104c55a96383497a772a307b346368133960b02ad03Eric Laurent diff = tmp2 - state7; 105c55a96383497a772a307b346368133960b02ad03Eric Laurent state7 = MUL_ACCUM_2(kResampleAllpass1[2], diff, state6); 106c55a96383497a772a307b346368133960b02ad03Eric Laurent state6 = tmp2; 107c55a96383497a772a307b346368133960b02ad03Eric Laurent 108c55a96383497a772a307b346368133960b02ad03Eric Laurent // add two allpass outputs, divide by two and round 109c55a96383497a772a307b346368133960b02ad03Eric Laurent out32 = (state3 + state7 + 1024) >> 11; 110c55a96383497a772a307b346368133960b02ad03Eric Laurent 111c55a96383497a772a307b346368133960b02ad03Eric Laurent // limit amplitude to prevent wrap-around, and write to output array 112c55a96383497a772a307b346368133960b02ad03Eric Laurent *out++ = WebRtcSpl_SatW32ToW16(out32); 113c55a96383497a772a307b346368133960b02ad03Eric Laurent } 114c55a96383497a772a307b346368133960b02ad03Eric Laurent 115c55a96383497a772a307b346368133960b02ad03Eric Laurent filtState[0] = state0; 116c55a96383497a772a307b346368133960b02ad03Eric Laurent filtState[1] = state1; 117c55a96383497a772a307b346368133960b02ad03Eric Laurent filtState[2] = state2; 118c55a96383497a772a307b346368133960b02ad03Eric Laurent filtState[3] = state3; 119c55a96383497a772a307b346368133960b02ad03Eric Laurent filtState[4] = state4; 120c55a96383497a772a307b346368133960b02ad03Eric Laurent filtState[5] = state5; 121c55a96383497a772a307b346368133960b02ad03Eric Laurent filtState[6] = state6; 122c55a96383497a772a307b346368133960b02ad03Eric Laurent filtState[7] = state7; 123c55a96383497a772a307b346368133960b02ad03Eric Laurent} 124c55a96383497a772a307b346368133960b02ad03Eric Laurent 125c55a96383497a772a307b346368133960b02ad03Eric Laurent 126c55a96383497a772a307b346368133960b02ad03Eric Laurentvoid WebRtcSpl_UpsampleBy2(const WebRtc_Word16* in, WebRtc_Word16 len, 127c55a96383497a772a307b346368133960b02ad03Eric Laurent WebRtc_Word16* out, WebRtc_Word32* filtState) { 128c55a96383497a772a307b346368133960b02ad03Eric Laurent WebRtc_Word32 tmp1, tmp2, diff, in32, out32; 129c55a96383497a772a307b346368133960b02ad03Eric Laurent WebRtc_Word16 i; 130c55a96383497a772a307b346368133960b02ad03Eric Laurent 131c55a96383497a772a307b346368133960b02ad03Eric Laurent register WebRtc_Word32 state0 = filtState[0]; 132c55a96383497a772a307b346368133960b02ad03Eric Laurent register WebRtc_Word32 state1 = filtState[1]; 133c55a96383497a772a307b346368133960b02ad03Eric Laurent register WebRtc_Word32 state2 = filtState[2]; 134c55a96383497a772a307b346368133960b02ad03Eric Laurent register WebRtc_Word32 state3 = filtState[3]; 135c55a96383497a772a307b346368133960b02ad03Eric Laurent register WebRtc_Word32 state4 = filtState[4]; 136c55a96383497a772a307b346368133960b02ad03Eric Laurent register WebRtc_Word32 state5 = filtState[5]; 137c55a96383497a772a307b346368133960b02ad03Eric Laurent register WebRtc_Word32 state6 = filtState[6]; 138c55a96383497a772a307b346368133960b02ad03Eric Laurent register WebRtc_Word32 state7 = filtState[7]; 139c55a96383497a772a307b346368133960b02ad03Eric Laurent 140c55a96383497a772a307b346368133960b02ad03Eric Laurent for (i = len; i > 0; i--) { 141c55a96383497a772a307b346368133960b02ad03Eric Laurent // lower allpass filter 142c55a96383497a772a307b346368133960b02ad03Eric Laurent in32 = (WebRtc_Word32)(*in++) << 10; 143c55a96383497a772a307b346368133960b02ad03Eric Laurent diff = in32 - state1; 144c55a96383497a772a307b346368133960b02ad03Eric Laurent tmp1 = MUL_ACCUM_1(kResampleAllpass1[0], diff, state0); 145c55a96383497a772a307b346368133960b02ad03Eric Laurent state0 = in32; 146c55a96383497a772a307b346368133960b02ad03Eric Laurent diff = tmp1 - state2; 147c55a96383497a772a307b346368133960b02ad03Eric Laurent tmp2 = MUL_ACCUM_1(kResampleAllpass1[1], diff, state1); 148c55a96383497a772a307b346368133960b02ad03Eric Laurent state1 = tmp1; 149c55a96383497a772a307b346368133960b02ad03Eric Laurent diff = tmp2 - state3; 150c55a96383497a772a307b346368133960b02ad03Eric Laurent state3 = MUL_ACCUM_2(kResampleAllpass1[2], diff, state2); 151c55a96383497a772a307b346368133960b02ad03Eric Laurent state2 = tmp2; 152c55a96383497a772a307b346368133960b02ad03Eric Laurent 153c55a96383497a772a307b346368133960b02ad03Eric Laurent // round; limit amplitude to prevent wrap-around; write to output array 154c55a96383497a772a307b346368133960b02ad03Eric Laurent out32 = (state3 + 512) >> 10; 155c55a96383497a772a307b346368133960b02ad03Eric Laurent *out++ = WebRtcSpl_SatW32ToW16(out32); 156c55a96383497a772a307b346368133960b02ad03Eric Laurent 157c55a96383497a772a307b346368133960b02ad03Eric Laurent // upper allpass filter 158c55a96383497a772a307b346368133960b02ad03Eric Laurent diff = in32 - state5; 159c55a96383497a772a307b346368133960b02ad03Eric Laurent tmp1 = MUL_ACCUM_1(kResampleAllpass2[0], diff, state4); 160c55a96383497a772a307b346368133960b02ad03Eric Laurent state4 = in32; 161c55a96383497a772a307b346368133960b02ad03Eric Laurent diff = tmp1 - state6; 162c55a96383497a772a307b346368133960b02ad03Eric Laurent tmp2 = MUL_ACCUM_2(kResampleAllpass2[1], diff, state5); 163c55a96383497a772a307b346368133960b02ad03Eric Laurent state5 = tmp1; 164c55a96383497a772a307b346368133960b02ad03Eric Laurent diff = tmp2 - state7; 165c55a96383497a772a307b346368133960b02ad03Eric Laurent state7 = MUL_ACCUM_2(kResampleAllpass2[2], diff, state6); 166c55a96383497a772a307b346368133960b02ad03Eric Laurent state6 = tmp2; 167c55a96383497a772a307b346368133960b02ad03Eric Laurent 168c55a96383497a772a307b346368133960b02ad03Eric Laurent // round; limit amplitude to prevent wrap-around; write to output array 169c55a96383497a772a307b346368133960b02ad03Eric Laurent out32 = (state7 + 512) >> 10; 170c55a96383497a772a307b346368133960b02ad03Eric Laurent *out++ = WebRtcSpl_SatW32ToW16(out32); 171c55a96383497a772a307b346368133960b02ad03Eric Laurent } 172c55a96383497a772a307b346368133960b02ad03Eric Laurent 173c55a96383497a772a307b346368133960b02ad03Eric Laurent filtState[0] = state0; 174c55a96383497a772a307b346368133960b02ad03Eric Laurent filtState[1] = state1; 175c55a96383497a772a307b346368133960b02ad03Eric Laurent filtState[2] = state2; 176c55a96383497a772a307b346368133960b02ad03Eric Laurent filtState[3] = state3; 177c55a96383497a772a307b346368133960b02ad03Eric Laurent filtState[4] = state4; 178c55a96383497a772a307b346368133960b02ad03Eric Laurent filtState[5] = state5; 179c55a96383497a772a307b346368133960b02ad03Eric Laurent filtState[6] = state6; 180c55a96383497a772a307b346368133960b02ad03Eric Laurent filtState[7] = state7; 181c55a96383497a772a307b346368133960b02ad03Eric Laurent} 182