1/*
2 * Copyright (C) 2004-2010 NXP Software
3 * Copyright (C) 2010 The Android Open Source Project
4 *
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
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
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.
16 */
17
18
19/****************************************************************************************/
20/*                                                                                        */
21/*    Includes                                                                              */
22/*                                                                                        */
23/****************************************************************************************/
24
25#include "LVM_Private.h"
26#include "VectorArithmetic.h"
27
28/****************************************************************************************/
29/*                                                                                      */
30/* FUNCTION:                 LVM_BufferManagedIn                                        */
31/*                                                                                      */
32/* DESCRIPTION:                                                                         */
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.                                                                  */
37/*                                                                                      */
38/* PARAMETERS:                                                                          */
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               */
44/*                                                                                      */
45/* RETURNS:                                                                             */
46/*    None                                                                              */
47/*                                                                                      */
48/* NOTES:                                                                               */
49/*                                                                                      */
50/****************************************************************************************/
51
52void LVM_BufferManagedIn(LVM_Handle_t       hInstance,
53                         const LVM_INT16    *pInData,
54                         LVM_INT16          **pToProcess,
55                         LVM_INT16          **pProcessed,
56                         LVM_UINT16         *pNumSamples)
57{
58
59    LVM_INT16        SampleCount;           /* Number of samples to be processed this call */
60    LVM_INT16        NumSamples;            /* Number of samples in scratch buffer */
61    LVM_INT16        *pStart;
62    LVM_Instance_t   *pInstance = (LVM_Instance_t  *)hInstance;
63    LVM_Buffer_t     *pBuffer;
64    LVM_INT16        *pDest;
65    LVM_INT16        NumChannels =2;
66
67
68    /*
69     * Set the processing address pointers
70     */
71    pBuffer     = pInstance->pBufferManagement;
72    pDest       = pBuffer->pScratch;
73    *pToProcess = pBuffer->pScratch;
74    *pProcessed = pBuffer->pScratch;
75
76    /*
77     * Check if it is the first call of a block
78     */
79    if (pInstance->SamplesToProcess == 0)
80    {
81        /*
82         * First call for a new block of samples
83         */
84        pInstance->SamplesToProcess = (LVM_INT16)(*pNumSamples + pBuffer->InDelaySamples);
85        pInstance->pInputSamples    = (LVM_INT16 *)pInData;
86        pBuffer->BufferState        = LVM_FIRSTCALL;
87    }
88    pStart = pInstance->pInputSamples;                       /* Pointer to the input samples */
89    pBuffer->SamplesToOutput  = 0;                           /* Samples to output is same as number read for inplace processing */
90
91
92    /*
93     * Calculate the number of samples to process this call and update the buffer state
94     */
95    if (pInstance->SamplesToProcess > pInstance->InternalBlockSize)
96    {
97        /*
98         * Process the maximum bock size of samples.
99         */
100        SampleCount = pInstance->InternalBlockSize;
101        NumSamples  = pInstance->InternalBlockSize;
102    }
103    else
104    {
105        /*
106         * Last call for the block, so calculate how many frames and samples to process
107          */
108        LVM_INT16   NumFrames;
109
110        NumSamples  = pInstance->SamplesToProcess;
111        NumFrames    = (LVM_INT16)(NumSamples >> MIN_INTERNAL_BLOCKSHIFT);
112        SampleCount = (LVM_INT16)(NumFrames << MIN_INTERNAL_BLOCKSHIFT);
113
114        /*
115         * Update the buffer state
116         */
117        if (pBuffer->BufferState == LVM_FIRSTCALL)
118        {
119            pBuffer->BufferState = LVM_FIRSTLASTCALL;
120        }
121        else
122        {
123            pBuffer->BufferState = LVM_LASTCALL;
124        }
125    }
126    *pNumSamples = (LVM_UINT16)SampleCount;                        /* Set the number of samples to process this call */
127
128
129    /*
130     * Copy samples from the delay buffer as required
131     */
132    if (((pBuffer->BufferState == LVM_FIRSTCALL) ||
133        (pBuffer->BufferState == LVM_FIRSTLASTCALL)) &&
134        (pBuffer->InDelaySamples != 0))
135    {
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 */
141    }
142
143
144    /*
145     * Copy the rest of the samples for this call from the input buffer
146     */
147    if (NumSamples > 0)
148    {
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 */
153
154        /*
155         * Update the input data pointer and samples to output
156         */
157        pBuffer->SamplesToOutput = (LVM_INT16)(pBuffer->SamplesToOutput + NumSamples); /* Update samples to output */
158    }
159
160
161    /*
162      * Update the sample count and input pointer
163     */
164    pInstance->SamplesToProcess  = (LVM_INT16)(pInstance->SamplesToProcess - SampleCount);      /* Update the count of samples */
165    pInstance->pInputSamples     = pStart;                                                      /* Update input sample pointer */
166
167
168    /*
169     * Save samples to the delay buffer if any left unprocessed
170     */
171    if ((pBuffer->BufferState == LVM_FIRSTLASTCALL) ||
172        (pBuffer->BufferState == LVM_LASTCALL))
173    {
174        NumSamples = pInstance->SamplesToProcess;
175        pStart     = pBuffer->pScratch;                             /* Start of the buffer */
176        pStart    += NumChannels*SampleCount;                       /* Offset by the number of processed samples */
177        if (NumSamples != 0)
178        {
179            Copy_16(pStart,                                         /* Source */
180                    &pBuffer->InDelayBuffer[0],                     /* Destination */
181                    (LVM_INT16)(NumChannels*NumSamples));           /* Number of input samples */
182        }
183
184
185        /*
186         * Update the delay sample count
187         */
188        pBuffer->InDelaySamples     = NumSamples;                   /* Number of delay sample pairs */
189        pInstance->SamplesToProcess = 0;                            /* All Samples used */
190    }
191}
192
193
194/****************************************************************************************/
195/*                                                                                      */
196/* FUNCTION:                 LVM_BufferUnmanagedIn                                      */
197/*                                                                                      */
198/* DESCRIPTION:                                                                         */
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.                                         */
203/*                                                                                      */
204/* PARAMETERS:                                                                          */
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               */
209/*                                                                                      */
210/* RETURNS:                                                                             */
211/*    None                                                                              */
212/*                                                                                      */
213/* NOTES:                                                                               */
214/*                                                                                      */
215/****************************************************************************************/
216
217void LVM_BufferUnmanagedIn(LVM_Handle_t     hInstance,
218                           LVM_INT16        **pToProcess,
219                           LVM_INT16        **pProcessed,
220                           LVM_UINT16       *pNumSamples)
221{
222
223    LVM_Instance_t    *pInstance = (LVM_Instance_t  *)hInstance;
224
225
226    /*
227     * Check if this is the first call of a block
228     */
229    if (pInstance->SamplesToProcess == 0)
230    {
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;
234
235
236        /*
237         * Set te block size to process
238         */
239        if (pInstance->SamplesToProcess > pInstance->InternalBlockSize)
240        {
241            *pNumSamples = (LVM_UINT16)pInstance->InternalBlockSize;
242        }
243        else
244        {
245            *pNumSamples = (LVM_UINT16)pInstance->SamplesToProcess;
246        }
247    }
248
249    /*
250     * Set the process pointers
251     */
252    *pToProcess = pInstance->pInputSamples;
253    *pProcessed = pInstance->pOutputSamples;
254}
255
256
257/****************************************************************************************/
258/*                                                                                      */
259/* FUNCTION:                 LVM_BufferOptimisedIn                                      */
260/*                                                                                      */
261/* DESCRIPTION:                                                                         */
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.                                             */
266/*                                                                                      */
267/* PARAMETERS:                                                                          */
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               */
273/*                                                                                      */
274/* RETURNS:                                                                             */
275/*    None                                                                              */
276/*                                                                                      */
277/* NOTES:                                                                               */
278/*                                                                                      */
279/****************************************************************************************/
280
281void LVM_BufferOptimisedIn(LVM_Handle_t         hInstance,
282                           const LVM_INT16      *pInData,
283                           LVM_INT16            **pToProcess,
284                           LVM_INT16            **pProcessed,
285                           LVM_UINT16           *pNumSamples)
286{
287
288    LVM_Instance_t   *pInstance = (LVM_Instance_t  *)hInstance;
289    LVM_Buffer_t     *pBuffer    = pInstance->pBufferManagement;
290    LVM_INT16        *pDest;
291    LVM_INT16        SampleCount;
292    LVM_INT16        NumSamples;
293    LVM_INT16        NumFrames;
294
295    /*
296     * Check if it is the first call for this block
297     */
298    if (pInstance->SamplesToProcess == 0)
299    {
300        /*
301         * First call for a new block of samples
302         */
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 */
308
309
310        /*
311         * Copy the already processed samples to the output buffer
312         */
313        if (pBuffer->OutDelaySamples != 0)
314        {
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 */
320        }
321        *pToProcess = pDest;                                    /* Set the address to start processing */
322        *pProcessed = pDest;                                    /* Process in the output buffer, now inplace */
323
324        /*
325         * Copy the input delay buffer (unprocessed) samples to the output buffer
326         */
327        if (pBuffer->InDelaySamples != 0)
328        {
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 */
333        }
334
335
336        /*
337         * Calculate how many input samples to process and copy
338         */
339        NumSamples    = (LVM_INT16)(*pNumSamples - pBuffer->OutDelaySamples);  /* Number that will fit in the output buffer */
340        if (NumSamples >= pInstance->InternalBlockSize)
341        {
342            NumSamples = pInstance->InternalBlockSize;
343        }
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 */
349
350
351        /*
352         * Copy samples from the input buffer and update counts and pointers
353         */
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 */
360    }
361    else
362    {
363        /*
364         * Second or subsequent call in optimised mode
365         */
366        if (pBuffer->SamplesToOutput >= MIN_INTERNAL_BLOCKSIZE)
367        {
368            /*
369             * More samples can be processed directly in the output buffer
370             */
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)
375            {
376                NumSamples = pInstance->InternalBlockSize;
377            }
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 */
381
382
383            /*
384             * Copy samples from the input buffer and update counts and pointers
385             */
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 */
393        }
394        else
395        {
396            /*
397             * The remaining samples can not be processed in the output buffer
398             */
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 */
406
407
408            /*
409             * Copy samples from the input buffer and update counts and pointers
410             */
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 */
416        }
417    }
418}
419
420/****************************************************************************************/
421/*                                                                                      */
422/* FUNCTION:                 LVM_BufferIn                                               */
423/*                                                                                      */
424/* DESCRIPTION:                                                                         */
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                     */
434/*                                                                                      */
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.            */
443/*                                                                                      */
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.                                                         */
447/*                                                                                      */
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.                                                              */
451/*                                                                                      */
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   */
459/*  frame size.                                                                         */
460/*                                                                                      */
461/* PARAMETERS:                                                                          */
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               */
467/*                                                                                      */
468/* RETURNS:                                                                             */
469/*    None                                                                              */
470/*                                                                                      */
471/* NOTES:                                                                               */
472/*                                                                                      */
473/****************************************************************************************/
474
475void LVM_BufferIn(LVM_Handle_t      hInstance,
476                  const LVM_INT16   *pInData,
477                  LVM_INT16         **pToProcess,
478                  LVM_INT16         **pProcessed,
479                  LVM_UINT16        *pNumSamples)
480{
481
482    LVM_Instance_t    *pInstance = (LVM_Instance_t  *)hInstance;
483
484
485    /*
486     * Check which mode, managed or unmanaged
487     */
488    if (pInstance->InstParams.BufferMode == LVM_MANAGED_BUFFERS)
489    {
490        LVM_BufferManagedIn(hInstance,
491                            pInData,
492                            pToProcess,
493                            pProcessed,
494                            pNumSamples);
495    }
496    else
497    {
498        LVM_BufferUnmanagedIn(hInstance,
499                              pToProcess,
500                              pProcessed,
501                              pNumSamples);
502    }
503}
504
505/****************************************************************************************/
506/*                                                                                      */
507/* FUNCTION:                 LVM_BufferManagedOut                                       */
508/*                                                                                      */
509/* DESCRIPTION:                                                                         */
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   */
512/*  buffer.                                                                             */
513/*                                                                                      */
514/* PARAMETERS:                                                                          */
515/*    hInstance        - Instance handle                                                */
516/*    pOutData        - Pointer to the output data stream                               */
517/*    pNumSamples        - Pointer to the number of samples to process                  */
518/*                                                                                      */
519/* RETURNS:                                                                             */
520/*    None                                                                              */
521/*                                                                                      */
522/* NOTES:                                                                               */
523/*                                                                                      */
524/****************************************************************************************/
525
526void LVM_BufferManagedOut(LVM_Handle_t        hInstance,
527                          LVM_INT16            *pOutData,
528                          LVM_UINT16        *pNumSamples)
529{
530
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;
535    LVM_INT16       *pStart;
536    LVM_INT16       *pDest;
537
538
539    /*
540     * Set the pointers
541     */
542    NumSamples = pBuffer->SamplesToOutput;
543    pStart     = pBuffer->pScratch;
544
545
546    /*
547     * check if it is the first call of a block
548      */
549    if ((pBuffer->BufferState == LVM_FIRSTCALL) ||
550        (pBuffer->BufferState == LVM_FIRSTLASTCALL))
551    {
552        /* First call for a new block */
553        pInstance->pOutputSamples = pOutData;                        /* Initialise the destination */
554    }
555    pDest = pInstance->pOutputSamples;                               /* Set the output address */
556
557
558    /*
559     * If the number of samples is non-zero then there are still samples to send to
560     * the output buffer
561     */
562    if ((NumSamples != 0) &&
563        (pBuffer->OutDelaySamples != 0))
564    {
565        /*
566         * Copy the delayed output buffer samples to the output
567         */
568        if (pBuffer->OutDelaySamples <= NumSamples)
569        {
570            /*
571             * Copy all output delay samples to the output
572             */
573            Copy_16(&pBuffer->OutDelayBuffer[0],                    /* Source */
574                    pDest,                                          /* Detsination */
575                    (LVM_INT16)(2*pBuffer->OutDelaySamples));       /* Number of delay samples */
576
577            /*
578             * Update the pointer and sample counts
579             */
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 */
583
584        }
585        else
586        {
587            /*
588             * Copy only some of the ouput delay samples to the output
589             */
590            Copy_16(&pBuffer->OutDelayBuffer[0],                    /* Source */
591                    pDest,                                          /* Detsination */
592                    (LVM_INT16)(2*NumSamples));                     /* Number of delay samples */
593
594            /*
595             * Update the pointer and sample counts
596             */
597            pDest += 2*NumSamples;                                                              /* Output sample pointer */
598            pBuffer->OutDelaySamples = (LVM_INT16)(pBuffer->OutDelaySamples - NumSamples);      /* No samples left in the buffer */
599
600
601            /*
602             * Realign the delay buffer data to avoid using circular buffer management
603             */
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 */
608        }
609    }
610
611
612    /*
613     * Copy the processed results to the output
614     */
615    if ((NumSamples != 0) &&
616        (SampleCount != 0))
617    {
618        if (SampleCount <= NumSamples)
619        {
620            /*
621             * Copy all processed samples to the output
622             */
623            Copy_16(pStart,                                      /* Source */
624                    pDest,                                       /* Detsination */
625                    (LVM_INT16)(2*SampleCount));                 /* Number of processed samples */
626
627            /*
628             * Update the pointer and sample counts
629             */
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 */
633        }
634        else
635        {
636            /*
637             * Copy only some processed samples to the output
638             */
639            Copy_16(pStart,                                         /* Source */
640                    pDest,                                          /* Destination */
641                    (LVM_INT16)(2*NumSamples));                     /* Number of processed samples */
642
643
644            /*
645             * Update the pointers and sample counts
646               */
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 */
651        }
652    }
653
654
655    /*
656     * Copy the remaining processed data to the output delay buffer
657     */
658    if (SampleCount != 0)
659    {
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 */
664    }
665
666
667    /*
668     * pointers, counts and set default buffer processing
669     */
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 */
674}
675
676
677/****************************************************************************************/
678/*                                                                                      */
679/* FUNCTION:                 LVM_BufferUnmanagedOut                                     */
680/*                                                                                      */
681/* DESCRIPTION:                                                                         */
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.               */
684/*                                                                                      */
685/* PARAMETERS:                                                                          */
686/*    hInstance        - Instance handle                                                */
687/*    pNumSamples        - Pointer to the number of samples to process                  */
688/*                                                                                      */
689/* RETURNS:                                                                             */
690/*    None                                                                              */
691/*                                                                                      */
692/* NOTES:                                                                               */
693/*                                                                                      */
694/****************************************************************************************/
695
696void LVM_BufferUnmanagedOut(LVM_Handle_t        hInstance,
697                            LVM_UINT16          *pNumSamples)
698{
699
700    LVM_Instance_t      *pInstance  = (LVM_Instance_t  *)hInstance;
701    LVM_INT16           NumChannels =2;
702
703
704    /*
705     * Update sample counts
706     */
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 */
710
711    /*
712     * Set te block size to process
713     */
714    if (pInstance->SamplesToProcess > pInstance->InternalBlockSize)
715    {
716        *pNumSamples = (LVM_UINT16)pInstance->InternalBlockSize;
717    }
718    else
719    {
720        *pNumSamples = (LVM_UINT16)pInstance->SamplesToProcess;
721    }
722}
723
724
725/****************************************************************************************/
726/*                                                                                      */
727/* FUNCTION:                 LVM_BufferOptimisedOut                                     */
728/*                                                                                      */
729/* DESCRIPTION:                                                                         */
730/*  This works in conjunction with the optimised input routine and copies the last few  */
731/*  processed and unprocessed samples to their respective buffers.                      */
732/*                                                                                      */
733/* PARAMETERS:                                                                          */
734/*    hInstance        - Instance handle                                                */
735/*    pNumSamples        - Pointer to the number of samples to process                  */
736/*                                                                                      */
737/* RETURNS:                                                                             */
738/*    None                                                                              */
739/*                                                                                      */
740/* NOTES:                                                                               */
741/*                                                                                      */
742/****************************************************************************************/
743
744void LVM_BufferOptimisedOut(LVM_Handle_t    hInstance,
745                            LVM_UINT16        *pNumSamples)
746{
747
748    LVM_Instance_t      *pInstance = (LVM_Instance_t  *)hInstance;
749    LVM_Buffer_t        *pBuffer   = pInstance->pBufferManagement;
750
751    /*
752     * Check if it is the last block to process
753     */
754    if (pBuffer->BufferState == LVM_LASTCALL)
755    {
756        LVM_INT16    *pSrc = pBuffer->pScratch;
757
758        /*
759         * Copy the unprocessed samples to the input delay buffer
760         */
761        if (pInstance->SamplesToProcess != 0)
762        {
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;
768        }
769        else
770        {
771            pBuffer->InDelaySamples = 0;
772        }
773
774
775        /*
776         * Fill the last empty spaces in the output buffer
777         */
778        if (pBuffer->SamplesToOutput != 0)
779        {
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 */
786        }
787
788
789        /*
790         * Save any remaining processed samples in the output delay buffer
791         */
792        if (*pNumSamples != 0)
793        {
794            Copy_16(pSrc,                                           /* Source */
795                    &pBuffer->OutDelayBuffer[0],                    /* Destination */
796                    (LVM_INT16)(2**pNumSamples));                   /* Number of input samples */
797
798            pBuffer->OutDelaySamples = (LVM_INT16)*pNumSamples;
799
800            *pNumSamples = 0;                                      /* No more samples in this block */
801        }
802        else
803        {
804            pBuffer->OutDelaySamples = 0;
805        }
806    }
807}
808
809
810/****************************************************************************************/
811/*                                                                                      */
812/* FUNCTION:                 LVM_BufferOut                                              */
813/*                                                                                      */
814/* DESCRIPTION:                                                                         */
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                     */
821/*                                                                                      */
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.            */
827/*                                                                                      */
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.                                                         */
831/*                                                                                      */
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.    */
834/*                                                                                      */
835/* PARAMETERS:                                                                          */
836/*    hInstance        - Instance handle                                                */
837/*    pOutData        - Pointer to the output data stream                               */
838/*    pNumSamples        - Pointer to the number of samples to process                  */
839/*                                                                                      */
840/* RETURNS:                                                                             */
841/*    None                                                                              */
842/*                                                                                      */
843/* NOTES:                                                                               */
844/*                                                                                      */
845/****************************************************************************************/
846
847void LVM_BufferOut(LVM_Handle_t     hInstance,
848                   LVM_INT16        *pOutData,
849                   LVM_UINT16       *pNumSamples)
850{
851
852    LVM_Instance_t    *pInstance  = (LVM_Instance_t  *)hInstance;
853
854
855    /*
856     * Check which mode, managed or unmanaged
857     */
858    if (pInstance->InstParams.BufferMode == LVM_MANAGED_BUFFERS)
859    {
860        LVM_BufferManagedOut(hInstance,
861                             pOutData,
862                             pNumSamples);
863    }
864    else
865    {
866        LVM_BufferUnmanagedOut(hInstance,
867                               pNumSamples);
868    }
869}
870
871