blob: c6195e799954463ad5b439e789c2f3bbf9c638eb [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
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/*
13 * This file contains implementations of the divisions
14 * WebRtcSpl_DivU32U16()
15 * WebRtcSpl_DivW32W16()
16 * WebRtcSpl_DivW32W16ResW16()
17 * WebRtcSpl_DivResultInQ31()
18 * WebRtcSpl_DivW32HiLow()
19 *
20 * The description header can be found in signal_processing_library.h
21 *
22 */
23
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020024#include "common_audio/signal_processing/include/signal_processing_library.h"
25#include "rtc_base/sanitizer.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000026
pbos@webrtc.orgb0913072013-04-09 16:40:28 +000027uint32_t WebRtcSpl_DivU32U16(uint32_t num, uint16_t den)
niklase@google.com470e71d2011-07-07 08:21:25 +000028{
29 // Guard against division with 0
30 if (den != 0)
31 {
pbos@webrtc.orgb0913072013-04-09 16:40:28 +000032 return (uint32_t)(num / den);
niklase@google.com470e71d2011-07-07 08:21:25 +000033 } else
34 {
pbos@webrtc.orgb0913072013-04-09 16:40:28 +000035 return (uint32_t)0xFFFFFFFF;
niklase@google.com470e71d2011-07-07 08:21:25 +000036 }
37}
38
pbos@webrtc.orgb0913072013-04-09 16:40:28 +000039int32_t WebRtcSpl_DivW32W16(int32_t num, int16_t den)
niklase@google.com470e71d2011-07-07 08:21:25 +000040{
41 // Guard against division with 0
42 if (den != 0)
43 {
pbos@webrtc.orgb0913072013-04-09 16:40:28 +000044 return (int32_t)(num / den);
niklase@google.com470e71d2011-07-07 08:21:25 +000045 } else
46 {
pbos@webrtc.orgb0913072013-04-09 16:40:28 +000047 return (int32_t)0x7FFFFFFF;
niklase@google.com470e71d2011-07-07 08:21:25 +000048 }
49}
50
pbos@webrtc.orgb0913072013-04-09 16:40:28 +000051int16_t WebRtcSpl_DivW32W16ResW16(int32_t num, int16_t den)
niklase@google.com470e71d2011-07-07 08:21:25 +000052{
53 // Guard against division with 0
54 if (den != 0)
55 {
pbos@webrtc.orgb0913072013-04-09 16:40:28 +000056 return (int16_t)(num / den);
niklase@google.com470e71d2011-07-07 08:21:25 +000057 } else
58 {
pbos@webrtc.orgb0913072013-04-09 16:40:28 +000059 return (int16_t)0x7FFF;
niklase@google.com470e71d2011-07-07 08:21:25 +000060 }
61}
62
pbos@webrtc.orgb0913072013-04-09 16:40:28 +000063int32_t WebRtcSpl_DivResultInQ31(int32_t num, int32_t den)
niklase@google.com470e71d2011-07-07 08:21:25 +000064{
pbos@webrtc.orgb0913072013-04-09 16:40:28 +000065 int32_t L_num = num;
66 int32_t L_den = den;
67 int32_t div = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +000068 int k = 31;
69 int change_sign = 0;
70
71 if (num == 0)
72 return 0;
73
74 if (num < 0)
75 {
76 change_sign++;
77 L_num = -num;
78 }
79 if (den < 0)
80 {
81 change_sign++;
82 L_den = -den;
83 }
84 while (k--)
85 {
86 div <<= 1;
87 L_num <<= 1;
88 if (L_num >= L_den)
89 {
90 L_num -= L_den;
91 div++;
92 }
93 }
94 if (change_sign == 1)
95 {
96 div = -div;
97 }
98 return div;
99}
100
oprypin8ad0e582017-09-05 03:00:37 -0700101int32_t RTC_NO_SANITIZE("signed-integer-overflow") // bugs.webrtc.org/5486
102WebRtcSpl_DivW32HiLow(int32_t num, int16_t den_hi, int16_t den_low)
niklase@google.com470e71d2011-07-07 08:21:25 +0000103{
pbos@webrtc.orgb0913072013-04-09 16:40:28 +0000104 int16_t approx, tmp_hi, tmp_low, num_hi, num_low;
105 int32_t tmpW32;
niklase@google.com470e71d2011-07-07 08:21:25 +0000106
pbos@webrtc.orgb0913072013-04-09 16:40:28 +0000107 approx = (int16_t)WebRtcSpl_DivW32W16((int32_t)0x1FFFFFFF, den_hi);
niklase@google.com470e71d2011-07-07 08:21:25 +0000108 // result in Q14 (Note: 3FFFFFFF = 0.5 in Q30)
109
110 // tmpW32 = 1/den = approx * (2.0 - den * approx) (in Q30)
Bjorn Volckeraffcfb22015-04-24 08:12:07 +0200111 tmpW32 = (den_hi * approx << 1) + ((den_low * approx >> 15) << 1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000112 // tmpW32 = den * approx
113
pbos@webrtc.orgb0913072013-04-09 16:40:28 +0000114 tmpW32 = (int32_t)0x7fffffffL - tmpW32; // result in Q30 (tmpW32 = 2.0-(den*approx))
oprypin8ad0e582017-09-05 03:00:37 -0700115 // UBSan: 2147483647 - -2 cannot be represented in type 'int'
niklase@google.com470e71d2011-07-07 08:21:25 +0000116
117 // Store tmpW32 in hi and low format
bjornv@webrtc.orgf5670952014-10-29 10:29:16 +0000118 tmp_hi = (int16_t)(tmpW32 >> 16);
119 tmp_low = (int16_t)((tmpW32 - ((int32_t)tmp_hi << 16)) >> 1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000120
121 // tmpW32 = 1/den in Q29
Bjorn Volckeraffcfb22015-04-24 08:12:07 +0200122 tmpW32 = (tmp_hi * approx + (tmp_low * approx >> 15)) << 1;
niklase@google.com470e71d2011-07-07 08:21:25 +0000123
124 // 1/den in hi and low format
bjornv@webrtc.orgf5670952014-10-29 10:29:16 +0000125 tmp_hi = (int16_t)(tmpW32 >> 16);
126 tmp_low = (int16_t)((tmpW32 - ((int32_t)tmp_hi << 16)) >> 1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000127
128 // Store num in hi and low format
bjornv@webrtc.orgf5670952014-10-29 10:29:16 +0000129 num_hi = (int16_t)(num >> 16);
130 num_low = (int16_t)((num - ((int32_t)num_hi << 16)) >> 1);
niklase@google.com470e71d2011-07-07 08:21:25 +0000131
132 // num * (1/den) by 32 bit multiplication (result in Q28)
133
Bjorn Volckeraffcfb22015-04-24 08:12:07 +0200134 tmpW32 = num_hi * tmp_hi + (num_hi * tmp_low >> 15) +
135 (num_low * tmp_hi >> 15);
niklase@google.com470e71d2011-07-07 08:21:25 +0000136
137 // Put result in Q31 (convert from Q28)
138 tmpW32 = WEBRTC_SPL_LSHIFT_W32(tmpW32, 3);
139
140 return tmpW32;
141}