1 /*
2  * Copyright (C) 2004-2010 NXP Software
3  * Copyright (C) 2010 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 /************************************************************************/
19 /*                                                                      */
20 /*     %created_by:    sra % (CM/S)*/
21 /*     %name:          dB_to_Lin32.c % (CM/S)*/
22 /*     %version:       2 % (CM/S)*/
23 /*     %date_created:  Wed Jun 18 11:27:46 2008 % (CM/S)*/
24 /*                                                                      */
25 /************************************************************************/
26 
27 /*######################################################################################*/
28 /*  Include files                                                                       */
29 /*######################################################################################*/
30 
31 #include "ScalarArithmetic.h"
32 
33 
34 /****************************************************************************************
35  *  Name        : dB_to_Lin32()
36  *  Input       : Signed 16-bit integer
37  *                  MSB (16) = sign bit
38  *                  (15->05) = integer part
39  *                  (04->01) = decimal part
40  *  Output      : Signed 32-bit integer
41  *                  MSB (32) = sign bit
42  *                  (31->16) = integer part
43  *                  (15->01) = decimal part
44  *  Returns     : Lin value format 1.16.15
45  *  Description :
46  *  Remarks     :  Makes an approximation to the conversion by counting the number
47  *                 of 6dB steps for use as shifts and then interpolates with a remainder
48  *                 with the equation:
49  *
50  *                 Correction = (Remainder / 1.5029) - (Remainder^2 / 6)
51  *
52  *                 The two coefficients are scaled from 0x40000000 in 96 steps and calculated
53  *                 as follows:
54  *
55  *                 FIRST_COEF  = 0x80000000 / (96 * 1.5029)
56  *                 SECOND_COEF = 0x80000000 / (96^2 * 6)
57  *
58  ****************************************************************************************/
59 
60 #define FOUR_OVER_SIX    21846                  /* (4 / 6) * 2^15 */
61 #define SIX_DB           96                     /* 6 * 16 or 6dB in Q11.4 format */
62 #define FIRST_COEF_NEG   14884305
63 #define FIRST_COEF_POS   7442152                /* FIRST_COEF_NEG / 2 */
64 #define SECOND_COEF      38836
65 #define MAX_VALUE        1536                   /* 96 * 16 */
66 
dB_to_Lin32(LVM_INT16 db_fix)67 LVM_INT32   dB_to_Lin32(LVM_INT16    db_fix)
68 {
69     LVM_INT32 Lin_val_32;
70     LVM_INT16 Shift;
71     LVM_INT32 Remain;
72 
73 
74     /*
75      * Check sign of the input
76      */
77     if (db_fix<0)
78     {
79         if (db_fix > -MAX_VALUE)
80         {
81             Shift  = (LVM_INT16)((((LVM_UINT32)(-db_fix) >> 4) * FOUR_OVER_SIX) >> 17);        /* Number of 6dB steps in Q11.4 format */
82             Remain = -db_fix - (Shift * SIX_DB);
83             Remain = (0x7FFFFFFF - (Remain * FIRST_COEF_NEG)) + (Remain * Remain * SECOND_COEF);
84             Lin_val_32 = (LVM_INT32)((LVM_UINT32)Remain >> (16 + Shift));
85         }
86         else
87         {
88             Lin_val_32 = 0;
89         }
90     }
91     else
92     {
93         if (db_fix < MAX_VALUE)
94         {
95             Shift  = (LVM_INT16)((((LVM_UINT32)db_fix >> 4) * FOUR_OVER_SIX) >> 17);        /* Number of 6dB steps in Q11.4 format */
96             Remain = db_fix - (Shift * SIX_DB);
97             Remain = 0x3FFFFFFF + (Remain * FIRST_COEF_POS) + (Remain * Remain * SECOND_COEF);
98             Lin_val_32 = (LVM_INT32)((LVM_UINT32)Remain >> (15 - Shift));
99         }
100         else
101         {
102             Lin_val_32 = 0x7FFFFFFF;
103         }
104     }
105 
106 
107     return Lin_val_32;  /* format 1.16.15 */
108 }
109 
110