2 * Copyright (C) 2004-2010 NXP Software
3 * Copyright (C) 2010 The Android Open Source Project
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
19 /****************************************************************************************/
23 /****************************************************************************************/
25 #include "LVM_Private.h"
26 #include "VectorArithmetic.h"
28 /****************************************************************************************/
30 /* FUNCTION: LVM_BufferManagedIn */
33 /* Full buffer management allowing the user to provide input and output buffers on */
34 /* any alignment and with any number of samples. The alignment is corrected within */
35 /* the buffer management and the samples are grouped in to blocks of the correct size */
36 /* before processing. */
39 /* hInstance - Instance handle */
40 /* pInData - Pointer to the input data stream */
41 /* *pToProcess - Pointer to pointer to the start of data processing */
42 /* *pProcessed - Pointer to pointer to the destination of the processed data */
43 /* pNumSamples - Pointer to the number of samples to process */
50 /****************************************************************************************/
52 void LVM_BufferManagedIn(LVM_Handle_t hInstance,
53 const LVM_INT16 *pInData,
54 LVM_INT16 **pToProcess,
55 LVM_INT16 **pProcessed,
56 LVM_UINT16 *pNumSamples)
59 LVM_INT16 SampleCount; /* Number of samples to be processed this call */
60 LVM_INT16 NumSamples; /* Number of samples in scratch buffer */
62 LVM_Instance_t *pInstance = (LVM_Instance_t *)hInstance;
63 LVM_Buffer_t *pBuffer;
65 LVM_INT16 NumChannels =2;
69 * Set the processing address pointers
71 pBuffer = pInstance->pBufferManagement;
72 pDest = pBuffer->pScratch;
73 *pToProcess = pBuffer->pScratch;
74 *pProcessed = pBuffer->pScratch;
77 * Check if it is the first call of a block
79 if (pInstance->SamplesToProcess == 0)
82 * First call for a new block of samples
84 pInstance->SamplesToProcess = (LVM_INT16)(*pNumSamples + pBuffer->InDelaySamples);
85 pInstance->pInputSamples = (LVM_INT16 *)pInData;
86 pBuffer->BufferState = LVM_FIRSTCALL;
88 pStart = pInstance->pInputSamples; /* Pointer to the input samples */
89 pBuffer->SamplesToOutput = 0; /* Samples to output is same as number read for inplace processing */
93 * Calculate the number of samples to process this call and update the buffer state
95 if (pInstance->SamplesToProcess > pInstance->InternalBlockSize)
98 * Process the maximum bock size of samples.
100 SampleCount = pInstance->InternalBlockSize;
101 NumSamples = pInstance->InternalBlockSize;
106 * Last call for the block, so calculate how many frames and samples to process
110 NumSamples = pInstance->SamplesToProcess;
111 NumFrames = (LVM_INT16)(NumSamples >> MIN_INTERNAL_BLOCKSHIFT);
112 SampleCount = (LVM_INT16)(NumFrames << MIN_INTERNAL_BLOCKSHIFT);
115 * Update the buffer state
117 if (pBuffer->BufferState == LVM_FIRSTCALL)
119 pBuffer->BufferState = LVM_FIRSTLASTCALL;
123 pBuffer->BufferState = LVM_LASTCALL;
126 *pNumSamples = (LVM_UINT16)SampleCount; /* Set the number of samples to process this call */
130 * Copy samples from the delay buffer as required
132 if (((pBuffer->BufferState == LVM_FIRSTCALL) ||
133 (pBuffer->BufferState == LVM_FIRSTLASTCALL)) &&
134 (pBuffer->InDelaySamples != 0))
136 Copy_16(&pBuffer->InDelayBuffer[0], /* Source */
137 pDest, /* Destination */
138 (LVM_INT16)(NumChannels*pBuffer->InDelaySamples)); /* Number of delay samples, left and right */
139 NumSamples = (LVM_INT16)(NumSamples - pBuffer->InDelaySamples); /* Update sample count */
140 pDest += NumChannels * pBuffer->InDelaySamples; /* Update the destination pointer */
145 * Copy the rest of the samples for this call from the input buffer
149 Copy_16(pStart, /* Source */
150 pDest, /* Destination */
151 (LVM_INT16)(NumChannels*NumSamples)); /* Number of input samples */
152 pStart += NumChannels * NumSamples; /* Update the input pointer */
155 * Update the input data pointer and samples to output
157 pBuffer->SamplesToOutput = (LVM_INT16)(pBuffer->SamplesToOutput + NumSamples); /* Update samples to output */
162 * Update the sample count and input pointer
164 pInstance->SamplesToProcess = (LVM_INT16)(pInstance->SamplesToProcess - SampleCount); /* Update the count of samples */
165 pInstance->pInputSamples = pStart; /* Update input sample pointer */
169 * Save samples to the delay buffer if any left unprocessed
171 if ((pBuffer->BufferState == LVM_FIRSTLASTCALL) ||
172 (pBuffer->BufferState == LVM_LASTCALL))
174 NumSamples = pInstance->SamplesToProcess;
175 pStart = pBuffer->pScratch; /* Start of the buffer */
176 pStart += NumChannels*SampleCount; /* Offset by the number of processed samples */
179 Copy_16(pStart, /* Source */
180 &pBuffer->InDelayBuffer[0], /* Destination */
181 (LVM_INT16)(NumChannels*NumSamples)); /* Number of input samples */
186 * Update the delay sample count
188 pBuffer->InDelaySamples = NumSamples; /* Number of delay sample pairs */
189 pInstance->SamplesToProcess = 0; /* All Samples used */
194 /****************************************************************************************/
196 /* FUNCTION: LVM_BufferUnmanagedIn */
199 /* This mode is selected by the user code and disables the buffer management with the */
200 /* exception of the maximum block size processing. The user must ensure that the */
201 /* input and output buffers are 32-bit aligned and also that the number of samples to */
202 /* process is a correct multiple of samples. */
205 /* hInstance - Instance handle */
206 /* *pToProcess - Pointer to the start of data processing */
207 /* *pProcessed - Pointer to the destination of the processed data */
208 /* pNumSamples - Pointer to the number of samples to process */
215 /****************************************************************************************/
217 void LVM_BufferUnmanagedIn(LVM_Handle_t hInstance,
218 LVM_INT16 **pToProcess,
219 LVM_INT16 **pProcessed,
220 LVM_UINT16 *pNumSamples)
223 LVM_Instance_t *pInstance = (LVM_Instance_t *)hInstance;
227 * Check if this is the first call of a block
229 if (pInstance->SamplesToProcess == 0)
231 pInstance->SamplesToProcess = (LVM_INT16)*pNumSamples; /* Get the number of samples on first call */
232 pInstance->pInputSamples = *pToProcess; /* Get the I/O pointers */
233 pInstance->pOutputSamples = *pProcessed;
237 * Set te block size to process
239 if (pInstance->SamplesToProcess > pInstance->InternalBlockSize)
241 *pNumSamples = (LVM_UINT16)pInstance->InternalBlockSize;
245 *pNumSamples = (LVM_UINT16)pInstance->SamplesToProcess;
250 * Set the process pointers
252 *pToProcess = pInstance->pInputSamples;
253 *pProcessed = pInstance->pOutputSamples;
257 /****************************************************************************************/
259 /* FUNCTION: LVM_BufferOptimisedIn */
262 /* Optimised buffer management for the case where the data is outplace processing, */
263 /* the output data is 32-bit aligned and there are sufficient samples to allow some */
264 /* processing directly in the output buffer. This saves one data copy per sample */
265 /* compared with the unoptimsed version. */
268 /* hInstance - Instance handle */
269 /* pInData - Pointer to the input data stream */
270 /* *pToProcess - Pointer to the start of data processing */
271 /* *pProcessed - Pointer to the destination of the processed data */
272 /* pNumSamples - Pointer to the number of samples to process */
279 /****************************************************************************************/
281 void LVM_BufferOptimisedIn(LVM_Handle_t hInstance,
282 const LVM_INT16 *pInData,
283 LVM_INT16 **pToProcess,
284 LVM_INT16 **pProcessed,
285 LVM_UINT16 *pNumSamples)
288 LVM_Instance_t *pInstance = (LVM_Instance_t *)hInstance;
289 LVM_Buffer_t *pBuffer = pInstance->pBufferManagement;
291 LVM_INT16 SampleCount;
292 LVM_INT16 NumSamples;
296 * Check if it is the first call for this block
298 if (pInstance->SamplesToProcess == 0)
301 * First call for a new block of samples
303 pBuffer->BufferState = LVM_FIRSTCALL;
304 pInstance->pInputSamples = (LVM_INT16 *)pInData;
305 pInstance->SamplesToProcess = (LVM_INT16)*pNumSamples;
306 pBuffer->SamplesToOutput = (LVM_INT16)*pNumSamples;
307 pDest = *pProcessed; /* The start of the output buffer */
311 * Copy the already processed samples to the output buffer
313 if (pBuffer->OutDelaySamples != 0)
315 Copy_16(&pBuffer->OutDelayBuffer[0], /* Source */
316 pDest, /* Detsination */
317 (LVM_INT16)(2*pBuffer->OutDelaySamples)); /* Number of delay samples */
318 pDest += 2 * pBuffer->OutDelaySamples; /* Update the output pointer */
319 pBuffer->SamplesToOutput = (LVM_INT16)(pBuffer->SamplesToOutput - pBuffer->OutDelaySamples); /* Update the numbr of samples to output */
321 *pToProcess = pDest; /* Set the address to start processing */
322 *pProcessed = pDest; /* Process in the output buffer, now inplace */
325 * Copy the input delay buffer (unprocessed) samples to the output buffer
327 if (pBuffer->InDelaySamples != 0)
329 Copy_16(&pBuffer->InDelayBuffer[0], /* Source */
330 pDest, /* Destination */
331 (LVM_INT16)(2*pBuffer->InDelaySamples)); /* Number of delay samples */
332 pDest += 2 * pBuffer->InDelaySamples; /* Update the output pointer */
337 * Calculate how many input samples to process and copy
339 NumSamples = (LVM_INT16)(*pNumSamples - pBuffer->OutDelaySamples); /* Number that will fit in the output buffer */
340 if (NumSamples >= pInstance->InternalBlockSize)
342 NumSamples = pInstance->InternalBlockSize;
344 NumFrames = (LVM_INT16)(NumSamples >> MIN_INTERNAL_BLOCKSHIFT);
345 SampleCount = (LVM_INT16)(NumFrames << MIN_INTERNAL_BLOCKSHIFT);
346 *pNumSamples = (LVM_UINT16)SampleCount; /* The number of samples to process */
347 pBuffer->SamplesToOutput = (LVM_INT16)(pBuffer->SamplesToOutput - SampleCount); /* Update the number of samples to output */
348 SampleCount = (LVM_INT16)(SampleCount - pBuffer->InDelaySamples); /* The number of samples to copy from the input */
352 * Copy samples from the input buffer and update counts and pointers
354 Copy_16(pInstance->pInputSamples, /* Source */
355 pDest, /* Destination */
356 (LVM_INT16)(2*SampleCount)); /* Number of input samples */
357 pInstance->pInputSamples += 2 * SampleCount; /* Update the input pointer */
358 pInstance->pOutputSamples = pDest + (2 * SampleCount); /* Update the output pointer */
359 pInstance->SamplesToProcess = (LVM_INT16)(pInstance->SamplesToProcess - SampleCount); /* Samples left in the input buffer */
364 * Second or subsequent call in optimised mode
366 if (pBuffer->SamplesToOutput >= MIN_INTERNAL_BLOCKSIZE)
369 * More samples can be processed directly in the output buffer
371 *pToProcess = pInstance->pOutputSamples; /* Set the address to start processing */
372 *pProcessed = pInstance->pOutputSamples; /* Process in the output buffer, now inplace */
373 NumSamples = pBuffer->SamplesToOutput; /* Number that will fit in the output buffer */
374 if (NumSamples >= pInstance->InternalBlockSize)
376 NumSamples = pInstance->InternalBlockSize;
378 NumFrames = (LVM_INT16)(NumSamples >> MIN_INTERNAL_BLOCKSHIFT);
379 SampleCount = (LVM_INT16)(NumFrames << MIN_INTERNAL_BLOCKSHIFT);
380 *pNumSamples = (LVM_UINT16)SampleCount; /* The number of samples to process */
384 * Copy samples from the input buffer and update counts and pointers
386 Copy_16(pInstance->pInputSamples, /* Source */
387 pInstance->pOutputSamples, /* Destination */
388 (LVM_INT16)(2*SampleCount)); /* Number of input samples */
389 pInstance->pInputSamples += 2 * SampleCount; /* Update the input pointer */
390 pInstance->pOutputSamples += 2 * SampleCount; /* Update the output pointer */
391 pInstance->SamplesToProcess = (LVM_INT16)(pInstance->SamplesToProcess - SampleCount); /* Samples left in the input buffer */
392 pBuffer->SamplesToOutput = (LVM_INT16)(pBuffer->SamplesToOutput - SampleCount); /* Number that will fit in the output buffer */
397 * The remaining samples can not be processed in the output buffer
399 pBuffer->BufferState = LVM_LASTCALL; /* Indicate this is the last bock to process */
400 *pToProcess = pBuffer->pScratch; /* Set the address to start processing */
401 *pProcessed = pBuffer->pScratch; /* Process in the output buffer, now inplace */
402 NumSamples = pInstance->SamplesToProcess; /* Number left to be processed */
403 NumFrames = (LVM_INT16)(NumSamples >> MIN_INTERNAL_BLOCKSHIFT);
404 SampleCount = (LVM_INT16)(NumFrames << MIN_INTERNAL_BLOCKSHIFT);
405 *pNumSamples = (LVM_UINT16)SampleCount; /* The number of samples to process */
409 * Copy samples from the input buffer and update counts and pointers
411 Copy_16(pInstance->pInputSamples, /* Source */
412 pBuffer->pScratch, /* Destination */
413 (LVM_INT16)(2*SampleCount)); /* Number of input samples */
414 pInstance->pInputSamples += 2 * SampleCount; /* Update the input pointer */
415 pInstance->SamplesToProcess = (LVM_INT16)(pInstance->SamplesToProcess - SampleCount); /* Samples left in the input buffer */
420 /****************************************************************************************/
422 /* FUNCTION: LVM_BufferIn */
425 /* This function manages the data input, it has the following features: */
426 /* - Accepts data in 16-bit aligned memory */
427 /* - Copies the data to 32-bit aligned memory */
428 /* - Converts Mono inputs to Mono-in-Stereo */
429 /* - Accepts any number of samples as input, except 0 */
430 /* - Breaks the input sample stream in to blocks of the configured frame size or */
431 /* multiples of the frame size */
432 /* - Limits the processing block size to the maximum block size. */
433 /* - Works with inplace or outplace processing automatically */
435 /* To manage the data the function has a number of operating states: */
436 /* LVM_FIRSTCALL - The first call for this block of input samples */
437 /* LVM_MAXBLOCKCALL - The current block is the maximum size. Only used for the */
438 /* second and subsequent blocks. */
439 /* LVM_LASTCALL - The last call for this block of input samples */
440 /* LVM_FIRSTLASTCALL - This is the first and last call for this block of input*/
441 /* samples, this occurs when the number of samples to */
442 /* process is less than the maximum block size. */
444 /* The function uses an internal delay buffer the size of the minimum frame, this is */
445 /* used to temporarily hold samples when the number of samples to process is not a */
446 /* multiple of the frame size. */
448 /* To ensure correct operation with inplace buffering the number of samples to output*/
449 /* per call is calculated in this function and is set to the number of samples read */
450 /* from the input buffer. */
452 /* The total number of samples to process is stored when the function is called for */
453 /* the first time. The value is overwritten by the size of the block to be processed */
454 /* in each call so the size of the processing blocks can be controlled. The number of */
455 /* samples actually processed for each block of input samples is always a multiple of*/
456 /* the frame size so for any particular block of input samples the actual number of */
457 /* processed samples may not match the number of input samples, sometime it will be */
458 /* sometimes less. The average is the same and the difference is never more than the */
462 /* hInstance - Instance handle */
463 /* pInData - Pointer to the input data stream */
464 /* *pToProcess - Pointer to the start of data processing */
465 /* *pProcessed - Pointer to the destination of the processed data */
466 /* pNumSamples - Pointer to the number of samples to process */
473 /****************************************************************************************/
475 void LVM_BufferIn(LVM_Handle_t hInstance,
476 const LVM_INT16 *pInData,
477 LVM_INT16 **pToProcess,
478 LVM_INT16 **pProcessed,
479 LVM_UINT16 *pNumSamples)
482 LVM_Instance_t *pInstance = (LVM_Instance_t *)hInstance;
486 * Check which mode, managed or unmanaged
488 if (pInstance->InstParams.BufferMode == LVM_MANAGED_BUFFERS)
490 LVM_BufferManagedIn(hInstance,
498 LVM_BufferUnmanagedIn(hInstance,
505 /****************************************************************************************/
507 /* FUNCTION: LVM_BufferManagedOut */
510 /* Full buffer management output. This works in conjunction with the managed input */
511 /* routine and ensures the correct number of samples are always output to the output */
515 /* hInstance - Instance handle */
516 /* pOutData - Pointer to the output data stream */
517 /* pNumSamples - Pointer to the number of samples to process */
524 /****************************************************************************************/
526 void LVM_BufferManagedOut(LVM_Handle_t hInstance,
528 LVM_UINT16 *pNumSamples)
531 LVM_Instance_t *pInstance = (LVM_Instance_t *)hInstance;
532 LVM_Buffer_t *pBuffer = pInstance->pBufferManagement;
533 LVM_INT16 SampleCount = (LVM_INT16)*pNumSamples;
534 LVM_INT16 NumSamples;
542 NumSamples = pBuffer->SamplesToOutput;
543 pStart = pBuffer->pScratch;
547 * check if it is the first call of a block
549 if ((pBuffer->BufferState == LVM_FIRSTCALL) ||
550 (pBuffer->BufferState == LVM_FIRSTLASTCALL))
552 /* First call for a new block */
553 pInstance->pOutputSamples = pOutData; /* Initialise the destination */
555 pDest = pInstance->pOutputSamples; /* Set the output address */
559 * If the number of samples is non-zero then there are still samples to send to
562 if ((NumSamples != 0) &&
563 (pBuffer->OutDelaySamples != 0))
566 * Copy the delayed output buffer samples to the output
568 if (pBuffer->OutDelaySamples <= NumSamples)
571 * Copy all output delay samples to the output
573 Copy_16(&pBuffer->OutDelayBuffer[0], /* Source */
574 pDest, /* Detsination */
575 (LVM_INT16)(2*pBuffer->OutDelaySamples)); /* Number of delay samples */
578 * Update the pointer and sample counts
580 pDest += 2*pBuffer->OutDelaySamples; /* Output sample pointer */
581 NumSamples = (LVM_INT16)(NumSamples - pBuffer->OutDelaySamples); /* Samples left to send */
582 pBuffer->OutDelaySamples = 0; /* No samples left in the buffer */
588 * Copy only some of the ouput delay samples to the output
590 Copy_16(&pBuffer->OutDelayBuffer[0], /* Source */
591 pDest, /* Detsination */
592 (LVM_INT16)(2*NumSamples)); /* Number of delay samples */
595 * Update the pointer and sample counts
597 pDest += 2*NumSamples; /* Output sample pointer */
598 pBuffer->OutDelaySamples = (LVM_INT16)(pBuffer->OutDelaySamples - NumSamples); /* No samples left in the buffer */
602 * Realign the delay buffer data to avoid using circular buffer management
604 Copy_16(&pBuffer->OutDelayBuffer[2*NumSamples], /* Source */
605 &pBuffer->OutDelayBuffer[0], /* Destination */
606 (LVM_INT16)(2*pBuffer->OutDelaySamples)); /* Number of samples to move */
607 NumSamples = 0; /* Samples left to send */
613 * Copy the processed results to the output
615 if ((NumSamples != 0) &&
618 if (SampleCount <= NumSamples)
621 * Copy all processed samples to the output
623 Copy_16(pStart, /* Source */
624 pDest, /* Detsination */
625 (LVM_INT16)(2*SampleCount)); /* Number of processed samples */
628 * Update the pointer and sample counts
630 pDest += 2 * SampleCount; /* Output sample pointer */
631 NumSamples = (LVM_INT16)(NumSamples - SampleCount); /* Samples left to send */
632 SampleCount = 0; /* No samples left in the buffer */
637 * Copy only some processed samples to the output
639 Copy_16(pStart, /* Source */
640 pDest, /* Destination */
641 (LVM_INT16)(2*NumSamples)); /* Number of processed samples */
645 * Update the pointers and sample counts
647 pStart += 2 * NumSamples; /* Processed sample pointer */
648 pDest += 2 * NumSamples; /* Output sample pointer */
649 SampleCount = (LVM_INT16)(SampleCount - NumSamples); /* Processed samples left */
650 NumSamples = 0; /* Clear the sample count */
656 * Copy the remaining processed data to the output delay buffer
658 if (SampleCount != 0)
660 Copy_16(pStart, /* Source */
661 &pBuffer->OutDelayBuffer[2*pBuffer->OutDelaySamples], /* Destination */
662 (LVM_INT16)(2*SampleCount)); /* Number of processed samples */
663 pBuffer->OutDelaySamples = (LVM_INT16)(pBuffer->OutDelaySamples + SampleCount); /* Update the buffer count */
668 * pointers, counts and set default buffer processing
670 pBuffer->SamplesToOutput = NumSamples; /* Samples left to send */
671 pInstance->pOutputSamples = pDest; /* Output sample pointer */
672 pBuffer->BufferState = LVM_MAXBLOCKCALL; /* Set for the default call block size */
673 *pNumSamples = (LVM_UINT16)pInstance->SamplesToProcess; /* This will terminate the loop when all samples processed */
677 /****************************************************************************************/
679 /* FUNCTION: LVM_BufferUnmanagedOut */
682 /* This works in conjunction with the unmanaged input routine and updates the number */
683 /* of samples left to be processed and adjusts the buffer pointers. */
686 /* hInstance - Instance handle */
687 /* pNumSamples - Pointer to the number of samples to process */
694 /****************************************************************************************/
696 void LVM_BufferUnmanagedOut(LVM_Handle_t hInstance,
697 LVM_UINT16 *pNumSamples)
700 LVM_Instance_t *pInstance = (LVM_Instance_t *)hInstance;
701 LVM_INT16 NumChannels =2;
705 * Update sample counts
707 pInstance->pInputSamples += (LVM_INT16)(*pNumSamples * NumChannels); /* Update the I/O pointers */
708 pInstance->pOutputSamples += (LVM_INT16)(*pNumSamples * 2);
709 pInstance->SamplesToProcess = (LVM_INT16)(pInstance->SamplesToProcess - *pNumSamples); /* Update the sample count */
712 * Set te block size to process
714 if (pInstance->SamplesToProcess > pInstance->InternalBlockSize)
716 *pNumSamples = (LVM_UINT16)pInstance->InternalBlockSize;
720 *pNumSamples = (LVM_UINT16)pInstance->SamplesToProcess;
725 /****************************************************************************************/
727 /* FUNCTION: LVM_BufferOptimisedOut */
730 /* This works in conjunction with the optimised input routine and copies the last few */
731 /* processed and unprocessed samples to their respective buffers. */
734 /* hInstance - Instance handle */
735 /* pNumSamples - Pointer to the number of samples to process */
742 /****************************************************************************************/
744 void LVM_BufferOptimisedOut(LVM_Handle_t hInstance,
745 LVM_UINT16 *pNumSamples)
748 LVM_Instance_t *pInstance = (LVM_Instance_t *)hInstance;
749 LVM_Buffer_t *pBuffer = pInstance->pBufferManagement;
752 * Check if it is the last block to process
754 if (pBuffer->BufferState == LVM_LASTCALL)
756 LVM_INT16 *pSrc = pBuffer->pScratch;
759 * Copy the unprocessed samples to the input delay buffer
761 if (pInstance->SamplesToProcess != 0)
763 Copy_16(pInstance->pInputSamples, /* Source */
764 &pBuffer->InDelayBuffer[0], /* Destination */
765 (LVM_INT16)(2*pInstance->SamplesToProcess)); /* Number of input samples */
766 pBuffer->InDelaySamples = pInstance->SamplesToProcess;
767 pInstance->SamplesToProcess = 0;
771 pBuffer->InDelaySamples = 0;
776 * Fill the last empty spaces in the output buffer
778 if (pBuffer->SamplesToOutput != 0)
780 Copy_16(pSrc, /* Source */
781 pInstance->pOutputSamples, /* Destination */
782 (LVM_INT16)(2*pBuffer->SamplesToOutput)); /* Number of input samples */
783 *pNumSamples = (LVM_UINT16)(*pNumSamples - pBuffer->SamplesToOutput);
784 pSrc += 2 * pBuffer->SamplesToOutput; /* Update scratch pointer */
785 pBuffer->SamplesToOutput = 0; /* No more samples in this block */
790 * Save any remaining processed samples in the output delay buffer
792 if (*pNumSamples != 0)
794 Copy_16(pSrc, /* Source */
795 &pBuffer->OutDelayBuffer[0], /* Destination */
796 (LVM_INT16)(2**pNumSamples)); /* Number of input samples */
798 pBuffer->OutDelaySamples = (LVM_INT16)*pNumSamples;
800 *pNumSamples = 0; /* No more samples in this block */
804 pBuffer->OutDelaySamples = 0;
810 /****************************************************************************************/
812 /* FUNCTION: LVM_BufferOut */
815 /* This function manages the data output, it has the following features: */
816 /* - Output data to 16-bit aligned memory */
817 /* - Reads data from 32-bit aligned memory */
818 /* - Reads data only in blocks of frame size or multiples of frame size */
819 /* - Writes the same number of samples as the LVM_BufferIn function reads */
820 /* - Works with inplace or outplace processing automatically */
822 /* To manage the data the function has a number of operating states: */
823 /* LVM_FIRSTCALL - The first call for this block of input samples */
824 /* LVM_FIRSTLASTCALL - This is the first and last call for this block of input*/
825 /* samples, this occurs when the number of samples to */
826 /* process is less than the maximum block size. */
828 /* The function uses an internal delay buffer the size of the minimum frame, this is */
829 /* used to temporarily hold samples when the number of samples to write is not a */
830 /* multiple of the frame size. */
832 /* To ensure correct operation with inplace buffering the number of samples to output*/
833 /* per call is always the same as the number of samples read from the input buffer. */
836 /* hInstance - Instance handle */
837 /* pOutData - Pointer to the output data stream */
838 /* pNumSamples - Pointer to the number of samples to process */
845 /****************************************************************************************/
847 void LVM_BufferOut(LVM_Handle_t hInstance,
849 LVM_UINT16 *pNumSamples)
852 LVM_Instance_t *pInstance = (LVM_Instance_t *)hInstance;
856 * Check which mode, managed or unmanaged
858 if (pInstance->InstParams.BufferMode == LVM_MANAGED_BUFFERS)
860 LVM_BufferManagedOut(hInstance,
866 LVM_BufferUnmanagedOut(hInstance,