diff options
Diffstat (limited to 'media/libeffects/lvm/lib/Bundle/src/LVM_Buffers.c')
-rwxr-xr-x | media/libeffects/lvm/lib/Bundle/src/LVM_Buffers.c | 878 |
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); + } +} + |