diff options
Diffstat (limited to 'src/common_audio/signal_processing/division_operations.c')
-rw-r--r-- | src/common_audio/signal_processing/division_operations.c | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/src/common_audio/signal_processing/division_operations.c b/src/common_audio/signal_processing/division_operations.c new file mode 100644 index 0000000000..b143373a2f --- /dev/null +++ b/src/common_audio/signal_processing/division_operations.c @@ -0,0 +1,144 @@ +/* + * 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 implementations of the divisions + * WebRtcSpl_DivU32U16() + * WebRtcSpl_DivW32W16() + * WebRtcSpl_DivW32W16ResW16() + * WebRtcSpl_DivResultInQ31() + * WebRtcSpl_DivW32HiLow() + * + * The description header can be found in signal_processing_library.h + * + */ + +#include "signal_processing_library.h" + +WebRtc_UWord32 WebRtcSpl_DivU32U16(WebRtc_UWord32 num, WebRtc_UWord16 den) +{ + // Guard against division with 0 + if (den != 0) + { + return (WebRtc_UWord32)(num / den); + } else + { + return (WebRtc_UWord32)0xFFFFFFFF; + } +} + +WebRtc_Word32 WebRtcSpl_DivW32W16(WebRtc_Word32 num, WebRtc_Word16 den) +{ + // Guard against division with 0 + if (den != 0) + { + return (WebRtc_Word32)(num / den); + } else + { + return (WebRtc_Word32)0x7FFFFFFF; + } +} + +WebRtc_Word16 WebRtcSpl_DivW32W16ResW16(WebRtc_Word32 num, WebRtc_Word16 den) +{ + // Guard against division with 0 + if (den != 0) + { + return (WebRtc_Word16)(num / den); + } else + { + return (WebRtc_Word16)0x7FFF; + } +} + +WebRtc_Word32 WebRtcSpl_DivResultInQ31(WebRtc_Word32 num, WebRtc_Word32 den) +{ + WebRtc_Word32 L_num = num; + WebRtc_Word32 L_den = den; + WebRtc_Word32 div = 0; + int k = 31; + int change_sign = 0; + + if (num == 0) + return 0; + + if (num < 0) + { + change_sign++; + L_num = -num; + } + if (den < 0) + { + change_sign++; + L_den = -den; + } + while (k--) + { + div <<= 1; + L_num <<= 1; + if (L_num >= L_den) + { + L_num -= L_den; + div++; + } + } + if (change_sign == 1) + { + div = -div; + } + return div; +} + +WebRtc_Word32 WebRtcSpl_DivW32HiLow(WebRtc_Word32 num, WebRtc_Word16 den_hi, + WebRtc_Word16 den_low) +{ + WebRtc_Word16 approx, tmp_hi, tmp_low, num_hi, num_low; + WebRtc_Word32 tmpW32; + + approx = (WebRtc_Word16)WebRtcSpl_DivW32W16((WebRtc_Word32)0x1FFFFFFF, den_hi); + // result in Q14 (Note: 3FFFFFFF = 0.5 in Q30) + + // tmpW32 = 1/den = approx * (2.0 - den * approx) (in Q30) + tmpW32 = (WEBRTC_SPL_MUL_16_16(den_hi, approx) << 1) + + ((WEBRTC_SPL_MUL_16_16(den_low, approx) >> 15) << 1); + // tmpW32 = den * approx + + tmpW32 = (WebRtc_Word32)0x7fffffffL - tmpW32; // result in Q30 (tmpW32 = 2.0-(den*approx)) + + // Store tmpW32 in hi and low format + tmp_hi = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmpW32, 16); + tmp_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((tmpW32 + - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)tmp_hi, 16)), 1); + + // tmpW32 = 1/den in Q29 + tmpW32 = ((WEBRTC_SPL_MUL_16_16(tmp_hi, approx) + (WEBRTC_SPL_MUL_16_16(tmp_low, approx) + >> 15)) << 1); + + // 1/den in hi and low format + tmp_hi = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmpW32, 16); + tmp_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((tmpW32 + - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)tmp_hi, 16)), 1); + + // Store num in hi and low format + num_hi = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(num, 16); + num_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((num + - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)num_hi, 16)), 1); + + // num * (1/den) by 32 bit multiplication (result in Q28) + + tmpW32 = (WEBRTC_SPL_MUL_16_16(num_hi, tmp_hi) + (WEBRTC_SPL_MUL_16_16(num_hi, tmp_low) + >> 15) + (WEBRTC_SPL_MUL_16_16(num_low, tmp_hi) >> 15)); + + // Put result in Q31 (convert from Q28) + tmpW32 = WEBRTC_SPL_LSHIFT_W32(tmpW32, 3); + + return tmpW32; +} |