145 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			145 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
 | |
|  *
 | |
|  *  Use of this source code is governed by a BSD-style license
 | |
|  *  that can be found in the LICENSE file in the root of the source
 | |
|  *  tree. An additional intellectual property rights grant can be found
 | |
|  *  in the file PATENTS.  All contributing project authors may
 | |
|  *  be found in the AUTHORS file in the root of the source tree.
 | |
|  */
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * This file contains implementations of the divisions
 | |
|  * WebRtcSpl_DivU32U16()
 | |
|  * WebRtcSpl_DivW32W16()
 | |
|  * WebRtcSpl_DivW32W16ResW16()
 | |
|  * WebRtcSpl_DivResultInQ31()
 | |
|  * WebRtcSpl_DivW32HiLow()
 | |
|  *
 | |
|  * The description header can be found in signal_processing_library.h
 | |
|  *
 | |
|  */
 | |
| 
 | |
| #include "signal_processing_library.h"
 | |
| 
 | |
| WebRtc_UWord32 WebRtcSpl_DivU32U16(WebRtc_UWord32 num, WebRtc_UWord16 den)
 | |
| {
 | |
|     // Guard against division with 0
 | |
|     if (den != 0)
 | |
|     {
 | |
|         return (WebRtc_UWord32)(num / den);
 | |
|     } else
 | |
|     {
 | |
|         return (WebRtc_UWord32)0xFFFFFFFF;
 | |
|     }
 | |
| }
 | |
| 
 | |
| WebRtc_Word32 WebRtcSpl_DivW32W16(WebRtc_Word32 num, WebRtc_Word16 den)
 | |
| {
 | |
|     // Guard against division with 0
 | |
|     if (den != 0)
 | |
|     {
 | |
|         return (WebRtc_Word32)(num / den);
 | |
|     } else
 | |
|     {
 | |
|         return (WebRtc_Word32)0x7FFFFFFF;
 | |
|     }
 | |
| }
 | |
| 
 | |
| WebRtc_Word16 WebRtcSpl_DivW32W16ResW16(WebRtc_Word32 num, WebRtc_Word16 den)
 | |
| {
 | |
|     // Guard against division with 0
 | |
|     if (den != 0)
 | |
|     {
 | |
|         return (WebRtc_Word16)(num / den);
 | |
|     } else
 | |
|     {
 | |
|         return (WebRtc_Word16)0x7FFF;
 | |
|     }
 | |
| }
 | |
| 
 | |
| WebRtc_Word32 WebRtcSpl_DivResultInQ31(WebRtc_Word32 num, WebRtc_Word32 den)
 | |
| {
 | |
|     WebRtc_Word32 L_num = num;
 | |
|     WebRtc_Word32 L_den = den;
 | |
|     WebRtc_Word32 div = 0;
 | |
|     int k = 31;
 | |
|     int change_sign = 0;
 | |
| 
 | |
|     if (num == 0)
 | |
|         return 0;
 | |
| 
 | |
|     if (num < 0)
 | |
|     {
 | |
|         change_sign++;
 | |
|         L_num = -num;
 | |
|     }
 | |
|     if (den < 0)
 | |
|     {
 | |
|         change_sign++;
 | |
|         L_den = -den;
 | |
|     }
 | |
|     while (k--)
 | |
|     {
 | |
|         div <<= 1;
 | |
|         L_num <<= 1;
 | |
|         if (L_num >= L_den)
 | |
|         {
 | |
|             L_num -= L_den;
 | |
|             div++;
 | |
|         }
 | |
|     }
 | |
|     if (change_sign == 1)
 | |
|     {
 | |
|         div = -div;
 | |
|     }
 | |
|     return div;
 | |
| }
 | |
| 
 | |
| WebRtc_Word32 WebRtcSpl_DivW32HiLow(WebRtc_Word32 num, WebRtc_Word16 den_hi,
 | |
|                                     WebRtc_Word16 den_low)
 | |
| {
 | |
|     WebRtc_Word16 approx, tmp_hi, tmp_low, num_hi, num_low;
 | |
|     WebRtc_Word32 tmpW32;
 | |
| 
 | |
|     approx = (WebRtc_Word16)WebRtcSpl_DivW32W16((WebRtc_Word32)0x1FFFFFFF, den_hi);
 | |
|     // result in Q14 (Note: 3FFFFFFF = 0.5 in Q30)
 | |
| 
 | |
|     // tmpW32 = 1/den = approx * (2.0 - den * approx) (in Q30)
 | |
|     tmpW32 = (WEBRTC_SPL_MUL_16_16(den_hi, approx) << 1)
 | |
|             + ((WEBRTC_SPL_MUL_16_16(den_low, approx) >> 15) << 1);
 | |
|     // tmpW32 = den * approx
 | |
| 
 | |
|     tmpW32 = (WebRtc_Word32)0x7fffffffL - tmpW32; // result in Q30 (tmpW32 = 2.0-(den*approx))
 | |
| 
 | |
|     // Store tmpW32 in hi and low format
 | |
|     tmp_hi = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmpW32, 16);
 | |
|     tmp_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((tmpW32
 | |
|             - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)tmp_hi, 16)), 1);
 | |
| 
 | |
|     // tmpW32 = 1/den in Q29
 | |
|     tmpW32 = ((WEBRTC_SPL_MUL_16_16(tmp_hi, approx) + (WEBRTC_SPL_MUL_16_16(tmp_low, approx)
 | |
|             >> 15)) << 1);
 | |
| 
 | |
|     // 1/den in hi and low format
 | |
|     tmp_hi = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(tmpW32, 16);
 | |
|     tmp_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((tmpW32
 | |
|             - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)tmp_hi, 16)), 1);
 | |
| 
 | |
|     // Store num in hi and low format
 | |
|     num_hi = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32(num, 16);
 | |
|     num_low = (WebRtc_Word16)WEBRTC_SPL_RSHIFT_W32((num
 | |
|             - WEBRTC_SPL_LSHIFT_W32((WebRtc_Word32)num_hi, 16)), 1);
 | |
| 
 | |
|     // num * (1/den) by 32 bit multiplication (result in Q28)
 | |
| 
 | |
|     tmpW32 = (WEBRTC_SPL_MUL_16_16(num_hi, tmp_hi) + (WEBRTC_SPL_MUL_16_16(num_hi, tmp_low)
 | |
|             >> 15) + (WEBRTC_SPL_MUL_16_16(num_low, tmp_hi) >> 15));
 | |
| 
 | |
|     // Put result in Q31 (convert from Q28)
 | |
|     tmpW32 = WEBRTC_SPL_LSHIFT_W32(tmpW32, 3);
 | |
| 
 | |
|     return tmpW32;
 | |
| }
 | 
