1e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent/* 2e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * 4e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * Use of this source code is governed by a BSD-style license 5e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * that can be found in the LICENSE file in the root of the source 6e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * tree. An additional intellectual property rights grant can be found 7e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * in the file PATENTS. All contributing project authors may 8e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * be found in the AUTHORS file in the root of the source tree. 9e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent */ 10e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 11e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 12e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent/* 13e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * This file contains implementations of the divisions 14e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * WebRtcSpl_DivU32U16() 15e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * WebRtcSpl_DivW32W16() 16e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * WebRtcSpl_DivW32W16ResW16() 17e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * WebRtcSpl_DivResultInQ31() 18e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * WebRtcSpl_DivW32HiLow() 19e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * 20e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * The description header can be found in signal_processing_library.h 21e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent * 22e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent */ 23e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 24e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent#include "signal_processing_library.h" 25e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 26e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentWebRtc_UWord32 WebRtcSpl_DivU32U16(WebRtc_UWord32 num, WebRtc_UWord16 den) 27e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{ 28e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // Guard against division with 0 29e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (den != 0) 30e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 31e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return (WebRtc_UWord32)(num / den); 32e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else 33e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 34e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return (WebRtc_UWord32)0xFFFFFFFF; 35e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 36e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 37e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 38e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentWebRtc_Word32 WebRtcSpl_DivW32W16(WebRtc_Word32 num, WebRtc_Word16 den) 39e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{ 40e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // Guard against division with 0 41e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (den != 0) 42e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 43e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return (WebRtc_Word32)(num / den); 44e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else 45e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 46e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return (WebRtc_Word32)0x7FFFFFFF; 47e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 48e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 49e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 50e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentWebRtc_Word16 WebRtcSpl_DivW32W16ResW16(WebRtc_Word32 num, WebRtc_Word16 den) 51e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{ 52e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // Guard against division with 0 53e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (den != 0) 54e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 55e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return (WebRtc_Word16)(num / den); 56e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } else 57e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 58e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return (WebRtc_Word16)0x7FFF; 59e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 60e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 61e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 62e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentWebRtc_Word32 WebRtcSpl_DivResultInQ31(WebRtc_Word32 num, WebRtc_Word32 den) 63e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{ 64e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word32 L_num = num; 65e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word32 L_den = den; 66e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word32 div = 0; 67e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent int k = 31; 68e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent int change_sign = 0; 69e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 70e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (num == 0) 71e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return 0; 72e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 73e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (num < 0) 74e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 75e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent change_sign++; 76e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent L_num = -num; 77e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 78e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (den < 0) 79e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 80e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent change_sign++; 81e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent L_den = -den; 82e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 83e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent while (k--) 84e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 85e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent div <<= 1; 86e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent L_num <<= 1; 87e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (L_num >= L_den) 88e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 89e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent L_num -= L_den; 90e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent div++; 91e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 92e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 93e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent if (change_sign == 1) 94e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent { 95e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent div = -div; 96e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent } 97e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return div; 98e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 99e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 100e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric LaurentWebRtc_Word32 WebRtcSpl_DivW32HiLow(WebRtc_Word32 num, WebRtc_Word16 den_hi, 101e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word16 den_low) 102e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent{ 103e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word16 approx, tmp_hi, tmp_low, num_hi, num_low; 104e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent WebRtc_Word32 tmpW32; 105e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 106e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent approx = (WebRtc_Word16)WebRtcSpl_DivW32W16((WebRtc_Word32)0x1FFFFFFF, den_hi); 107e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // result in Q14 (Note: 3FFFFFFF = 0.5 in Q30) 108e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 109e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // tmpW32 = 1/den = approx * (2.0 - den * approx) (in Q30) 110e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmpW32 = (WEBRTC_SPL_MUL_16_16(den_hi, approx) << 1) 111e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent + ((WEBRTC_SPL_MUL_16_16(den_low, approx) >> 15) << 1); 112e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // tmpW32 = den * approx 113e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 114e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmpW32 = (WebRtc_Word32)0x7fffffffL - tmpW32; // result in Q30 (tmpW32 = 2.0-(den*approx)) 115e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 116e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // Store tmpW32 in hi and low format 117e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp_hi = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmpW32, 16); 118e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((tmpW32 119e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)tmp_hi, 16)), 1); 120e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 121e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // tmpW32 = 1/den in Q29 122e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmpW32 = ((WEBRTC_SPL_MUL_16_16(tmp_hi, approx) + (WEBRTC_SPL_MUL_16_16(tmp_low, approx) 123e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent >> 15)) << 1); 124e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 125e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // 1/den in hi and low format 126e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp_hi = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmpW32, 16); 127e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmp_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((tmpW32 128e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)tmp_hi, 16)), 1); 129e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 130e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // Store num in hi and low format 131e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent num_hi = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(num, 16); 132e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent num_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((num 133e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)num_hi, 16)), 1); 134e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 135e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // num * (1/den) by 32 bit multiplication (result in Q28) 136e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 137e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmpW32 = (WEBRTC_SPL_MUL_16_16(num_hi, tmp_hi) + (WEBRTC_SPL_MUL_16_16(num_hi, tmp_low) 138e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent >> 15) + (WEBRTC_SPL_MUL_16_16(num_low, tmp_hi) >> 15)); 139e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 140e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent // Put result in Q31 (convert from Q28) 141e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent tmpW32 = WEBRTC_SPL_LSHIFT_W32(tmpW32, 3); 142e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent 143e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent return tmpW32; 144e48d5845c8b35de2ab73ea055c18a61fa3a9f0beEric Laurent} 145