division_operations.c (3157B)
1 /* 2 * Copyright (c) 2011 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 implementations of the divisions 13 * WebRtcSpl_DivU32U16() 14 * WebRtcSpl_DivW32W16() 15 * WebRtcSpl_DivW32W16ResW16() 16 * WebRtcSpl_DivResultInQ31() 17 * WebRtcSpl_DivW32HiLow() 18 * 19 * The description header can be found in signal_processing_library.h 20 * 21 */ 22 23 #include "common_audio/signal_processing/include/signal_processing_library.h" 24 #include "rtc_base/sanitizer.h" 25 26 uint32_t WebRtcSpl_DivU32U16(uint32_t num, uint16_t den) { 27 // Guard against division with 0 28 if (den != 0) { 29 return (uint32_t)(num / den); 30 } else { 31 return (uint32_t)0xFFFFFFFF; 32 } 33 } 34 35 int32_t WebRtcSpl_DivW32W16(int32_t num, int16_t den) { 36 // Guard against division with 0 37 if (den != 0) { 38 return (int32_t)(num / den); 39 } else { 40 return (int32_t)0x7FFFFFFF; 41 } 42 } 43 44 int16_t WebRtcSpl_DivW32W16ResW16(int32_t num, int16_t den) { 45 // Guard against division with 0 46 if (den != 0) { 47 return (int16_t)(num / den); 48 } else { 49 return (int16_t)0x7FFF; 50 } 51 } 52 53 int32_t WebRtcSpl_DivResultInQ31(int32_t num, int32_t den) { 54 int32_t L_num = num; 55 int32_t L_den = den; 56 int32_t div = 0; 57 int k = 31; 58 int change_sign = 0; 59 60 if (num == 0) 61 return 0; 62 63 if (num < 0) { 64 change_sign++; 65 L_num = -num; 66 } 67 if (den < 0) { 68 change_sign++; 69 L_den = -den; 70 } 71 while (k--) { 72 div <<= 1; 73 L_num <<= 1; 74 if (L_num >= L_den) { 75 L_num -= L_den; 76 div++; 77 } 78 } 79 if (change_sign == 1) { 80 div = -div; 81 } 82 return div; 83 } 84 85 int32_t WebRtcSpl_DivW32HiLow(int32_t num, int16_t den_hi, int16_t den_low) { 86 int16_t approx, tmp_hi, tmp_low, num_hi, num_low; 87 int32_t tmpW32; 88 89 approx = (int16_t)WebRtcSpl_DivW32W16((int32_t)0x1FFFFFFF, den_hi); 90 // result in Q14 (Note: 3FFFFFFF = 0.5 in Q30) 91 92 // tmpW32 = 1/den = approx * (2.0 - den * approx) (in Q30) 93 tmpW32 = (den_hi * approx << 1) + ((den_low * approx >> 15) << 1); 94 // tmpW32 = den * approx 95 96 // result in Q30 (tmpW32 = 2.0-(den*approx)) 97 tmpW32 = (int32_t)((int64_t)0x7fffffffL - tmpW32); 98 99 // Store tmpW32 in hi and low format 100 tmp_hi = (int16_t)(tmpW32 >> 16); 101 tmp_low = (int16_t)((tmpW32 - ((int32_t)tmp_hi << 16)) >> 1); 102 103 // tmpW32 = 1/den in Q29 104 tmpW32 = (tmp_hi * approx + (tmp_low * approx >> 15)) << 1; 105 106 // 1/den in hi and low format 107 tmp_hi = (int16_t)(tmpW32 >> 16); 108 tmp_low = (int16_t)((tmpW32 - ((int32_t)tmp_hi << 16)) >> 1); 109 110 // Store num in hi and low format 111 num_hi = (int16_t)(num >> 16); 112 num_low = (int16_t)((num - ((int32_t)num_hi << 16)) >> 1); 113 114 // num * (1/den) by 32 bit multiplication (result in Q28) 115 116 tmpW32 = 117 num_hi * tmp_hi + (num_hi * tmp_low >> 15) + (num_low * tmp_hi >> 15); 118 119 // Put result in Q31 (convert from Q28) 120 tmpW32 = WEBRTC_SPL_LSHIFT_W32(tmpW32, 3); 121 122 return tmpW32; 123 }