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 "LVDBE.h" 25#include "LVDBE_Private.h" 26#include "VectorArithmetic.h" 27#include "AGC.h" 28#include "LVDBE_Coeffs.h" /* Filter coefficients */ 29 30/********************************************************************************************/ 31/* */ 32/* FUNCTION: LVDBE_Process */ 33/* */ 34/* DESCRIPTION: */ 35/* Process function for the Bass Enhancement module. */ 36/* */ 37/* Data can be processed in two formats, stereo or mono-in-stereo. Data in mono */ 38/* format is not supported, the calling routine must convert the mono stream to */ 39/* mono-in-stereo. */ 40/* ___________ */ 41/* ________ | | ________ */ 42/* | | _____ |------------------------->| | | | */ 43/* | 16-bit | | | | ________ | | | 32-bit | */ 44/* -+-->| to |-->| HPF |--| | | _____ | AGC Mixer |-->| to |--| */ 45/* | | 32-bit | |_____| | | Stereo | | | | | | 16-bit | | */ 46/* | |________| |-->| to |-->| BPF |-->| | |________| 0 */ 47/* | | Mono | |_____| |___________| \--> */ 48/* | |________| */ 49/* | _________ 0 */ 50/* | | | | */ 51/* |----------------------------------------------------| Volume |-----------------| */ 52/* | Control | */ 53/* |_________| */ 54/* */ 55/* PARAMETERS: */ 56/* hInstance Instance handle */ 57/* pInData Pointer to the input data */ 58/* pOutData Pointer to the output data */ 59/* NumSamples Number of samples in the input buffer */ 60/* */ 61/* RETURNS: */ 62/* LVDBE_SUCCESS Succeeded */ 63/* LVDBE_TOOMANYSAMPLES NumSamples was larger than the maximum block size */ 64/* */ 65/* NOTES: */ 66/* 1. The input and output data must be 32-bit format. The input is scaled by a shift */ 67/* when converting from 16-bit format, this scaling allows for internal headroom in the */ 68/* bass enhancement algorithm. */ 69/* 2. For a 16-bit implementation the converstion to 32-bit is removed and replaced with */ 70/* the headroom loss. This headroom loss is compensated in the volume control so the */ 71/* overall end to end gain is odB. */ 72/* */ 73/********************************************************************************************/ 74#ifndef BUILD_FLOAT 75LVDBE_ReturnStatus_en LVDBE_Process(LVDBE_Handle_t hInstance, 76 const LVM_INT16 *pInData, LVM_INT16 *pOutData, LVM_UINT16 NumSamples) { 77 78 LVDBE_Instance_t *pInstance = (LVDBE_Instance_t *) hInstance; 79 LVM_INT32 *pScratch = 80 (LVM_INT32 *) pInstance->MemoryTable.Region[LVDBE_MEMREGION_SCRATCH].pBaseAddress; 81 LVM_INT32 *pMono; 82 LVM_INT16 *pInput = (LVM_INT16 *) pInData; 83 84 /* Scratch for Volume Control starts at offset of 2*NumSamples short values from pScratch */ 85 LVM_INT16 *pScratchVol = (LVM_INT16 *) (&pScratch[NumSamples]); 86 87 /* Scratch for Mono path starts at offset of 2*NumSamples 32-bit values from pScratch */ 88 pMono = &pScratch[2 * NumSamples]; 89 90 /* 91 * Check the number of samples is not too large 92 */ 93 if (NumSamples > pInstance->Capabilities.MaxBlockSize) { 94 return (LVDBE_TOOMANYSAMPLES); 95 } 96 97 /* 98 * Check if the algorithm is enabled 99 */ 100 /* DBE path is processed when DBE is ON or during On/Off transitions */ 101 if ((pInstance->Params.OperatingMode == LVDBE_ON) 102 || (LVC_Mixer_GetCurrent( 103 &pInstance->pData->BypassMixer.MixerStream[0]) 104 != LVC_Mixer_GetTarget( 105 &pInstance->pData->BypassMixer.MixerStream[0]))) { 106 107 /* 108 * Convert 16-bit samples to 32-bit and scale 109 * (For a 16-bit implementation apply headroom loss here) 110 */ 111 Int16LShiftToInt32_16x32(pInput, /* Source 16-bit data */ 112 pScratch, /* Dest. 32-bit data */ 113 (LVM_INT16) (2 * NumSamples), /* Left and right */ 114 LVDBE_SCALESHIFT); /* Shift scale */ 115 116 /* 117 * Apply the high pass filter if selected 118 */ 119 if (pInstance->Params.HPFSelect == LVDBE_HPF_ON) { 120 BQ_2I_D32F32C30_TRC_WRA_01(&pInstance->pCoef->HPFInstance,/* Filter instance */ 121 (LVM_INT32 *) pScratch, /* Source */ 122 (LVM_INT32 *) pScratch, /* Destination */ 123 (LVM_INT16) NumSamples); /* Number of samples */ 124 } 125 126 /* 127 * Create the mono stream 128 */ 129 From2iToMono_32(pScratch, /* Stereo source */ 130 pMono, /* Mono destination */ 131 (LVM_INT16) NumSamples); /* Number of samples */ 132 133 /* 134 * Apply the band pass filter 135 */ 136 BP_1I_D32F32C30_TRC_WRA_02(&pInstance->pCoef->BPFInstance, /* Filter instance */ 137 (LVM_INT32 *) pMono, /* Source */ 138 (LVM_INT32 *) pMono, /* Destination */ 139 (LVM_INT16) NumSamples); /* Number of samples */ 140 141 /* 142 * Apply the AGC and mix 143 */ 144 AGC_MIX_VOL_2St1Mon_D32_WRA(&pInstance->pData->AGCInstance, /* Instance pointer */ 145 pScratch, /* Stereo source */ 146 pMono, /* Mono band pass source */ 147 pScratch, /* Stereo destination */ 148 NumSamples); /* Number of samples */ 149 150 /* 151 * Convert 32-bit samples to 16-bit and saturate 152 * (Not required for 16-bit implemenations) 153 */ 154 Int32RShiftToInt16_Sat_32x16(pScratch, /* Source 32-bit data */ 155 (LVM_INT16 *) pScratch, /* Dest. 16-bit data */ 156 (LVM_INT16) (2 * NumSamples), /* Left and right */ 157 LVDBE_SCALESHIFT); /* Shift scale */ 158 159 } 160 161 /* Bypass Volume path is processed when DBE is OFF or during On/Off transitions */ 162 if ((pInstance->Params.OperatingMode == LVDBE_OFF) 163 || (LVC_Mixer_GetCurrent( 164 &pInstance->pData->BypassMixer.MixerStream[1]) 165 != LVC_Mixer_GetTarget( 166 &pInstance->pData->BypassMixer.MixerStream[1]))) { 167 168 /* 169 * The algorithm is disabled but volume management is required to compensate for 170 * headroom and volume (if enabled) 171 */ 172 LVC_MixSoft_1St_D16C31_SAT(&pInstance->pData->BypassVolume, pInData, 173 pScratchVol, (LVM_INT16) (2 * NumSamples)); /* Left and right */ 174 175 } 176 177 /* 178 * Mix DBE processed path and bypass volume path 179 */ 180 LVC_MixSoft_2St_D16C31_SAT(&pInstance->pData->BypassMixer, 181 (LVM_INT16 *) pScratch, pScratchVol, pOutData, 182 (LVM_INT16) (2 * NumSamples)); 183 184 return (LVDBE_SUCCESS); 185} 186#else /*BUILD_FLOAT*/ 187LVDBE_ReturnStatus_en LVDBE_Process(LVDBE_Handle_t hInstance, 188 const LVM_FLOAT *pInData, 189 LVM_FLOAT *pOutData, 190 LVM_UINT16 NumSamples) 191{ 192 193 LVDBE_Instance_t *pInstance =(LVDBE_Instance_t *)hInstance; 194 LVM_FLOAT *pScratch_in = (LVM_FLOAT *)pInstance->MemoryTable.Region 195 [LVDBE_MEMREGION_SCRATCH].pBaseAddress; 196 LVM_FLOAT *pScratch = pScratch_in + 2 * NumSamples; 197 LVM_FLOAT *pMono; 198 LVM_INT32 ii = 0; 199 200 /* Scratch for Volume Control starts at offset of 4*NumSamples float values from pScratch */ 201 LVM_FLOAT *pScratchVol = (LVM_FLOAT *)(&pScratch_in[4 * NumSamples]); 202// LVM_INT16 *pScratchVol_int = (LVM_INT16 *)(pScratchVol); 203 204 /* Scratch for Mono path starts at offset of 6*NumSamples 32-bit values from pScratch */ 205 pMono = &pScratch_in[4 * NumSamples]; 206 207 /* 208 * Check the number of samples is not too large 209 */ 210 if (NumSamples > pInstance->Capabilities.MaxBlockSize) 211 { 212 return(LVDBE_TOOMANYSAMPLES); 213 } 214 215 /* 216 * Convert 16-bit samples to Float 217 */ 218 Copy_Float(pInData, /* Source 16-bit data */ 219 pScratch_in, /* Dest. 32-bit data */ 220 (LVM_INT16)(2 * NumSamples)); /* Left and right */ 221 222 for (ii = 0; ii < 2 * NumSamples; ii++) { 223 pScratch[ii] = pScratch_in[ii]; 224 } 225 /* 226 * Check if the algorithm is enabled 227 */ 228 /* DBE path is processed when DBE is ON or during On/Off transitions */ 229 if ((pInstance->Params.OperatingMode == LVDBE_ON)|| 230 (LVC_Mixer_GetCurrent(&pInstance->pData->BypassMixer.MixerStream[0]) 231 !=LVC_Mixer_GetTarget(&pInstance->pData->BypassMixer.MixerStream[0]))) 232 { 233 234 /* 235 * Apply the high pass filter if selected 236 */ 237 if (pInstance->Params.HPFSelect == LVDBE_HPF_ON) 238 { 239 BQ_2I_D32F32C30_TRC_WRA_01(&pInstance->pCoef->HPFInstance,/* Filter instance */ 240 (LVM_FLOAT *)pScratch, /* Source */ 241 (LVM_FLOAT *)pScratch, /* Destination */ 242 (LVM_INT16)NumSamples); /* Number of samples */ 243 } 244 245 /* 246 * Create the mono stream 247 */ 248 From2iToMono_Float((LVM_FLOAT *)pScratch, /* Stereo source */ 249 pMono, /* Mono destination */ 250 (LVM_INT16)NumSamples); /* Number of samples */ 251 252 /* 253 * Apply the band pass filter 254 */ 255 BP_1I_D32F32C30_TRC_WRA_02(&pInstance->pCoef->BPFInstance, /* Filter instance */ 256 (LVM_FLOAT *)pMono, /* Source */ 257 (LVM_FLOAT *)pMono, /* Destination */ 258 (LVM_INT16)NumSamples); /* Number of samples */ 259 260 /* 261 * Apply the AGC and mix 262 */ 263 AGC_MIX_VOL_2St1Mon_D32_WRA(&pInstance->pData->AGCInstance, /* Instance pointer */ 264 pScratch, /* Stereo source */ 265 pMono, /* Mono band pass source */ 266 pScratch, /* Stereo destination */ 267 NumSamples); /* Number of samples */ 268 269 for (ii = 0; ii < 2 * NumSamples; ii++) { 270 //TODO: replace with existing clamping function 271 if(pScratch[ii] < -1.0) { 272 pScratch[ii] = -1.0; 273 } else if(pScratch[ii] > 1.0) { 274 pScratch[ii] = 1.0; 275 } 276 } 277 } 278 279 /* Bypass Volume path is processed when DBE is OFF or during On/Off transitions */ 280 if ((pInstance->Params.OperatingMode == LVDBE_OFF)|| 281 (LVC_Mixer_GetCurrent(&pInstance->pData->BypassMixer.MixerStream[1]) 282 !=LVC_Mixer_GetTarget(&pInstance->pData->BypassMixer.MixerStream[1]))) 283 { 284 285 /* 286 * The algorithm is disabled but volume management is required to compensate for 287 * headroom and volume (if enabled) 288 */ 289 LVC_MixSoft_1St_D16C31_SAT(&pInstance->pData->BypassVolume, 290 pScratch_in, 291 pScratchVol, 292 (LVM_INT16)(2 * NumSamples)); /* Left and right */ 293 } 294 295 /* 296 * Mix DBE processed path and bypass volume path 297 */ 298 LVC_MixSoft_2St_D16C31_SAT(&pInstance->pData->BypassMixer, 299 pScratch, 300 pScratchVol, 301 pOutData, 302 (LVM_INT16)(2 * NumSamples)); 303 304 return(LVDBE_SUCCESS); 305} 306#endif 307