LVCS_Process.c revision 2c8e5cab3faa6d360e222b7a6c40a80083d021ac
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     $Author: beq07716 $
21     $Revision: 1001 $
22     $Date: 2010-06-28 13:23:02 +0200 (Mon, 28 Jun 2010) $
23
24*************************************************************************************/
25
26
27/************************************************************************************/
28/*                                                                                  */
29/*  Includes                                                                        */
30/*                                                                                  */
31/************************************************************************************/
32
33#include "LVCS.h"
34#include "LVCS_Private.h"
35#include "VectorArithmetic.h"
36#include "CompLim.h"
37
38/************************************************************************************/
39/*                                                                                  */
40/* FUNCTION:                LVCS_Process_CS                                         */
41/*                                                                                  */
42/* DESCRIPTION:                                                                     */
43/*  Process function for the Concert Sound module based on the following block      */
44/*  diagram:                                                                        */
45/*            _________    ________    _____    _______     ___   ______            */
46/*           |         |  |        |  |     |  |       |   |   | |      |           */
47/*     ----->| Stereo  |->| Reverb |->| Equ |->| Alpha |-->| + |-| Gain |---->      */
48/*        |  | Enhance |  |________|  |_____|  |_______|   |___| |______|           */
49/*        |  |_________|                                     |                      */
50/*        |                                 ___________      |                      */
51/*        |                                |           |     |                      */
52/*        |------------------------------->| 1 - Alpha |-----|                      */
53/*                                         |___________|                            */
54/*                                                                                  */
55/*  The Stereo Enhancer, Reverb and Equaliser blocks are each configured to have    */
56/*  their gain to give a near peak to peak output (-0.1dBFS) with a worst case      */
57/*  input signal. The gains of these blocks are re-combined in the Alpha mixer and  */
58/*  the gain block folloing the sum.                                                */
59/*                                                                                  */
60/*  The processing uses the output buffer for data storage after each processing    */
61/*  block. When processing is inplace a copy of the input signal is made in scratch */
62/*  memory for the 1-Alpha path.                                                    */
63/*                                                                                  */
64/*                                                                                  */
65/* PARAMETERS:                                                                      */
66/*  hInstance               Instance handle                                         */
67/*  pInData                 Pointer to the input data                               */
68/*  pOutData                Pointer to the output data                              */
69/*  NumSamples              Number of samples in the input buffer                   */
70/*                                                                                  */
71/* RETURNS:                                                                         */
72/*  LVCS_Success            Succeeded                                               */
73/*                                                                                  */
74/* NOTES:                                                                           */
75/*                                                                                  */
76/************************************************************************************/
77
78LVCS_ReturnStatus_en LVCS_Process_CS(LVCS_Handle_t              hInstance,
79                                     const LVM_INT16            *pInData,
80                                     LVM_INT16                  *pOutData,
81                                     LVM_UINT16                 NumSamples)
82{
83    const LVM_INT16     *pInput;
84    LVCS_Instance_t     *pInstance = (LVCS_Instance_t  *)hInstance;
85    LVM_INT16           *pScratch  = (LVM_INT16 *)pInstance->MemoryTable.Region[LVCS_MEMREGION_TEMPORARY_FAST].pBaseAddress;
86    LVCS_ReturnStatus_en err;
87
88    /*
89     * Check if the processing is inplace
90     */
91    if (pInData == pOutData)
92    {
93        /* Processing inplace */
94        pInput = pScratch + (2*NumSamples);
95        Copy_16((LVM_INT16 *)pInData,           /* Source */
96                (LVM_INT16 *)pInput,            /* Destination */
97                (LVM_INT16)(2*NumSamples));     /* Left and right */
98    }
99    else
100    {
101        /* Processing outplace */
102        pInput = pInData;
103    }
104
105    /*
106     * Call the stereo enhancer
107     */
108    err=LVCS_StereoEnhancer(hInstance,              /* Instance handle */
109                        pInData,                    /* Pointer to the input data */
110                        pOutData,                   /* Pointer to the output data */
111                        NumSamples);                /* Number of samples to process */
112
113    /*
114     * Call the reverb generator
115     */
116    err=LVCS_ReverbGenerator(hInstance,             /* Instance handle */
117                         pOutData,                  /* Pointer to the input data */
118                         pOutData,                  /* Pointer to the output data */
119                         NumSamples);               /* Number of samples to process */
120
121    /*
122     * Call the equaliser
123     */
124    err=LVCS_Equaliser(hInstance,                   /* Instance handle */
125                   pOutData,                        /* Pointer to the input data */
126                   NumSamples);                     /* Number of samples to process */
127
128    /*
129     * Call the bypass mixer
130     */
131    err=LVCS_BypassMixer(hInstance,                 /* Instance handle */
132                     pOutData,                      /* Pointer to the processed data */
133                     pInput,                        /* Pointer to the input (unprocessed) data */
134                     pOutData,                      /* Pointer to the output data */
135                     NumSamples);                   /* Number of samples to process */
136
137    if(err !=LVCS_SUCCESS)
138    {
139        return err;
140    }
141
142    return(LVCS_SUCCESS);
143}
144
145/************************************************************************************/
146/*                                                                                  */
147/* FUNCTION:                LVCS_Process                                            */
148/*                                                                                  */
149/* DESCRIPTION:                                                                     */
150/*  Process function for the Concert Sound module. The implementation supports two  */
151/*  variants of the algorithm, one for headphones and one for mobile speakers.      */
152/*                                                                                  */
153/*  Data can be processed in two formats, stereo or mono-in-stereo. Data in mono    */
154/*  format is not supported, the calling routine must convert the mono stream to    */
155/*  mono-in-stereo.                                                                 */
156/*                                                                                  */
157/*                                                                                  */
158/* PARAMETERS:                                                                      */
159/*  hInstance               Instance handle                                         */
160/*  pInData                 Pointer to the input data                               */
161/*  pOutData                Pointer to the output data                              */
162/*  NumSamples              Number of samples in the input buffer                   */
163/*                                                                                  */
164/* RETURNS:                                                                         */
165/*  LVCS_Success            Succeeded                                               */
166/*  LVCS_TooManySamples     NumSamples was larger than the maximum block size       */
167/*                                                                                  */
168/* NOTES:                                                                           */
169/*                                                                                  */
170/************************************************************************************/
171
172LVCS_ReturnStatus_en LVCS_Process(LVCS_Handle_t             hInstance,
173                                  const LVM_INT16           *pInData,
174                                  LVM_INT16                 *pOutData,
175                                  LVM_UINT16                NumSamples)
176{
177
178    LVCS_Instance_t *pInstance =(LVCS_Instance_t  *)hInstance;
179    LVCS_ReturnStatus_en err;
180
181    /*
182     * Check the number of samples is not too large
183     */
184    if (NumSamples > pInstance->Capabilities.MaxBlockSize)
185    {
186        return(LVCS_TOOMANYSAMPLES);
187    }
188
189    /*
190     * Check if the algorithm is enabled
191     */
192    if (pInstance->Params.OperatingMode != LVCS_OFF)
193    {
194        /*
195         * Call CS process function
196         */
197            err=LVCS_Process_CS(hInstance,
198                            pInData,
199                            pOutData,
200                            NumSamples);
201
202        /*
203         * Compress to reduce expansion effect of Concert Sound and correct volume
204         * differences for difference settings. Not applied in test modes
205         */
206        if ((pInstance->Params.OperatingMode == LVCS_ON)&&(pInstance->Params.CompressorMode == LVM_MODE_ON))
207        {
208            LVM_INT16 Gain = pInstance->VolCorrect.CompMin;
209            LVM_INT32 Current1;
210
211            Current1 = LVC_Mixer_GetCurrent(&pInstance->BypassMix.Mixer_Instance.MixerStream[0]);
212            Gain = (LVM_INT16)(  pInstance->VolCorrect.CompMin
213                               - (((LVM_INT32)pInstance->VolCorrect.CompMin  * (Current1)) >> 15)
214                               + (((LVM_INT32)pInstance->VolCorrect.CompFull * (Current1)) >> 15) );
215
216            NonLinComp_D16(Gain,                    /* Compressor gain setting */
217                           pOutData,
218                           pOutData,
219                           (LVM_INT32)(2*NumSamples));
220        }
221
222
223        if(pInstance->bInOperatingModeTransition == LVM_TRUE){
224
225            /*
226             * Re-init bypass mix when timer has completed
227             */
228            if ((pInstance->bTimerDone == LVM_TRUE) &&
229                (pInstance->BypassMix.Mixer_Instance.MixerStream[1].CallbackSet == 0))
230            {
231                err=LVCS_BypassMixInit(hInstance,
232                                   &pInstance->Params);
233
234                if(err != LVCS_SUCCESS)
235                {
236                    return err;
237                }
238
239            }
240            else{
241                LVM_Timer ( &pInstance->TimerInstance,
242                            (LVM_INT16)NumSamples);
243            }
244        }
245    }
246    else
247    {
248        if (pInData != pOutData)
249        {
250            /*
251             * The algorithm is disabled so just copy the data
252             */
253            Copy_16((LVM_INT16 *)pInData,               /* Source */
254                (LVM_INT16 *)pOutData,                  /* Destination */
255                (LVM_INT16)(2*NumSamples));             /* Left and right */
256        }
257    }
258
259
260    return(LVCS_SUCCESS);
261}
262
263
264
265
266
267
268
269
270
271
272