• 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 #include <system/audio.h>
24 #include <stdlib.h>
25 #include "LVCS.h"
26 #include "LVCS_Private.h"
27 #include "LVCS_ReverbGenerator.h"
28 #include "LVC_Mixer.h"
29 #include "VectorArithmetic.h"
30 #include "BIQUAD.h"
31 #include "LVCS_Tables.h"
32 
33 /************************************************************************************/
34 /*                                                                                  */
35 /* FUNCTION:                LVCS_ReverbGeneratorInit                                */
36 /*                                                                                  */
37 /* DESCRIPTION:                                                                     */
38 /*  Initialises the reverb module. The delay buffer size is configured for the      */
39 /*  sample rate and the speaker type.                                               */
40 /*                                                                                  */
41 /*  The routine may also be called for re-initialisation, i.e. when one of the      */
42 /*  control parameters has changed. In this case the delay and filters are only     */
43 /*  re-initialised if one of the following two conditions is met:                   */
44 /*      -   the sample rate has changed                                             */
45 /*      -   the speaker type changes to/from the mobile speaker                     */
46 /*                                                                                  */
47 /*                                                                                  */
48 /* PARAMETERS:                                                                      */
49 /*  hInstance               Instance Handle                                         */
50 /*  pParams                 Pointer to the inialisation parameters                  */
51 /*                                                                                  */
52 /* RETURNS:                                                                         */
53 /*  LVCS_Success            Always succeeds                                         */
54 /*                                                                                  */
55 /* NOTES:                                                                           */
56 /*  1.  In the delay settings 'Samples' is the number of samples to the end of the  */
57 /*      buffer.                                                                     */
58 /*  2.  The numerator coefficients of the filter are negated to cause an inversion. */
59 /*                                                                                  */
60 /************************************************************************************/
LVCS_ReverbGeneratorInit(LVCS_Handle_t hInstance,LVCS_Params_t * pParams)61 LVCS_ReturnStatus_en LVCS_ReverbGeneratorInit(LVCS_Handle_t hInstance, LVCS_Params_t* pParams) {
62     LVM_UINT16 Delay;
63     LVM_UINT16 Offset;
64     LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
65     LVCS_ReverbGenerator_t* pConfig = (LVCS_ReverbGenerator_t*)&pInstance->Reverberation;
66     const BiquadA012B12CoefsSP_t* pReverbCoefTable;
67 
68     /*
69      * Initialise the delay and filters if:
70      *  - the sample rate has changed
71      *  - the speaker type has changed to or from the mobile speaker
72      */
73     if (pInstance->Params.SampleRate != pParams->SampleRate) /* Sample rate change test */
74 
75     {
76         /*
77          * Setup the delay
78          */
79         Delay = (LVM_UINT16)LVCS_StereoDelayCS[(LVM_UINT16)pParams->SampleRate];
80 
81         pConfig->DelaySize =
82                 (pParams->NrChannels == FCC_1) ? (LVM_INT16)Delay : (LVM_INT16)(FCC_2 * Delay);
83         pConfig->DelayOffset = 0;
84         memset(pConfig->StereoSamples, 0, sizeof(pConfig->StereoSamples));
85         /*
86          * Setup the filters
87          */
88         Offset = (LVM_UINT16)pParams->SampleRate;
89         pReverbCoefTable = (BiquadA012B12CoefsSP_t*)&LVCS_ReverbCoefTable[0];
90 
91         std::array<LVM_FLOAT, android::audio_utils::kBiquadNumCoefs> coefs = {
92                 pReverbCoefTable[Offset].A0, pReverbCoefTable[Offset].A1,
93                 pReverbCoefTable[Offset].A2, pReverbCoefTable[Offset].B1,
94                 pReverbCoefTable[Offset].B2};
95         pInstance->pRevBiquad.reset(new android::audio_utils::BiquadFilter<LVM_FLOAT>(
96                 (pParams->NrChannels == FCC_1) ? FCC_1 : FCC_2, coefs));
97 
98         /*
99          * Setup the mixer
100          */
101         pConfig->ProcGain = (LVM_UINT16)(HEADPHONEGAINPROC);
102         pConfig->UnprocGain = (LVM_UINT16)(HEADPHONEGAINUNPROC);
103     }
104 
105     if (pInstance->Params.ReverbLevel != pParams->ReverbLevel) {
106         LVM_INT32 ReverbPercentage = 83886;        // 1 Percent Reverb i.e 1/100 in Q 23 format
107         ReverbPercentage *= pParams->ReverbLevel;  // Actual Reverb Level in Q 23 format
108         pConfig->ReverbLevel = ((LVM_FLOAT)(ReverbPercentage >> 8)) / 32767.0f;
109     }
110     return (LVCS_SUCCESS);
111 }
112 /************************************************************************************/
113 /*                                                                                  */
114 /* FUNCTION:                LVCS_Reverb                                             */
115 /*                                                                                  */
116 /* DESCRIPTION:                                                                     */
117 /*  Create reverb using the block of input samples based on the following block     */
118 /*  diagram:                                                                        */
119 /*                           ________              ________                         */
120 /*                          |        |            |        |                        */
121 /*     _____     _______    |        |----------->|        |    ______     ___      */
122 /*    |     |   |       |   | Stereo |            | L & R  |   |      |   |   |     */
123 /* -->| LPF |-->| Delay |-->|   to   |    ____    |   to   |-->| Gain |-->| + |-->  */
124 /*  | |_____|   |_______|   | L & R  |   |    |   | Stereo |   |______|   |___|     */
125 /*  |                       |        |-->| -1 |-->|        |                |       */
126 /*  |                       |________|   |____|   |________|                |       */
127 /*  |                                                                       |       */
128 /*  |-----------------------------------------------------------------------|       */
129 /*                                                                                  */
130 /*  The input buffer is broken in to sub-blocks of the size of the delay or less.   */
131 /*  This allows the delay buffer to be treated as a circular buffer but processed   */
132 /*  as a linear buffer.                                                             */
133 /*                                                                                  */
134 /*                                                                                  */
135 /* PARAMETERS:                                                                      */
136 /*  hInstance               Instance Handle                                         */
137 /*  pInData                 Pointer to the input buffer                             */
138 /*  pOutData                Pointer to the output buffer                            */
139 /*  NumSamples              Number of samples to process                            */
140 /*                                                                                  */
141 /* RETURNS:                                                                         */
142 /*  LVCS_Success            Always succeeds                                         */
143 /*                                                                                  */
144 /* NOTES:                                                                           */
145 /*  1.  Process in blocks of samples the size of the delay where possible, if not   */
146 /*      the number of samples left over                                             */
147 /*  2.  The Gain is combined with the LPF and incorporated in to the coefficients   */
148 /*                                                                                  */
149 /************************************************************************************/
LVCS_ReverbGenerator(LVCS_Handle_t hInstance,const LVM_FLOAT * pInData,LVM_FLOAT * pOutData,LVM_UINT16 NumSamples)150 LVCS_ReturnStatus_en LVCS_ReverbGenerator(LVCS_Handle_t hInstance, const LVM_FLOAT* pInData,
151                                           LVM_FLOAT* pOutData, LVM_UINT16 NumSamples) {
152     LVCS_Instance_t* pInstance = (LVCS_Instance_t*)hInstance;
153     LVCS_ReverbGenerator_t* pConfig = (LVCS_ReverbGenerator_t*)&pInstance->Reverberation;
154     LVM_FLOAT* pScratch;
155     LVM_INT32 NumChannels = pInstance->Params.NrChannels;
156     LVM_UINT16 destNumSamples =
157             (pInstance->Params.NrChannels == FCC_1) ? NumSamples : FCC_2 * NumSamples;
158 
159     pScratch = (LVM_FLOAT*)pInstance->pScratch;
160 
161     /*
162      * Copy the data to the output in outplace processing
163      */
164     if (pInData != pOutData) {
165         /*
166          * Reverb not required so just copy the data
167          */
168         Copy_Float((LVM_FLOAT*)pInData,        /* Source */
169                    (LVM_FLOAT*)pOutData,       /* Destination */
170                    (LVM_INT16)destNumSamples); /* Number of frames */
171     }
172 
173     /*
174      * Check if the reverb is required
175      */
176     /* Disable when CS4MS in stereo mode */
177     if ((((LVCS_OutputDevice_en)pInstance->Params.SpeakerType == LVCS_HEADPHONE) ||
178          (pInstance->Params.SpeakerType == LVCS_EX_HEADPHONES) ||
179          (pInstance->Params.SourceFormat != LVCS_STEREO)) &&
180         /* For validation testing */
181         ((pInstance->Params.OperatingMode & LVCS_REVERBSWITCH) != 0)) {
182         /********************************************************************************/
183         /*                                                                              */
184         /* Copy the input data to scratch memory and filter it                          */
185         /*                                                                              */
186         /********************************************************************************/
187 
188         /*
189          * Copy the input data to the scratch memory
190          */
191         Copy_Float((LVM_FLOAT*)pInData,        /* Source */
192                    (LVM_FLOAT*)pScratch,       /* Destination */
193                    (LVM_INT16)destNumSamples); /* Number of frames */
194 
195         /*
196          * Filter the data
197          */
198         pInstance->pRevBiquad->process(pScratch, pScratch, NumSamples);
199 
200         Mult3s_Float((LVM_FLOAT*)pScratch, pConfig->ReverbLevel, (LVM_FLOAT*)pScratch,
201                      (LVM_INT16)destNumSamples); /* Number of frames */
202 
203         /*
204          * Apply the delay mix
205          */
206         DelayMix_Float((LVM_FLOAT*)pScratch, &pConfig->StereoSamples[0], pConfig->DelaySize,
207                        pOutData, &pConfig->DelayOffset, (LVM_INT16)NumSamples, NumChannels);
208     }
209 
210     return (LVCS_SUCCESS);
211 }
212