12c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*
22c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Copyright (C) 2004-2010 NXP Software
32c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Copyright (C) 2010 The Android Open Source Project
42c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent *
52c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Licensed under the Apache License, Version 2.0 (the "License");
62c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * you may not use this file except in compliance with the License.
72c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * You may obtain a copy of the License at
82c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent *
92c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent *      http://www.apache.org/licenses/LICENSE-2.0
102c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent *
112c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Unless required by applicable law or agreed to in writing, software
122c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * distributed under the License is distributed on an "AS IS" BASIS,
132c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
142c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * See the License for the specific language governing permissions and
152c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * limitations under the License.
162c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent */
172c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
182c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
192c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/************************************************************************************/
202c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
212c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  Includes                                                                        */
222c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
232c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/************************************************************************************/
242c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
252c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#include "LVCS.h"
262c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#include "LVCS_Private.h"
272c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#include "VectorArithmetic.h"
282c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#include "CompLim.h"
292c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
302c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/************************************************************************************/
312c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
322c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* FUNCTION:                LVCS_Process_CS                                         */
332c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
342c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* DESCRIPTION:                                                                     */
352c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  Process function for the Concert Sound module based on the following block      */
362c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  diagram:                                                                        */
372c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*            _________    ________    _____    _______     ___   ______            */
382c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*           |         |  |        |  |     |  |       |   |   | |      |           */
392c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*     ----->| Stereo  |->| Reverb |->| Equ |->| Alpha |-->| + |-| Gain |---->      */
402c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*        |  | Enhance |  |________|  |_____|  |_______|   |___| |______|           */
412c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*        |  |_________|                                     |                      */
422c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*        |                                 ___________      |                      */
432c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*        |                                |           |     |                      */
442c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*        |------------------------------->| 1 - Alpha |-----|                      */
452c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                         |___________|                            */
462c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
472c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  The Stereo Enhancer, Reverb and Equaliser blocks are each configured to have    */
482c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  their gain to give a near peak to peak output (-0.1dBFS) with a worst case      */
492c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  input signal. The gains of these blocks are re-combined in the Alpha mixer and  */
502c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  the gain block folloing the sum.                                                */
512c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
522c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  The processing uses the output buffer for data storage after each processing    */
532c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  block. When processing is inplace a copy of the input signal is made in scratch */
542c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  memory for the 1-Alpha path.                                                    */
552c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
562c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
572c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* PARAMETERS:                                                                      */
582c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  hInstance               Instance handle                                         */
592c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  pInData                 Pointer to the input data                               */
602c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  pOutData                Pointer to the output data                              */
612c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  NumSamples              Number of samples in the input buffer                   */
622c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
632c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* RETURNS:                                                                         */
642c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  LVCS_Success            Succeeded                                               */
652c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
662c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* NOTES:                                                                           */
672c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
682c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/************************************************************************************/
69d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri#ifdef BUILD_FLOAT
70d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh KaturiLVCS_ReturnStatus_en LVCS_Process_CS(LVCS_Handle_t              hInstance,
71d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                                     const LVM_FLOAT            *pInData,
72d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                                     LVM_FLOAT                  *pOutData,
73d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                                     LVM_UINT16                 NumSamples)
74d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri{
75d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    const LVM_FLOAT     *pInput;
76d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    LVCS_Instance_t     *pInstance = (LVCS_Instance_t  *)hInstance;
77d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    LVM_FLOAT           *pScratch;
78d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    LVCS_ReturnStatus_en err;
79d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri
80d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    pScratch  = (LVM_FLOAT *) \
81d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                  pInstance->MemoryTable.Region[LVCS_MEMREGION_TEMPORARY_FAST].pBaseAddress;
822c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
83d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    /*
84d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri     * Check if the processing is inplace
85d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri     */
86d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    if (pInData == pOutData)
87d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    {
88d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri        /* Processing inplace */
89d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri        pInput = pScratch + (2 * NumSamples);
90d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri        Copy_Float((LVM_FLOAT *)pInData,           /* Source */
91d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                   (LVM_FLOAT *)pInput,            /* Destination */
92d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                   (LVM_INT16)(2 * NumSamples));     /* Left and right */
93d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    }
94d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    else
95d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    {
96d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri        /* Processing outplace */
97d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri        pInput = pInData;
98d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    }
99d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri
100d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    /*
101d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri     * Call the stereo enhancer
102d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri     */
103d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    err = LVCS_StereoEnhancer(hInstance,              /* Instance handle */
104d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                              pInData,                    /* Pointer to the input data */
105d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                              pOutData,                   /* Pointer to the output data */
106d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                              NumSamples);                /* Number of samples to process */
107d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri
108d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    /*
109d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri     * Call the reverb generator
110d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri     */
111d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    err = LVCS_ReverbGenerator(hInstance,             /* Instance handle */
112d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                               pOutData,                  /* Pointer to the input data */
113d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                               pOutData,                  /* Pointer to the output data */
114d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                               NumSamples);               /* Number of samples to process */
115d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri
116d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    /*
117d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri     * Call the equaliser
118d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri     */
119d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    err = LVCS_Equaliser(hInstance,                   /* Instance handle */
120d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                         pOutData,                        /* Pointer to the input data */
121d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                         NumSamples);                     /* Number of samples to process */
122d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri
123d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    /*
124d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri     * Call the bypass mixer
125d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri     */
126d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    err = LVCS_BypassMixer(hInstance,                 /* Instance handle */
127d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                           pOutData,                      /* Pointer to the processed data */
128d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                           pInput,                        /* Pointer to the input (unprocessed) data */
129d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                           pOutData,                      /* Pointer to the output data */
130d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                           NumSamples);                   /* Number of samples to process */
131d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri
132d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    if(err != LVCS_SUCCESS)
133d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    {
134d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri        return err;
135d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    }
136d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri
137d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    return(LVCS_SUCCESS);
138d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri}
139d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri#else
1402c8e5cab3faa6d360e222b7a6c40a80083d021acEric LaurentLVCS_ReturnStatus_en LVCS_Process_CS(LVCS_Handle_t              hInstance,
1412c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                     const LVM_INT16            *pInData,
1422c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                     LVM_INT16                  *pOutData,
1432c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                     LVM_UINT16                 NumSamples)
1442c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent{
1452c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    const LVM_INT16     *pInput;
1462c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVCS_Instance_t     *pInstance = (LVCS_Instance_t  *)hInstance;
1472c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVM_INT16           *pScratch  = (LVM_INT16 *)pInstance->MemoryTable.Region[LVCS_MEMREGION_TEMPORARY_FAST].pBaseAddress;
1482c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVCS_ReturnStatus_en err;
1492c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1502c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    /*
1512c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     * Check if the processing is inplace
1522c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     */
1532c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    if (pInData == pOutData)
1542c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    {
1552c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        /* Processing inplace */
1562c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        pInput = pScratch + (2*NumSamples);
1572c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        Copy_16((LVM_INT16 *)pInData,           /* Source */
1582c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                (LVM_INT16 *)pInput,            /* Destination */
1592c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                (LVM_INT16)(2*NumSamples));     /* Left and right */
1602c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    }
1612c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    else
1622c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    {
1632c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        /* Processing outplace */
1642c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        pInput = pInData;
1652c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    }
1662c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1672c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    /*
1682c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     * Call the stereo enhancer
1692c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     */
1702c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    err=LVCS_StereoEnhancer(hInstance,              /* Instance handle */
1712c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                        pInData,                    /* Pointer to the input data */
1722c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                        pOutData,                   /* Pointer to the output data */
1732c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                        NumSamples);                /* Number of samples to process */
1742c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1752c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    /*
1762c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     * Call the reverb generator
1772c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     */
1782c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    err=LVCS_ReverbGenerator(hInstance,             /* Instance handle */
1792c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                         pOutData,                  /* Pointer to the input data */
1802c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                         pOutData,                  /* Pointer to the output data */
1812c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                         NumSamples);               /* Number of samples to process */
1822c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1832c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    /*
1842c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     * Call the equaliser
1852c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     */
1862c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    err=LVCS_Equaliser(hInstance,                   /* Instance handle */
1872c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                   pOutData,                        /* Pointer to the input data */
1882c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                   NumSamples);                     /* Number of samples to process */
1892c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1902c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    /*
1912c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     * Call the bypass mixer
1922c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     */
1932c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    err=LVCS_BypassMixer(hInstance,                 /* Instance handle */
1942c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                     pOutData,                      /* Pointer to the processed data */
1952c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                     pInput,                        /* Pointer to the input (unprocessed) data */
1962c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                     pOutData,                      /* Pointer to the output data */
1972c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                     NumSamples);                   /* Number of samples to process */
1982c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1992c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    if(err !=LVCS_SUCCESS)
2002c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    {
2012c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        return err;
2022c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    }
2032c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
2042c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    return(LVCS_SUCCESS);
2052c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent}
206d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri#endif
2072c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/************************************************************************************/
2082c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
2092c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* FUNCTION:                LVCS_Process                                            */
2102c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
2112c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* DESCRIPTION:                                                                     */
2122c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  Process function for the Concert Sound module. The implementation supports two  */
2132c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  variants of the algorithm, one for headphones and one for mobile speakers.      */
2142c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
2152c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  Data can be processed in two formats, stereo or mono-in-stereo. Data in mono    */
2162c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  format is not supported, the calling routine must convert the mono stream to    */
2172c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  mono-in-stereo.                                                                 */
2182c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
2192c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
2202c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* PARAMETERS:                                                                      */
2212c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  hInstance               Instance handle                                         */
2222c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  pInData                 Pointer to the input data                               */
2232c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  pOutData                Pointer to the output data                              */
2242c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  NumSamples              Number of samples in the input buffer                   */
2252c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
2262c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* RETURNS:                                                                         */
2272c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  LVCS_Success            Succeeded                                               */
2282c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  LVCS_TooManySamples     NumSamples was larger than the maximum block size       */
2292c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
2302c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* NOTES:                                                                           */
2312c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
2322c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/************************************************************************************/
233d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri#ifdef BUILD_FLOAT
234d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh KaturiLVCS_ReturnStatus_en LVCS_Process(LVCS_Handle_t             hInstance,
235d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                                  const LVM_FLOAT           *pInData,
236d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                                  LVM_FLOAT                 *pOutData,
237d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                                  LVM_UINT16                NumSamples)
238d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri{
2392c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
240d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    LVCS_Instance_t *pInstance = (LVCS_Instance_t  *)hInstance;
241d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    LVCS_ReturnStatus_en err;
242d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri
243d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    /*
244d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri     * Check the number of samples is not too large
245d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri     */
246d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    if (NumSamples > pInstance->Capabilities.MaxBlockSize)
247d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    {
248d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri        return(LVCS_TOOMANYSAMPLES);
249d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    }
250d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri
251d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    /*
252d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri     * Check if the algorithm is enabled
253d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri     */
254d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    if (pInstance->Params.OperatingMode != LVCS_OFF)
255d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    {
256d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri        /*
257d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri         * Call CS process function
258d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri         */
259d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri            err = LVCS_Process_CS(hInstance,
260d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                                  pInData,
261d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                                  pOutData,
262d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                                  NumSamples);
263d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri
264d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri
265d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri        /*
266d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri         * Compress to reduce expansion effect of Concert Sound and correct volume
267d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri         * differences for difference settings. Not applied in test modes
268d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri         */
269d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri        if ((pInstance->Params.OperatingMode == LVCS_ON)&& \
270d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                                        (pInstance->Params.CompressorMode == LVM_MODE_ON))
271d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri        {
272d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri            LVM_FLOAT Gain = pInstance->VolCorrect.CompMin;
273d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri            LVM_FLOAT Current1;
274d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri
275d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri            Current1 = LVC_Mixer_GetCurrent(&pInstance->BypassMix.Mixer_Instance.MixerStream[0]);
276d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri            Gain = (LVM_FLOAT)(  pInstance->VolCorrect.CompMin
277d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                               - (((LVM_FLOAT)pInstance->VolCorrect.CompMin  * (Current1)))
278d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                               + (((LVM_FLOAT)pInstance->VolCorrect.CompFull * (Current1))));
279d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri
280d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri            if(NumSamples < LVCS_COMPGAINFRAME)
281d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri            {
282d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                NonLinComp_Float(Gain,                    /* Compressor gain setting */
283d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                                 pOutData,
284d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                                 pOutData,
285d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                                 (LVM_INT32)(2 * NumSamples));
286d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri            }
287d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri            else
288d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri            {
289d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                LVM_FLOAT  GainStep;
290d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                LVM_FLOAT  FinalGain;
291d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                LVM_INT16  SampleToProcess = NumSamples;
292d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                LVM_FLOAT  *pOutPtr;
293d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri
294d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                /* Large changes in Gain can cause clicks in output
295d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                   Split data into small blocks and use interpolated gain values */
296d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri
297d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                GainStep = (LVM_FLOAT)(((Gain-pInstance->CompressGain) * \
298d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                                                LVCS_COMPGAINFRAME) / NumSamples);
299d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri
300d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                if((GainStep == 0) && (pInstance->CompressGain < Gain))
301d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                {
302d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                    GainStep = 1;
303d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                }
304d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                else
305d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                {
306d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                    if((GainStep == 0) && (pInstance->CompressGain > Gain))
307d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                    {
308d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                        GainStep = -1;
309d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                    }
310d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                }
311d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri
312d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                FinalGain = Gain;
313d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                Gain = pInstance->CompressGain;
314d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                pOutPtr = pOutData;
315d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri
316d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                while(SampleToProcess > 0)
317d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                {
318d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                    Gain = (LVM_FLOAT)(Gain + GainStep);
319d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                    if((GainStep > 0) && (FinalGain <= Gain))
320d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                    {
321d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                        Gain = FinalGain;
322d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                        GainStep = 0;
323d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                    }
324d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri
325d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                    if((GainStep < 0) && (FinalGain > Gain))
326d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                    {
327d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                        Gain = FinalGain;
328d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                        GainStep = 0;
329d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                    }
330d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri
331d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                    if(SampleToProcess > LVCS_COMPGAINFRAME)
332d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                    {
333d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                        NonLinComp_Float(Gain,                    /* Compressor gain setting */
334d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                                         pOutPtr,
335d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                                         pOutPtr,
336d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                                         (LVM_INT32)(2 * LVCS_COMPGAINFRAME));
337d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                        pOutPtr += (2 * LVCS_COMPGAINFRAME);
338d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                        SampleToProcess = (LVM_INT16)(SampleToProcess - LVCS_COMPGAINFRAME);
339d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                    }
340d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                    else
341d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                    {
342d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                        NonLinComp_Float(Gain,                    /* Compressor gain setting */
343d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                                         pOutPtr,
344d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                                         pOutPtr,
345d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                                         (LVM_INT32)(2 * SampleToProcess));
346d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                        SampleToProcess = 0;
347d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                    }
348d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri
349d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                }
350d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri            }
351d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri
352d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri            /* Store gain value*/
353d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri            pInstance->CompressGain = Gain;
354d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri        }
355d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri
356d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri
357d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri        if(pInstance->bInOperatingModeTransition == LVM_TRUE){
358d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri
359d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri            /*
360d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri             * Re-init bypass mix when timer has completed
361d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri             */
362d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri            if ((pInstance->bTimerDone == LVM_TRUE) &&
363d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                (pInstance->BypassMix.Mixer_Instance.MixerStream[1].CallbackSet == 0))
364d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri            {
365d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                err = LVCS_BypassMixInit(hInstance,
366d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                                         &pInstance->Params);
367d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri
368d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                if(err != LVCS_SUCCESS)
369d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                {
370d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                    return err;
371d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                }
372d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri
373d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri            }
374d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri            else{
375d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                LVM_Timer ( &pInstance->TimerInstance,
376d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                            (LVM_INT16)NumSamples);
377d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri            }
378d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri        }
379d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    }
380d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    else
381d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    {
382d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri        if (pInData != pOutData)
383d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri        {
384d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri            /*
385d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri             * The algorithm is disabled so just copy the data
386d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri             */
387d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri            Copy_Float((LVM_FLOAT *)pInData,               /* Source */
388d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                       (LVM_FLOAT *)pOutData,                  /* Destination */
389d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri                       (LVM_INT16)(2 * NumSamples));             /* Left and right */
390d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri        }
391d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    }
392d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri
393d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri
394d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri    return(LVCS_SUCCESS);
395d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri}
396d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri#else
3972c8e5cab3faa6d360e222b7a6c40a80083d021acEric LaurentLVCS_ReturnStatus_en LVCS_Process(LVCS_Handle_t             hInstance,
3982c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                  const LVM_INT16           *pInData,
3992c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                  LVM_INT16                 *pOutData,
4002c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                  LVM_UINT16                NumSamples)
4012c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent{
4022c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
4032c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVCS_Instance_t *pInstance =(LVCS_Instance_t  *)hInstance;
4042c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVCS_ReturnStatus_en err;
4052c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
4062c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    /*
4072c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     * Check the number of samples is not too large
4082c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     */
4092c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    if (NumSamples > pInstance->Capabilities.MaxBlockSize)
4102c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    {
4112c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        return(LVCS_TOOMANYSAMPLES);
4122c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    }
4132c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
4142c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    /*
4152c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     * Check if the algorithm is enabled
4162c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent     */
4172c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    if (pInstance->Params.OperatingMode != LVCS_OFF)
4182c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    {
4192c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        /*
4202c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         * Call CS process function
4212c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         */
4222c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            err=LVCS_Process_CS(hInstance,
4232c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                            pInData,
4242c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                            pOutData,
4252c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                            NumSamples);
4262c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
4272c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        /*
4282c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         * Compress to reduce expansion effect of Concert Sound and correct volume
4292c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         * differences for difference settings. Not applied in test modes
4302c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         */
4312c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        if ((pInstance->Params.OperatingMode == LVCS_ON)&&(pInstance->Params.CompressorMode == LVM_MODE_ON))
4322c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        {
4332c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            LVM_INT16 Gain = pInstance->VolCorrect.CompMin;
4342c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            LVM_INT32 Current1;
4352c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
4362c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            Current1 = LVC_Mixer_GetCurrent(&pInstance->BypassMix.Mixer_Instance.MixerStream[0]);
4372c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            Gain = (LVM_INT16)(  pInstance->VolCorrect.CompMin
4382c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                               - (((LVM_INT32)pInstance->VolCorrect.CompMin  * (Current1)) >> 15)
4392c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                               + (((LVM_INT32)pInstance->VolCorrect.CompFull * (Current1)) >> 15) );
4402c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
441d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent            if(NumSamples < LVCS_COMPGAINFRAME)
442d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent            {
443d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                NonLinComp_D16(Gain,                    /* Compressor gain setting */
444d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                    pOutData,
445d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                    pOutData,
446d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                    (LVM_INT32)(2*NumSamples));
447d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent            }
448d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent            else
449d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent            {
450d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                LVM_INT16  GainStep;
451d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                LVM_INT16  FinalGain;
452d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                LVM_INT16  SampleToProcess = NumSamples;
453d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                LVM_INT16  *pOutPtr;
454d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent
455d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                /* Large changes in Gain can cause clicks in output
456d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                   Split data into small blocks and use interpolated gain values */
457d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent
458d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                GainStep = (LVM_INT16)(((Gain-pInstance->CompressGain) * LVCS_COMPGAINFRAME)/NumSamples);
459d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent
460d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                if((GainStep ==0)&&(pInstance->CompressGain < Gain))
461d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                {
462d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                    GainStep=1;
463d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                }
464d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                else
465d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                {
466d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                    if((GainStep ==0)&&(pInstance->CompressGain > Gain))
467d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                    {
468d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                        GainStep=-1;
469d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                    }
470d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                }
471d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent
472d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                FinalGain = Gain;
473d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                Gain = pInstance->CompressGain;
474d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                pOutPtr = pOutData;
475d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent
476d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                while(SampleToProcess > 0)
477d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                {
478d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                    Gain = (LVM_INT16)(Gain + GainStep);
479d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                    if((GainStep > 0)&& (FinalGain <= Gain))
480d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                    {
481d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                        Gain = FinalGain;
482d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                        GainStep =0;
483d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                    }
484d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent
485d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                    if((GainStep < 0)&& (FinalGain > Gain))
486d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                    {
487d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                        Gain = FinalGain;
488d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                        GainStep =0;
489d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                    }
490d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent
491d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                    if(SampleToProcess > LVCS_COMPGAINFRAME)
492d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                    {
493d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                        NonLinComp_D16(Gain,                    /* Compressor gain setting */
494d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                            pOutPtr,
495d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                            pOutPtr,
496d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                            (LVM_INT32)(2*LVCS_COMPGAINFRAME));
497d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                        pOutPtr +=(2*LVCS_COMPGAINFRAME);
498d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                        SampleToProcess = (LVM_INT16)(SampleToProcess-LVCS_COMPGAINFRAME);
499d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                    }
500d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                    else
501d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                    {
502d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                        NonLinComp_D16(Gain,                    /* Compressor gain setting */
503d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                            pOutPtr,
504d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                            pOutPtr,
505d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                            (LVM_INT32)(2*SampleToProcess));
506d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent
507d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                        SampleToProcess = 0;
508d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                    }
509d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent
510d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent                }
511d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent            }
512d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent
513d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent            /* Store gain value*/
514d918324d44aa48b3b064ea9b87d0c520c38f15a9Eric Laurent            pInstance->CompressGain = Gain;
5152c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        }
5162c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
5172c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
5182c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        if(pInstance->bInOperatingModeTransition == LVM_TRUE){
5192c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
5202c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            /*
5212c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent             * Re-init bypass mix when timer has completed
5222c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent             */
5232c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            if ((pInstance->bTimerDone == LVM_TRUE) &&
5242c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                (pInstance->BypassMix.Mixer_Instance.MixerStream[1].CallbackSet == 0))
5252c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            {
5262c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                err=LVCS_BypassMixInit(hInstance,
5272c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                   &pInstance->Params);
5282c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
5292c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                if(err != LVCS_SUCCESS)
5302c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                {
5312c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                    return err;
5322c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                }
5332c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
5342c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            }
5352c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            else{
5362c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                LVM_Timer ( &pInstance->TimerInstance,
5372c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                            (LVM_INT16)NumSamples);
5382c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            }
5392c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        }
5402c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    }
5412c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    else
5422c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    {
5432c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        if (pInData != pOutData)
5442c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        {
5452c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            /*
5462c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent             * The algorithm is disabled so just copy the data
5472c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent             */
5482c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            Copy_16((LVM_INT16 *)pInData,               /* Source */
5492c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                (LVM_INT16 *)pOutData,                  /* Destination */
5502c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                (LVM_INT16)(2*NumSamples));             /* Left and right */
5512c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        }
5522c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    }
5532c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
5542c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
5552c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    return(LVCS_SUCCESS);
5562c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent}
557d7d013446a64c6de9f0f2dfe098a721b140e0b48Ramesh Katuri#endif
558