1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* 2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Use of this source code is governed by a BSD-style license 5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * that can be found in the LICENSE file in the root of the source 6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * tree. An additional intellectual property rights grant can be found 7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * in the file PATENTS. All contributing project authors may 8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */ 10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 11b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* 13b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * This file contains implementations of the divisions 14b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * WebRtcSpl_DivU32U16() 15b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * WebRtcSpl_DivW32W16() 16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * WebRtcSpl_DivW32W16ResW16() 17b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * WebRtcSpl_DivResultInQ31() 18b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * WebRtcSpl_DivW32HiLow() 19b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * The description header can be found in signal_processing_library.h 21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */ 23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 24f24ac5923cbe5e806fac59a0d15e32567553ce8epbos@webrtc.org#include "webrtc/common_audio/signal_processing/include/signal_processing_library.h" 25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 26c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.orguint32_t WebRtcSpl_DivU32U16(uint32_t num, uint16_t den) 27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Guard against division with 0 29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (den != 0) 30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 31c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org return (uint32_t)(num / den); 32b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else 33b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 34c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org return (uint32_t)0xFFFFFFFF; 35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 38c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.orgint32_t WebRtcSpl_DivW32W16(int32_t num, int16_t den) 39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Guard against division with 0 41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (den != 0) 42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 43c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org return (int32_t)(num / den); 44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else 45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 46c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org return (int32_t)0x7FFFFFFF; 47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 48b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 50c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.orgint16_t WebRtcSpl_DivW32W16ResW16(int32_t num, int16_t den) 51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Guard against division with 0 53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (den != 0) 54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 55c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org return (int16_t)(num / den); 56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else 57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 58c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org return (int16_t)0x7FFF; 59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 62c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.orgint32_t WebRtcSpl_DivResultInQ31(int32_t num, int32_t den) 63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 64c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org int32_t L_num = num; 65c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org int32_t L_den = den; 66c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org int32_t div = 0; 67b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int k = 31; 68b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int change_sign = 0; 69b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 70b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (num == 0) 71b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 72b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (num < 0) 74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org change_sign++; 76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org L_num = -num; 77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (den < 0) 79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org change_sign++; 81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org L_den = -den; 82b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org while (k--) 84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org div <<= 1; 86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org L_num <<= 1; 87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (L_num >= L_den) 88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org L_num -= L_den; 90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org div++; 91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (change_sign == 1) 94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org div = -div; 96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return div; 98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 100c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.orgint32_t WebRtcSpl_DivW32HiLow(int32_t num, int16_t den_hi, int16_t den_low) 101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org{ 102c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org int16_t approx, tmp_hi, tmp_low, num_hi, num_low; 103c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org int32_t tmpW32; 104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 105c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org approx = (int16_t)WebRtcSpl_DivW32W16((int32_t)0x1FFFFFFF, den_hi); 106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // result in Q14 (Note: 3FFFFFFF = 0.5 in Q30) 107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // tmpW32 = 1/den = approx * (2.0 - den * approx) (in Q30) 109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmpW32 = (WEBRTC_SPL_MUL_16_16(den_hi, approx) << 1) 110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org + ((WEBRTC_SPL_MUL_16_16(den_low, approx) >> 15) << 1); 111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // tmpW32 = den * approx 112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 113c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org tmpW32 = (int32_t)0x7fffffffL - tmpW32; // result in Q30 (tmpW32 = 2.0-(den*approx)) 114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Store tmpW32 in hi and low format 116c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org tmp_hi = (int16_t)WEBRTC_SPL_RSHIFT_W32(tmpW32, 16); 117c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org tmp_low = (int16_t)WEBRTC_SPL_RSHIFT_W32((tmpW32 118c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org - WEBRTC_SPL_LSHIFT_W32((int32_t)tmp_hi, 16)), 1); 119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // tmpW32 = 1/den in Q29 121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmpW32 = ((WEBRTC_SPL_MUL_16_16(tmp_hi, approx) + (WEBRTC_SPL_MUL_16_16(tmp_low, approx) 122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org >> 15)) << 1); 123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // 1/den in hi and low format 125c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org tmp_hi = (int16_t)WEBRTC_SPL_RSHIFT_W32(tmpW32, 16); 126c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org tmp_low = (int16_t)WEBRTC_SPL_RSHIFT_W32((tmpW32 127c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org - WEBRTC_SPL_LSHIFT_W32((int32_t)tmp_hi, 16)), 1); 128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Store num in hi and low format 130c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org num_hi = (int16_t)WEBRTC_SPL_RSHIFT_W32(num, 16); 131c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org num_low = (int16_t)WEBRTC_SPL_RSHIFT_W32((num 132c49ec1327c1d956c6c889cf1f32a7f9920d76149pbos@webrtc.org - WEBRTC_SPL_LSHIFT_W32((int32_t)num_hi, 16)), 1); 133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // num * (1/den) by 32 bit multiplication (result in Q28) 135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmpW32 = (WEBRTC_SPL_MUL_16_16(num_hi, tmp_hi) + (WEBRTC_SPL_MUL_16_16(num_hi, tmp_low) 137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org >> 15) + (WEBRTC_SPL_MUL_16_16(num_low, tmp_hi) >> 15)); 138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Put result in Q31 (convert from Q28) 140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org tmpW32 = WEBRTC_SPL_LSHIFT_W32(tmpW32, 3); 141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return tmpW32; 143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 144