• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 /*  Includes                                                                        */
21 /*                                                                                  */
22 /************************************************************************************/
23 
24 #include <system/audio.h>
25 #include "LVCS.h"
26 #include "LVCS_Private.h"
27 #include "LVCS_StereoEnhancer.h"
28 #include "VectorArithmetic.h"
29 #include "LVCS_Tables.h"
30 
31 /************************************************************************************/
32 /*                                                                                  */
33 /* FUNCTION:                LVCS_StereoEnhanceInit                                  */
34 /*                                                                                  */
35 /* DESCRIPTION:                                                                     */
36 /*  Initialises the stereo enhancement module based on the sample rate.             */
37 /*                                                                                  */
38 /*  The function selects the coefficients for the filters and clears the data       */
39 /*  history. It is also used for re-initialisation when one of the system control   */
40 /*  parameters changes but will only change the coefficients and clear the history  */
41 /*  if the sample rate or speaker type has changed.                                 */
42 /*                                                                                  */
43 /* PARAMETERS:                                                                      */
44 /*  hInstance               Instance Handle                                         */
45 /*  pParams                 Initialisation parameters                               */
46 /*                                                                                  */
47 /* RETURNS:                                                                         */
48 /*  LVCS_Success            Always succeeds                                         */
49 /*                                                                                  */
50 /* NOTES:                                                                           */
51 /*                                                                                  */
52 /************************************************************************************/
LVCS_SEnhancerInit(LVCS_Handle_t hInstance,LVCS_Params_t * pParams)53 LVCS_ReturnStatus_en LVCS_SEnhancerInit(LVCS_Handle_t hInstance, LVCS_Params_t* pParams) {
54     LVM_UINT16 Offset;
55     LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
56     const BiquadA012B12CoefsSP_t* pSESideCoefs;
57 
58     /*
59      * If the sample rate or speaker type has changed update the filters
60      */
61     if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
62         (pInstance->Params.SpeakerType != pParams->SpeakerType)) {
63         /*
64          * Set the filter coefficients based on the sample rate
65          */
66         /* Mid filter */
67         Offset = (LVM_UINT16)pParams->SampleRate;
68 
69         std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
70                 LVCS_SEMidCoefTable[Offset].A0, LVCS_SEMidCoefTable[Offset].A1, 0.0,
71                 LVCS_SEMidCoefTable[Offset].B1, 0.0};
72         pInstance->pSEMidBiquad.reset(
73                 new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_1, coefs));
74 
75         Offset = (LVM_UINT16)(pParams->SampleRate);
76         pSESideCoefs = (BiquadA012B12CoefsSP_t*)&LVCS_SESideCoefTable[0];
77 
78         /* Side filter */
79         coefs = {pSESideCoefs[Offset].A0, pSESideCoefs[Offset].A1, pSESideCoefs[Offset].A2,
80                  pSESideCoefs[Offset].B1, pSESideCoefs[Offset].B2};
81         pInstance->pSESideBiquad.reset(
82                 new android::audio_utils::BiquadFilter<LVM_FLOAT>(FCC_1, coefs));
83     }
84 
85     return (LVCS_SUCCESS);
86 }
87 /************************************************************************************/
88 /*                                                                                  */
89 /* FUNCTION:                LVCS_StereoEnhance                                      */
90 /*                                                                                  */
91 /* DESCRIPTION:                                                                     */
92 /*  Enhance the stereo image in the input samples based on the following block      */
93 /*  diagram:                                                                        */
94 /*                                                                                  */
95 /*                               ________                                           */
96 /*          ________            |        |          ________                        */
97 /*         |        |  Middle   | Treble |         |        |                       */
98 /*         |        |---------->| Boost  |-------->|        |                       */
99 /*         | Stereo |           |________|         | M & S  |                       */
100 /*      -->|   to   |            ________          |   to   |-->                    */
101 /*         | M & S  |  Side     |        |         | Stereo |                       */
102 /*         |        |---------->| Side   |-------->|        |                       */
103 /*         |________|           | Boost  |         |________|                       */
104 /*                              |________|                                          */
105 /*                                                                                  */
106 /*                                                                                  */
107 /*  If the input signal is a mono signal there will be no side signal and hence     */
108 /*  the side filter will not be run. In mobile speaker mode the middle filter is    */
109 /*  not required and the Trebble boost filter is replaced by a simple gain block.   */
110 /*                                                                                  */
111 /*                                                                                  */
112 /* PARAMETERS:                                                                      */
113 /*  hInstance               Instance Handle                                         */
114 /*  pInData                 Pointer to the input data                               */
115 /*  pOutData                Pointer to the output data                              */
116 /*  NumSamples              Number of samples to process                            */
117 /*                                                                                  */
118 /* RETURNS:                                                                         */
119 /*  LVCS_Success            Always succeeds                                         */
120 /*                                                                                  */
121 /* NOTES:                                                                           */
122 /*  1.  The side filter is not used in Mobile Speaker mode                          */
123 /*                                                                                  */
124 /************************************************************************************/
LVCS_StereoEnhancer(LVCS_Handle_t hInstance,const LVM_FLOAT * pInData,LVM_FLOAT * pOutData,LVM_UINT16 NumSamples)125 LVCS_ReturnStatus_en LVCS_StereoEnhancer(LVCS_Handle_t hInstance, const LVM_FLOAT* pInData,
126                                          LVM_FLOAT* pOutData, LVM_UINT16 NumSamples) {
127     LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
128     LVCS_StereoEnhancer_t* pConfig = (LVCS_StereoEnhancer_t*)&pInstance->StereoEnhancer;
129     LVM_FLOAT* pScratch;
130     pScratch = (LVM_FLOAT*)pInstance->pScratch;
131     LVM_INT32 NumChannels = pInstance->Params.NrChannels;
132     LVM_UINT16 destNumSamples = (NumChannels == FCC_1) ? NumSamples : FCC_2 * NumSamples;
133     /*
134      * Check if the Stereo Enhancer is enabled
135      */
136     if ((pInstance->Params.OperatingMode & LVCS_STEREOENHANCESWITCH) != 0) {
137         /*
138          * Convert from stereo to middle and side
139          */
140         if (NumChannels == 1) {
141             // Copy same input to scratch as Middle data
142             Copy_Float((LVM_FLOAT*)pInData, (LVM_FLOAT*)pScratch, (LVM_INT16)NumSamples);
143         } else {
144             From2iToMS_Float(pInData, pScratch, pScratch + NumSamples, (LVM_INT16)NumSamples);
145         }
146 
147         /*
148          * Apply filter to the middle signal
149          */
150         if (pInstance->OutputDevice == LVCS_HEADPHONE) {
151             pInstance->pSEMidBiquad->process(pScratch, pScratch, NumSamples);
152         } else {
153             Mult3s_Float(pScratch,                    /* Source */
154                          (LVM_FLOAT)pConfig->MidGain, /* Gain */
155                          pScratch,                    /* Destination */
156                          (LVM_INT16)NumSamples);      /* Number of samples */
157         }
158 
159         /*
160          * Apply the filter the side signal only in stereo mode for headphones
161          * and in all modes for mobile speakers
162          */
163         if (pInstance->Params.SourceFormat == LVCS_STEREO) {
164             pInstance->pSESideBiquad->process(pScratch + NumSamples, pScratch + NumSamples,
165                                               NumSamples);
166         }
167 
168         if (NumChannels == 1) {
169             // Copy processed Middle data from scratch to pOutData
170             Copy_Float((LVM_FLOAT*)pScratch, (LVM_FLOAT*)pOutData, (LVM_INT16)NumSamples);
171         } else {
172             /*
173              * Convert from middle and side to stereo
174              */
175             MSTo2i_Sat_Float(pScratch, pScratch + NumSamples, pOutData, (LVM_INT16)NumSamples);
176         }
177 
178     } else {
179         /*
180          * The stereo enhancer is disabled so just copy the data
181          */
182         Copy_Float((LVM_FLOAT*)pInData,        /* Source */
183                    (LVM_FLOAT*)pOutData,       /* Destination */
184                    (LVM_INT16)destNumSamples); /* Number of frames */
185     }
186 
187     return (LVCS_SUCCESS);
188 }
189