blob: e9554f441800ad2b1e74676f2e849c98f74b27fa [file] [log] [blame]
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +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
pbos@webrtc.orgabf0cd82013-05-27 09:49:58 +000024#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +000025
pbos@webrtc.org1727dc72013-04-09 16:40:28 +000026uint32_t WebRtcSpl_DivU32U16(uint32_t num, uint16_t den)
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +000027{
28 // Guard against division with 0
29 if (den != 0)
30 {
pbos@webrtc.org1727dc72013-04-09 16:40:28 +000031 return (uint32_t)(num / den);
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +000032 } else
33 {
pbos@webrtc.org1727dc72013-04-09 16:40:28 +000034 return (uint32_t)0xFFFFFFFF;
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +000035 }
36}
37
pbos@webrtc.org1727dc72013-04-09 16:40:28 +000038int32_t WebRtcSpl_DivW32W16(int32_t num, int16_t den)
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +000039{
40 // Guard against division with 0
41 if (den != 0)
42 {
pbos@webrtc.org1727dc72013-04-09 16:40:28 +000043 return (int32_t)(num / den);
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +000044 } else
45 {
pbos@webrtc.org1727dc72013-04-09 16:40:28 +000046 return (int32_t)0x7FFFFFFF;
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +000047 }
48}
49
pbos@webrtc.org1727dc72013-04-09 16:40:28 +000050int16_t WebRtcSpl_DivW32W16ResW16(int32_t num, int16_t den)
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +000051{
52 // Guard against division with 0
53 if (den != 0)
54 {
pbos@webrtc.org1727dc72013-04-09 16:40:28 +000055 return (int16_t)(num / den);
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +000056 } else
57 {
pbos@webrtc.org1727dc72013-04-09 16:40:28 +000058 return (int16_t)0x7FFF;
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +000059 }
60}
61
pbos@webrtc.org1727dc72013-04-09 16:40:28 +000062int32_t WebRtcSpl_DivResultInQ31(int32_t num, int32_t den)
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +000063{
pbos@webrtc.org1727dc72013-04-09 16:40:28 +000064 int32_t L_num = num;
65 int32_t L_den = den;
66 int32_t div = 0;
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +000067 int k = 31;
68 int change_sign = 0;
69
70 if (num == 0)
71 return 0;
72
73 if (num < 0)
74 {
75 change_sign++;
76 L_num = -num;
77 }
78 if (den < 0)
79 {
80 change_sign++;
81 L_den = -den;
82 }
83 while (k--)
84 {
85 div <<= 1;
86 L_num <<= 1;
87 if (L_num >= L_den)
88 {
89 L_num -= L_den;
90 div++;
91 }
92 }
93 if (change_sign == 1)
94 {
95 div = -div;
96 }
97 return div;
98}
99
pbos@webrtc.org1727dc72013-04-09 16:40:28 +0000100int32_t WebRtcSpl_DivW32HiLow(int32_t num, int16_t den_hi, int16_t den_low)
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +0000101{
pbos@webrtc.org1727dc72013-04-09 16:40:28 +0000102 int16_t approx, tmp_hi, tmp_low, num_hi, num_low;
103 int32_t tmpW32;
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +0000104
pbos@webrtc.org1727dc72013-04-09 16:40:28 +0000105 approx = (int16_t)WebRtcSpl_DivW32W16((int32_t)0x1FFFFFFF, den_hi);
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +0000106 // result in Q14 (Note: 3FFFFFFF = 0.5 in Q30)
107
108 // tmpW32 = 1/den = approx * (2.0 - den * approx) (in Q30)
109 tmpW32 = (WEBRTC_SPL_MUL_16_16(den_hi, approx) << 1)
110 + ((WEBRTC_SPL_MUL_16_16(den_low, approx) >> 15) << 1);
111 // tmpW32 = den * approx
112
pbos@webrtc.org1727dc72013-04-09 16:40:28 +0000113 tmpW32 = (int32_t)0x7fffffffL - tmpW32; // result in Q30 (tmpW32 = 2.0-(den*approx))
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +0000114
115 // Store tmpW32 in hi and low format
pbos@webrtc.org1727dc72013-04-09 16:40:28 +0000116 tmp_hi = (int16_t)WEBRTC_SPL_RSHIFT_W32(tmpW32, 16);
117 tmp_low = (int16_t)WEBRTC_SPL_RSHIFT_W32((tmpW32
118 - WEBRTC_SPL_LSHIFT_W32((int32_t)tmp_hi, 16)), 1);
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +0000119
120 // tmpW32 = 1/den in Q29
121 tmpW32 = ((WEBRTC_SPL_MUL_16_16(tmp_hi, approx) + (WEBRTC_SPL_MUL_16_16(tmp_low, approx)
122 >> 15)) << 1);
123
124 // 1/den in hi and low format
pbos@webrtc.org1727dc72013-04-09 16:40:28 +0000125 tmp_hi = (int16_t)WEBRTC_SPL_RSHIFT_W32(tmpW32, 16);
126 tmp_low = (int16_t)WEBRTC_SPL_RSHIFT_W32((tmpW32
127 - WEBRTC_SPL_LSHIFT_W32((int32_t)tmp_hi, 16)), 1);
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +0000128
129 // Store num in hi and low format
pbos@webrtc.org1727dc72013-04-09 16:40:28 +0000130 num_hi = (int16_t)WEBRTC_SPL_RSHIFT_W32(num, 16);
131 num_low = (int16_t)WEBRTC_SPL_RSHIFT_W32((num
132 - WEBRTC_SPL_LSHIFT_W32((int32_t)num_hi, 16)), 1);
andrew@webrtc.orga7b57da2012-10-22 18:19:23 +0000133
134 // num * (1/den) by 32 bit multiplication (result in Q28)
135
136 tmpW32 = (WEBRTC_SPL_MUL_16_16(num_hi, tmp_hi) + (WEBRTC_SPL_MUL_16_16(num_hi, tmp_low)
137 >> 15) + (WEBRTC_SPL_MUL_16_16(num_low, tmp_hi) >> 15));
138
139 // Put result in Q31 (convert from Q28)
140 tmpW32 = WEBRTC_SPL_LSHIFT_W32(tmpW32, 3);
141
142 return tmpW32;
143}