summaryrefslogtreecommitdiffstats
path: root/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.c
diff options
context:
space:
mode:
Diffstat (limited to 'media/libeffects/lvm/lib/Reverb/src/LVREV_Process.c')
-rwxr-xr-xmedia/libeffects/lvm/lib/Reverb/src/LVREV_Process.c550
1 files changed, 550 insertions, 0 deletions
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.c
new file mode 100755
index 0000000..822ac8f
--- /dev/null
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.c
@@ -0,0 +1,550 @@
+/*
+ * Copyright (C) 2004-2010 NXP Software
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/****************************************************************************************/
+/* */
+/* Project:: */
+/* $Author: nxp007753 $ */
+/* $Revision: 1316 $ */
+/* $Date: 2010-07-23 11:53:24 +0200 (Fri, 23 Jul 2010) $ */
+/* */
+/****************************************************************************************/
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+#include "LVREV_Private.h"
+#include "VectorArithmetic.h"
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVREV_Process */
+/* */
+/* DESCRIPTION: */
+/* Process function for the LVREV module. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pInData Pointer to the input data */
+/* pOutData Pointer to the output data */
+/* NumSamples Number of samples in the input buffer */
+/* */
+/* RETURNS: */
+/* LVREV_Success Succeeded */
+/* LVREV_INVALIDNUMSAMPLES NumSamples was larger than the maximum block size */
+/* LVREV_NULLADDRESS When one of hInstance, pInData or pOutData is NULL */
+/* */
+/* NOTES: */
+/* 1. The input and output buffers must be 32-bit aligned */
+/* */
+/****************************************************************************************/
+LVREV_ReturnStatus_en LVREV_Process(LVREV_Handle_t hInstance,
+ const LVM_INT32 *pInData,
+ LVM_INT32 *pOutData,
+ const LVM_UINT16 NumSamples)
+{
+ LVREV_Instance_st *pLVREV_Private = (LVREV_Instance_st *)hInstance;
+ LVM_INT32 *pInput = (LVM_INT32 *)pInData;
+ LVM_INT32 *pOutput = pOutData;
+ LVM_INT32 SamplesToProcess, RemainingSamples, format;
+
+ /*
+ * Check for error conditions
+ */
+
+ /* Check for NULL pointers */
+ if((hInstance == LVM_NULL) || (pInData == LVM_NULL) || (pOutData == LVM_NULL))
+ {
+ return LVREV_NULLADDRESS;
+ }
+
+
+ /*
+ * Apply the new controls settings if required
+ */
+ if(pLVREV_Private->bControlPending == LVM_TRUE)
+ {
+ LVREV_ReturnStatus_en errorCode;
+
+ /*
+ * Clear the pending flag and update the control settings
+ */
+ pLVREV_Private->bControlPending = LVM_FALSE;
+
+ errorCode = LVREV_ApplyNewSettings (pLVREV_Private);
+
+ if(errorCode != LVREV_SUCCESS)
+ {
+ return errorCode;
+ }
+ }
+
+ /*
+ * Trap the case where the number of samples is zero.
+ */
+ if (NumSamples == 0)
+ {
+ return LVREV_SUCCESS;
+ }
+
+ RemainingSamples = (LVM_INT32)NumSamples;
+
+ format = 1;
+ if (pLVREV_Private->CurrentParams.SourceFormat != LVM_MONO)
+ {
+ format = 2;
+ }
+
+ while (RemainingSamples!=0)
+ {
+ /*
+ * If OFF copy and reformat the data as necessary
+ */
+ if (pLVREV_Private->CurrentParams.OperatingMode == LVM_MODE_OFF)
+ {
+ if((pInput != pOutput) || (pLVREV_Private->CurrentParams.SourceFormat == LVM_MONO))
+ {
+ /*
+ * Copy the data to the output buffer
+ */
+
+ if (pLVREV_Private->CurrentParams.SourceFormat != LVM_MONO)
+ {
+ RemainingSamples = (RemainingSamples << 1); /* Stereo data */
+ }
+
+ Copy_16((LVM_INT16 *)pInput,
+ (LVM_INT16 *)pOutput,
+ (LVM_INT16)(RemainingSamples << 1));
+ }
+
+ RemainingSamples = 0;
+ }
+
+ /*
+ * Process the data
+ */
+ else
+ {
+
+ if(RemainingSamples > pLVREV_Private->MaxBlkLen)
+ {
+ SamplesToProcess = pLVREV_Private->MaxBlkLen;
+ RemainingSamples = (LVM_INT16)(RemainingSamples - SamplesToProcess);
+ }
+ else
+ {
+ SamplesToProcess = RemainingSamples;
+ RemainingSamples = 0;
+ }
+
+ ReverbBlock(pInput, pOutput, pLVREV_Private, (LVM_UINT16)SamplesToProcess);
+
+ pInput = (LVM_INT32 *)(pInput +(SamplesToProcess*format));
+ pOutput = (LVM_INT32 *)(pOutput+(SamplesToProcess*format));
+ }
+ }
+
+ return LVREV_SUCCESS;
+}
+
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: ReverbBlock */
+/* */
+/* DESCRIPTION: */
+/* Process function for the LVREV module. */
+/* */
+/* PARAMETERS: */
+/* hInstance Instance handle */
+/* pInData Pointer to the input data */
+/* pOutData Pointer to the output data */
+/* NumSamples Number of samples in the input buffer */
+/* */
+/* RETURNS: */
+/* LVREV_Success Succeeded */
+/* LVREV_INVALIDNUMSAMPLES NumSamples was larger than the maximum block size */
+/* LVREV_NULLADDRESS When one of hInstance, pInData or pOutData is NULL */
+/* */
+/* NOTES: */
+/* 1. The input and output buffers must be 32-bit aligned */
+/* */
+/****************************************************************************************/
+
+void ReverbBlock(LVM_INT32 *pInput, LVM_INT32 *pOutput, LVREV_Instance_st *pPrivate, LVM_UINT16 NumSamples)
+{
+ LVM_INT16 j, size;
+ LVM_INT32 *pDelayLine;
+ LVM_INT32 *pDelayLineInput = pPrivate->pScratch;
+ LVM_INT32 *pScratch = pPrivate->pScratch;
+ LVM_INT32 *pIn;
+ LVM_INT32 *pTemp = pPrivate->pInputSave;
+ LVM_INT32 NumberOfDelayLines;
+
+ /******************************************************************************
+ * All calculations will go into the buffer pointed to by pTemp, this will *
+ * then be mixed with the original input to create the final output. *
+ * *
+ * When INPLACE processing is selected this must be a temporary buffer and *
+ * hence this is the worst case, so for simplicity this will ALWAYS be so *
+ * *
+ * The input buffer will remain untouched until the output of the mixer if *
+ * INPLACE processing is selected. *
+ * *
+ * The temp buffer will always be NumSamples in size regardless of MONO or *
+ * STEREO input. In the case of stereo input all processing is done in MONO *
+ * and the final output is converted to STEREO after the mixer *
+ ******************************************************************************/
+
+ if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4 )
+ {
+ NumberOfDelayLines = 4;
+ }
+ else if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_2 )
+ {
+ NumberOfDelayLines = 2;
+ }
+ else
+ {
+ NumberOfDelayLines = 1;
+ }
+
+ if(pPrivate->CurrentParams.SourceFormat == LVM_MONO)
+ {
+ pIn = pInput;
+ }
+ else
+ {
+ /*
+ * Stereo to mono conversion
+ */
+
+ From2iToMono_32( pInput,
+ pTemp,
+ (LVM_INT16)NumSamples);
+
+ pIn = pTemp;
+ }
+
+ Mult3s_32x16(pIn,
+ (LVM_INT16)LVREV_HEADROOM,
+ pTemp,
+ (LVM_INT16)NumSamples);
+
+ /*
+ * High pass filter
+ */
+ FO_1I_D32F32C31_TRC_WRA_01( &pPrivate->pFastCoef->HPCoefs,
+ pTemp,
+ pTemp,
+ (LVM_INT16)NumSamples);
+ /*
+ * Low pass filter
+ */
+ FO_1I_D32F32C31_TRC_WRA_01( &pPrivate->pFastCoef->LPCoefs,
+ pTemp,
+ pTemp,
+ (LVM_INT16)NumSamples);
+
+ /*
+ * Process all delay lines
+ */
+
+ for(j = 0; j < NumberOfDelayLines; j++)
+ {
+ pDelayLine = pPrivate->pScratchDelayLine[j];
+
+ /*
+ * All-pass filter with pop and click suppression
+ */
+ /* Get the smoothed, delayed output. Put it in the output buffer */
+ MixSoft_2St_D32C31_SAT(&pPrivate->Mixer_APTaps[j],
+ pPrivate->pOffsetA[j],
+ pPrivate->pOffsetB[j],
+ pDelayLine,
+ (LVM_INT16)NumSamples);
+ /* Re-align the all pass filter delay buffer and copying the fixed delay data to the AP delay in the process */
+ Copy_16((LVM_INT16 *)&pPrivate->pDelay_T[j][NumSamples],
+ (LVM_INT16 *)pPrivate->pDelay_T[j],
+ (LVM_INT16)((pPrivate->T[j]-NumSamples) << 1)); /* 32-bit data */
+ /* Apply the smoothed feedback and save to fixed delay input (currently empty) */
+ MixSoft_1St_D32C31_WRA(&pPrivate->Mixer_SGFeedback[j],
+ pDelayLine,
+ &pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples],
+ (LVM_INT16)NumSamples);
+ /* Sum into the AP delay line */
+ Mac3s_Sat_32x16(&pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples],
+ -0x7fff, /* Invert since the feedback coefficient is negative */
+ &pPrivate->pDelay_T[j][pPrivate->Delay_AP[j]-NumSamples],
+ (LVM_INT16)NumSamples);
+ /* Apply smoothed feedforward sand save to fixed delay input (currently empty) */
+ MixSoft_1St_D32C31_WRA(&pPrivate->Mixer_SGFeedforward[j],
+ &pPrivate->pDelay_T[j][pPrivate->Delay_AP[j]-NumSamples],
+ &pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples],
+ (LVM_INT16)NumSamples);
+ /* Sum into the AP output */
+ Mac3s_Sat_32x16(&pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples],
+ 0x7fff,
+ pDelayLine,
+ (LVM_INT16)NumSamples);
+
+ /*
+ * Feedback gain
+ */
+ MixSoft_1St_D32C31_WRA(&pPrivate->FeedbackMixer[j], pDelayLine, pDelayLine, NumSamples);
+
+ /*
+ * Low pass filter
+ */
+ FO_1I_D32F32C31_TRC_WRA_01( &pPrivate->pFastCoef->RevLPCoefs[j],
+ pDelayLine,
+ pDelayLine,
+ (LVM_INT16)NumSamples);
+ }
+
+ /*
+ * Apply rotation matrix and delay samples
+ */
+ for(j = 0; j < NumberOfDelayLines; j++)
+ {
+
+ Copy_16( (LVM_INT16*)(pTemp),
+ (LVM_INT16*)(pDelayLineInput),
+ (LVM_INT16)(NumSamples << 1));
+
+ /*
+ * Rotation matrix mix
+ */
+ switch(j)
+ {
+ case 3:
+ /*
+ * Add delay line 1 and 2 contribution
+ */
+ Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[1], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
+ Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[2], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
+
+ break;
+ case 2:
+
+ /*
+ * Add delay line 0 and 3 contribution
+ */
+ Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[0], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
+ Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[3], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
+
+ break;
+ case 1:
+ if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
+ {
+ /*
+ * Add delay line 0 and 3 contribution
+ */
+ Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[0], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
+ Add2_Sat_32x32(pPrivate->pScratchDelayLine[3], pDelayLineInput, (LVM_INT16)NumSamples);
+
+ }
+ else
+ {
+ /*
+ * Add delay line 0 and 1 contribution
+ */
+ Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[0], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
+ Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[1], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
+
+ }
+ break;
+ case 0:
+ if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_4)
+ {
+ /*
+ * Add delay line 1 and 2 contribution
+ */
+ Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[1], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
+ Add2_Sat_32x32(pPrivate->pScratchDelayLine[2], pDelayLineInput, (LVM_INT16)NumSamples);
+
+ }
+ else if(pPrivate->InstanceParams.NumDelays == LVREV_DELAYLINES_2)
+ {
+ /*
+ * Add delay line 0 and 1 contribution
+ */
+ Add2_Sat_32x32(pPrivate->pScratchDelayLine[0], pDelayLineInput, (LVM_INT16)NumSamples);
+ Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[1], -0x8000, pDelayLineInput, (LVM_INT16)NumSamples);
+
+ }
+ else
+ {
+ /*
+ * Add delay line 0 contribution
+ */
+
+ /* SOURCE DESTINATION*/
+ Add2_Sat_32x32(pPrivate->pScratchDelayLine[0], pDelayLineInput, (LVM_INT16)NumSamples);
+ }
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * Delay samples
+ */
+ Copy_16((LVM_INT16 *)pDelayLineInput,
+ (LVM_INT16 *)&pPrivate->pDelay_T[j][pPrivate->T[j]-NumSamples],
+ (LVM_INT16)(NumSamples << 1)); /* 32-bit data */
+
+ }
+
+
+ /*
+ * Create stereo output
+ */
+ switch(pPrivate->InstanceParams.NumDelays)
+ {
+ case LVREV_DELAYLINES_4:
+ Add2_Sat_32x32(pPrivate->pScratchDelayLine[3],
+ pPrivate->pScratchDelayLine[0],
+ (LVM_INT16)NumSamples);
+ Add2_Sat_32x32(pPrivate->pScratchDelayLine[2],
+ pPrivate->pScratchDelayLine[1],
+ (LVM_INT16)NumSamples);
+
+ if(pPrivate->CurrentParams.SourceFormat != LVM_MONO)
+ {
+ JoinTo2i_32x32(pPrivate->pScratchDelayLine[0],
+ pPrivate->pScratchDelayLine[1],
+ pTemp,
+ (LVM_INT16)NumSamples);
+
+ }
+ else
+ {
+ Add2_Sat_32x32(pPrivate->pScratchDelayLine[1],
+ pPrivate->pScratchDelayLine[0],
+ (LVM_INT16)NumSamples);
+
+ /*Apply 3-dB gain in-order to compensate for the gain change in stereo mode*/
+ Mult3s_32x16(pPrivate->pScratchDelayLine[0],
+ LVREV_MIN3DB,
+ pTemp,
+ (LVM_INT16)NumSamples);
+ }
+ break;
+ case LVREV_DELAYLINES_2:
+
+ Copy_16( (LVM_INT16*)pPrivate->pScratchDelayLine[1],
+ (LVM_INT16*)pScratch,
+ (LVM_INT16)(NumSamples << 1));
+
+
+
+ if(pPrivate->CurrentParams.SourceFormat != LVM_MONO)
+ {
+
+ Mac3s_Sat_32x16(pPrivate->pScratchDelayLine[0],
+ -0x8000,
+ pScratch,
+ (LVM_INT16)NumSamples);
+ }
+
+ Add2_Sat_32x32(pPrivate->pScratchDelayLine[1],
+ pPrivate->pScratchDelayLine[0],
+ (LVM_INT16)NumSamples);
+
+
+ if(pPrivate->CurrentParams.SourceFormat != LVM_MONO)
+ {
+ JoinTo2i_32x32(pPrivate->pScratchDelayLine[0],
+ pScratch,
+ pTemp,
+ (LVM_INT16)NumSamples);
+ }
+ else
+ {
+ Copy_16( (LVM_INT16*)pPrivate->pScratchDelayLine[0],
+ (LVM_INT16*)pTemp,
+ (LVM_INT16)(NumSamples << 1));
+
+ }
+ break;
+ case LVREV_DELAYLINES_1:
+ if(pPrivate->CurrentParams.SourceFormat != LVM_MONO)
+ {
+
+ MonoTo2I_32(pPrivate->pScratchDelayLine[0],
+ pTemp,
+ (LVM_INT16)NumSamples);
+ }
+ else
+ {
+ pTemp = pPrivate->pScratchDelayLine[0];
+ }
+ break;
+ default:
+ break;
+ }
+
+
+ /*
+ * Dry/wet mixer
+ */
+ if(pPrivate->CurrentParams.SourceFormat != LVM_MONO)
+ {
+ size = (LVM_INT16)(NumSamples << 1);
+ }
+ else
+ {
+ size = (LVM_INT16)NumSamples;
+ }
+
+ MixSoft_2St_D32C31_SAT(&pPrivate->BypassMixer,
+ pInput,
+ pTemp,
+ pOutput,
+ size);
+
+ /* Apply Gain*/
+ if(pPrivate->CurrentParams.SourceFormat != LVM_MONO)
+ {
+ size = (LVM_INT16)(NumSamples << 1);
+ }
+ else
+ {
+ size = (LVM_INT16)NumSamples;
+ }
+
+ Shift_Sat_v32xv32 (LVREV_OUTPUTGAIN_SHIFT,
+ pOutput,
+ pOutput,
+ size);
+
+ MixSoft_1St_D32C31_WRA(&pPrivate->GainMixer,
+ pOutput,
+ pOutput,
+ size);
+ return;
+}
+
+
+/* End of file */
+