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/*
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
24#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
25
26uint32_t WebRtcSpl_DivU32U16(uint32_t num, uint16_t den)
27{
28    // Guard against division with 0
29    if (den != 0)
30    {
31        return (uint32_t)(num / den);
32    } else
33    {
34        return (uint32_t)0xFFFFFFFF;
35    }
36}
37
38int32_t WebRtcSpl_DivW32W16(int32_t num, int16_t den)
39{
40    // Guard against division with 0
41    if (den != 0)
42    {
43        return (int32_t)(num / den);
44    } else
45    {
46        return (int32_t)0x7FFFFFFF;
47    }
48}
49
50int16_t WebRtcSpl_DivW32W16ResW16(int32_t num, int16_t den)
51{
52    // Guard against division with 0
53    if (den != 0)
54    {
55        return (int16_t)(num / den);
56    } else
57    {
58        return (int16_t)0x7FFF;
59    }
60}
61
62int32_t WebRtcSpl_DivResultInQ31(int32_t num, int32_t den)
63{
64    int32_t L_num = num;
65    int32_t L_den = den;
66    int32_t div = 0;
67    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
100int32_t WebRtcSpl_DivW32HiLow(int32_t num, int16_t den_hi, int16_t den_low)
101{
102    int16_t approx, tmp_hi, tmp_low, num_hi, num_low;
103    int32_t tmpW32;
104
105    approx = (int16_t)WebRtcSpl_DivW32W16((int32_t)0x1FFFFFFF, den_hi);
106    // 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
113    tmpW32 = (int32_t)0x7fffffffL - tmpW32; // result in Q30 (tmpW32 = 2.0-(den*approx))
114
115    // Store tmpW32 in hi and low format
116    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);
119
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
125    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);
128
129    // Store num in hi and low format
130    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);
133
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}
144