libeffects: Add multichannel processing support
Multichannel processing support added for Bundled effects including
Bass Enhancement (DBE)
N Band Equalizer (EQNB)
Concert Surround / Stereo Widening (CS)
Parametric Spectrum Analysis (PSA)
DC removal
Treble Boost
Test: Solo Tester, CTS Effects Test, Local Native Test
Bug: 72223862
Change-Id: Ide86b529a7574c26306098fedd7b276b3688998f
diff --git a/media/libeffects/lvm/lib/Android.bp b/media/libeffects/lvm/lib/Android.bp
index 5c57c43..7a32d3f 100644
--- a/media/libeffects/lvm/lib/Android.bp
+++ b/media/libeffects/lvm/lib/Android.bp
@@ -129,11 +129,14 @@
"Common/lib",
"Bundle/lib",
],
-
+ shared_libs: [
+ "liblog",
+ ],
cflags: [
"-fvisibility=hidden",
"-DBUILD_FLOAT",
"-DHIGHER_FS",
+ "-DSUPPORT_MC",
"-Wall",
"-Werror",
diff --git a/media/libeffects/lvm/lib/Bass/lib/LVDBE.h b/media/libeffects/lvm/lib/Bass/lib/LVDBE.h
index 4c2b954..a1fa79a 100644
--- a/media/libeffects/lvm/lib/Bass/lib/LVDBE.h
+++ b/media/libeffects/lvm/lib/Bass/lib/LVDBE.h
@@ -256,6 +256,9 @@
LVDBE_Volume_en VolumeControl;
LVM_INT16 VolumedB;
LVM_INT16 HeadroomdB;
+#ifdef SUPPORT_MC
+ LVM_INT16 NrChannels;
+#endif
} LVDBE_Params_t;
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.c b/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.c
index fd4016b..0ba2c86 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.c
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Control.c
@@ -118,7 +118,7 @@
* Calculate the table offsets
*/
LVM_UINT16 Offset = (LVM_UINT16)((LVM_UINT16)pParams->SampleRate + \
- (LVM_UINT16)(pParams->CentreFrequency * (1+LVDBE_FS_48000)));
+ (LVM_UINT16)(pParams->CentreFrequency * (1+LVDBE_FS_48000)));
#endif
/*
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.c b/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.c
index 3fff2a2..2946734 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.c
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Init.c
@@ -95,7 +95,7 @@
#ifdef BUILD_FLOAT
pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].Size = sizeof(LVDBE_Coef_FLOAT_t);
#else
- pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].Size = sizeof(LVDBE_Coef_t);
+ pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].Size = sizeof(LVDBE_Coef_t);
#endif
pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].Alignment = LVDBE_PERSISTENT_COEF_ALIGN;
pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].Type = LVDBE_PERSISTENT_COEF;
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h b/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
index 4e5207f..4225a30 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Private.h
@@ -64,7 +64,12 @@
#define LVDBE_PERSISTENT_COEF_ALIGN 4 /* 32-bit alignment for coef */
#define LVDBE_SCRATCH_ALIGN 4 /* 32-bit alignment for long data */
+#ifdef SUPPORT_MC
+/* Number of buffers required for inplace processing */
+#define LVDBE_SCRATCHBUFFERS_INPLACE (LVM_MAX_CHANNELS * 3)
+#else
#define LVDBE_SCRATCHBUFFERS_INPLACE 6 /* Number of buffers required for inplace processing */
+#endif
#define LVDBE_MIXER_TC 5 /* Mixer time */
#define LVDBE_BYPASS_MIXER_TC 100 /* Bypass mixer time */
diff --git a/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.c b/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.c
index 10ea700..c4d3403 100644
--- a/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.c
+++ b/media/libeffects/lvm/lib/Bass/src/LVDBE_Process.c
@@ -21,11 +21,13 @@
/* */
/****************************************************************************************/
+#include <string.h> // memset
#include "LVDBE.h"
#include "LVDBE_Private.h"
#include "VectorArithmetic.h"
#include "AGC.h"
#include "LVDBE_Coeffs.h" /* Filter coefficients */
+#include <log/log.h>
/********************************************************************************************/
/* */
@@ -187,42 +189,49 @@
LVDBE_ReturnStatus_en LVDBE_Process(LVDBE_Handle_t hInstance,
const LVM_FLOAT *pInData,
LVM_FLOAT *pOutData,
- LVM_UINT16 NumSamples)
+ const LVM_UINT16 NrFrames) // updated to use samples = frames * channels.
{
-
LVDBE_Instance_t *pInstance =(LVDBE_Instance_t *)hInstance;
- LVM_FLOAT *pScratch_in = (LVM_FLOAT *)pInstance->MemoryTable.Region
- [LVDBE_MEMREGION_SCRATCH].pBaseAddress;
- LVM_FLOAT *pScratch = pScratch_in + 2 * NumSamples;
- LVM_FLOAT *pMono;
- LVM_INT32 ii = 0;
- /* Scratch for Volume Control starts at offset of 4*NumSamples float values from pScratch */
- LVM_FLOAT *pScratchVol = (LVM_FLOAT *)(&pScratch_in[4 * NumSamples]);
-// LVM_INT16 *pScratchVol_int = (LVM_INT16 *)(pScratchVol);
+ /*Extract number of Channels info*/
+#ifdef SUPPORT_MC
+ // Mono passed in as stereo
+ const LVM_INT32 NrChannels = pInstance->Params.NrChannels == 1
+ ? 2 : pInstance->Params.NrChannels;
+#else
+ const LVM_INT32 NrChannels = 2; // FCC_2
+#endif
+ const LVM_INT32 NrSamples = NrChannels * NrFrames;
- /* Scratch for Mono path starts at offset of 6*NumSamples 32-bit values from pScratch */
- pMono = &pScratch_in[4 * NumSamples];
+ /* Space to store DBE path computation */
+ LVM_FLOAT * const pScratch =
+ (LVM_FLOAT *)pInstance->MemoryTable.Region[LVDBE_MEMREGION_SCRATCH].pBaseAddress;
/*
- * Check the number of samples is not too large
+ * Scratch for Mono path starts at offset of
+ * NrSamples float values from pScratch.
*/
- if (NumSamples > pInstance->Capabilities.MaxBlockSize)
+ LVM_FLOAT * const pMono = pScratch + NrSamples;
+
+ /*
+ * TRICKY: pMono is used and discarded by the DBE path.
+ * so it is available for use for the pScratchVol
+ * path which is computed afterwards.
+ *
+ * Space to store Volume Control path computation.
+ * This is identical to pMono (see TRICKY comment).
+ */
+ LVM_FLOAT * const pScratchVol = pMono;
+
+ /*
+ * Check the number of frames is not too large
+ */
+ if (NrFrames > pInstance->Capabilities.MaxBlockSize)
{
- return(LVDBE_TOOMANYSAMPLES);
+ return LVDBE_TOOMANYSAMPLES;
}
/*
- * Convert 16-bit samples to Float
- */
- Copy_Float(pInData, /* Source 16-bit data */
- pScratch_in, /* Dest. 32-bit data */
- (LVM_INT16)(2 * NumSamples)); /* Left and right */
-
- for (ii = 0; ii < 2 * NumSamples; ii++) {
- pScratch[ii] = pScratch_in[ii];
- }
- /*
* Check if the algorithm is enabled
*/
/* DBE path is processed when DBE is ON or during On/Off transitions */
@@ -230,50 +239,81 @@
(LVC_Mixer_GetCurrent(&pInstance->pData->BypassMixer.MixerStream[0])
!=LVC_Mixer_GetTarget(&pInstance->pData->BypassMixer.MixerStream[0])))
{
+ // make copy of input data
+ Copy_Float(pInData,
+ pScratch,
+ (LVM_INT16)NrSamples);
/*
* Apply the high pass filter if selected
*/
if (pInstance->Params.HPFSelect == LVDBE_HPF_ON)
{
+#ifdef SUPPORT_MC
+ BQ_MC_D32F32C30_TRC_WRA_01(&pInstance->pCoef->HPFInstance, /* Filter instance */
+ pScratch, /* Source */
+ pScratch, /* Destination */
+ (LVM_INT16)NrFrames,
+ (LVM_INT16)NrChannels);
+#else
BQ_2I_D32F32C30_TRC_WRA_01(&pInstance->pCoef->HPFInstance,/* Filter instance */
- (LVM_FLOAT *)pScratch, /* Source */
- (LVM_FLOAT *)pScratch, /* Destination */
- (LVM_INT16)NumSamples); /* Number of samples */
+ pScratch, /* Source */
+ pScratch, /* Destination */
+ (LVM_INT16)NrFrames);
+#endif
}
/*
* Create the mono stream
*/
- From2iToMono_Float((LVM_FLOAT *)pScratch, /* Stereo source */
+#ifdef SUPPORT_MC
+ FromMcToMono_Float(pScratch, /* Source */
+ pMono, /* Mono destination */
+ (LVM_INT16)NrFrames, /* Number of frames */
+ (LVM_INT16)NrChannels);
+#else
+ From2iToMono_Float(pScratch, /* Stereo source */
pMono, /* Mono destination */
- (LVM_INT16)NumSamples); /* Number of samples */
+ (LVM_INT16)NrFrames);
+#endif
/*
* Apply the band pass filter
*/
BP_1I_D32F32C30_TRC_WRA_02(&pInstance->pCoef->BPFInstance, /* Filter instance */
- (LVM_FLOAT *)pMono, /* Source */
- (LVM_FLOAT *)pMono, /* Destination */
- (LVM_INT16)NumSamples); /* Number of samples */
+ pMono, /* Source */
+ pMono, /* Destination */
+ (LVM_INT16)NrFrames);
/*
* Apply the AGC and mix
*/
+#ifdef SUPPORT_MC
+ AGC_MIX_VOL_Mc1Mon_D32_WRA(&pInstance->pData->AGCInstance, /* Instance pointer */
+ pScratch, /* Source */
+ pMono, /* Mono band pass source */
+ pScratch, /* Destination */
+ NrFrames, /* Number of frames */
+ NrChannels); /* Number of channels */
+#else
AGC_MIX_VOL_2St1Mon_D32_WRA(&pInstance->pData->AGCInstance, /* Instance pointer */
pScratch, /* Stereo source */
pMono, /* Mono band pass source */
pScratch, /* Stereo destination */
- NumSamples); /* Number of samples */
+ NrFrames);
+#endif
- for (ii = 0; ii < 2 * NumSamples; ii++) {
+ for (LVM_INT32 ii = 0; ii < NrSamples; ++ii) {
//TODO: replace with existing clamping function
- if(pScratch[ii] < -1.0) {
+ if (pScratch[ii] < -1.0) {
pScratch[ii] = -1.0;
- } else if(pScratch[ii] > 1.0) {
+ } else if (pScratch[ii] > 1.0) {
pScratch[ii] = 1.0;
}
}
+ } else {
+ // clear DBE processed path
+ memset(pScratch, 0, sizeof(*pScratch) * NrSamples);
}
/* Bypass Volume path is processed when DBE is OFF or during On/Off transitions */
@@ -286,21 +326,40 @@
* The algorithm is disabled but volume management is required to compensate for
* headroom and volume (if enabled)
*/
- LVC_MixSoft_1St_D16C31_SAT(&pInstance->pData->BypassVolume,
- pScratch_in,
+#ifdef SUPPORT_MC
+ LVC_MixSoft_Mc_D16C31_SAT(&pInstance->pData->BypassVolume,
+ pInData,
pScratchVol,
- (LVM_INT16)(2 * NumSamples)); /* Left and right */
+ (LVM_INT16)NrFrames,
+ (LVM_INT16)NrChannels);
+#else
+ LVC_MixSoft_1St_D16C31_SAT(&pInstance->pData->BypassVolume,
+ pInData,
+ pScratchVol,
+ (LVM_INT16)NrSamples); /* Left and right, really # samples */
+#endif
+ } else {
+ // clear bypass volume path
+ memset(pScratchVol, 0, sizeof(*pScratchVol) * NrSamples);
}
/*
* Mix DBE processed path and bypass volume path
*/
+#ifdef SUPPORT_MC
+ LVC_MixSoft_2Mc_D16C31_SAT(&pInstance->pData->BypassMixer,
+ pScratch,
+ pScratchVol,
+ pOutData,
+ (LVM_INT16)NrFrames,
+ (LVM_INT16)NrChannels);
+#else
LVC_MixSoft_2St_D16C31_SAT(&pInstance->pData->BypassMixer,
pScratch,
pScratchVol,
pOutData,
- (LVM_INT16)(2 * NumSamples));
-
- return(LVDBE_SUCCESS);
+ (LVM_INT16)NrSamples);
+#endif
+ return LVDBE_SUCCESS;
}
#endif
diff --git a/media/libeffects/lvm/lib/Bundle/lib/LVM.h b/media/libeffects/lvm/lib/Bundle/lib/LVM.h
index 9b6da31..83ecae1 100644
--- a/media/libeffects/lvm/lib/Bundle/lib/LVM.h
+++ b/media/libeffects/lvm/lib/Bundle/lib/LVM.h
@@ -296,6 +296,9 @@
/* Spectrum Analyzer parameters Control */
LVM_PSA_Mode_en PSA_Enable;
LVM_PSA_DecaySpeed_en PSA_PeakDecayRate; /* Peak value decay rate*/
+#ifdef SUPPORT_MC
+ LVM_INT32 NrChannels;
+#endif
} LVM_ControlParams_t;
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Buffers.c b/media/libeffects/lvm/lib/Bundle/src/LVM_Buffers.c
index 0a3c30e..37272e3 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Buffers.c
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Buffers.c
@@ -25,6 +25,8 @@
#include "LVM_Private.h"
#include "VectorArithmetic.h"
+#include <log/log.h>
+
/****************************************************************************************/
/* */
/* FUNCTION: LVM_BufferManagedIn */
@@ -62,8 +64,11 @@
LVM_Instance_t *pInstance = (LVM_Instance_t *)hInstance;
LVM_Buffer_t *pBuffer;
LVM_FLOAT *pDest;
+#ifdef SUPPORT_MC
+ LVM_INT16 NumChannels = pInstance->NrChannels;
+#else
LVM_INT16 NumChannels = 2;
-
+#endif
/*
* Set the processing address pointers
@@ -207,8 +212,7 @@
LVM_Instance_t *pInstance = (LVM_Instance_t *)hInstance;
LVM_Buffer_t *pBuffer;
LVM_INT16 *pDest;
- LVM_INT16 NumChannels =2;
-
+ LVM_INT16 NumChannels = 2;
/*
* Set the processing address pointers
@@ -499,7 +503,7 @@
if (pBuffer->OutDelaySamples != 0)
{
Copy_16(&pBuffer->OutDelayBuffer[0], /* Source */
- pDest, /* Detsination */
+ pDest, /* Destination */
(LVM_INT16)(2*pBuffer->OutDelaySamples)); /* Number of delay samples */
pDest += 2 * pBuffer->OutDelaySamples; /* Update the output pointer */
pBuffer->SamplesToOutput = (LVM_INT16)(pBuffer->SamplesToOutput - pBuffer->OutDelaySamples); /* Update the numbr of samples to output */
@@ -750,7 +754,11 @@
LVM_INT16 NumSamples;
LVM_FLOAT *pStart;
LVM_FLOAT *pDest;
-
+#ifdef SUPPORT_MC
+ LVM_INT32 NrChannels = pInstance->NrChannels;
+#define NrFrames NumSamples // alias for clarity
+#define FrameCount SampleCount
+#endif
/*
* Set the pointers
@@ -758,7 +766,6 @@
NumSamples = pBuffer->SamplesToOutput;
pStart = pBuffer->pScratch;
-
/*
* check if it is the first call of a block
*/
@@ -786,14 +793,25 @@
/*
* Copy all output delay samples to the output
*/
+#ifdef SUPPORT_MC
Copy_Float(&pBuffer->OutDelayBuffer[0], /* Source */
- pDest, /* Detsination */
+ pDest, /* Destination */
+ /* Number of delay samples */
+ (LVM_INT16)(NrChannels * pBuffer->OutDelaySamples));
+#else
+ Copy_Float(&pBuffer->OutDelayBuffer[0], /* Source */
+ pDest, /* Destination */
(LVM_INT16)(2 * pBuffer->OutDelaySamples)); /* Number of delay samples */
+#endif
/*
* Update the pointer and sample counts
*/
+#ifdef SUPPORT_MC
+ pDest += NrChannels * pBuffer->OutDelaySamples; /* Output sample pointer */
+#else
pDest += 2 * pBuffer->OutDelaySamples; /* Output sample pointer */
+#endif
NumSamples = (LVM_INT16)(NumSamples - pBuffer->OutDelaySamples); /* Samples left \
to send */
pBuffer->OutDelaySamples = 0; /* No samples left in the buffer */
@@ -803,23 +821,40 @@
/*
* Copy only some of the ouput delay samples to the output
*/
+#ifdef SUPPORT_MC
Copy_Float(&pBuffer->OutDelayBuffer[0], /* Source */
- pDest, /* Detsination */
+ pDest, /* Destination */
+ (LVM_INT16)(NrChannels * NrFrames)); /* Number of delay samples */
+#else
+ Copy_Float(&pBuffer->OutDelayBuffer[0], /* Source */
+ pDest, /* Destination */
(LVM_INT16)(2 * NumSamples)); /* Number of delay samples */
+#endif
/*
* Update the pointer and sample counts
*/
+#ifdef SUPPORT_MC
+ pDest += NrChannels * NrFrames; /* Output sample pointer */
+#else
pDest += 2 * NumSamples; /* Output sample pointer */
+#endif
/* No samples left in the buffer */
pBuffer->OutDelaySamples = (LVM_INT16)(pBuffer->OutDelaySamples - NumSamples);
/*
* Realign the delay buffer data to avoid using circular buffer management
*/
+#ifdef SUPPORT_MC
+ Copy_Float(&pBuffer->OutDelayBuffer[NrChannels * NrFrames], /* Source */
+ &pBuffer->OutDelayBuffer[0], /* Destination */
+ /* Number of samples to move */
+ (LVM_INT16)(NrChannels * pBuffer->OutDelaySamples));
+#else
Copy_Float(&pBuffer->OutDelayBuffer[2 * NumSamples], /* Source */
&pBuffer->OutDelayBuffer[0], /* Destination */
(LVM_INT16)(2 * pBuffer->OutDelaySamples)); /* Number of samples to move */
+#endif
NumSamples = 0; /* Samples left to send */
}
}
@@ -836,13 +871,23 @@
/*
* Copy all processed samples to the output
*/
+#ifdef SUPPORT_MC
Copy_Float(pStart, /* Source */
- pDest, /* Detsination */
+ pDest, /* Destination */
+ (LVM_INT16)(NrChannels * FrameCount)); /* Number of processed samples */
+#else
+ Copy_Float(pStart, /* Source */
+ pDest, /* Destination */
(LVM_INT16)(2 * SampleCount)); /* Number of processed samples */
+#endif
/*
* Update the pointer and sample counts
*/
+#ifdef SUPPORT_MC
+ pDest += NrChannels * FrameCount; /* Output sample pointer */
+#else
pDest += 2 * SampleCount; /* Output sample pointer */
+#endif
NumSamples = (LVM_INT16)(NumSamples - SampleCount); /* Samples left to send */
SampleCount = 0; /* No samples left in the buffer */
}
@@ -851,14 +896,25 @@
/*
* Copy only some processed samples to the output
*/
+#ifdef SUPPORT_MC
+ Copy_Float(pStart, /* Source */
+ pDest, /* Destination */
+ (LVM_INT16)(NrChannels * NrFrames)); /* Number of processed samples */
+#else
Copy_Float(pStart, /* Source */
pDest, /* Destination */
(LVM_INT16)(2 * NumSamples)); /* Number of processed samples */
+#endif
/*
* Update the pointers and sample counts
*/
+#ifdef SUPPORT_MC
+ pStart += NrChannels * NrFrames; /* Processed sample pointer */
+ pDest += NrChannels * NrFrames; /* Output sample pointer */
+#else
pStart += 2 * NumSamples; /* Processed sample pointer */
pDest += 2 * NumSamples; /* Output sample pointer */
+#endif
SampleCount = (LVM_INT16)(SampleCount - NumSamples); /* Processed samples left */
NumSamples = 0; /* Clear the sample count */
}
@@ -870,9 +926,16 @@
*/
if (SampleCount != 0)
{
+#ifdef SUPPORT_MC
+ Copy_Float(pStart, /* Source */
+ /* Destination */
+ &pBuffer->OutDelayBuffer[NrChannels * pBuffer->OutDelaySamples],
+ (LVM_INT16)(NrChannels * FrameCount)); /* Number of processed samples */
+#else
Copy_Float(pStart, /* Source */
&pBuffer->OutDelayBuffer[2 * pBuffer->OutDelaySamples], /* Destination */
(LVM_INT16)(2 * SampleCount)); /* Number of processed samples */
+#endif
/* Update the buffer count */
pBuffer->OutDelaySamples = (LVM_INT16)(pBuffer->OutDelaySamples + SampleCount);
}
@@ -1063,14 +1126,24 @@
{
LVM_Instance_t *pInstance = (LVM_Instance_t *)hInstance;
- LVM_INT16 NumChannels =2;
+#ifdef SUPPORT_MC
+ LVM_INT16 NumChannels = pInstance->NrChannels;
+#undef NrFrames
+#define NrFrames (*pNumSamples) // alias for clarity
+#else
+ LVM_INT16 NumChannels = 2;
+#endif
/*
* Update sample counts
*/
pInstance->pInputSamples += (LVM_INT16)(*pNumSamples * NumChannels); /* Update the I/O pointers */
+#ifdef SUPPORT_MC
+ pInstance->pOutputSamples += (LVM_INT16)(NrFrames * NumChannels);
+#else
pInstance->pOutputSamples += (LVM_INT16)(*pNumSamples * 2);
+#endif
pInstance->SamplesToProcess = (LVM_INT16)(pInstance->SamplesToProcess - *pNumSamples); /* Update the sample count */
/*
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Control.c b/media/libeffects/lvm/lib/Bundle/src/LVM_Control.c
index cfe53b8..7b85f23 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Control.c
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Control.c
@@ -28,6 +28,8 @@
#include "LVM_Tables.h"
#include "LVM_Private.h"
+#include <log/log.h>
+
/****************************************************************************************/
/* */
/* FUNCTION: LVM_SetControlParameters */
@@ -75,12 +77,22 @@
(pParams->SampleRate != LVM_FS_16000) && (pParams->SampleRate != LVM_FS_22050) && (pParams->SampleRate != LVM_FS_24000) &&
(pParams->SampleRate != LVM_FS_32000) && (pParams->SampleRate != LVM_FS_44100) && (pParams->SampleRate != LVM_FS_48000)) ||
#endif
+#ifdef SUPPORT_MC
+ ((pParams->SourceFormat != LVM_STEREO) &&
+ (pParams->SourceFormat != LVM_MONOINSTEREO) &&
+ (pParams->SourceFormat != LVM_MONO) &&
+ (pParams->SourceFormat != LVM_MULTICHANNEL)) ||
+#else
((pParams->SourceFormat != LVM_STEREO) && (pParams->SourceFormat != LVM_MONOINSTEREO) && (pParams->SourceFormat != LVM_MONO)) ||
+#endif
(pParams->SpeakerType > LVM_EX_HEADPHONES))
{
return (LVM_OUTOFRANGE);
}
+#ifdef SUPPORT_MC
+ pInstance->Params.NrChannels = pParams->NrChannels;
+#endif
/*
* Cinema Sound parameters
*/
@@ -569,6 +581,10 @@
} while ((pInstance->ControlPending != LVM_FALSE) &&
(Count > 0));
+#ifdef SUPPORT_MC
+ pInstance->NrChannels = LocalParams.NrChannels;
+#endif
+
/* Clear all internal data if format change*/
if(LocalParams.SourceFormat != pInstance->Params.SourceFormat)
{
@@ -719,6 +735,9 @@
DBE_Params.HeadroomdB = 0;
DBE_Params.VolumeControl = LVDBE_VOLUME_OFF;
DBE_Params.VolumedB = 0;
+#ifdef SUPPORT_MC
+ DBE_Params.NrChannels = LocalParams.NrChannels;
+#endif
/*
* Make the changes
@@ -775,7 +794,9 @@
{
EQNB_Params.SourceFormat = LVEQNB_MONOINSTEREO; /* Force to Mono-in-Stereo mode */
}
-
+#ifdef SUPPORT_MC
+ EQNB_Params.NrChannels = LocalParams.NrChannels;
+#endif
/*
* Set the control flag
@@ -849,7 +870,9 @@
CS_Params.SampleRate = LocalParams.SampleRate;
CS_Params.ReverbLevel = LocalParams.VirtualizerReverbLevel;
CS_Params.EffectLevel = LocalParams.CS_EffectLevel;
-
+#ifdef SUPPORT_MC
+ CS_Params.NrChannels = LocalParams.NrChannels;
+#endif
/*
* Set the control flag
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Init.c b/media/libeffects/lvm/lib/Bundle/src/LVM_Init.c
index 26c1c4f..ade329b 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Init.c
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Init.c
@@ -584,8 +584,11 @@
/*
* DC removal filter
*/
+#ifdef SUPPORT_MC
+ DC_Mc_D16_TRC_WRA_01_Init(&pInstance->DC_RemovalInstance);
+#else
DC_2I_D16_TRC_WRA_01_Init(&pInstance->DC_RemovalInstance);
-
+#endif
/*
* Treble Enhancement
@@ -1039,7 +1042,11 @@
LVM_SetHeadroomParams(hInstance, &HeadroomParams);
/* DC removal filter */
+#ifdef SUPPORT_MC
+ DC_Mc_D16_TRC_WRA_01_Init(&pInstance->DC_RemovalInstance);
+#else
DC_2I_D16_TRC_WRA_01_Init(&pInstance->DC_RemovalInstance);
+#endif
return LVM_SUCCESS;
}
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h b/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h
index b453222..19d1532 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Private.h
@@ -144,12 +144,19 @@
LVM_FLOAT *pScratch; /* Bundle scratch buffer */
LVM_INT16 BufferState; /* Buffer status */
+#ifdef SUPPORT_MC
+ LVM_FLOAT InDelayBuffer[3 * LVM_MAX_CHANNELS * MIN_INTERNAL_BLOCKSIZE];
+#else
LVM_FLOAT InDelayBuffer[6 * MIN_INTERNAL_BLOCKSIZE]; /* Input buffer delay line, \
left and right */
+#endif
LVM_INT16 InDelaySamples; /* Number of samples in the input delay buffer */
-
+#ifdef SUPPORT_MC
+ LVM_FLOAT OutDelayBuffer[LVM_MAX_CHANNELS * MIN_INTERNAL_BLOCKSIZE];
+#else
LVM_FLOAT OutDelayBuffer[2 * MIN_INTERNAL_BLOCKSIZE]; /* Output buffer delay \
line */
+#endif
LVM_INT16 OutDelaySamples; /* Number of samples in the output delay buffer, \
left and right */
LVM_INT16 SamplesToOutput; /* Samples to write to the output */
@@ -282,6 +289,10 @@
LVM_INT16 NoSmoothVolume; /* Enable or disable smooth volume changes*/
+#ifdef SUPPORT_MC
+ LVM_INT16 NrChannels;
+#endif
+
} LVM_Instance_t;
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Process.c b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.c
index 4a19a13..94ba278 100644
--- a/media/libeffects/lvm/lib/Bundle/src/LVM_Process.c
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Process.c
@@ -65,6 +65,10 @@
LVM_FLOAT *pToProcess = (LVM_FLOAT *)pInData;
LVM_FLOAT *pProcessed = pOutData;
LVM_ReturnStatus_en Status;
+#ifdef SUPPORT_MC
+ LVM_INT32 NrChannels = pInstance->NrChannels;
+#define NrFrames SampleCount // alias for clarity
+#endif
/*
* Check if the number of samples is zero
@@ -112,6 +116,10 @@
if (pInstance->ControlPending == LVM_TRUE)
{
Status = LVM_ApplyNewSettings(hInstance);
+#ifdef SUPPORT_MC
+ /* Update the local variable NrChannels from pInstance->NrChannels value */
+ NrChannels = pInstance->NrChannels;
+#endif
if(Status != LVM_SUCCESS)
{
@@ -130,6 +138,9 @@
(LVM_INT16)NumSamples); /* Number of input samples */
pInput = pOutData;
pToProcess = pOutData;
+#ifdef SUPPORT_MC
+ NrChannels = 2;
+#endif
}
@@ -153,7 +164,6 @@
*/
if (SampleCount != 0)
{
-
/*
* Apply ConcertSound if required
*/
@@ -171,10 +181,18 @@
*/
if (pInstance->VC_Active!=0)
{
+#ifdef SUPPORT_MC
+ LVC_MixSoft_Mc_D16C31_SAT(&pInstance->VC_Volume,
+ pToProcess,
+ pProcessed,
+ (LVM_INT16)(NrFrames),
+ NrChannels);
+#else
LVC_MixSoft_1St_D16C31_SAT(&pInstance->VC_Volume,
pToProcess,
pProcessed,
(LVM_INT16)(2 * SampleCount)); /* Left and right*/
+#endif
pToProcess = pProcessed;
}
@@ -221,20 +239,33 @@
/*
* Apply the filter
*/
+#ifdef SUPPORT_MC
+ FO_Mc_D16F32C15_LShx_TRC_WRA_01(&pInstance->pTE_State->TrebleBoost_State,
+ pProcessed,
+ pProcessed,
+ (LVM_INT16)NrFrames,
+ (LVM_INT16)NrChannels);
+#else
FO_2I_D16F32C15_LShx_TRC_WRA_01(&pInstance->pTE_State->TrebleBoost_State,
pProcessed,
pProcessed,
(LVM_INT16)SampleCount);
+#endif
}
-
- /*
- * Volume balance
- */
- LVC_MixSoft_1St_2i_D16C31_SAT(&pInstance->VC_BalanceMix,
- pProcessed,
- pProcessed,
- SampleCount);
+#ifdef SUPPORT_MC
+ /* TODO - Multichannel support to be added */
+ if (NrChannels == 2)
+#endif
+ {
+ /*
+ * Volume balance
+ */
+ LVC_MixSoft_1St_2i_D16C31_SAT(&pInstance->VC_BalanceMix,
+ pProcessed,
+ pProcessed,
+ SampleCount);
+ }
/*
* Perform Parametric Spectum Analysis
@@ -242,28 +273,39 @@
if ((pInstance->Params.PSA_Enable == LVM_PSA_ON) &&
(pInstance->InstParams.PSA_Included == LVM_PSA_ON))
{
- From2iToMono_Float(pProcessed,
- pInstance->pPSAInput,
- (LVM_INT16)(SampleCount));
+#ifdef SUPPORT_MC
+ FromMcToMono_Float(pProcessed,
+ pInstance->pPSAInput,
+ (LVM_INT16)(NrFrames),
+ NrChannels);
+#else
+ From2iToMono_Float(pProcessed,
+ pInstance->pPSAInput,
+ (LVM_INT16)(SampleCount));
+#endif
- LVPSA_Process(pInstance->hPSAInstance,
- pInstance->pPSAInput,
- (LVM_UINT16)(SampleCount),
- AudioTime);
+ LVPSA_Process(pInstance->hPSAInstance,
+ pInstance->pPSAInput,
+ (LVM_UINT16)(SampleCount),
+ AudioTime);
}
-
/*
* DC removal
*/
+#ifdef SUPPORT_MC
+ DC_Mc_D16_TRC_WRA_01(&pInstance->DC_RemovalInstance,
+ pProcessed,
+ pProcessed,
+ (LVM_INT16)NrFrames,
+ NrChannels);
+#else
DC_2I_D16_TRC_WRA_01(&pInstance->DC_RemovalInstance,
pProcessed,
pProcessed,
(LVM_INT16)SampleCount);
-
-
+#endif
}
-
/*
* Manage the output buffer
*/
@@ -497,4 +539,4 @@
return(LVM_SUCCESS);
}
-#endif
\ No newline at end of file
+#endif
diff --git a/media/libeffects/lvm/lib/Common/lib/AGC.h b/media/libeffects/lvm/lib/Common/lib/AGC.h
index 9a3d35d..06e742e 100644
--- a/media/libeffects/lvm/lib/Common/lib/AGC.h
+++ b/media/libeffects/lvm/lib/Common/lib/AGC.h
@@ -78,6 +78,15 @@
const LVM_FLOAT *pMonoSrc, /* Mono source */
LVM_FLOAT *pDst, /* Stereo destination */
LVM_UINT16 n); /* Number of samples */
+#ifdef SUPPORT_MC
+void AGC_MIX_VOL_Mc1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_FLOAT_t *pInstance, /* Instance pointer */
+ const LVM_FLOAT *pStSrc, /* Source */
+ const LVM_FLOAT *pMonoSrc, /* Mono source */
+ LVM_FLOAT *pDst, /* Destination */
+ LVM_UINT16 NrFrames, /* Number of frames */
+ LVM_UINT16 NrChannels); /* Number of channels */
+#endif
+
#else
void AGC_MIX_VOL_2St1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_D32_t *pInstance, /* Instance pointer */
const LVM_INT32 *pStSrc, /* Stereo source */
diff --git a/media/libeffects/lvm/lib/Common/lib/BIQUAD.h b/media/libeffects/lvm/lib/Common/lib/BIQUAD.h
index 3ee7f63..01539b2 100644
--- a/media/libeffects/lvm/lib/Common/lib/BIQUAD.h
+++ b/media/libeffects/lvm/lib/Common/lib/BIQUAD.h
@@ -30,8 +30,17 @@
#ifdef BUILD_FLOAT
typedef struct
{
+#ifdef SUPPORT_MC
+ /* The memory region created by this structure instance is typecast
+ * into another structure containing a pointer and an array of filter
+ * coefficients. In one case this memory region is used for storing
+ * DC component of channels
+ */
+ LVM_FLOAT *pStorage;
+ LVM_FLOAT Storage[LVM_MAX_CHANNELS];
+#else
LVM_FLOAT Storage[6];
-
+#endif
} Biquad_FLOAT_Instance_t;
#else
typedef struct
@@ -179,7 +188,12 @@
typedef struct
{
- LVM_FLOAT Storage[ (2 * 2) ]; /* Two channels, two taps of size LVM_INT32 */
+#ifdef SUPPORT_MC
+ /* LVM_MAX_CHANNELS channels, two taps of size LVM_FLOAT */
+ LVM_FLOAT Storage[ (LVM_MAX_CHANNELS * 2) ];
+#else
+ LVM_FLOAT Storage[ (2 * 2) ]; /* Two channels, two taps of size LVM_FLOAT */
+#endif
} Biquad_2I_Order1_FLOAT_Taps_t;
#else
typedef struct
@@ -197,12 +211,17 @@
#ifdef BUILD_FLOAT
typedef struct
{
- LVM_FLOAT Storage[ (1 * 4) ]; /* One channel, four taps of size LVM_INT32 */
+ LVM_FLOAT Storage[ (1 * 4) ]; /* One channel, four taps of size LVM_FLOAT */
} Biquad_1I_Order2_FLOAT_Taps_t;
typedef struct
{
- LVM_FLOAT Storage[ (2 * 4) ]; /* Two channels, four taps of size LVM_INT32 */
+#ifdef SUPPORT_MC
+ /* LVM_MAX_CHANNELS, four taps of size LVM_FLOAT */
+ LVM_FLOAT Storage[ (LVM_MAX_CHANNELS * 4) ];
+#else
+ LVM_FLOAT Storage[ (2 * 4) ]; /* Two channels, four taps of size LVM_FLOAT */
+#endif
} Biquad_2I_Order2_FLOAT_Taps_t;
#else
typedef struct
@@ -366,6 +385,13 @@
LVM_FLOAT *pDataIn,
LVM_FLOAT *pDataOut,
LVM_INT16 NrSamples);
+#ifdef SUPPORT_MC
+void BQ_MC_D32F32C30_TRC_WRA_01 ( Biquad_FLOAT_Instance_t *pInstance,
+ LVM_FLOAT *pDataIn,
+ LVM_FLOAT *pDataOut,
+ LVM_INT16 NrFrames,
+ LVM_INT16 NrChannels);
+#endif
#else
void BQ_2I_D32F32Cll_TRC_WRA_01_Init ( Biquad_Instance_t *pInstance,
Biquad_2I_Order2_Taps_t *pTaps,
@@ -434,6 +460,13 @@
LVM_FLOAT *pDataIn,
LVM_FLOAT *pDataOut,
LVM_INT16 NrSamples);
+#ifdef SUPPORT_MC
+void FO_Mc_D16F32C15_LShx_TRC_WRA_01(Biquad_FLOAT_Instance_t *pInstance,
+ LVM_FLOAT *pDataIn,
+ LVM_FLOAT *pDataOut,
+ LVM_INT16 NrFrames,
+ LVM_INT16 NrChannels);
+#endif
#else
void FO_1I_D32F32Cll_TRC_WRA_01_Init( Biquad_Instance_t *pInstance,
Biquad_1I_Order1_Taps_t *pTaps,
@@ -527,6 +560,13 @@
LVM_FLOAT *pDataIn,
LVM_FLOAT *pDataOut,
LVM_INT16 NrSamples);
+#ifdef SUPPORT_MC
+void PK_Mc_D32F32C14G11_TRC_WRA_01(Biquad_FLOAT_Instance_t *pInstance,
+ LVM_FLOAT *pDataIn,
+ LVM_FLOAT *pDataOut,
+ LVM_INT16 NrFrames,
+ LVM_INT16 NrChannels);
+#endif
#else
void PK_2I_D32F32C14G11_TRC_WRA_01 ( Biquad_Instance_t *pInstance,
LVM_INT32 *pDataIn,
@@ -540,12 +580,22 @@
/*** 16 bit data path STEREO ******************************************************/
#ifdef BUILD_FLOAT
+#ifdef SUPPORT_MC
+void DC_Mc_D16_TRC_WRA_01_Init ( Biquad_FLOAT_Instance_t *pInstance);
+
+void DC_Mc_D16_TRC_WRA_01 ( Biquad_FLOAT_Instance_t *pInstance,
+ LVM_FLOAT *pDataIn,
+ LVM_FLOAT *pDataOut,
+ LVM_INT16 NrFrames,
+ LVM_INT16 NrChannels);
+#else
void DC_2I_D16_TRC_WRA_01_Init ( Biquad_FLOAT_Instance_t *pInstance);
void DC_2I_D16_TRC_WRA_01 ( Biquad_FLOAT_Instance_t *pInstance,
LVM_FLOAT *pDataIn,
LVM_FLOAT *pDataOut,
LVM_INT16 NrSamples);
+#endif
#else
void DC_2I_D16_TRC_WRA_01_Init ( Biquad_Instance_t *pInstance);
diff --git a/media/libeffects/lvm/lib/Common/lib/LVM_Timer.h b/media/libeffects/lvm/lib/Common/lib/LVM_Timer.h
index 81e288c..a76354d 100644
--- a/media/libeffects/lvm/lib/Common/lib/LVM_Timer.h
+++ b/media/libeffects/lvm/lib/Common/lib/LVM_Timer.h
@@ -44,7 +44,15 @@
typedef struct
{
- LVM_INT32 Storage[6];
+ /*
+ * The memory area created using this structure is internally
+ * typecast to LVM_Timer_Instance_Private_t and used.
+ * The LVM_Timer_Instance_Private_t structure has 3 pointer type elements
+ * 2 elements of type LVM_INT32 and one element of type LVM_INT16.
+ * Inorder to cater both 32 and 64 bit builds, Storage array should
+ * have a minimum of 9 elements of type LVM_INT32.
+ */
+ LVM_INT32 Storage[9];
} LVM_Timer_Instance_t;
diff --git a/media/libeffects/lvm/lib/Common/lib/LVM_Types.h b/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
index ea16072..303b62d 100644
--- a/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
+++ b/media/libeffects/lvm/lib/Common/lib/LVM_Types.h
@@ -122,6 +122,12 @@
#endif // NATIVE_FLOAT_BUFFER
+#ifdef SUPPORT_MC
+#define LVM_MAX_CHANNELS 8 // FCC_8
+#else
+#define LVM_MAX_CHANNELS 2 // FCC_2
+#endif
+
/****************************************************************************************/
/* */
/* Standard Enumerated types */
@@ -143,6 +149,9 @@
LVM_STEREO = 0,
LVM_MONOINSTEREO = 1,
LVM_MONO = 2,
+#ifdef SUPPORT_MC
+ LVM_MULTICHANNEL = 3,
+#endif
LVM_SOURCE_DUMMY = LVM_MAXENUM
} LVM_Format_en;
diff --git a/media/libeffects/lvm/lib/Common/lib/VectorArithmetic.h b/media/libeffects/lvm/lib/Common/lib/VectorArithmetic.h
index 0ba20a3..7468a90 100644
--- a/media/libeffects/lvm/lib/Common/lib/VectorArithmetic.h
+++ b/media/libeffects/lvm/lib/Common/lib/VectorArithmetic.h
@@ -47,6 +47,16 @@
void Copy_Float( const LVM_FLOAT *src,
LVM_FLOAT *dst,
LVM_INT16 n );
+#ifdef SUPPORT_MC
+void Copy_Float_Mc_Stereo( const LVM_FLOAT *src,
+ LVM_FLOAT *dst,
+ LVM_INT16 NrFrames,
+ LVM_INT32 NrChannels);
+void Copy_Float_Stereo_Mc( const LVM_FLOAT *src,
+ LVM_FLOAT *dst,
+ LVM_INT16 NrFrames,
+ LVM_INT32 NrChannels);
+#endif
#else
void Copy_16( const LVM_INT16 *src,
LVM_INT16 *dst,
@@ -181,6 +191,12 @@
void From2iToMono_Float( const LVM_FLOAT *src,
LVM_FLOAT *dst,
LVM_INT16 n);
+#ifdef SUPPORT_MC
+void FromMcToMono_Float(const LVM_FLOAT *src,
+ LVM_FLOAT *dst,
+ LVM_INT16 NrFrames,
+ LVM_INT16 NrChannels);
+#endif
#else
void From2iToMono_32( const LVM_INT32 *src,
LVM_INT32 *dst,
diff --git a/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.c b/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.c
index fa9f01f..5c8655f 100644
--- a/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.c
+++ b/media/libeffects/lvm/lib/Common/src/AGC_MIX_VOL_2St1Mon_D32_WRA.c
@@ -305,4 +305,150 @@
return;
}
+#ifdef SUPPORT_MC
+/****************************************************************************************/
+/* */
+/* FUNCTION: AGC_MIX_VOL_Mc1Mon_D32_WRA */
+/* */
+/* DESCRIPTION: */
+/* Apply AGC and mix signals */
+/* */
+/* */
+/* McSrc ------------------| */
+/* | */
+/* ______ _|_ ________ */
+/* | | | | | | */
+/* MonoSrc -->| AGC |---->| + |----->| Volume |------------------------------+---> */
+/* | Gain | |___| | Gain | | */
+/* |______| |________| | */
+/* /|\ __________ ________ | */
+/* | | | | | | */
+/* |-------------------------------| AGC Gain |<--| Peak |<--| */
+/* | Update | | Detect | */
+/* |__________| |________| */
+/* */
+/* */
+/* PARAMETERS: */
+/* pInstance Instance pointer */
+/* pMcSrc Multichannel source */
+/* pMonoSrc Mono band pass source */
+/* pDst Multichannel destination */
+/* NrFrames Number of frames */
+/* NrChannels Number of channels */
+/* */
+/* RETURNS: */
+/* Void */
+/* */
+/* NOTES: */
+/* */
+/****************************************************************************************/
+void AGC_MIX_VOL_Mc1Mon_D32_WRA(AGC_MIX_VOL_2St1Mon_FLOAT_t *pInstance,
+ const LVM_FLOAT *pMcSrc,
+ const LVM_FLOAT *pMonoSrc,
+ LVM_FLOAT *pDst,
+ LVM_UINT16 NrFrames,
+ LVM_UINT16 NrChannels)
+{
+
+ /*
+ * General variables
+ */
+ LVM_UINT16 i, jj; /* Sample index */
+ LVM_FLOAT SampleVal; /* Sample value */
+ LVM_FLOAT Mono; /* Mono sample */
+ LVM_FLOAT AbsPeak; /* Absolute peak signal */
+ LVM_FLOAT AGC_Mult; /* Short AGC gain */
+ LVM_FLOAT Vol_Mult; /* Short volume */
+
+
+ /*
+ * Instance control variables
+ */
+ LVM_FLOAT AGC_Gain = pInstance->AGC_Gain; /* Get the current AGC gain */
+ LVM_FLOAT AGC_MaxGain = pInstance->AGC_MaxGain; /* Get maximum AGC gain */
+ LVM_FLOAT AGC_Attack = pInstance->AGC_Attack; /* Attack scaler */
+ /* Decay scaler */
+ LVM_FLOAT AGC_Decay = (pInstance->AGC_Decay * (1 << (DECAY_SHIFT)));
+ LVM_FLOAT AGC_Target = pInstance->AGC_Target; /* Get the target level */
+ LVM_FLOAT Vol_Current = pInstance->Volume; /* Actual volume setting */
+ LVM_FLOAT Vol_Target = pInstance->Target; /* Target volume setting */
+ LVM_FLOAT Vol_TC = pInstance->VolumeTC; /* Time constant */
+
+
+ /*
+ * Process on a sample by sample basis
+ */
+ for (i = 0; i < NrFrames; i++) /* For each frame */
+ {
+
+ /*
+ * Get the scalers
+ */
+ AGC_Mult = (LVM_FLOAT)(AGC_Gain); /* Get the AGC gain */
+ Vol_Mult = (LVM_FLOAT)(Vol_Current); /* Get the volume gain */
+
+ AbsPeak = 0.0f;
+ /*
+ * Get the input samples
+ */
+ for (jj = 0; jj < NrChannels; jj++)
+ {
+ SampleVal = *pMcSrc++; /* Get the sample value of jj Channel*/
+ Mono = *pMonoSrc; /* Get the mono sample */
+
+ /*
+ * Apply the AGC gain to the mono input and mix with the input signal
+ */
+ SampleVal += (Mono * AGC_Mult); /* Mix in the mono signal */
+
+ /*
+ * Apply the volume and write to the output stream
+ */
+ SampleVal = SampleVal * Vol_Mult;
+
+ *pDst++ = SampleVal; /* Save the results */
+
+ /*
+ * Update the AGC gain
+ */
+ AbsPeak = Abs_Float(SampleVal) > AbsPeak ? Abs_Float(SampleVal) : AbsPeak;
+ }
+ if (AbsPeak > AGC_Target)
+ {
+ /*
+ * The signal is too large so decrease the gain
+ */
+ AGC_Gain = AGC_Gain * AGC_Attack;
+ }
+ else
+ {
+ /*
+ * The signal is too small so increase the gain
+ */
+ if (AGC_Gain > AGC_MaxGain)
+ {
+ AGC_Gain -= (AGC_Decay);
+ }
+ else
+ {
+ AGC_Gain += (AGC_Decay);
+ }
+ }
+ pMonoSrc++;
+ /*
+ * Update the gain
+ */
+ Vol_Current += (Vol_Target - Vol_Current) * ((LVM_FLOAT)Vol_TC / VOL_TC_FLOAT);
+ }
+
+
+ /*
+ * Update the parameters
+ */
+ pInstance->Volume = Vol_Current; /* Actual volume setting */
+ pInstance->AGC_Gain = AGC_Gain;
+
+ return;
+}
+#endif /*SUPPORT_MC*/
#endif /*BUILD_FLOAT*/
diff --git a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_TRC_WRA_01.c
index 960de79..d63365c 100644
--- a/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_TRC_WRA_01.c
+++ b/media/libeffects/lvm/lib/Common/src/BQ_2I_D32F32C30_TRC_WRA_01.c
@@ -123,6 +123,87 @@
}
}
+
+#ifdef SUPPORT_MC
+/**************************************************************************
+ ASSUMPTIONS:
+ COEFS-
+ pBiquadState->coefs[0] is A2, pBiquadState->coefs[1] is A1
+ pBiquadState->coefs[2] is A0, pBiquadState->coefs[3] is -B2
+ pBiquadState->coefs[4] is -B1
+
+ DELAYS-
+ pBiquadState->pDelays[0] to
+ pBiquadState->pDelays[NrChannels - 1] is x(n-1) for all NrChannels
+
+ pBiquadState->pDelays[NrChannels] to
+ pBiquadState->pDelays[2*NrChannels - 1] is x(n-2) for all NrChannels
+
+ pBiquadState->pDelays[2*NrChannels] to
+ pBiquadState->pDelays[3*NrChannels - 1] is y(n-1) for all NrChannels
+
+ pBiquadState->pDelays[3*NrChannels] to
+ pBiquadState->pDelays[4*NrChannels - 1] is y(n-2) for all NrChannels
+***************************************************************************/
+void BQ_MC_D32F32C30_TRC_WRA_01 ( Biquad_FLOAT_Instance_t *pInstance,
+ LVM_FLOAT *pDataIn,
+ LVM_FLOAT *pDataOut,
+ LVM_INT16 NrFrames,
+ LVM_INT16 NrChannels)
+
+
+ {
+ LVM_FLOAT yn, temp;
+ LVM_INT16 ii, jj;
+ PFilter_State_FLOAT pBiquadState = (PFilter_State_FLOAT) pInstance;
+
+ for (ii = NrFrames; ii != 0; ii--)
+ {
+ /**************************************************************************
+ PROCESSING CHANNEL-WISE
+ ***************************************************************************/
+ for (jj = 0; jj < NrChannels; jj++)
+ {
+ /* yn= (A2 * x(n-2)) */
+ yn = pBiquadState->coefs[0] * pBiquadState->pDelays[NrChannels + jj];
+
+ /* yn+= (A1 * x(n-1)) */
+ temp = pBiquadState->coefs[1] * pBiquadState->pDelays[jj];
+ yn += temp;
+
+ /* yn+= (A0 * x(n)) */
+ temp = pBiquadState->coefs[2] * (*pDataIn);
+ yn += temp;
+
+ /* yn+= (-B2 * y(n-2)) */
+ temp = pBiquadState->coefs[3] * pBiquadState->pDelays[NrChannels*3 + jj];
+ yn += temp;
+
+ /* yn+= (-B1 * y(n-1)) */
+ temp = pBiquadState->coefs[4] * pBiquadState->pDelays[NrChannels*2 + jj];
+ yn += temp;
+
+ /**************************************************************************
+ UPDATING THE DELAYS
+ ***************************************************************************/
+ pBiquadState->pDelays[NrChannels * 3 + jj] =
+ pBiquadState->pDelays[NrChannels * 2 + jj]; /* y(n-2)=y(n-1)*/
+ pBiquadState->pDelays[NrChannels * 1 + jj] =
+ pBiquadState->pDelays[jj]; /* x(n-2)=x(n-1)*/
+ pBiquadState->pDelays[NrChannels * 2 + jj] = (LVM_FLOAT)yn; /* Update y(n-1)*/
+ pBiquadState->pDelays[jj] = (*pDataIn); /* Update x(n-1)*/
+ pDataIn++;
+ /**************************************************************************
+ WRITING THE OUTPUT
+ ***************************************************************************/
+ *pDataOut = (LVM_FLOAT)yn; /* Write jj Channel output */
+ pDataOut++;
+ }
+ }
+
+ }
+#endif /*SUPPORT_MC*/
+
#else
void BQ_2I_D32F32C30_TRC_WRA_01 ( Biquad_Instance_t *pInstance,
LVM_INT32 *pDataIn,
diff --git a/media/libeffects/lvm/lib/Common/src/Copy_16.c b/media/libeffects/lvm/lib/Common/src/Copy_16.c
index e489031..1f9f659 100644
--- a/media/libeffects/lvm/lib/Common/src/Copy_16.c
+++ b/media/libeffects/lvm/lib/Common/src/Copy_16.c
@@ -84,5 +84,65 @@
return;
}
+#ifdef SUPPORT_MC
+// Extract out the stereo channel pair from multichannel source.
+void Copy_Float_Mc_Stereo(const LVM_FLOAT *src,
+ LVM_FLOAT *dst,
+ LVM_INT16 NrFrames, /* Number of frames */
+ LVM_INT32 NrChannels)
+{
+ LVM_INT16 ii;
+
+ if (NrChannels >= 2)
+ {
+ for (ii = NrFrames; ii != 0; ii--)
+ {
+ dst[0] = src[0];
+ dst[1] = src[1];
+ dst += 2;
+ src += NrChannels;
+ }
+ }
+ else if (NrChannels == 1)
+ { // not expected to occur, provided for completeness.
+ src += (NrFrames - 1);
+ dst += 2 * (NrFrames - 1);
+ for (ii = NrFrames; ii != 0; ii--)
+ {
+ dst[0] = src[0];
+ dst[1] = src[0];
+ dst -= 2;
+ src --;
+ }
+ }
+}
+
+// Merge a multichannel source with stereo contained in dst, to dst.
+void Copy_Float_Stereo_Mc(const LVM_FLOAT *src,
+ LVM_FLOAT *dst,
+ LVM_INT16 NrFrames, /* Number of frames*/
+ LVM_INT32 NrChannels)
+{
+ LVM_INT16 ii, jj;
+ LVM_FLOAT *src_st = dst + 2 * (NrFrames - 1);
+
+ // repack dst which carries stereo information
+ // together with the upper channels of src.
+ dst += NrChannels * (NrFrames - 1);
+ src += NrChannels * (NrFrames - 1);
+ for (ii = NrFrames; ii != 0; ii--)
+ {
+ dst[0] = src_st[0];
+ dst[1] = src_st[1];
+ for (jj = 2; jj < NrChannels; jj++)
+ {
+ dst[jj] = src[jj];
+ }
+ dst -= NrChannels;
+ src -= NrChannels;
+ src_st -= 2;
+ }
+}
+#endif
#endif
/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.c
index d261c9e..13fac5e 100644
--- a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.c
+++ b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01.c
@@ -33,7 +33,7 @@
RightDC = pBiquadState->RightDC;
for(j = NrSamples-1; j >= 0; j--)
{
- /* Subtract DC an saturate */
+ /* Subtract DC and saturate */
Diff =* (pDataIn++) - (LeftDC);
if (Diff > 1.0f) {
Diff = 1.0f; }
@@ -64,6 +64,58 @@
}
+#ifdef SUPPORT_MC
+/*
+ * FUNCTION: DC_Mc_D16_TRC_WRA_01
+ *
+ * DESCRIPTION:
+ * DC removal from all channels of a multichannel input
+ *
+ * PARAMETERS:
+ * pInstance Instance pointer
+ * pDataIn Input/Source
+ * pDataOut Output/Destination
+ * NrFrames Number of frames
+ * NrChannels Number of channels
+ *
+ * RETURNS:
+ * void
+ *
+ */
+void DC_Mc_D16_TRC_WRA_01(Biquad_FLOAT_Instance_t *pInstance,
+ LVM_FLOAT *pDataIn,
+ LVM_FLOAT *pDataOut,
+ LVM_INT16 NrFrames,
+ LVM_INT16 NrChannels)
+ {
+ LVM_FLOAT *ChDC;
+ LVM_FLOAT Diff;
+ LVM_INT32 j;
+ LVM_INT32 i;
+ PFilter_FLOAT_State_Mc pBiquadState = (PFilter_FLOAT_State_Mc) pInstance;
+
+ ChDC = &pBiquadState->ChDC[0];
+ for (j = NrFrames - 1; j >= 0; j--)
+ {
+ /* Subtract DC and saturate */
+ for (i = NrChannels - 1; i >= 0; i--)
+ {
+ Diff = *(pDataIn++) - (ChDC[i]);
+ if (Diff > 1.0f) {
+ Diff = 1.0f;
+ } else if (Diff < -1.0f) {
+ Diff = -1.0f; }
+ *(pDataOut++) = (LVM_FLOAT)Diff;
+ if (Diff < 0) {
+ ChDC[i] -= DC_FLOAT_STEP;
+ } else {
+ ChDC[i] += DC_FLOAT_STEP; }
+ }
+
+ }
+
+ }
+#endif
#else
void DC_2I_D16_TRC_WRA_01( Biquad_Instance_t *pInstance,
LVM_INT16 *pDataIn,
diff --git a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.c b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.c
index 4f4fcd8..0f941a0 100644
--- a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.c
+++ b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Init.c
@@ -24,6 +24,17 @@
pBiquadState->LeftDC = 0.0f;
pBiquadState->RightDC = 0.0f;
}
+#ifdef SUPPORT_MC
+void DC_Mc_D16_TRC_WRA_01_Init(Biquad_FLOAT_Instance_t *pInstance)
+{
+ PFilter_FLOAT_State_Mc pBiquadState = (PFilter_FLOAT_State_Mc) pInstance;
+ LVM_INT32 i;
+ for (i = 0; i < LVM_MAX_CHANNELS; i++)
+ {
+ pBiquadState->ChDC[i] = 0.0f;
+ }
+}
+#endif
#else
void DC_2I_D16_TRC_WRA_01_Init(Biquad_Instance_t *pInstance)
{
diff --git a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Private.h b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Private.h
index fa6b729..db3a6d3 100644
--- a/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/DC_2I_D16_TRC_WRA_01_Private.h
@@ -34,6 +34,13 @@
LVM_FLOAT RightDC; /* RightDC */
}Filter_FLOAT_State;
typedef Filter_FLOAT_State * PFilter_FLOAT_State ;
+#ifdef SUPPORT_MC
+typedef struct _Filter_FLOAT_State_Mc_
+{
+ LVM_FLOAT ChDC[LVM_MAX_CHANNELS]; /* ChannelDC */
+} Filter_FLOAT_State_Mc;
+typedef Filter_FLOAT_State_Mc * PFilter_FLOAT_State_Mc ;
+#endif
#else
typedef struct _Filter_State_
{
diff --git a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.c
index 192927c..2a50f18 100644
--- a/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.c
+++ b/media/libeffects/lvm/lib/Common/src/FO_2I_D16F32C15_LShx_TRC_WRA_01.c
@@ -117,6 +117,93 @@
}
}
+#ifdef SUPPORT_MC
+/**************************************************************************
+ASSUMPTIONS:
+COEFS-
+pBiquadState->coefs[0] is A1,
+pBiquadState->coefs[1] is A0,
+pBiquadState->coefs[2] is -B1,
+DELAYS-
+pBiquadState->pDelays[2*ch + 0] is x(n-1) of the 'ch' - channel
+pBiquadState->pDelays[2*ch + 1] is y(n-1) of the 'ch' - channel
+The index 'ch' runs from 0 to (NrChannels - 1)
+
+PARAMETERS:
+ pInstance Pointer Instance
+ pDataIn Input/Source
+ pDataOut Output/Destination
+ NrFrames Number of frames
+ NrChannels Number of channels
+
+RETURNS:
+ void
+***************************************************************************/
+void FO_Mc_D16F32C15_LShx_TRC_WRA_01(Biquad_FLOAT_Instance_t *pInstance,
+ LVM_FLOAT *pDataIn,
+ LVM_FLOAT *pDataOut,
+ LVM_INT16 NrFrames,
+ LVM_INT16 NrChannels)
+ {
+ LVM_FLOAT yn;
+ LVM_FLOAT Temp;
+ LVM_INT16 ii;
+ LVM_INT16 ch;
+ PFilter_Float_State pBiquadState = (PFilter_Float_State) pInstance;
+
+ LVM_FLOAT *pDelays = pBiquadState->pDelays;
+ LVM_FLOAT *pCoefs = &pBiquadState->coefs[0];
+ LVM_FLOAT A0 = pCoefs[1];
+ LVM_FLOAT A1 = pCoefs[0];
+ LVM_FLOAT B1 = pCoefs[2];
+
+
+
+
+ for (ii = NrFrames; ii != 0; ii--)
+ {
+
+ /**************************************************************************
+ PROCESSING OF THE CHANNELS
+ ***************************************************************************/
+ for (ch = 0; ch < NrChannels; ch++)
+ {
+ // yn =A1 * x(n-1)
+ yn = (LVM_FLOAT)A1 * pDelays[0];
+
+ // yn+=A0 * x(n)
+ yn += (LVM_FLOAT)A0 * (*pDataIn);
+
+ // yn += (-B1 * y(n-1))
+ Temp = B1 * pDelays[1];
+ yn += Temp;
+
+
+ /**************************************************************************
+ UPDATING THE DELAYS
+ ***************************************************************************/
+ pDelays[1] = yn; // Update y(n-1)
+ pDelays[0] = (*pDataIn++); // Update x(n-1)
+
+ /**************************************************************************
+ WRITING THE OUTPUT
+ ***************************************************************************/
+
+ /*Saturate results*/
+ if (yn > 1.0f)
+ {
+ yn = 1.0f;
+ } else if (yn < -1.0f) {
+ yn = -1.0f;
+ }
+
+ *pDataOut++ = (LVM_FLOAT)yn;
+ pDelays += 2;
+ }
+ pDelays -= NrChannels * 2;
+ }
+ }
+#endif
#else
void FO_2I_D16F32C15_LShx_TRC_WRA_01(Biquad_Instance_t *pInstance,
LVM_INT16 *pDataIn,
diff --git a/media/libeffects/lvm/lib/Common/src/From2iToMono_32.c b/media/libeffects/lvm/lib/Common/src/From2iToMono_32.c
index ac1eea8..d02af88 100644
--- a/media/libeffects/lvm/lib/Common/src/From2iToMono_32.c
+++ b/media/libeffects/lvm/lib/Common/src/From2iToMono_32.c
@@ -68,5 +68,47 @@
return;
}
+#ifdef SUPPORT_MC
+/*
+ * FUNCTION: FromMcToMono_Float
+ *
+ * DESCRIPTION:
+ * Creates a mono stream from a multichannel input taking the avergae of
+ * sample values of all channels
+ *
+ * PARAMETERS:
+ * src Source
+ * dst Destination
+ * NrFrames Number of frames
+ * NrChannels Number of channels
+ *
+ * RETURNS:
+ * void
+ *
+ */
+void FromMcToMono_Float(const LVM_FLOAT *src,
+ LVM_FLOAT *dst,
+ LVM_INT16 NrFrames,
+ LVM_INT16 NrChannels)
+{
+ LVM_INT16 ii, jj;
+ LVM_FLOAT Temp;
+
+ for (ii = NrFrames; ii != 0; ii--)
+ {
+ Temp = 0.0f;
+ for (jj = NrChannels; jj !=0; jj--)
+ {
+ Temp += (*src);
+ src++;
+ }
+ *dst = Temp / NrChannels;
+ dst++;
+ }
+
+ return;
+}
+#endif
+
#endif
/**********************************************************************************/
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.c
index d2694cc..419c7c5 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.c
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixInSoft_D16C31_SAT.c
@@ -26,10 +26,10 @@
FUNCTION LVCore_MIXSOFT_1ST_D16C31_WRA
***********************************************************************************/
#ifdef BUILD_FLOAT
-void LVC_Core_MixInSoft_D16C31_SAT( LVMixer3_FLOAT_st *ptrInstance,
- const LVM_FLOAT *src,
- LVM_FLOAT *dst,
- LVM_INT16 n)
+void LVC_Core_MixInSoft_D16C31_SAT(LVMixer3_FLOAT_st *ptrInstance,
+ const LVM_FLOAT *src,
+ LVM_FLOAT *dst,
+ LVM_INT16 n)
{
LVM_INT16 OutLoop;
@@ -114,6 +114,139 @@
}
pInstance->Current = Current;
}
+#ifdef SUPPORT_MC
+/*
+ * FUNCTION: LVC_Core_MixInSoft_Mc_D16C31_SAT
+ *
+ * DESCRIPTION:
+ * Mixer function with support for processing multichannel input.
+ *
+ * PARAMETERS:
+ * ptrInstance Instance pointer
+ * src Source
+ * dst Destination
+ * NrFrames Number of frames
+ * NrChannels Number of channels
+ *
+ * RETURNS:
+ * void
+ *
+ */
+void LVC_Core_MixInSoft_Mc_D16C31_SAT(LVMixer3_FLOAT_st *ptrInstance,
+ const LVM_FLOAT *src,
+ LVM_FLOAT *dst,
+ LVM_INT16 NrFrames,
+ LVM_INT16 NrChannels)
+{
+
+ LVM_INT16 OutLoop;
+ LVM_INT16 InLoop;
+ LVM_INT32 ii, jj;
+ Mix_Private_FLOAT_st *pInstance = (Mix_Private_FLOAT_st *)(ptrInstance->PrivateParams);
+ LVM_FLOAT Delta = pInstance->Delta;
+ LVM_FLOAT Current = pInstance->Current;
+ LVM_FLOAT Target = pInstance->Target;
+ LVM_FLOAT Temp;
+
+ /*
+ * Same operation is performed on consecutive frames.
+ * So two frames are processed in one iteration and
+ * the loop will run only for half the NrFrames value times.
+ */
+ InLoop = (LVM_INT16)(NrFrames >> 1);
+ /* OutLoop is calculated to handle cases where NrFrames value can be odd.*/
+ OutLoop = (LVM_INT16)(NrFrames - (InLoop << 1));
+
+ if (Current < Target) {
+ if (OutLoop) {
+ Temp = Current + Delta;
+ Current = Temp;
+ if (Current > Target)
+ Current = Target;
+
+ for (ii = OutLoop*NrChannels; ii != 0; ii--) {
+ Temp = (*dst) + (*(src++) * Current);
+ if (Temp > 1.0f)
+ *dst++ = 1.0f;
+ else if (Temp < -1.0f)
+ *dst++ = -1.0f;
+ else
+ *dst++ = Temp;
+ }
+ }
+
+ for (ii = InLoop; ii != 0; ii--) {
+ Temp = Current + Delta;
+ Current = Temp;
+ if (Current > Target)
+ Current = Target;
+
+ for (jj = NrChannels; jj != 0 ; jj--) {
+ Temp = (*dst) + (*(src++) * Current);
+ if (Temp > 1.0f)
+ *dst++ = 1.0f;
+ else if (Temp < -1.0f)
+ *dst++ = -1.0f;
+ else
+ *dst++ = Temp;
+
+ Temp = (*dst) + (*(src++) * Current);
+ if (Temp > 1.0f)
+ *dst++ = 1.0f;
+ else if (Temp < -1.0f)
+ *dst++ = -1.0f;
+ else
+ *dst++ = Temp;
+
+ }
+ }
+ }
+ else{
+ if (OutLoop) {
+ Current -= Delta;
+ if (Current < Target)
+ Current = Target;
+
+ for (ii = OutLoop*NrChannels; ii != 0; ii--) {
+ Temp = (*dst) + (*(src++) * Current);
+ if (Temp > 1.0f)
+ *dst++ = 1.0f;
+ else if (Temp < -1.0f)
+ *dst++ = -1.0f;
+ else
+ *dst++ = Temp;
+ }
+ }
+
+ for (ii = InLoop; ii != 0; ii--) {
+ Current -= Delta;
+ if (Current < Target)
+ Current = Target;
+
+ for (jj = NrChannels; jj != 0 ; jj--) {
+ Temp = (*dst) + (*(src++) * Current);
+ if (Temp > 1.0f)
+ *dst++ = 1.0f;
+ else if (Temp < -1.0f)
+ *dst++ = -1.0f;
+ else
+ *dst++ = Temp;
+
+ Temp = (*dst) + (*(src++) * Current);
+ if (Temp > 1.0f)
+ *dst++ = 1.0f;
+ else if (Temp < -1.0f)
+ *dst++ = -1.0f;
+ else
+ *dst++ = Temp;
+
+ }
+ }
+ }
+ pInstance->Current = Current;
+}
+
+#endif
#else
void LVC_Core_MixInSoft_D16C31_SAT( LVMixer3_st *ptrInstance,
const LVM_INT16 *src,
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.c b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.c
index b5e7f5c..5bfdad8 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.c
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Core_MixSoft_1St_D16C31_WRA.c
@@ -27,10 +27,10 @@
FUNCTION LVCore_MIXSOFT_1ST_D16C31_WRA
***********************************************************************************/
#ifdef BUILD_FLOAT
-void LVC_Core_MixSoft_1St_D16C31_WRA( LVMixer3_FLOAT_st *ptrInstance,
- const LVM_FLOAT *src,
- LVM_FLOAT *dst,
- LVM_INT16 n)
+void LVC_Core_MixSoft_1St_D16C31_WRA(LVMixer3_FLOAT_st *ptrInstance,
+ const LVM_FLOAT *src,
+ LVM_FLOAT *dst,
+ LVM_INT16 n)
{
LVM_INT16 OutLoop;
LVM_INT16 InLoop;
@@ -105,6 +105,119 @@
}
pInstance->Current=Current;
}
+
+
+#ifdef SUPPORT_MC
+/*
+ * FUNCTION: LVC_Core_MixSoft_Mc_D16C31_WRA
+ *
+ * DESCRIPTION:
+ * Mixer function with support for processing multichannel input
+ *
+ * PARAMETERS:
+ * ptrInstance Instance pointer
+ * src Source
+ * dst Destination
+ * NrFrames Number of frames
+ * NrChannels Number of channels
+ *
+ * RETURNS:
+ * void
+ *
+ */
+void LVC_Core_MixSoft_Mc_D16C31_WRA(LVMixer3_FLOAT_st *ptrInstance,
+ const LVM_FLOAT *src,
+ LVM_FLOAT *dst,
+ LVM_INT16 NrFrames,
+ LVM_INT16 NrChannels)
+{
+ LVM_INT16 OutLoop;
+ LVM_INT16 InLoop;
+ LVM_INT32 ii, jj;
+ Mix_Private_FLOAT_st *pInstance=(Mix_Private_FLOAT_st *)(ptrInstance->PrivateParams);
+ LVM_FLOAT Delta= (LVM_FLOAT)pInstance->Delta;
+ LVM_FLOAT Current = (LVM_FLOAT)pInstance->Current;
+ LVM_FLOAT Target= (LVM_FLOAT)pInstance->Target;
+ LVM_FLOAT Temp;
+
+ /*
+ * Same operation is performed on consecutive frames.
+ * So two frames are processed in one iteration and
+ * the loop will run only for half the NrFrames value times.
+ */
+ InLoop = (LVM_INT16)(NrFrames >> 1);
+ /* OutLoop is calculated to handle cases where NrFrames value can be odd.*/
+ OutLoop = (LVM_INT16)(NrFrames - (InLoop << 1));
+
+ if (Current<Target) {
+ if (OutLoop) {
+
+ Temp = Current + Delta;
+ if (Temp > 1.0f)
+ Temp = 1.0f;
+ else if (Temp < -1.0f)
+ Temp = -1.0f;
+
+ Current=Temp;
+ if (Current > Target)
+ Current = Target;
+
+ for (ii = OutLoop; ii != 0; ii--) {
+ for (jj = NrChannels; jj !=0; jj--) {
+ *(dst++) = (((LVM_FLOAT)*(src++) * (LVM_FLOAT)Current));
+ }
+ }
+ }
+
+ for (ii = InLoop; ii != 0; ii--) {
+
+ Temp = Current + Delta;
+
+ if (Temp > 1.0f)
+ Temp = 1.0f;
+ else if (Temp < -1.0f)
+ Temp = -1.0f;
+
+ Current=Temp;
+ if (Current > Target)
+ Current = Target;
+
+ for (jj = NrChannels; jj != 0 ; jj--)
+ {
+ *(dst++) = (((LVM_FLOAT)*(src++) * Current));
+ *(dst++) = (((LVM_FLOAT)*(src++) * Current));
+ }
+ }
+ }
+ else{
+ if (OutLoop) {
+ Current -= Delta;
+ if (Current < Target)
+ Current = Target;
+
+ for (ii = OutLoop; ii != 0; ii--) {
+ for (jj = NrChannels; jj !=0; jj--) {
+ *(dst++) = (((LVM_FLOAT)*(src++) * (LVM_FLOAT)Current));
+ }
+ }
+ }
+
+ for (ii = InLoop; ii != 0; ii--) {
+ Current -= Delta;
+ if (Current < Target)
+ Current = Target;
+
+ for (jj = NrChannels; jj != 0 ; jj--)
+ {
+ *(dst++) = (((LVM_FLOAT)*(src++) * Current));
+ *(dst++) = (((LVM_FLOAT)*(src++) * Current));
+ }
+ }
+ }
+ pInstance->Current=Current;
+}
+#endif
+
#else
void LVC_Core_MixSoft_1St_D16C31_WRA( LVMixer3_st *ptrInstance,
const LVM_INT16 *src,
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_MixInSoft_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_MixInSoft_D16C31_SAT.c
index 192f126..65956f7 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_MixInSoft_D16C31_SAT.c
+++ b/media/libeffects/lvm/lib/Common/src/LVC_MixInSoft_D16C31_SAT.c
@@ -34,10 +34,10 @@
FUNCTION MIXINSOFT_D16C31_SAT
***********************************************************************************/
#ifdef BUILD_FLOAT
-void LVC_MixInSoft_D16C31_SAT( LVMixer3_1St_FLOAT_st *ptrInstance,
- LVM_FLOAT *src,
- LVM_FLOAT *dst,
- LVM_INT16 n)
+void LVC_MixInSoft_D16C31_SAT(LVMixer3_1St_FLOAT_st *ptrInstance,
+ const LVM_FLOAT *src,
+ LVM_FLOAT *dst,
+ LVM_INT16 n)
{
char HardMixing = TRUE;
LVM_FLOAT TargetGain;
@@ -106,6 +106,110 @@
}
}
+
+
+
+#ifdef SUPPORT_MC
+/*
+ * FUNCTION: LVC_MixInSoft_Mc_D16C31_SAT
+ *
+ * DESCRIPTION:
+ * Mixer function with support for processing multichannel input
+ *
+ * PARAMETERS:
+ * ptrInstance Instance pointer
+ * src Source
+ * dst Destination
+ * NrFrames Number of frames
+ * NrChannels Number of channels
+ *
+ * RETURNS:
+ * void
+ *
+ */
+void LVC_MixInSoft_Mc_D16C31_SAT(LVMixer3_1St_FLOAT_st *ptrInstance,
+ const LVM_FLOAT *src,
+ LVM_FLOAT *dst,
+ LVM_INT16 NrFrames,
+ LVM_INT16 NrChannels)
+{
+ char HardMixing = TRUE;
+ LVM_FLOAT TargetGain;
+ Mix_Private_FLOAT_st *pInstance = \
+ (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[0].PrivateParams);
+
+ if (NrFrames <= 0) return;
+
+ /******************************************************************************
+ SOFT MIXING
+ *******************************************************************************/
+ if (pInstance->Current != pInstance->Target)
+ {
+ if (pInstance->Delta == 1.0f) {
+ pInstance->Current = pInstance->Target;
+ TargetGain = pInstance->Target;
+ LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
+ }else if (Abs_Float(pInstance->Current - pInstance->Target) < pInstance->Delta) {
+ pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
+ Make them equal. */
+ TargetGain = pInstance->Target;
+ LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
+ }else{
+ /* Soft mixing has to be applied */
+ HardMixing = FALSE;
+ LVC_Core_MixInSoft_Mc_D16C31_SAT(&(ptrInstance->MixerStream[0]),
+ src,
+ dst,
+ NrFrames,
+ NrChannels);
+ }
+ }
+
+ /******************************************************************************
+ HARD MIXING
+ *******************************************************************************/
+
+ if (HardMixing) {
+ if (pInstance->Target != 0) { /* Nothing to do in case Target = 0 */
+ if ((pInstance->Target) == 1.0f) {
+ Add2_Sat_Float(src, dst, NrFrames*NrChannels);
+ }
+ else{
+ Mac3s_Sat_Float(src,
+ (pInstance->Target),
+ dst,
+ NrFrames * NrChannels);
+ /* In case the LVCore function would have changed the Current value */
+ pInstance->Current = pInstance->Target;
+ }
+ }
+ }
+
+
+ /******************************************************************************
+ CALL BACK
+ *******************************************************************************/
+
+ if (ptrInstance->MixerStream[0].CallbackSet) {
+ if (Abs_Float(pInstance->Current - pInstance->Target) < pInstance->Delta) {
+ pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
+ Make them equal. */
+ TargetGain = pInstance->Target;
+ LVC_Mixer_SetTarget(ptrInstance->MixerStream, TargetGain);
+ ptrInstance->MixerStream[0].CallbackSet = FALSE;
+ if (ptrInstance->MixerStream[0].pCallBack != 0) {
+ (*ptrInstance->MixerStream[0].pCallBack) (\
+ ptrInstance->MixerStream[0].pCallbackHandle,
+ ptrInstance->MixerStream[0].pGeneralPurpose,
+ ptrInstance->MixerStream[0].CallbackParam);
+ }
+ }
+ }
+
+}
+#endif
+
+
#else
void LVC_MixInSoft_D16C31_SAT( LVMixer3_1St_st *ptrInstance,
LVM_INT16 *src,
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_D16C31_SAT.c
index 1017de3..0678ae0 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_D16C31_SAT.c
+++ b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_1St_D16C31_SAT.c
@@ -103,6 +103,101 @@
}
}
}
+#ifdef SUPPORT_MC
+/*
+ * FUNCTION: LVC_MixSoft_Mc_D16C31_SAT
+ *
+ * DESCRIPTION:
+ * Mixer function with support for processing multichannel input
+ *
+ * PARAMETERS:
+ * ptrInstance Instance pointer
+ * src Source
+ * dst Destination
+ * NrFrames Number of Frames
+ * NrChannels Number of channels
+ *
+ * RETURNS:
+ * void
+ *
+ */
+void LVC_MixSoft_Mc_D16C31_SAT(LVMixer3_1St_FLOAT_st *ptrInstance,
+ const LVM_FLOAT *src,
+ LVM_FLOAT *dst,
+ LVM_INT16 NrFrames,
+ LVM_INT16 NrChannels)
+{
+ char HardMixing = TRUE;
+ LVM_FLOAT TargetGain;
+ Mix_Private_FLOAT_st *pInstance = \
+ (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[0].PrivateParams);
+
+ if (NrFrames <= 0) return;
+
+ /******************************************************************************
+ SOFT MIXING
+ *******************************************************************************/
+ if (pInstance->Current != pInstance->Target)
+ {
+ if (pInstance->Delta == 1.0f) {
+ pInstance->Current = pInstance->Target;
+ TargetGain = pInstance->Target;
+ LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
+ }else if (Abs_Float(pInstance->Current - pInstance->Target) < pInstance->Delta) {
+ pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
+ Make them equal. */
+ TargetGain = pInstance->Target;
+ LVC_Mixer_SetTarget(&(ptrInstance->MixerStream[0]), TargetGain);
+ }else{
+ /* Soft mixing has to be applied */
+ HardMixing = FALSE;
+ LVC_Core_MixSoft_Mc_D16C31_WRA(&(ptrInstance->MixerStream[0]),
+ src,
+ dst,
+ NrFrames,
+ NrChannels);
+ }
+ }
+
+ /******************************************************************************
+ HARD MIXING
+ *******************************************************************************/
+
+ if (HardMixing) {
+ if (pInstance->Target == 0)
+ LoadConst_Float(0.0, dst, NrFrames * NrChannels);
+ else {
+ if ((pInstance->Target) != 1.0f)
+ Mult3s_Float(src, (pInstance->Target), dst, NrFrames * NrChannels);
+ else if (src != dst)
+ Copy_Float(src, dst, NrFrames * NrChannels);
+ }
+
+ }
+
+ /******************************************************************************
+ CALL BACK
+ *******************************************************************************/
+
+ if (ptrInstance->MixerStream[0].CallbackSet) {
+ if (Abs_Float(pInstance->Current - pInstance->Target) < pInstance->Delta) {
+ pInstance->Current = pInstance->Target; /* Difference is not significant anymore. \
+ Make them equal. */
+ TargetGain = pInstance->Target;
+ LVC_Mixer_SetTarget(ptrInstance->MixerStream, TargetGain);
+ ptrInstance->MixerStream[0].CallbackSet = FALSE;
+ if (ptrInstance->MixerStream[0].pCallBack != 0) {
+ (*ptrInstance->MixerStream[0].pCallBack) (\
+ ptrInstance->MixerStream[0].pCallbackHandle,
+ ptrInstance->MixerStream[0].pGeneralPurpose,
+ ptrInstance->MixerStream[0].CallbackParam);
+ }
+ }
+ }
+}
+
+#endif
+
#else
void LVC_MixSoft_1St_D16C31_SAT( LVMixer3_1St_st *ptrInstance,
const LVM_INT16 *src,
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_2St_D16C31_SAT.c b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_2St_D16C31_SAT.c
index 3c90071..8a89de1 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_2St_D16C31_SAT.c
+++ b/media/libeffects/lvm/lib/Common/src/LVC_MixSoft_2St_D16C31_SAT.c
@@ -26,11 +26,11 @@
FUNCTION LVC_MixSoft_2St_D16C31_SAT.c
***********************************************************************************/
#ifdef BUILD_FLOAT
-void LVC_MixSoft_2St_D16C31_SAT( LVMixer3_2St_FLOAT_st *ptrInstance,
- const LVM_FLOAT *src1,
- LVM_FLOAT *src2,
- LVM_FLOAT *dst,
- LVM_INT16 n)
+void LVC_MixSoft_2St_D16C31_SAT(LVMixer3_2St_FLOAT_st *ptrInstance,
+ const LVM_FLOAT *src1,
+ const LVM_FLOAT *src2,
+ LVM_FLOAT *dst,
+ LVM_INT16 n)
{
Mix_Private_FLOAT_st *pInstance1 = \
(Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[0].PrivateParams);
@@ -67,6 +67,70 @@
src1, src2, dst, n);
}
}
+
+#ifdef SUPPORT_MC
+/*
+ * FUNCTION: LVC_MixSoft_2Mc_D16C31_SAT
+ *
+ * DESCRIPTION:
+ * 2 stream Mixer function with support for processing multichannel input
+ *
+ * PARAMETERS:
+ * ptrInstance Instance pointer
+ * src1 First multichannel source
+ * src2 Second multichannel source
+ * dst Destination
+ * NrFrames Number of frames
+ * NrChannels Number of channels
+ *
+ * RETURNS:
+ * void
+ *
+ */
+void LVC_MixSoft_2Mc_D16C31_SAT(LVMixer3_2St_FLOAT_st *ptrInstance,
+ const LVM_FLOAT *src1,
+ const LVM_FLOAT *src2,
+ LVM_FLOAT *dst,
+ LVM_INT16 NrFrames,
+ LVM_INT16 NrChannels)
+{
+ Mix_Private_FLOAT_st *pInstance1 = \
+ (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[0].PrivateParams);
+ Mix_Private_FLOAT_st *pInstance2 = \
+ (Mix_Private_FLOAT_st *)(ptrInstance->MixerStream[1].PrivateParams);
+
+ if (NrFrames <= 0) return;
+
+ /******************************************************************************
+ SOFT MIXING
+ *******************************************************************************/
+ if ((pInstance1->Current == pInstance1->Target) && (pInstance1->Current == 0)) {
+ LVC_MixSoft_Mc_D16C31_SAT((LVMixer3_1St_FLOAT_st *)(&ptrInstance->MixerStream[1]),
+ src2, dst, NrFrames, NrChannels);
+ }
+ else if ((pInstance2->Current == pInstance2->Target) && (pInstance2->Current == 0)) {
+ LVC_MixSoft_Mc_D16C31_SAT((LVMixer3_1St_FLOAT_st *)(&ptrInstance->MixerStream[0]),
+ src1, dst, NrFrames, NrChannels);
+ }
+ else if ((pInstance1->Current != pInstance1->Target) || \
+ (pInstance2->Current != pInstance2->Target))
+ {
+ LVC_MixSoft_Mc_D16C31_SAT((LVMixer3_1St_FLOAT_st *)(&ptrInstance->MixerStream[0]),
+ src1, dst, NrFrames, NrChannels);
+ LVC_MixInSoft_Mc_D16C31_SAT((LVMixer3_1St_FLOAT_st *)(&ptrInstance->MixerStream[1]),
+ src2, dst, NrFrames, NrChannels);
+ }
+ else{
+ /******************************************************************************
+ HARD MIXING
+ *******************************************************************************/
+ LVC_Core_MixHard_2St_D16C31_SAT(&ptrInstance->MixerStream[0],
+ &ptrInstance->MixerStream[1],
+ src1, src2, dst, NrFrames * NrChannels);
+ }
+}
+#endif
+
#else
void LVC_MixSoft_2St_D16C31_SAT( LVMixer3_2St_st *ptrInstance,
const LVM_INT16 *src1,
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h b/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h
index f904915..7f18747 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer.h
@@ -157,10 +157,18 @@
/*** 16 bit functions *************************************************************/
#ifdef BUILD_FLOAT
-void LVC_MixSoft_1St_D16C31_SAT( LVMixer3_1St_FLOAT_st *pInstance,
- const LVM_FLOAT *src,
- LVM_FLOAT *dst,
- LVM_INT16 n);
+void LVC_MixSoft_1St_D16C31_SAT(LVMixer3_1St_FLOAT_st *pInstance,
+ const LVM_FLOAT *src,
+ LVM_FLOAT *dst,
+ LVM_INT16 n);
+#ifdef SUPPORT_MC
+void LVC_MixSoft_Mc_D16C31_SAT(LVMixer3_1St_FLOAT_st *pInstance,
+ const LVM_FLOAT *src,
+ LVM_FLOAT *dst,
+ LVM_INT16 NrFrames,
+ LVM_INT16 NrChannels);
+#endif
+
#else
void LVC_MixSoft_1St_D16C31_SAT( LVMixer3_1St_st *pInstance,
const LVM_INT16 *src,
@@ -169,10 +177,18 @@
#endif
#ifdef BUILD_FLOAT
-void LVC_MixInSoft_D16C31_SAT( LVMixer3_1St_FLOAT_st *pInstance,
- LVM_FLOAT *src,
- LVM_FLOAT *dst,
- LVM_INT16 n);
+void LVC_MixInSoft_D16C31_SAT(LVMixer3_1St_FLOAT_st *pInstance,
+ const LVM_FLOAT *src,
+ LVM_FLOAT *dst,
+ LVM_INT16 n);
+#ifdef SUPPORT_MC
+void LVC_MixInSoft_Mc_D16C31_SAT(LVMixer3_1St_FLOAT_st *pInstance,
+ const LVM_FLOAT *src,
+ LVM_FLOAT *dst,
+ LVM_INT16 NrFrames,
+ LVM_INT16 NrChannels);
+#endif
+
#else
void LVC_MixInSoft_D16C31_SAT( LVMixer3_1St_st *pInstance,
LVM_INT16 *src,
@@ -181,11 +197,19 @@
#endif
#ifdef BUILD_FLOAT
-void LVC_MixSoft_2St_D16C31_SAT( LVMixer3_2St_FLOAT_st *pInstance,
- const LVM_FLOAT *src1,
- LVM_FLOAT *src2,
- LVM_FLOAT *dst, /* dst cannot be equal to src2 */
- LVM_INT16 n);
+void LVC_MixSoft_2St_D16C31_SAT(LVMixer3_2St_FLOAT_st *pInstance,
+ const LVM_FLOAT *src1,
+ const LVM_FLOAT *src2,
+ LVM_FLOAT *dst, /* dst cannot be equal to src2 */
+ LVM_INT16 n);
+#ifdef SUPPORT_MC
+void LVC_MixSoft_2Mc_D16C31_SAT(LVMixer3_2St_FLOAT_st *pInstance,
+ const LVM_FLOAT *src1,
+ const LVM_FLOAT *src2,
+ LVM_FLOAT *dst, /* dst cannot be equal to src2 */
+ LVM_INT16 NrFrames,
+ LVM_INT16 NrChannels);
+#endif
#else
void LVC_MixSoft_2St_D16C31_SAT( LVMixer3_2St_st *pInstance,
const LVM_INT16 *src1,
@@ -200,10 +224,10 @@
/* Gain values should not be more that 1.0 */
/**********************************************************************************/
#ifdef BUILD_FLOAT
-void LVC_MixSoft_1St_2i_D16C31_SAT( LVMixer3_2St_FLOAT_st *pInstance,
- const LVM_FLOAT *src,
- LVM_FLOAT *dst, /* dst can be equal to src */
- LVM_INT16 n); /* Number of stereo samples */
+void LVC_MixSoft_1St_2i_D16C31_SAT(LVMixer3_2St_FLOAT_st *pInstance,
+ const LVM_FLOAT *src,
+ LVM_FLOAT *dst, /* dst can be equal to src */
+ LVM_INT16 n); /* Number of stereo samples */
#else
void LVC_MixSoft_1St_2i_D16C31_SAT( LVMixer3_2St_st *pInstance,
const LVM_INT16 *src,
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetTarget.c b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetTarget.c
index c67455a..507eefa 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetTarget.c
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_GetTarget.c
@@ -35,7 +35,7 @@
{
LVM_FLOAT TargetGain;
Mix_Private_FLOAT_st *pInstance = (Mix_Private_FLOAT_st *)pStream->PrivateParams;
-
+
TargetGain = pInstance->Target; // TargetGain
return TargetGain;
}
diff --git a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h
index d0d0e1f..f10094b 100644
--- a/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h
+++ b/media/libeffects/lvm/lib/Common/src/LVC_Mixer_Private.h
@@ -62,6 +62,13 @@
const LVM_FLOAT *src,
LVM_FLOAT *dst,
LVM_INT16 n);
+#ifdef SUPPORT_MC
+void LVC_Core_MixInSoft_Mc_D16C31_SAT(LVMixer3_FLOAT_st *ptrInstance,
+ const LVM_FLOAT *src,
+ LVM_FLOAT *dst,
+ LVM_INT16 NrFrames,
+ LVM_INT16 NrChannels);
+#endif
#else
void LVC_Core_MixInSoft_D16C31_SAT( LVMixer3_st *pInstance,
const LVM_INT16 *src,
@@ -73,6 +80,13 @@
const LVM_FLOAT *src,
LVM_FLOAT *dst,
LVM_INT16 n);
+#ifdef SUPPORT_MC
+void LVC_Core_MixSoft_Mc_D16C31_WRA(LVMixer3_FLOAT_st *ptrInstance,
+ const LVM_FLOAT *src,
+ LVM_FLOAT *dst,
+ LVM_INT16 NrFrames,
+ LVM_INT16 NrChannels);
+#endif
#else
void LVC_Core_MixSoft_1St_D16C31_WRA( LVMixer3_st *pInstance,
const LVM_INT16 *src,
diff --git a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.c b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.c
index 9c17a05..6c8b2db 100644
--- a/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.c
+++ b/media/libeffects/lvm/lib/Common/src/PK_2I_D32F32C14G11_TRC_WRA_01.c
@@ -119,6 +119,80 @@
}
}
+
+#ifdef SUPPORT_MC
+/**************************************************************************
+DELAYS-
+pBiquadState->pDelays[0] to
+pBiquadState->pDelays[NrChannels - 1] is x(n-1) for all NrChannels
+
+pBiquadState->pDelays[NrChannels] to
+pBiquadState->pDelays[2*NrChannels - 1] is x(n-2) for all NrChannels
+
+pBiquadState->pDelays[2*NrChannels] to
+pBiquadState->pDelays[3*NrChannels - 1] is y(n-1) for all NrChannels
+
+pBiquadState->pDelays[3*NrChannels] to
+pBiquadState->pDelays[4*NrChannels - 1] is y(n-2) for all NrChannels
+***************************************************************************/
+
+void PK_Mc_D32F32C14G11_TRC_WRA_01 (Biquad_FLOAT_Instance_t *pInstance,
+ LVM_FLOAT *pDataIn,
+ LVM_FLOAT *pDataOut,
+ LVM_INT16 NrFrames,
+ LVM_INT16 NrChannels)
+ {
+ LVM_FLOAT yn, ynO, temp;
+ LVM_INT16 ii, jj;
+ PFilter_State_Float pBiquadState = (PFilter_State_Float) pInstance;
+
+ for (ii = NrFrames; ii != 0; ii--)
+ {
+
+ for (jj = 0; jj < NrChannels; jj++)
+ {
+ /**************************************************************************
+ PROCESSING OF THE jj CHANNEL
+ ***************************************************************************/
+ /* yn= (A0 * (x(n) - x(n-2)))*/
+ temp = (*pDataIn) - pBiquadState->pDelays[NrChannels + jj];
+ yn = temp * pBiquadState->coefs[0];
+
+ /* yn+= ((-B2 * y(n-2))) */
+ temp = pBiquadState->pDelays[NrChannels*3 + jj] * pBiquadState->coefs[1];
+ yn += temp;
+
+ /* yn+= ((-B1 * y(n-1))) */
+ temp = pBiquadState->pDelays[NrChannels*2 + jj] * pBiquadState->coefs[2];
+ yn += temp;
+
+ /* ynO= ((Gain * yn)) */
+ ynO = yn * pBiquadState->coefs[3];
+
+ /* ynO=(ynO + x(n))*/
+ ynO += (*pDataIn);
+
+ /**************************************************************************
+ UPDATING THE DELAYS
+ ***************************************************************************/
+ pBiquadState->pDelays[NrChannels * 3 + jj] =
+ pBiquadState->pDelays[NrChannels * 2 + jj]; /* y(n-2)=y(n-1)*/
+ pBiquadState->pDelays[NrChannels * 1 + jj] =
+ pBiquadState->pDelays[jj]; /* x(n-2)=x(n-1)*/
+ pBiquadState->pDelays[NrChannels * 2 + jj] = yn; /* Update y(n-1) */
+ pBiquadState->pDelays[jj] = (*pDataIn); /* Update x(n-1)*/
+ pDataIn++;
+
+ /**************************************************************************
+ WRITING THE OUTPUT
+ ***************************************************************************/
+ *pDataOut = ynO; /* Write output*/
+ pDataOut++;
+ }
+ }
+
+ }
+#endif
#else
void PK_2I_D32F32C14G11_TRC_WRA_01 ( Biquad_Instance_t *pInstance,
LVM_INT32 *pDataIn,
diff --git a/media/libeffects/lvm/lib/Eq/lib/LVEQNB.h b/media/libeffects/lvm/lib/Eq/lib/LVEQNB.h
index 8e0b738..e7fdbf6 100644
--- a/media/libeffects/lvm/lib/Eq/lib/LVEQNB.h
+++ b/media/libeffects/lvm/lib/Eq/lib/LVEQNB.h
@@ -267,7 +267,9 @@
/* Equaliser parameters */
LVM_UINT16 NBands; /* Number of bands */
LVEQNB_BandDef_t *pBandDefinition; /* Pointer to equaliser definitions */
-
+#ifdef SUPPORT_MC
+ LVM_INT16 NrChannels;
+#endif
} LVEQNB_Params_t;
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h
index 56b02e0..a9cd5fd 100644
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Private.h
@@ -46,7 +46,12 @@
#define LVEQNB_INSTANCE_ALIGN 4 /* 32-bit alignment for instance structures */
#define LVEQNB_DATA_ALIGN 4 /* 32-bit alignment for structures */
#define LVEQNB_COEF_ALIGN 4 /* 32-bit alignment for long words */
+#ifdef SUPPORT_MC
+/* Number of buffers required for inplace processing */
+#define LVEQNB_SCRATCHBUFFERS (LVM_MAX_CHANNELS * 2)
+#else
#define LVEQNB_SCRATCHBUFFERS 4 /* Number of buffers required for inplace processing */
+#endif
#define LVEQNB_SCRATCH_ALIGN 4 /* 32-bit alignment for long data */
#define LVEQNB_BYPASS_MIXER_TC 100 /* Bypass Mixer TC */
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c
index 6328181..d188c0e 100644
--- a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c
+++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Process.c
@@ -26,6 +26,7 @@
#include "VectorArithmetic.h"
#include "BIQUAD.h"
+#include <log/log.h>
/****************************************************************************************/
/* */
@@ -61,14 +62,18 @@
LVEQNB_ReturnStatus_en LVEQNB_Process(LVEQNB_Handle_t hInstance,
const LVM_FLOAT *pInData,
LVM_FLOAT *pOutData,
- LVM_UINT16 NumSamples)
-{
-
- LVM_UINT16 i;
- Biquad_FLOAT_Instance_t *pBiquad;
+ const LVM_UINT16 NrFrames)
+{ // updated to use samples = frames * channels.
LVEQNB_Instance_t *pInstance = (LVEQNB_Instance_t *)hInstance;
- LVM_FLOAT *pScratch;
+#ifdef SUPPORT_MC
+ // Mono passed in as stereo
+ const LVM_INT32 NrChannels = pInstance->Params.NrChannels == 1
+ ? 2 : pInstance->Params.NrChannels;
+#else
+ const LVM_INT32 NrChannels = 2; // FCC_2
+#endif
+ const LVM_INT32 NrSamples = NrChannels * NrFrames;
/* Check for NULL pointers */
if((hInstance == LVM_NULL) || (pInData == LVM_NULL) || (pOutData == LVM_NULL))
@@ -82,14 +87,14 @@
return LVEQNB_ALIGNMENTERROR;
}
- pScratch = (LVM_FLOAT *)pInstance->pFastTemporary;
+ LVM_FLOAT * const pScratch = (LVM_FLOAT *)pInstance->pFastTemporary;
/*
- * Check the number of samples is not too large
+ * Check the number of frames is not too large
*/
- if (NumSamples > pInstance->Capabilities.MaxBlockSize)
+ if (NrFrames > pInstance->Capabilities.MaxBlockSize)
{
- return(LVEQNB_TOOMANYSAMPLES);
+ return LVEQNB_TOOMANYSAMPLES;
}
if (pInstance->Params.OperatingMode == LVEQNB_ON)
@@ -97,16 +102,16 @@
/*
* Copy input data in to scratch buffer
*/
+ Copy_Float(pInData, /* Source */
+ pScratch, /* Destination */
+ (LVM_INT16)NrSamples);
- Copy_Float((LVM_FLOAT *)pInData, /* Source */
- pScratch, /* Destination */
- (LVM_INT16)(2 * NumSamples)); /* Left and Right */
/*
* For each section execte the filter unless the gain is 0dB
*/
if (pInstance->NBands != 0)
{
- for (i = 0; i < pInstance->NBands; i++)
+ for (LVM_UINT16 i = 0; i < pInstance->NBands; i++)
{
/*
* Check if band is non-zero dB gain
@@ -116,7 +121,7 @@
/*
* Get the address of the biquad instance
*/
- pBiquad = &pInstance->pEQNB_FilterState_Float[i];
+ Biquad_FLOAT_Instance_t *pBiquad = &pInstance->pEQNB_FilterState_Float[i];
/*
@@ -126,10 +131,18 @@
{
case LVEQNB_SinglePrecision_Float:
{
+#ifdef SUPPORT_MC
+ PK_Mc_D32F32C14G11_TRC_WRA_01(pBiquad,
+ pScratch,
+ pScratch,
+ (LVM_INT16)NrFrames,
+ (LVM_INT16)NrChannels);
+#else
PK_2I_D32F32C14G11_TRC_WRA_01(pBiquad,
- (LVM_FLOAT *)pScratch,
- (LVM_FLOAT *)pScratch,
- (LVM_INT16)NumSamples);
+ pScratch,
+ pScratch,
+ (LVM_INT16)NrFrames);
+#endif
break;
}
default:
@@ -141,19 +154,29 @@
if(pInstance->bInOperatingModeTransition == LVM_TRUE){
+#ifdef SUPPORT_MC
+ LVC_MixSoft_2Mc_D16C31_SAT(&pInstance->BypassMixer,
+ pScratch,
+ pInData,
+ pScratch,
+ (LVM_INT16)NrFrames,
+ (LVM_INT16)NrChannels);
+#else
LVC_MixSoft_2St_D16C31_SAT(&pInstance->BypassMixer,
- (LVM_FLOAT *)pScratch,
- (LVM_FLOAT *)pInData,
- (LVM_FLOAT *)pScratch,
- (LVM_INT16)(2 * NumSamples));
- Copy_Float((LVM_FLOAT*)pScratch, /* Source */
- pOutData, /* Destination */
- (LVM_INT16)(2 * NumSamples)); /* Left and Right samples */
+ pScratch,
+ pInData,
+ pScratch,
+ (LVM_INT16)NrSamples);
+#endif
+ // duplicate with else clause(s)
+ Copy_Float(pScratch, /* Source */
+ pOutData, /* Destination */
+ (LVM_INT16)NrSamples); /* All channel samples */
}
else{
Copy_Float(pScratch, /* Source */
pOutData, /* Destination */
- (LVM_INT16 )(2 * NumSamples)); /* Left and Right */
+ (LVM_INT16)NrSamples); /* All channel samples */
}
}
else
@@ -163,12 +186,12 @@
*/
if (pInData != pOutData)
{
- Copy_Float(pInData, /* Source */
- pOutData, /* Destination */
- (LVM_INT16)(2 * NumSamples)); /* Left and Right samples */
+ Copy_Float(pInData, /* Source */
+ pOutData, /* Destination */
+ (LVM_INT16)NrSamples); /* All channel samples */
}
}
- return(LVEQNB_SUCCESS);
+ return LVEQNB_SUCCESS;
}
#else
@@ -312,4 +335,4 @@
return(LVEQNB_SUCCESS);
}
-#endif
\ No newline at end of file
+#endif
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.c
index 566d84f..1d1283e 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.c
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_Process.c
@@ -579,7 +579,7 @@
pTemp,
pTemp,
(LVM_INT16)NumSamples);
-
+
/*
* Process all delay lines
*/
diff --git a/media/libeffects/lvm/lib/Reverb/src/LVREV_SetControlParameters.c b/media/libeffects/lvm/lib/Reverb/src/LVREV_SetControlParameters.c
index a719053..8c7807f 100644
--- a/media/libeffects/lvm/lib/Reverb/src/LVREV_SetControlParameters.c
+++ b/media/libeffects/lvm/lib/Reverb/src/LVREV_SetControlParameters.c
@@ -64,12 +64,21 @@
(
(pNewParams->SampleRate != LVM_FS_8000) && (pNewParams->SampleRate != LVM_FS_11025) && (pNewParams->SampleRate != LVM_FS_12000) &&
(pNewParams->SampleRate != LVM_FS_16000) && (pNewParams->SampleRate != LVM_FS_22050) && (pNewParams->SampleRate != LVM_FS_24000) &&
- (pNewParams->SampleRate != LVM_FS_32000) && (pNewParams->SampleRate != LVM_FS_44100) && (pNewParams->SampleRate != LVM_FS_48000)
+ (pNewParams->SampleRate != LVM_FS_32000) &&
+ (pNewParams->SampleRate != LVM_FS_44100) &&
+ (pNewParams->SampleRate != LVM_FS_48000)
#ifdef HIGHER_FS
&& (pNewParams->SampleRate != LVM_FS_96000) && (pNewParams->SampleRate != LVM_FS_192000)
#endif
)
+#ifdef SUPPORT_MC
+ || ((pNewParams->SourceFormat != LVM_STEREO) &&
+ (pNewParams->SourceFormat != LVM_MONOINSTEREO) &&
+ (pNewParams->SourceFormat != LVM_MONO) &&
+ (pNewParams->SourceFormat != LVM_MULTICHANNEL)))
+#else
|| ((pNewParams->SourceFormat != LVM_STEREO) && (pNewParams->SourceFormat != LVM_MONOINSTEREO) && (pNewParams->SourceFormat != LVM_MONO)) )
+#endif
{
return (LVREV_OUTOFRANGE);
}
diff --git a/media/libeffects/lvm/lib/StereoWidening/lib/LVCS.h b/media/libeffects/lvm/lib/StereoWidening/lib/LVCS.h
index e75695e..e507a7c 100644
--- a/media/libeffects/lvm/lib/StereoWidening/lib/LVCS.h
+++ b/media/libeffects/lvm/lib/StereoWidening/lib/LVCS.h
@@ -205,6 +205,9 @@
LVM_Fs_en SampleRate; /* Sampling rate */
LVM_INT16 EffectLevel; /* Effect level */
LVM_UINT16 ReverbLevel; /* Reverb level in % */
+#ifdef SUPPORT_MC
+ LVM_INT32 NrChannels;
+#endif
} LVCS_Params_t;
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h
index a97e4f0..ab8ccd1 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Private.h
@@ -61,6 +61,15 @@
/* Memory */
#define LVCS_SCRATCHBUFFERS 6 /* Number of buffers required for inplace processing */
+#ifdef SUPPORT_MC
+/*
+ * The Concert Surround module applies processing only on the first two
+ * channels of a multichannel input. The data of first two channels is copied
+ * from the multichannel input into scratch buffer. The buffers added here
+ * are used for this purpose
+ */
+#define LVCS_MC_SCRATCHBUFFERS 2
+#endif
/* General */
#define LVCS_INVALID 0xFFFF /* Invalid init parameter */
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Process.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Process.c
index 3956d4d..ef1d9eb 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Process.c
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Process.c
@@ -76,6 +76,22 @@
LVCS_Instance_t *pInstance = (LVCS_Instance_t *)hInstance;
LVM_FLOAT *pScratch;
LVCS_ReturnStatus_en err;
+#ifdef SUPPORT_MC
+ LVM_FLOAT *pStIn;
+ LVM_INT32 channels = pInstance->Params.NrChannels;
+#define NrFrames NumSamples // alias for clarity
+
+ /*In case of mono processing, stereo input is created from mono
+ *and stored in pInData before applying any of the effects.
+ *However we do not update the value pInstance->Params.NrChannels
+ *at this point.
+ *So to treat the pInData as stereo we are setting channels to 2
+ */
+ if (channels == 1)
+ {
+ channels = 2;
+ }
+#endif
pScratch = (LVM_FLOAT *) \
pInstance->MemoryTable.Region[LVCS_MEMREGION_TEMPORARY_FAST].pBaseAddress;
@@ -83,6 +99,25 @@
/*
* Check if the processing is inplace
*/
+#ifdef SUPPORT_MC
+ /*
+ * The pInput buffer holds the first 2 (Left, Right) channels information.
+ * Hence the memory required by this buffer is 2 * NumFrames.
+ * The Concert Surround module carries out processing only on L, R.
+ */
+ pInput = pScratch + (2 * NrFrames);
+ pStIn = pScratch + (LVCS_SCRATCHBUFFERS * NrFrames);
+ /* The first two channel data is extracted from the input data and
+ * copied into pInput buffer
+ */
+ Copy_Float_Mc_Stereo((LVM_FLOAT *)pInData,
+ (LVM_FLOAT *)pInput,
+ NrFrames,
+ channels);
+ Copy_Float((LVM_FLOAT *)pInput,
+ (LVM_FLOAT *)pStIn,
+ (LVM_INT16)(2 * NrFrames));
+#else
if (pInData == pOutData)
{
/* Processing inplace */
@@ -96,14 +131,21 @@
/* Processing outplace */
pInput = pInData;
}
-
+#endif
/*
* Call the stereo enhancer
*/
+#ifdef SUPPORT_MC
+ err = LVCS_StereoEnhancer(hInstance, /* Instance handle */
+ pStIn, /* Pointer to the input data */
+ pOutData, /* Pointer to the output data */
+ NrFrames); /* Number of frames to process */
+#else
err = LVCS_StereoEnhancer(hInstance, /* Instance handle */
pInData, /* Pointer to the input data */
pOutData, /* Pointer to the output data */
NumSamples); /* Number of samples to process */
+#endif
/*
* Call the reverb generator
@@ -112,7 +154,7 @@
pOutData, /* Pointer to the input data */
pOutData, /* Pointer to the output data */
NumSamples); /* Number of samples to process */
-
+
/*
* Call the equaliser
*/
@@ -239,7 +281,15 @@
LVCS_Instance_t *pInstance = (LVCS_Instance_t *)hInstance;
LVCS_ReturnStatus_en err;
-
+#ifdef SUPPORT_MC
+ /*Extract number of Channels info*/
+ LVM_INT32 channels = pInstance->Params.NrChannels;
+#define NrFrames NumSamples // alias for clarity
+ if (channels == 1)
+ {
+ channels = 2;
+ }
+#endif
/*
* Check the number of samples is not too large
*/
@@ -260,8 +310,8 @@
pInData,
pOutData,
NumSamples);
-
-
+
+
/*
* Compress to reduce expansion effect of Concert Sound and correct volume
* differences for difference settings. Not applied in test modes
@@ -376,17 +426,32 @@
(LVM_INT16)NumSamples);
}
}
+#ifdef SUPPORT_MC
+ Copy_Float_Stereo_Mc(pInData,
+ pOutData,
+ NrFrames,
+ channels);
+#endif
}
else
{
if (pInData != pOutData)
{
+#ifdef SUPPORT_MC
+ /*
+ * The algorithm is disabled so just copy the data
+ */
+ Copy_Float((LVM_FLOAT *)pInData, /* Source */
+ (LVM_FLOAT *)pOutData, /* Destination */
+ (LVM_INT16)(channels * NrFrames)); /* All Channels*/
+#else
/*
* The algorithm is disabled so just copy the data
*/
Copy_Float((LVM_FLOAT *)pInData, /* Source */
(LVM_FLOAT *)pOutData, /* Destination */
(LVM_INT16)(2 * NumSamples)); /* Left and right */
+#endif
}
}
diff --git a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.c b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.c
index e154e29..0765764 100644
--- a/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.c
+++ b/media/libeffects/lvm/lib/StereoWidening/src/LVCS_Tables.c
@@ -515,16 +515,16 @@
#if defined(BUILD_FLOAT) && defined(HIGHER_FS)
const LVM_INT16 LVCS_VolumeTCTable[11] = {LVCS_VOL_TC_Fs8000,
- LVCS_VOL_TC_Fs11025,
- LVCS_VOL_TC_Fs12000,
- LVCS_VOL_TC_Fs16000,
- LVCS_VOL_TC_Fs22050,
- LVCS_VOL_TC_Fs24000,
- LVCS_VOL_TC_Fs32000,
- LVCS_VOL_TC_Fs44100,
- LVCS_VOL_TC_Fs48000,
- LVCS_VOL_TC_Fs96000,
- LVCS_VOL_TC_Fs192000
+ LVCS_VOL_TC_Fs11025,
+ LVCS_VOL_TC_Fs12000,
+ LVCS_VOL_TC_Fs16000,
+ LVCS_VOL_TC_Fs22050,
+ LVCS_VOL_TC_Fs24000,
+ LVCS_VOL_TC_Fs32000,
+ LVCS_VOL_TC_Fs44100,
+ LVCS_VOL_TC_Fs48000,
+ LVCS_VOL_TC_Fs96000,
+ LVCS_VOL_TC_Fs192000
};
#else
const LVM_INT16 LVCS_VolumeTCTable[9] = {LVCS_VOL_TC_Fs8000,
@@ -546,16 +546,16 @@
/************************************************************************************/
#if defined(BUILD_FLOAT) && defined(HIGHER_FS)
const LVM_INT32 LVCS_SampleRateTable[11] = {8000,
- 11025,
- 12000,
- 16000,
- 22050,
- 24000,
- 32000,
- 44100,
- 48000,
- 96000,
- 192000
+ 11025,
+ 12000,
+ 16000,
+ 22050,
+ 24000,
+ 32000,
+ 44100,
+ 48000,
+ 96000,
+ 192000
};
#else
const LVM_INT16 LVCS_SampleRateTable[9] = {8000,