summaryrefslogtreecommitdiffstats
path: root/media/libeffects/lvm/lib/Bundle/src/LVM_Buffers.c
diff options
context:
space:
mode:
Diffstat (limited to 'media/libeffects/lvm/lib/Bundle/src/LVM_Buffers.c')
-rwxr-xr-xmedia/libeffects/lvm/lib/Bundle/src/LVM_Buffers.c878
1 files changed, 878 insertions, 0 deletions
diff --git a/media/libeffects/lvm/lib/Bundle/src/LVM_Buffers.c b/media/libeffects/lvm/lib/Bundle/src/LVM_Buffers.c
new file mode 100755
index 0000000..41785a3
--- /dev/null
+++ b/media/libeffects/lvm/lib/Bundle/src/LVM_Buffers.c
@@ -0,0 +1,878 @@
+/*
+ * 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.
+ */
+
+
+/****************************************************************************************
+
+ $Author: nxp007753 $
+ $Revision: 1082 $
+ $Date: 2010-07-05 12:44:39 +0200 (Mon, 05 Jul 2010) $
+
+*****************************************************************************************/
+
+/****************************************************************************************/
+/* */
+/* Includes */
+/* */
+/****************************************************************************************/
+
+#include "LVM_Private.h"
+#include "VectorArithmetic.h"
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_BufferManagedIn */
+/* */
+/* DESCRIPTION: */
+/* Full buffer management allowing the user to provide input and output buffers on */
+/* any alignment and with any number of samples. The alignment is corrected within */
+/* the buffer management and the samples are grouped in to blocks of the correct size */
+/* before processing. */
+/* */
+/* PARAMETERS: */
+/* hInstance - Instance handle */
+/* pInData - Pointer to the input data stream */
+/* *pToProcess - Pointer to pointer to the start of data processing */
+/* *pProcessed - Pointer to pointer to the destination of the processed data */
+/* pNumSamples - Pointer to the number of samples to process */
+/* */
+/* RETURNS: */
+/* None */
+/* */
+/* NOTES: */
+/* */
+/****************************************************************************************/
+
+void LVM_BufferManagedIn(LVM_Handle_t hInstance,
+ const LVM_INT16 *pInData,
+ LVM_INT16 **pToProcess,
+ LVM_INT16 **pProcessed,
+ LVM_UINT16 *pNumSamples)
+{
+
+ LVM_INT16 SampleCount; /* Number of samples to be processed this call */
+ LVM_INT16 NumSamples; /* Number of samples in scratch buffer */
+ LVM_INT16 *pStart;
+ LVM_Instance_t *pInstance = (LVM_Instance_t *)hInstance;
+ LVM_Buffer_t *pBuffer;
+ LVM_INT16 *pDest;
+ LVM_INT16 NumChannels =2;
+
+
+ /*
+ * Set the processing address pointers
+ */
+ pBuffer = pInstance->pBufferManagement;
+ pDest = pBuffer->pScratch;
+ *pToProcess = pBuffer->pScratch;
+ *pProcessed = pBuffer->pScratch;
+
+ /*
+ * Check if it is the first call of a block
+ */
+ if (pInstance->SamplesToProcess == 0)
+ {
+ /*
+ * First call for a new block of samples
+ */
+ pInstance->SamplesToProcess = (LVM_INT16)(*pNumSamples + pBuffer->InDelaySamples);
+ pInstance->pInputSamples = (LVM_INT16 *)pInData;
+ pBuffer->BufferState = LVM_FIRSTCALL;
+ }
+ pStart = pInstance->pInputSamples; /* Pointer to the input samples */
+ pBuffer->SamplesToOutput = 0; /* Samples to output is same as number read for inplace processing */
+
+
+ /*
+ * Calculate the number of samples to process this call and update the buffer state
+ */
+ if (pInstance->SamplesToProcess > pInstance->InternalBlockSize)
+ {
+ /*
+ * Process the maximum bock size of samples.
+ */
+ SampleCount = pInstance->InternalBlockSize;
+ NumSamples = pInstance->InternalBlockSize;
+ }
+ else
+ {
+ /*
+ * Last call for the block, so calculate how many frames and samples to process
+ */
+ LVM_INT16 NumFrames;
+
+ NumSamples = pInstance->SamplesToProcess;
+ NumFrames = (LVM_INT16)(NumSamples >> MIN_INTERNAL_BLOCKSHIFT);
+ SampleCount = (LVM_INT16)(NumFrames << MIN_INTERNAL_BLOCKSHIFT);
+
+ /*
+ * Update the buffer state
+ */
+ if (pBuffer->BufferState == LVM_FIRSTCALL)
+ {
+ pBuffer->BufferState = LVM_FIRSTLASTCALL;
+ }
+ else
+ {
+ pBuffer->BufferState = LVM_LASTCALL;
+ }
+ }
+ *pNumSamples = (LVM_UINT16)SampleCount; /* Set the number of samples to process this call */
+
+
+ /*
+ * Copy samples from the delay buffer as required
+ */
+ if (((pBuffer->BufferState == LVM_FIRSTCALL) ||
+ (pBuffer->BufferState == LVM_FIRSTLASTCALL)) &&
+ (pBuffer->InDelaySamples != 0))
+ {
+ Copy_16(&pBuffer->InDelayBuffer[0], /* Source */
+ pDest, /* Destination */
+ (LVM_INT16)(NumChannels*pBuffer->InDelaySamples)); /* Number of delay samples, left and right */
+ NumSamples = (LVM_INT16)(NumSamples - pBuffer->InDelaySamples); /* Update sample count */
+ pDest += NumChannels * pBuffer->InDelaySamples; /* Update the destination pointer */
+ }
+
+
+ /*
+ * Copy the rest of the samples for this call from the input buffer
+ */
+ if (NumSamples > 0)
+ {
+ Copy_16(pStart, /* Source */
+ pDest, /* Destination */
+ (LVM_INT16)(NumChannels*NumSamples)); /* Number of input samples */
+ pStart += NumChannels * NumSamples; /* Update the input pointer */
+
+ /*
+ * Update the input data pointer and samples to output
+ */
+ pBuffer->SamplesToOutput = (LVM_INT16)(pBuffer->SamplesToOutput + NumSamples); /* Update samples to output */
+ }
+
+
+ /*
+ * Update the sample count and input pointer
+ */
+ pInstance->SamplesToProcess = (LVM_INT16)(pInstance->SamplesToProcess - SampleCount); /* Update the count of samples */
+ pInstance->pInputSamples = pStart; /* Update input sample pointer */
+
+
+ /*
+ * Save samples to the delay buffer if any left unprocessed
+ */
+ if ((pBuffer->BufferState == LVM_FIRSTLASTCALL) ||
+ (pBuffer->BufferState == LVM_LASTCALL))
+ {
+ NumSamples = pInstance->SamplesToProcess;
+ pStart = pBuffer->pScratch; /* Start of the buffer */
+ pStart += NumChannels*SampleCount; /* Offset by the number of processed samples */
+ if (NumSamples != 0)
+ {
+ Copy_16(pStart, /* Source */
+ &pBuffer->InDelayBuffer[0], /* Destination */
+ (LVM_INT16)(NumChannels*NumSamples)); /* Number of input samples */
+ }
+
+
+ /*
+ * Update the delay sample count
+ */
+ pBuffer->InDelaySamples = NumSamples; /* Number of delay sample pairs */
+ pInstance->SamplesToProcess = 0; /* All Samples used */
+ }
+}
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_BufferUnmanagedIn */
+/* */
+/* DESCRIPTION: */
+/* This mode is selected by the user code and disables the buffer management with the */
+/* exception of the maximum block size processing. The user must ensure that the */
+/* input and output buffers are 32-bit aligned and also that the number of samples to */
+/* process is a correct multiple of samples. */
+/* */
+/* PARAMETERS: */
+/* hInstance - Instance handle */
+/* *pToProcess - Pointer to the start of data processing */
+/* *pProcessed - Pointer to the destination of the processed data */
+/* pNumSamples - Pointer to the number of samples to process */
+/* */
+/* RETURNS: */
+/* None */
+/* */
+/* NOTES: */
+/* */
+/****************************************************************************************/
+
+void LVM_BufferUnmanagedIn(LVM_Handle_t hInstance,
+ LVM_INT16 **pToProcess,
+ LVM_INT16 **pProcessed,
+ LVM_UINT16 *pNumSamples)
+{
+
+ LVM_Instance_t *pInstance = (LVM_Instance_t *)hInstance;
+
+
+ /*
+ * Check if this is the first call of a block
+ */
+ if (pInstance->SamplesToProcess == 0)
+ {
+ pInstance->SamplesToProcess = (LVM_INT16)*pNumSamples; /* Get the number of samples on first call */
+ pInstance->pInputSamples = *pToProcess; /* Get the I/O pointers */
+ pInstance->pOutputSamples = *pProcessed;
+
+
+ /*
+ * Set te block size to process
+ */
+ if (pInstance->SamplesToProcess > pInstance->InternalBlockSize)
+ {
+ *pNumSamples = (LVM_UINT16)pInstance->InternalBlockSize;
+ }
+ else
+ {
+ *pNumSamples = (LVM_UINT16)pInstance->SamplesToProcess;
+ }
+ }
+
+ /*
+ * Set the process pointers
+ */
+ *pToProcess = pInstance->pInputSamples;
+ *pProcessed = pInstance->pOutputSamples;
+}
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_BufferOptimisedIn */
+/* */
+/* DESCRIPTION: */
+/* Optimised buffer management for the case where the data is outplace processing, */
+/* the output data is 32-bit aligned and there are sufficient samples to allow some */
+/* processing directly in the output buffer. This saves one data copy per sample */
+/* compared with the unoptimsed version. */
+/* */
+/* PARAMETERS: */
+/* hInstance - Instance handle */
+/* pInData - Pointer to the input data stream */
+/* *pToProcess - Pointer to the start of data processing */
+/* *pProcessed - Pointer to the destination of the processed data */
+/* pNumSamples - Pointer to the number of samples to process */
+/* */
+/* RETURNS: */
+/* None */
+/* */
+/* NOTES: */
+/* */
+/****************************************************************************************/
+
+void LVM_BufferOptimisedIn(LVM_Handle_t hInstance,
+ const LVM_INT16 *pInData,
+ LVM_INT16 **pToProcess,
+ LVM_INT16 **pProcessed,
+ LVM_UINT16 *pNumSamples)
+{
+
+ LVM_Instance_t *pInstance = (LVM_Instance_t *)hInstance;
+ LVM_Buffer_t *pBuffer = pInstance->pBufferManagement;
+ LVM_INT16 *pDest;
+ LVM_INT16 SampleCount;
+ LVM_INT16 NumSamples;
+ LVM_INT16 NumFrames;
+
+ /*
+ * Check if it is the first call for this block
+ */
+ if (pInstance->SamplesToProcess == 0)
+ {
+ /*
+ * First call for a new block of samples
+ */
+ pBuffer->BufferState = LVM_FIRSTCALL;
+ pInstance->pInputSamples = (LVM_INT16 *)pInData;
+ pInstance->SamplesToProcess = (LVM_INT16)*pNumSamples;
+ pBuffer->SamplesToOutput = (LVM_INT16)*pNumSamples;
+ pDest = *pProcessed; /* The start of the output buffer */
+
+
+ /*
+ * Copy the already processed samples to the output buffer
+ */
+ if (pBuffer->OutDelaySamples != 0)
+ {
+ Copy_16(&pBuffer->OutDelayBuffer[0], /* Source */
+ pDest, /* Detsination */
+ (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 */
+ }
+ *pToProcess = pDest; /* Set the address to start processing */
+ *pProcessed = pDest; /* Process in the output buffer, now inplace */
+
+ /*
+ * Copy the input delay buffer (unprocessed) samples to the output buffer
+ */
+ if (pBuffer->InDelaySamples != 0)
+ {
+ Copy_16(&pBuffer->InDelayBuffer[0], /* Source */
+ pDest, /* Destination */
+ (LVM_INT16)(2*pBuffer->InDelaySamples)); /* Number of delay samples */
+ pDest += 2 * pBuffer->InDelaySamples; /* Update the output pointer */
+ }
+
+
+ /*
+ * Calculate how many input samples to process and copy
+ */
+ NumSamples = (LVM_INT16)(*pNumSamples - pBuffer->OutDelaySamples); /* Number that will fit in the output buffer */
+ if (NumSamples >= pInstance->InternalBlockSize)
+ {
+ NumSamples = pInstance->InternalBlockSize;
+ }
+ NumFrames = (LVM_INT16)(NumSamples >> MIN_INTERNAL_BLOCKSHIFT);
+ SampleCount = (LVM_INT16)(NumFrames << MIN_INTERNAL_BLOCKSHIFT);
+ *pNumSamples = (LVM_UINT16)SampleCount; /* The number of samples to process */
+ pBuffer->SamplesToOutput = (LVM_INT16)(pBuffer->SamplesToOutput - SampleCount); /* Update the number of samples to output */
+ SampleCount = (LVM_INT16)(SampleCount - pBuffer->InDelaySamples); /* The number of samples to copy from the input */
+
+
+ /*
+ * Copy samples from the input buffer and update counts and pointers
+ */
+ Copy_16(pInstance->pInputSamples, /* Source */
+ pDest, /* Destination */
+ (LVM_INT16)(2*SampleCount)); /* Number of input samples */
+ pInstance->pInputSamples += 2 * SampleCount; /* Update the input pointer */
+ pInstance->pOutputSamples = pDest + (2 * SampleCount); /* Update the output pointer */
+ pInstance->SamplesToProcess = (LVM_INT16)(pInstance->SamplesToProcess - SampleCount); /* Samples left in the input buffer */
+ }
+ else
+ {
+ /*
+ * Second or subsequent call in optimised mode
+ */
+ if (pBuffer->SamplesToOutput >= MIN_INTERNAL_BLOCKSIZE)
+ {
+ /*
+ * More samples can be processed directly in the output buffer
+ */
+ *pToProcess = pInstance->pOutputSamples; /* Set the address to start processing */
+ *pProcessed = pInstance->pOutputSamples; /* Process in the output buffer, now inplace */
+ NumSamples = pBuffer->SamplesToOutput; /* Number that will fit in the output buffer */
+ if (NumSamples >= pInstance->InternalBlockSize)
+ {
+ NumSamples = pInstance->InternalBlockSize;
+ }
+ NumFrames = (LVM_INT16)(NumSamples >> MIN_INTERNAL_BLOCKSHIFT);
+ SampleCount = (LVM_INT16)(NumFrames << MIN_INTERNAL_BLOCKSHIFT);
+ *pNumSamples = (LVM_UINT16)SampleCount; /* The number of samples to process */
+
+
+ /*
+ * Copy samples from the input buffer and update counts and pointers
+ */
+ Copy_16(pInstance->pInputSamples, /* Source */
+ pInstance->pOutputSamples, /* Destination */
+ (LVM_INT16)(2*SampleCount)); /* Number of input samples */
+ pInstance->pInputSamples += 2 * SampleCount; /* Update the input pointer */
+ pInstance->pOutputSamples += 2 * SampleCount; /* Update the output pointer */
+ pInstance->SamplesToProcess = (LVM_INT16)(pInstance->SamplesToProcess - SampleCount); /* Samples left in the input buffer */
+ pBuffer->SamplesToOutput = (LVM_INT16)(pBuffer->SamplesToOutput - SampleCount); /* Number that will fit in the output buffer */
+ }
+ else
+ {
+ /*
+ * The remaining samples can not be processed in the output buffer
+ */
+ pBuffer->BufferState = LVM_LASTCALL; /* Indicate this is the last bock to process */
+ *pToProcess = pBuffer->pScratch; /* Set the address to start processing */
+ *pProcessed = pBuffer->pScratch; /* Process in the output buffer, now inplace */
+ NumSamples = pInstance->SamplesToProcess; /* Number left to be processed */
+ NumFrames = (LVM_INT16)(NumSamples >> MIN_INTERNAL_BLOCKSHIFT);
+ SampleCount = (LVM_INT16)(NumFrames << MIN_INTERNAL_BLOCKSHIFT);
+ *pNumSamples = (LVM_UINT16)SampleCount; /* The number of samples to process */
+
+
+ /*
+ * Copy samples from the input buffer and update counts and pointers
+ */
+ Copy_16(pInstance->pInputSamples, /* Source */
+ pBuffer->pScratch, /* Destination */
+ (LVM_INT16)(2*SampleCount)); /* Number of input samples */
+ pInstance->pInputSamples += 2 * SampleCount; /* Update the input pointer */
+ pInstance->SamplesToProcess = (LVM_INT16)(pInstance->SamplesToProcess - SampleCount); /* Samples left in the input buffer */
+ }
+ }
+}
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_BufferIn */
+/* */
+/* DESCRIPTION: */
+/* This function manages the data input, it has the following features: */
+/* - Accepts data in 16-bit aligned memory */
+/* - Copies the data to 32-bit aligned memory */
+/* - Converts Mono inputs to Mono-in-Stereo */
+/* - Accepts any number of samples as input, except 0 */
+/* - Breaks the input sample stream in to blocks of the configured frame size or */
+/* multiples of the frame size */
+/* - Limits the processing block size to the maximum block size. */
+/* - Works with inplace or outplace processing automatically */
+/* */
+/* To manage the data the function has a number of operating states: */
+/* LVM_FIRSTCALL - The first call for this block of input samples */
+/* LVM_MAXBLOCKCALL - The current block is the maximum size. Only used for the */
+/* second and subsequent blocks. */
+/* LVM_LASTCALL - The last call for this block of input samples */
+/* LVM_FIRSTLASTCALL - This is the first and last call for this block of input*/
+/* samples, this occurs when the number of samples to */
+/* process is less than the maximum block size. */
+/* */
+/* The function uses an internal delay buffer the size of the minimum frame, this is */
+/* used to temporarily hold samples when the number of samples to process is not a */
+/* multiple of the frame size. */
+/* */
+/* To ensure correct operation with inplace buffering the number of samples to output*/
+/* per call is calculated in this function and is set to the number of samples read */
+/* from the input buffer. */
+/* */
+/* The total number of samples to process is stored when the function is called for */
+/* the first time. The value is overwritten by the size of the block to be processed */
+/* in each call so the size of the processing blocks can be controlled. The number of */
+/* samples actually processed for each block of input samples is always a multiple of*/
+/* the frame size so for any particular block of input samples the actual number of */
+/* processed samples may not match the number of input samples, sometime it will be */
+/* sometimes less. The average is the same and the difference is never more than the */
+/* frame size. */
+/* */
+/* PARAMETERS: */
+/* hInstance - Instance handle */
+/* pInData - Pointer to the input data stream */
+/* *pToProcess - Pointer to the start of data processing */
+/* *pProcessed - Pointer to the destination of the processed data */
+/* pNumSamples - Pointer to the number of samples to process */
+/* */
+/* RETURNS: */
+/* None */
+/* */
+/* NOTES: */
+/* */
+/****************************************************************************************/
+
+void LVM_BufferIn(LVM_Handle_t hInstance,
+ const LVM_INT16 *pInData,
+ LVM_INT16 **pToProcess,
+ LVM_INT16 **pProcessed,
+ LVM_UINT16 *pNumSamples)
+{
+
+ LVM_Instance_t *pInstance = (LVM_Instance_t *)hInstance;
+
+
+ /*
+ * Check which mode, managed or unmanaged
+ */
+ if (pInstance->InstParams.BufferMode == LVM_MANAGED_BUFFERS)
+ {
+ LVM_BufferManagedIn(hInstance,
+ pInData,
+ pToProcess,
+ pProcessed,
+ pNumSamples);
+ }
+ else
+ {
+ LVM_BufferUnmanagedIn(hInstance,
+ pToProcess,
+ pProcessed,
+ pNumSamples);
+ }
+}
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_BufferManagedOut */
+/* */
+/* DESCRIPTION: */
+/* Full buffer management output. This works in conjunction with the managed input */
+/* routine and ensures the correct number of samples are always output to the output */
+/* buffer. */
+/* */
+/* PARAMETERS: */
+/* hInstance - Instance handle */
+/* pOutData - Pointer to the output data stream */
+/* pNumSamples - Pointer to the number of samples to process */
+/* */
+/* RETURNS: */
+/* None */
+/* */
+/* NOTES: */
+/* */
+/****************************************************************************************/
+
+void LVM_BufferManagedOut(LVM_Handle_t hInstance,
+ LVM_INT16 *pOutData,
+ LVM_UINT16 *pNumSamples)
+{
+
+ LVM_Instance_t *pInstance = (LVM_Instance_t *)hInstance;
+ LVM_Buffer_t *pBuffer = pInstance->pBufferManagement;
+ LVM_INT16 SampleCount = (LVM_INT16)*pNumSamples;
+ LVM_INT16 NumSamples;
+ LVM_INT16 *pStart;
+ LVM_INT16 *pDest;
+
+
+ /*
+ * Set the pointers
+ */
+ NumSamples = pBuffer->SamplesToOutput;
+ pStart = pBuffer->pScratch;
+
+
+ /*
+ * check if it is the first call of a block
+ */
+ if ((pBuffer->BufferState == LVM_FIRSTCALL) ||
+ (pBuffer->BufferState == LVM_FIRSTLASTCALL))
+ {
+ /* First call for a new block */
+ pInstance->pOutputSamples = pOutData; /* Initialise the destination */
+ }
+ pDest = pInstance->pOutputSamples; /* Set the output address */
+
+
+ /*
+ * If the number of samples is non-zero then there are still samples to send to
+ * the output buffer
+ */
+ if ((NumSamples != 0) &&
+ (pBuffer->OutDelaySamples != 0))
+ {
+ /*
+ * Copy the delayed output buffer samples to the output
+ */
+ if (pBuffer->OutDelaySamples <= NumSamples)
+ {
+ /*
+ * Copy all output delay samples to the output
+ */
+ Copy_16(&pBuffer->OutDelayBuffer[0], /* Source */
+ pDest, /* Detsination */
+ (LVM_INT16)(2*pBuffer->OutDelaySamples)); /* Number of delay samples */
+
+ /*
+ * Update the pointer and sample counts
+ */
+ pDest += 2*pBuffer->OutDelaySamples; /* Output sample pointer */
+ NumSamples = (LVM_INT16)(NumSamples - pBuffer->OutDelaySamples); /* Samples left to send */
+ pBuffer->OutDelaySamples = 0; /* No samples left in the buffer */
+
+ }
+ else
+ {
+ /*
+ * Copy only some of the ouput delay samples to the output
+ */
+ Copy_16(&pBuffer->OutDelayBuffer[0], /* Source */
+ pDest, /* Detsination */
+ (LVM_INT16)(2*NumSamples)); /* Number of delay samples */
+
+ /*
+ * Update the pointer and sample counts
+ */
+ pDest += 2*NumSamples; /* Output sample pointer */
+ pBuffer->OutDelaySamples = (LVM_INT16)(pBuffer->OutDelaySamples - NumSamples); /* No samples left in the buffer */
+
+
+ /*
+ * Realign the delay buffer data to avoid using circular buffer management
+ */
+ Copy_16(&pBuffer->OutDelayBuffer[2*NumSamples], /* Source */
+ &pBuffer->OutDelayBuffer[0], /* Destination */
+ (LVM_INT16)(2*pBuffer->OutDelaySamples)); /* Number of samples to move */
+ NumSamples = 0; /* Samples left to send */
+ }
+ }
+
+
+ /*
+ * Copy the processed results to the output
+ */
+ if ((NumSamples != 0) &&
+ (SampleCount != 0))
+ {
+ if (SampleCount <= NumSamples)
+ {
+ /*
+ * Copy all processed samples to the output
+ */
+ Copy_16(pStart, /* Source */
+ pDest, /* Detsination */
+ (LVM_INT16)(2*SampleCount)); /* Number of processed samples */
+
+ /*
+ * Update the pointer and sample counts
+ */
+ pDest += 2 * SampleCount; /* Output sample pointer */
+ NumSamples = (LVM_INT16)(NumSamples - SampleCount); /* Samples left to send */
+ SampleCount = 0; /* No samples left in the buffer */
+ }
+ else
+ {
+ /*
+ * Copy only some processed samples to the output
+ */
+ Copy_16(pStart, /* Source */
+ pDest, /* Destination */
+ (LVM_INT16)(2*NumSamples)); /* Number of processed samples */
+
+
+ /*
+ * Update the pointers and sample counts
+ */
+ pStart += 2 * NumSamples; /* Processed sample pointer */
+ pDest += 2 * NumSamples; /* Output sample pointer */
+ SampleCount = (LVM_INT16)(SampleCount - NumSamples); /* Processed samples left */
+ NumSamples = 0; /* Clear the sample count */
+ }
+ }
+
+
+ /*
+ * Copy the remaining processed data to the output delay buffer
+ */
+ if (SampleCount != 0)
+ {
+ Copy_16(pStart, /* Source */
+ &pBuffer->OutDelayBuffer[2*pBuffer->OutDelaySamples], /* Destination */
+ (LVM_INT16)(2*SampleCount)); /* Number of processed samples */
+ pBuffer->OutDelaySamples = (LVM_INT16)(pBuffer->OutDelaySamples + SampleCount); /* Update the buffer count */
+ }
+
+
+ /*
+ * pointers, counts and set default buffer processing
+ */
+ pBuffer->SamplesToOutput = NumSamples; /* Samples left to send */
+ pInstance->pOutputSamples = pDest; /* Output sample pointer */
+ pBuffer->BufferState = LVM_MAXBLOCKCALL; /* Set for the default call block size */
+ *pNumSamples = (LVM_UINT16)pInstance->SamplesToProcess; /* This will terminate the loop when all samples processed */
+}
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_BufferUnmanagedOut */
+/* */
+/* DESCRIPTION: */
+/* This works in conjunction with the unmanaged input routine and updates the number */
+/* of samples left to be processed and adjusts the buffer pointers. */
+/* */
+/* PARAMETERS: */
+/* hInstance - Instance handle */
+/* pNumSamples - Pointer to the number of samples to process */
+/* */
+/* RETURNS: */
+/* None */
+/* */
+/* NOTES: */
+/* */
+/****************************************************************************************/
+
+void LVM_BufferUnmanagedOut(LVM_Handle_t hInstance,
+ LVM_UINT16 *pNumSamples)
+{
+
+ LVM_Instance_t *pInstance = (LVM_Instance_t *)hInstance;
+ LVM_INT16 NumChannels =2;
+
+
+ /*
+ * Update sample counts
+ */
+ pInstance->pInputSamples += (LVM_INT16)(*pNumSamples * NumChannels); /* Update the I/O pointers */
+ pInstance->pOutputSamples += (LVM_INT16)(*pNumSamples * 2);
+ pInstance->SamplesToProcess = (LVM_INT16)(pInstance->SamplesToProcess - *pNumSamples); /* Update the sample count */
+
+ /*
+ * Set te block size to process
+ */
+ if (pInstance->SamplesToProcess > pInstance->InternalBlockSize)
+ {
+ *pNumSamples = (LVM_UINT16)pInstance->InternalBlockSize;
+ }
+ else
+ {
+ *pNumSamples = (LVM_UINT16)pInstance->SamplesToProcess;
+ }
+}
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_BufferOptimisedOut */
+/* */
+/* DESCRIPTION: */
+/* This works in conjunction with the optimised input routine and copies the last few */
+/* processed and unprocessed samples to their respective buffers. */
+/* */
+/* PARAMETERS: */
+/* hInstance - Instance handle */
+/* pNumSamples - Pointer to the number of samples to process */
+/* */
+/* RETURNS: */
+/* None */
+/* */
+/* NOTES: */
+/* */
+/****************************************************************************************/
+
+void LVM_BufferOptimisedOut(LVM_Handle_t hInstance,
+ LVM_UINT16 *pNumSamples)
+{
+
+ LVM_Instance_t *pInstance = (LVM_Instance_t *)hInstance;
+ LVM_Buffer_t *pBuffer = pInstance->pBufferManagement;
+
+ /*
+ * Check if it is the last block to process
+ */
+ if (pBuffer->BufferState == LVM_LASTCALL)
+ {
+ LVM_INT16 *pSrc = pBuffer->pScratch;
+
+ /*
+ * Copy the unprocessed samples to the input delay buffer
+ */
+ if (pInstance->SamplesToProcess != 0)
+ {
+ Copy_16(pInstance->pInputSamples, /* Source */
+ &pBuffer->InDelayBuffer[0], /* Destination */
+ (LVM_INT16)(2*pInstance->SamplesToProcess)); /* Number of input samples */
+ pBuffer->InDelaySamples = pInstance->SamplesToProcess;
+ pInstance->SamplesToProcess = 0;
+ }
+ else
+ {
+ pBuffer->InDelaySamples = 0;
+ }
+
+
+ /*
+ * Fill the last empty spaces in the output buffer
+ */
+ if (pBuffer->SamplesToOutput != 0)
+ {
+ Copy_16(pSrc, /* Source */
+ pInstance->pOutputSamples, /* Destination */
+ (LVM_INT16)(2*pBuffer->SamplesToOutput)); /* Number of input samples */
+ *pNumSamples = (LVM_UINT16)(*pNumSamples - pBuffer->SamplesToOutput);
+ pSrc += 2 * pBuffer->SamplesToOutput; /* Update scratch pointer */
+ pBuffer->SamplesToOutput = 0; /* No more samples in this block */
+ }
+
+
+ /*
+ * Save any remaining processed samples in the output delay buffer
+ */
+ if (*pNumSamples != 0)
+ {
+ Copy_16(pSrc, /* Source */
+ &pBuffer->OutDelayBuffer[0], /* Destination */
+ (LVM_INT16)(2**pNumSamples)); /* Number of input samples */
+
+ pBuffer->OutDelaySamples = (LVM_INT16)*pNumSamples;
+
+ *pNumSamples = 0; /* No more samples in this block */
+ }
+ else
+ {
+ pBuffer->OutDelaySamples = 0;
+ }
+ }
+}
+
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVM_BufferOut */
+/* */
+/* DESCRIPTION: */
+/* This function manages the data output, it has the following features: */
+/* - Output data to 16-bit aligned memory */
+/* - Reads data from 32-bit aligned memory */
+/* - Reads data only in blocks of frame size or multiples of frame size */
+/* - Writes the same number of samples as the LVM_BufferIn function reads */
+/* - Works with inplace or outplace processing automatically */
+/* */
+/* To manage the data the function has a number of operating states: */
+/* LVM_FIRSTCALL - The first call for this block of input samples */
+/* LVM_FIRSTLASTCALL - This is the first and last call for this block of input*/
+/* samples, this occurs when the number of samples to */
+/* process is less than the maximum block size. */
+/* */
+/* The function uses an internal delay buffer the size of the minimum frame, this is */
+/* used to temporarily hold samples when the number of samples to write is not a */
+/* multiple of the frame size. */
+/* */
+/* To ensure correct operation with inplace buffering the number of samples to output*/
+/* per call is always the same as the number of samples read from the input buffer. */
+/* */
+/* PARAMETERS: */
+/* hInstance - Instance handle */
+/* pOutData - Pointer to the output data stream */
+/* pNumSamples - Pointer to the number of samples to process */
+/* */
+/* RETURNS: */
+/* None */
+/* */
+/* NOTES: */
+/* */
+/****************************************************************************************/
+
+void LVM_BufferOut(LVM_Handle_t hInstance,
+ LVM_INT16 *pOutData,
+ LVM_UINT16 *pNumSamples)
+{
+
+ LVM_Instance_t *pInstance = (LVM_Instance_t *)hInstance;
+
+
+ /*
+ * Check which mode, managed or unmanaged
+ */
+ if (pInstance->InstParams.BufferMode == LVM_MANAGED_BUFFERS)
+ {
+ LVM_BufferManagedOut(hInstance,
+ pOutData,
+ pNumSamples);
+ }
+ else
+ {
+ LVM_BufferUnmanagedOut(hInstance,
+ pNumSamples);
+ }
+}
+