LVM_Buffers.c revision 2c8e5cab3faa6d360e222b7a6c40a80083d021ac
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     $Author: nxp007753 $
22     $Revision: 1082 $
23     $Date: 2010-07-05 12:44:39 +0200 (Mon, 05 Jul 2010) $
24
25*****************************************************************************************/
26
27/****************************************************************************************/
28/*                                                                                        */
29/*    Includes                                                                              */
30/*                                                                                        */
31/****************************************************************************************/
32
33#include "LVM_Private.h"
34#include "VectorArithmetic.h"
35
36/****************************************************************************************/
37/*                                                                                      */
38/* FUNCTION:                 LVM_BufferManagedIn                                        */
39/*                                                                                      */
40/* DESCRIPTION:                                                                         */
41/*    Full buffer management allowing the user to provide input and output buffers on   */
42/*  any alignment and with any number of samples. The alignment is corrected within     */
43/*  the buffer management and the samples are grouped in to blocks of the correct size  */
44/*  before processing.                                                                  */
45/*                                                                                      */
46/* PARAMETERS:                                                                          */
47/*    hInstance        -    Instance handle                                             */
48/*    pInData            -    Pointer to the input data stream                          */
49/*  *pToProcess        -    Pointer to pointer to the start of data processing          */
50/*  *pProcessed        -    Pointer to pointer to the destination of the processed data */
51/*    pNumSamples        -    Pointer to the number of samples to process               */
52/*                                                                                      */
53/* RETURNS:                                                                             */
54/*    None                                                                              */
55/*                                                                                      */
56/* NOTES:                                                                               */
57/*                                                                                      */
58/****************************************************************************************/
59
60void LVM_BufferManagedIn(LVM_Handle_t       hInstance,
61                         const LVM_INT16    *pInData,
62                         LVM_INT16          **pToProcess,
63                         LVM_INT16          **pProcessed,
64                         LVM_UINT16         *pNumSamples)
65{
66
67    LVM_INT16        SampleCount;           /* Number of samples to be processed this call */
68    LVM_INT16        NumSamples;            /* Number of samples in scratch buffer */
69    LVM_INT16        *pStart;
70    LVM_Instance_t   *pInstance = (LVM_Instance_t  *)hInstance;
71    LVM_Buffer_t     *pBuffer;
72    LVM_INT16        *pDest;
73    LVM_INT16        NumChannels =2;
74
75
76    /*
77     * Set the processing address pointers
78     */
79    pBuffer     = pInstance->pBufferManagement;
80    pDest       = pBuffer->pScratch;
81    *pToProcess = pBuffer->pScratch;
82    *pProcessed = pBuffer->pScratch;
83
84    /*
85     * Check if it is the first call of a block
86     */
87    if (pInstance->SamplesToProcess == 0)
88    {
89        /*
90         * First call for a new block of samples
91         */
92        pInstance->SamplesToProcess = (LVM_INT16)(*pNumSamples + pBuffer->InDelaySamples);
93        pInstance->pInputSamples    = (LVM_INT16 *)pInData;
94        pBuffer->BufferState        = LVM_FIRSTCALL;
95    }
96    pStart = pInstance->pInputSamples;                       /* Pointer to the input samples */
97    pBuffer->SamplesToOutput  = 0;                           /* Samples to output is same as number read for inplace processing */
98
99
100    /*
101     * Calculate the number of samples to process this call and update the buffer state
102     */
103    if (pInstance->SamplesToProcess > pInstance->InternalBlockSize)
104    {
105        /*
106         * Process the maximum bock size of samples.
107         */
108        SampleCount = pInstance->InternalBlockSize;
109        NumSamples  = pInstance->InternalBlockSize;
110    }
111    else
112    {
113        /*
114         * Last call for the block, so calculate how many frames and samples to process
115          */
116        LVM_INT16   NumFrames;
117
118        NumSamples  = pInstance->SamplesToProcess;
119        NumFrames    = (LVM_INT16)(NumSamples >> MIN_INTERNAL_BLOCKSHIFT);
120        SampleCount = (LVM_INT16)(NumFrames << MIN_INTERNAL_BLOCKSHIFT);
121
122        /*
123         * Update the buffer state
124         */
125        if (pBuffer->BufferState == LVM_FIRSTCALL)
126        {
127            pBuffer->BufferState = LVM_FIRSTLASTCALL;
128        }
129        else
130        {
131            pBuffer->BufferState = LVM_LASTCALL;
132        }
133    }
134    *pNumSamples = (LVM_UINT16)SampleCount;                        /* Set the number of samples to process this call */
135
136
137    /*
138     * Copy samples from the delay buffer as required
139     */
140    if (((pBuffer->BufferState == LVM_FIRSTCALL) ||
141        (pBuffer->BufferState == LVM_FIRSTLASTCALL)) &&
142        (pBuffer->InDelaySamples != 0))
143    {
144        Copy_16(&pBuffer->InDelayBuffer[0],                             /* Source */
145                pDest,                                                  /* Destination */
146                (LVM_INT16)(NumChannels*pBuffer->InDelaySamples));      /* Number of delay samples, left and right */
147        NumSamples = (LVM_INT16)(NumSamples - pBuffer->InDelaySamples); /* Update sample count */
148        pDest += NumChannels * pBuffer->InDelaySamples;                 /* Update the destination pointer */
149    }
150
151
152    /*
153     * Copy the rest of the samples for this call from the input buffer
154     */
155    if (NumSamples > 0)
156    {
157        Copy_16(pStart,                                             /* Source */
158                pDest,                                              /* Destination */
159                (LVM_INT16)(NumChannels*NumSamples));               /* Number of input samples */
160        pStart += NumChannels * NumSamples;                         /* Update the input pointer */
161
162        /*
163         * Update the input data pointer and samples to output
164         */
165        pBuffer->SamplesToOutput = (LVM_INT16)(pBuffer->SamplesToOutput + NumSamples); /* Update samples to output */
166    }
167
168
169    /*
170      * Update the sample count and input pointer
171     */
172    pInstance->SamplesToProcess  = (LVM_INT16)(pInstance->SamplesToProcess - SampleCount);      /* Update the count of samples */
173    pInstance->pInputSamples     = pStart;                                                      /* Update input sample pointer */
174
175
176    /*
177     * Save samples to the delay buffer if any left unprocessed
178     */
179    if ((pBuffer->BufferState == LVM_FIRSTLASTCALL) ||
180        (pBuffer->BufferState == LVM_LASTCALL))
181    {
182        NumSamples = pInstance->SamplesToProcess;
183        pStart     = pBuffer->pScratch;                             /* Start of the buffer */
184        pStart    += NumChannels*SampleCount;                       /* Offset by the number of processed samples */
185        if (NumSamples != 0)
186        {
187            Copy_16(pStart,                                         /* Source */
188                    &pBuffer->InDelayBuffer[0],                     /* Destination */
189                    (LVM_INT16)(NumChannels*NumSamples));           /* Number of input samples */
190        }
191
192
193        /*
194         * Update the delay sample count
195         */
196        pBuffer->InDelaySamples     = NumSamples;                   /* Number of delay sample pairs */
197        pInstance->SamplesToProcess = 0;                            /* All Samples used */
198    }
199}
200
201
202/****************************************************************************************/
203/*                                                                                      */
204/* FUNCTION:                 LVM_BufferUnmanagedIn                                      */
205/*                                                                                      */
206/* DESCRIPTION:                                                                         */
207/*    This mode is selected by the user code and disables the buffer management with the */
208/*  exception of the maximum block size processing. The user must ensure that the       */
209/*  input and output buffers are 32-bit aligned and also that the number of samples to  */
210/*    process is a correct multiple of samples.                                         */
211/*                                                                                      */
212/* PARAMETERS:                                                                          */
213/*    hInstance        -    Instance handle                                             */
214/*  *pToProcess        -    Pointer to the start of data processing                     */
215/*  *pProcessed        -    Pointer to the destination of the processed data            */
216/*    pNumSamples        -    Pointer to the number of samples to process               */
217/*                                                                                      */
218/* RETURNS:                                                                             */
219/*    None                                                                              */
220/*                                                                                      */
221/* NOTES:                                                                               */
222/*                                                                                      */
223/****************************************************************************************/
224
225void LVM_BufferUnmanagedIn(LVM_Handle_t     hInstance,
226                           LVM_INT16        **pToProcess,
227                           LVM_INT16        **pProcessed,
228                           LVM_UINT16       *pNumSamples)
229{
230
231    LVM_Instance_t    *pInstance = (LVM_Instance_t  *)hInstance;
232
233
234    /*
235     * Check if this is the first call of a block
236     */
237    if (pInstance->SamplesToProcess == 0)
238    {
239        pInstance->SamplesToProcess = (LVM_INT16)*pNumSamples;       /* Get the number of samples on first call */
240        pInstance->pInputSamples    = *pToProcess;                   /* Get the I/O pointers */
241        pInstance->pOutputSamples    = *pProcessed;
242
243
244        /*
245         * Set te block size to process
246         */
247        if (pInstance->SamplesToProcess > pInstance->InternalBlockSize)
248        {
249            *pNumSamples = (LVM_UINT16)pInstance->InternalBlockSize;
250        }
251        else
252        {
253            *pNumSamples = (LVM_UINT16)pInstance->SamplesToProcess;
254        }
255    }
256
257    /*
258     * Set the process pointers
259     */
260    *pToProcess = pInstance->pInputSamples;
261    *pProcessed = pInstance->pOutputSamples;
262}
263
264
265/****************************************************************************************/
266/*                                                                                      */
267/* FUNCTION:                 LVM_BufferOptimisedIn                                      */
268/*                                                                                      */
269/* DESCRIPTION:                                                                         */
270/*    Optimised buffer management for the case where the data is outplace processing,   */
271/*    the output data is 32-bit aligned and there are sufficient samples to allow some  */
272/*    processing directly in the output buffer. This saves one data copy per sample     */
273/*    compared with the unoptimsed version.                                             */
274/*                                                                                      */
275/* PARAMETERS:                                                                          */
276/*    hInstance        -    Instance handle                                             */
277/*    pInData            -    Pointer to the input data stream                          */
278/*  *pToProcess        -    Pointer to the start of data processing                     */
279/*  *pProcessed        -    Pointer to the destination of the processed data            */
280/*    pNumSamples        -    Pointer to the number of samples to process               */
281/*                                                                                      */
282/* RETURNS:                                                                             */
283/*    None                                                                              */
284/*                                                                                      */
285/* NOTES:                                                                               */
286/*                                                                                      */
287/****************************************************************************************/
288
289void LVM_BufferOptimisedIn(LVM_Handle_t         hInstance,
290                           const LVM_INT16      *pInData,
291                           LVM_INT16            **pToProcess,
292                           LVM_INT16            **pProcessed,
293                           LVM_UINT16           *pNumSamples)
294{
295
296    LVM_Instance_t   *pInstance = (LVM_Instance_t  *)hInstance;
297    LVM_Buffer_t     *pBuffer    = pInstance->pBufferManagement;
298    LVM_INT16        *pDest;
299    LVM_INT16        SampleCount;
300    LVM_INT16        NumSamples;
301    LVM_INT16        NumFrames;
302
303    /*
304     * Check if it is the first call for this block
305     */
306    if (pInstance->SamplesToProcess == 0)
307    {
308        /*
309         * First call for a new block of samples
310         */
311        pBuffer->BufferState = LVM_FIRSTCALL;
312        pInstance->pInputSamples    = (LVM_INT16 *)pInData;
313        pInstance->SamplesToProcess = (LVM_INT16)*pNumSamples;
314        pBuffer->SamplesToOutput    = (LVM_INT16)*pNumSamples;
315        pDest = *pProcessed;                                    /* The start of the output buffer */
316
317
318        /*
319         * Copy the already processed samples to the output buffer
320         */
321        if (pBuffer->OutDelaySamples != 0)
322        {
323            Copy_16(&pBuffer->OutDelayBuffer[0],                    /* Source */
324                    pDest,                                          /* Detsination */
325                    (LVM_INT16)(2*pBuffer->OutDelaySamples));       /* Number of delay samples */
326            pDest += 2 * pBuffer->OutDelaySamples;                  /* Update the output pointer */
327            pBuffer->SamplesToOutput = (LVM_INT16)(pBuffer->SamplesToOutput - pBuffer->OutDelaySamples); /* Update the numbr of samples to output */
328        }
329        *pToProcess = pDest;                                    /* Set the address to start processing */
330        *pProcessed = pDest;                                    /* Process in the output buffer, now inplace */
331
332        /*
333         * Copy the input delay buffer (unprocessed) samples to the output buffer
334         */
335        if (pBuffer->InDelaySamples != 0)
336        {
337            Copy_16(&pBuffer->InDelayBuffer[0],                     /* Source */
338                    pDest,                                          /* Destination */
339                    (LVM_INT16)(2*pBuffer->InDelaySamples));        /* Number of delay samples */
340            pDest += 2 * pBuffer->InDelaySamples;                   /* Update the output pointer */
341        }
342
343
344        /*
345         * Calculate how many input samples to process and copy
346         */
347        NumSamples    = (LVM_INT16)(*pNumSamples - pBuffer->OutDelaySamples);  /* Number that will fit in the output buffer */
348        if (NumSamples >= pInstance->InternalBlockSize)
349        {
350            NumSamples = pInstance->InternalBlockSize;
351        }
352        NumFrames      = (LVM_INT16)(NumSamples >> MIN_INTERNAL_BLOCKSHIFT);
353        SampleCount   = (LVM_INT16)(NumFrames << MIN_INTERNAL_BLOCKSHIFT);
354        *pNumSamples  = (LVM_UINT16)SampleCount;                                        /* The number of samples to process */
355        pBuffer->SamplesToOutput = (LVM_INT16)(pBuffer->SamplesToOutput - SampleCount); /* Update the number of samples to output */
356        SampleCount   = (LVM_INT16)(SampleCount - pBuffer->InDelaySamples);             /* The number of samples to copy from the input */
357
358
359        /*
360         * Copy samples from the input buffer and update counts and pointers
361         */
362        Copy_16(pInstance->pInputSamples,                           /* Source */
363                pDest,                                              /* Destination */
364                (LVM_INT16)(2*SampleCount));                        /* Number of input samples */
365        pInstance->pInputSamples += 2 * SampleCount;                /* Update the input pointer */
366        pInstance->pOutputSamples = pDest + (2 * SampleCount);      /* Update the output pointer */
367        pInstance->SamplesToProcess = (LVM_INT16)(pInstance->SamplesToProcess - SampleCount); /* Samples left in the input buffer */
368    }
369    else
370    {
371        /*
372         * Second or subsequent call in optimised mode
373         */
374        if (pBuffer->SamplesToOutput >= MIN_INTERNAL_BLOCKSIZE)
375        {
376            /*
377             * More samples can be processed directly in the output buffer
378             */
379            *pToProcess = pInstance->pOutputSamples;                /* Set the address to start processing */
380            *pProcessed = pInstance->pOutputSamples;                /* Process in the output buffer, now inplace */
381            NumSamples  = pBuffer->SamplesToOutput;                 /* Number that will fit in the output buffer */
382            if (NumSamples >= pInstance->InternalBlockSize)
383            {
384                NumSamples = pInstance->InternalBlockSize;
385            }
386            NumFrames      = (LVM_INT16)(NumSamples >> MIN_INTERNAL_BLOCKSHIFT);
387            SampleCount   = (LVM_INT16)(NumFrames << MIN_INTERNAL_BLOCKSHIFT);
388            *pNumSamples  = (LVM_UINT16)SampleCount;            /* The number of samples to process */
389
390
391            /*
392             * Copy samples from the input buffer and update counts and pointers
393             */
394            Copy_16(pInstance->pInputSamples,                       /* Source */
395                    pInstance->pOutputSamples,                      /* Destination */
396                    (LVM_INT16)(2*SampleCount));                    /* Number of input samples */
397            pInstance->pInputSamples += 2 * SampleCount;            /* Update the input pointer */
398            pInstance->pOutputSamples += 2 * SampleCount;           /* Update the output pointer */
399            pInstance->SamplesToProcess = (LVM_INT16)(pInstance->SamplesToProcess - SampleCount);   /* Samples left in the input buffer */
400            pBuffer->SamplesToOutput = (LVM_INT16)(pBuffer->SamplesToOutput - SampleCount);         /* Number that will fit in the output buffer */
401        }
402        else
403        {
404            /*
405             * The remaining samples can not be processed in the output buffer
406             */
407            pBuffer->BufferState = LVM_LASTCALL;                    /* Indicate this is the last bock to process */
408            *pToProcess  = pBuffer->pScratch;                       /* Set the address to start processing */
409            *pProcessed  = pBuffer->pScratch;                       /* Process in the output buffer, now inplace */
410            NumSamples   = pInstance->SamplesToProcess;             /* Number left to be processed */
411            NumFrames     = (LVM_INT16)(NumSamples >> MIN_INTERNAL_BLOCKSHIFT);
412            SampleCount  = (LVM_INT16)(NumFrames << MIN_INTERNAL_BLOCKSHIFT);
413            *pNumSamples = (LVM_UINT16)SampleCount;                /* The number of samples to process */
414
415
416            /*
417             * Copy samples from the input buffer and update counts and pointers
418             */
419            Copy_16(pInstance->pInputSamples,                       /* Source */
420                    pBuffer->pScratch,                              /* Destination */
421                    (LVM_INT16)(2*SampleCount));                    /* Number of input samples */
422            pInstance->pInputSamples += 2 * SampleCount;            /* Update the input pointer */
423            pInstance->SamplesToProcess = (LVM_INT16)(pInstance->SamplesToProcess - SampleCount); /* Samples left in the input buffer */
424        }
425    }
426}
427
428/****************************************************************************************/
429/*                                                                                      */
430/* FUNCTION:                 LVM_BufferIn                                               */
431/*                                                                                      */
432/* DESCRIPTION:                                                                         */
433/*    This function manages the data input, it has the following features:              */
434/*        - Accepts data in 16-bit aligned memory                                       */
435/*        - Copies the data to 32-bit aligned memory                                    */
436/*        - Converts Mono inputs to Mono-in-Stereo                                      */
437/*        - Accepts any number of samples as input, except 0                            */
438/*        - Breaks the input sample stream in to blocks of the configured frame size or */
439/*          multiples of the frame size                                                 */
440/*        - Limits the processing block size to the maximum block size.                 */
441/*        - Works with inplace or outplace processing automatically                     */
442/*                                                                                      */
443/*  To manage the data the function has a number of operating states:                   */
444/*        LVM_FIRSTCALL        - The first call for this block of input samples         */
445/*        LVM_MAXBLOCKCALL    - The current block is the maximum size. Only used for the */
446/*                              second and subsequent blocks.                           */
447/*        LVM_LASTCALL        - The last call for this block of input samples           */
448/*        LVM_FIRSTLASTCALL    - This is the first and last call for this block of input*/
449/*                              samples, this occurs when the number of samples to      */
450/*                              process is less than the maximum block size.            */
451/*                                                                                      */
452/*    The function uses an internal delay buffer the size of the minimum frame, this is */
453/*  used to temporarily hold samples when the number of samples to process is not a     */
454/*  multiple of the frame size.                                                         */
455/*                                                                                      */
456/*    To ensure correct operation with inplace buffering the number of samples to output*/
457/*  per call is calculated in this function and is set to the number of samples read    */
458/*  from the input buffer.                                                              */
459/*                                                                                      */
460/*    The total number of samples to process is stored when the function is called for  */
461/*  the first time. The value is overwritten by the size of the block to be processed   */
462/*  in each call so the size of the processing blocks can be controlled. The number of  */
463/*    samples actually processed for each block of input samples is always a multiple of*/
464/*  the frame size so for any particular block of input samples the actual number of    */
465/*  processed samples may not match the number of input samples, sometime it will be    */
466/*  sometimes less. The average is the same and the difference is never more than the   */
467/*  frame size.                                                                         */
468/*                                                                                      */
469/* PARAMETERS:                                                                          */
470/*    hInstance        -    Instance handle                                             */
471/*    pInData            -    Pointer to the input data stream                          */
472/*  *pToProcess        -    Pointer to the start of data processing                     */
473/*  *pProcessed        -    Pointer to the destination of the processed data            */
474/*    pNumSamples        -    Pointer to the number of samples to process               */
475/*                                                                                      */
476/* RETURNS:                                                                             */
477/*    None                                                                              */
478/*                                                                                      */
479/* NOTES:                                                                               */
480/*                                                                                      */
481/****************************************************************************************/
482
483void LVM_BufferIn(LVM_Handle_t      hInstance,
484                  const LVM_INT16   *pInData,
485                  LVM_INT16         **pToProcess,
486                  LVM_INT16         **pProcessed,
487                  LVM_UINT16        *pNumSamples)
488{
489
490    LVM_Instance_t    *pInstance = (LVM_Instance_t  *)hInstance;
491
492
493    /*
494     * Check which mode, managed or unmanaged
495     */
496    if (pInstance->InstParams.BufferMode == LVM_MANAGED_BUFFERS)
497    {
498        LVM_BufferManagedIn(hInstance,
499                            pInData,
500                            pToProcess,
501                            pProcessed,
502                            pNumSamples);
503    }
504    else
505    {
506        LVM_BufferUnmanagedIn(hInstance,
507                              pToProcess,
508                              pProcessed,
509                              pNumSamples);
510    }
511}
512
513/****************************************************************************************/
514/*                                                                                      */
515/* FUNCTION:                 LVM_BufferManagedOut                                       */
516/*                                                                                      */
517/* DESCRIPTION:                                                                         */
518/*  Full buffer management output. This works in conjunction with the managed input     */
519/*  routine and ensures the correct number of samples are always output to the output   */
520/*  buffer.                                                                             */
521/*                                                                                      */
522/* PARAMETERS:                                                                          */
523/*    hInstance        - Instance handle                                                */
524/*    pOutData        - Pointer to the output data stream                               */
525/*    pNumSamples        - Pointer to the number of samples to process                  */
526/*                                                                                      */
527/* RETURNS:                                                                             */
528/*    None                                                                              */
529/*                                                                                      */
530/* NOTES:                                                                               */
531/*                                                                                      */
532/****************************************************************************************/
533
534void LVM_BufferManagedOut(LVM_Handle_t        hInstance,
535                          LVM_INT16            *pOutData,
536                          LVM_UINT16        *pNumSamples)
537{
538
539    LVM_Instance_t  *pInstance  = (LVM_Instance_t  *)hInstance;
540    LVM_Buffer_t    *pBuffer    = pInstance->pBufferManagement;
541    LVM_INT16       SampleCount = (LVM_INT16)*pNumSamples;
542    LVM_INT16       NumSamples;
543    LVM_INT16       *pStart;
544    LVM_INT16       *pDest;
545
546
547    /*
548     * Set the pointers
549     */
550    NumSamples = pBuffer->SamplesToOutput;
551    pStart     = pBuffer->pScratch;
552
553
554    /*
555     * check if it is the first call of a block
556      */
557    if ((pBuffer->BufferState == LVM_FIRSTCALL) ||
558        (pBuffer->BufferState == LVM_FIRSTLASTCALL))
559    {
560        /* First call for a new block */
561        pInstance->pOutputSamples = pOutData;                        /* Initialise the destination */
562    }
563    pDest = pInstance->pOutputSamples;                               /* Set the output address */
564
565
566    /*
567     * If the number of samples is non-zero then there are still samples to send to
568     * the output buffer
569     */
570    if ((NumSamples != 0) &&
571        (pBuffer->OutDelaySamples != 0))
572    {
573        /*
574         * Copy the delayed output buffer samples to the output
575         */
576        if (pBuffer->OutDelaySamples <= NumSamples)
577        {
578            /*
579             * Copy all output delay samples to the output
580             */
581            Copy_16(&pBuffer->OutDelayBuffer[0],                    /* Source */
582                    pDest,                                          /* Detsination */
583                    (LVM_INT16)(2*pBuffer->OutDelaySamples));       /* Number of delay samples */
584
585            /*
586             * Update the pointer and sample counts
587             */
588            pDest += 2*pBuffer->OutDelaySamples;                                /* Output sample pointer */
589            NumSamples = (LVM_INT16)(NumSamples - pBuffer->OutDelaySamples);    /* Samples left to send */
590            pBuffer->OutDelaySamples = 0;                                       /* No samples left in the buffer */
591
592        }
593        else
594        {
595            /*
596             * Copy only some of the ouput delay samples to the output
597             */
598            Copy_16(&pBuffer->OutDelayBuffer[0],                    /* Source */
599                    pDest,                                          /* Detsination */
600                    (LVM_INT16)(2*NumSamples));                     /* Number of delay samples */
601
602            /*
603             * Update the pointer and sample counts
604             */
605            pDest += 2*NumSamples;                                                              /* Output sample pointer */
606            pBuffer->OutDelaySamples = (LVM_INT16)(pBuffer->OutDelaySamples - NumSamples);      /* No samples left in the buffer */
607
608
609            /*
610             * Realign the delay buffer data to avoid using circular buffer management
611             */
612            Copy_16(&pBuffer->OutDelayBuffer[2*NumSamples],         /* Source */
613                    &pBuffer->OutDelayBuffer[0],                    /* Destination */
614                    (LVM_INT16)(2*pBuffer->OutDelaySamples));       /* Number of samples to move */
615            NumSamples = 0;                                         /* Samples left to send */
616        }
617    }
618
619
620    /*
621     * Copy the processed results to the output
622     */
623    if ((NumSamples != 0) &&
624        (SampleCount != 0))
625    {
626        if (SampleCount <= NumSamples)
627        {
628            /*
629             * Copy all processed samples to the output
630             */
631            Copy_16(pStart,                                      /* Source */
632                    pDest,                                       /* Detsination */
633                    (LVM_INT16)(2*SampleCount));                 /* Number of processed samples */
634
635            /*
636             * Update the pointer and sample counts
637             */
638            pDest      += 2 * SampleCount;                          /* Output sample pointer */
639            NumSamples  = (LVM_INT16)(NumSamples - SampleCount);    /* Samples left to send */
640            SampleCount = 0;                                        /* No samples left in the buffer */
641        }
642        else
643        {
644            /*
645             * Copy only some processed samples to the output
646             */
647            Copy_16(pStart,                                         /* Source */
648                    pDest,                                          /* Destination */
649                    (LVM_INT16)(2*NumSamples));                     /* Number of processed samples */
650
651
652            /*
653             * Update the pointers and sample counts
654               */
655            pStart      += 2 * NumSamples;                          /* Processed sample pointer */
656            pDest        += 2 * NumSamples;                         /* Output sample pointer */
657            SampleCount  = (LVM_INT16)(SampleCount - NumSamples);   /* Processed samples left */
658            NumSamples   = 0;                                       /* Clear the sample count */
659        }
660    }
661
662
663    /*
664     * Copy the remaining processed data to the output delay buffer
665     */
666    if (SampleCount != 0)
667    {
668        Copy_16(pStart,                                                 /* Source */
669                &pBuffer->OutDelayBuffer[2*pBuffer->OutDelaySamples],   /* Destination */
670                (LVM_INT16)(2*SampleCount));                            /* Number of processed samples */
671        pBuffer->OutDelaySamples = (LVM_INT16)(pBuffer->OutDelaySamples + SampleCount); /* Update the buffer count */
672    }
673
674
675    /*
676     * pointers, counts and set default buffer processing
677     */
678    pBuffer->SamplesToOutput  = NumSamples;                         /* Samples left to send */
679    pInstance->pOutputSamples = pDest;                              /* Output sample pointer */
680    pBuffer->BufferState      = LVM_MAXBLOCKCALL;                   /* Set for the default call block size */
681    *pNumSamples = (LVM_UINT16)pInstance->SamplesToProcess;         /* This will terminate the loop when all samples processed */
682}
683
684
685/****************************************************************************************/
686/*                                                                                      */
687/* FUNCTION:                 LVM_BufferUnmanagedOut                                     */
688/*                                                                                      */
689/* DESCRIPTION:                                                                         */
690/*  This works in conjunction with the unmanaged input routine and updates the number   */
691/*    of samples left to be processed    and adjusts the buffer pointers.               */
692/*                                                                                      */
693/* PARAMETERS:                                                                          */
694/*    hInstance        - Instance handle                                                */
695/*    pNumSamples        - Pointer to the number of samples to process                  */
696/*                                                                                      */
697/* RETURNS:                                                                             */
698/*    None                                                                              */
699/*                                                                                      */
700/* NOTES:                                                                               */
701/*                                                                                      */
702/****************************************************************************************/
703
704void LVM_BufferUnmanagedOut(LVM_Handle_t        hInstance,
705                            LVM_UINT16          *pNumSamples)
706{
707
708    LVM_Instance_t      *pInstance  = (LVM_Instance_t  *)hInstance;
709    LVM_INT16           NumChannels =2;
710
711
712    /*
713     * Update sample counts
714     */
715    pInstance->pInputSamples    += (LVM_INT16)(*pNumSamples * NumChannels); /* Update the I/O pointers */
716    pInstance->pOutputSamples   += (LVM_INT16)(*pNumSamples * 2);
717    pInstance->SamplesToProcess  = (LVM_INT16)(pInstance->SamplesToProcess - *pNumSamples); /* Update the sample count */
718
719    /*
720     * Set te block size to process
721     */
722    if (pInstance->SamplesToProcess > pInstance->InternalBlockSize)
723    {
724        *pNumSamples = (LVM_UINT16)pInstance->InternalBlockSize;
725    }
726    else
727    {
728        *pNumSamples = (LVM_UINT16)pInstance->SamplesToProcess;
729    }
730}
731
732
733/****************************************************************************************/
734/*                                                                                      */
735/* FUNCTION:                 LVM_BufferOptimisedOut                                     */
736/*                                                                                      */
737/* DESCRIPTION:                                                                         */
738/*  This works in conjunction with the optimised input routine and copies the last few  */
739/*  processed and unprocessed samples to their respective buffers.                      */
740/*                                                                                      */
741/* PARAMETERS:                                                                          */
742/*    hInstance        - Instance handle                                                */
743/*    pNumSamples        - Pointer to the number of samples to process                  */
744/*                                                                                      */
745/* RETURNS:                                                                             */
746/*    None                                                                              */
747/*                                                                                      */
748/* NOTES:                                                                               */
749/*                                                                                      */
750/****************************************************************************************/
751
752void LVM_BufferOptimisedOut(LVM_Handle_t    hInstance,
753                            LVM_UINT16        *pNumSamples)
754{
755
756    LVM_Instance_t      *pInstance = (LVM_Instance_t  *)hInstance;
757    LVM_Buffer_t        *pBuffer   = pInstance->pBufferManagement;
758
759    /*
760     * Check if it is the last block to process
761     */
762    if (pBuffer->BufferState == LVM_LASTCALL)
763    {
764        LVM_INT16    *pSrc = pBuffer->pScratch;
765
766        /*
767         * Copy the unprocessed samples to the input delay buffer
768         */
769        if (pInstance->SamplesToProcess != 0)
770        {
771            Copy_16(pInstance->pInputSamples,                       /* Source */
772                    &pBuffer->InDelayBuffer[0],                     /* Destination */
773                    (LVM_INT16)(2*pInstance->SamplesToProcess));    /* Number of input samples */
774            pBuffer->InDelaySamples = pInstance->SamplesToProcess;
775            pInstance->SamplesToProcess = 0;
776        }
777        else
778        {
779            pBuffer->InDelaySamples = 0;
780        }
781
782
783        /*
784         * Fill the last empty spaces in the output buffer
785         */
786        if (pBuffer->SamplesToOutput != 0)
787        {
788            Copy_16(pSrc,                                           /* Source */
789                    pInstance->pOutputSamples,                      /* Destination */
790                    (LVM_INT16)(2*pBuffer->SamplesToOutput));       /* Number of input samples */
791            *pNumSamples = (LVM_UINT16)(*pNumSamples - pBuffer->SamplesToOutput);
792            pSrc += 2 * pBuffer->SamplesToOutput;                  /* Update scratch pointer */
793            pBuffer->SamplesToOutput = 0;                          /* No more samples in this block */
794        }
795
796
797        /*
798         * Save any remaining processed samples in the output delay buffer
799         */
800        if (*pNumSamples != 0)
801        {
802            Copy_16(pSrc,                                           /* Source */
803                    &pBuffer->OutDelayBuffer[0],                    /* Destination */
804                    (LVM_INT16)(2**pNumSamples));                   /* Number of input samples */
805
806            pBuffer->OutDelaySamples = (LVM_INT16)*pNumSamples;
807
808            *pNumSamples = 0;                                      /* No more samples in this block */
809        }
810        else
811        {
812            pBuffer->OutDelaySamples = 0;
813        }
814    }
815}
816
817
818/****************************************************************************************/
819/*                                                                                      */
820/* FUNCTION:                 LVM_BufferOut                                              */
821/*                                                                                      */
822/* DESCRIPTION:                                                                         */
823/*  This function manages the data output, it has the following features:               */
824/*        - Output data to 16-bit aligned memory                                        */
825/*        - Reads data from 32-bit aligned memory                                       */
826/*        - Reads data only in blocks of frame size or multiples of frame size          */
827/*        - Writes the same number of samples as the LVM_BufferIn function reads        */
828/*        - Works with inplace or outplace processing automatically                     */
829/*                                                                                      */
830/*  To manage the data the function has a number of operating states:                   */
831/*        LVM_FIRSTCALL        - The first call for this block of input samples         */
832/*        LVM_FIRSTLASTCALL    - This is the first and last call for this block of input*/
833/*                              samples, this occurs when the number of samples to      */
834/*                              process is less than the maximum block size.            */
835/*                                                                                      */
836/*    The function uses an internal delay buffer the size of the minimum frame, this is */
837/*  used to temporarily hold samples when the number of samples to write is not a       */
838/*  multiple of the frame size.                                                         */
839/*                                                                                      */
840/*    To ensure correct operation with inplace buffering the number of samples to output*/
841/*  per call is always the same as the number of samples read from the input buffer.    */
842/*                                                                                      */
843/* PARAMETERS:                                                                          */
844/*    hInstance        - Instance handle                                                */
845/*    pOutData        - Pointer to the output data stream                               */
846/*    pNumSamples        - Pointer to the number of samples to process                  */
847/*                                                                                      */
848/* RETURNS:                                                                             */
849/*    None                                                                              */
850/*                                                                                      */
851/* NOTES:                                                                               */
852/*                                                                                      */
853/****************************************************************************************/
854
855void LVM_BufferOut(LVM_Handle_t     hInstance,
856                   LVM_INT16        *pOutData,
857                   LVM_UINT16       *pNumSamples)
858{
859
860    LVM_Instance_t    *pInstance  = (LVM_Instance_t  *)hInstance;
861
862
863    /*
864     * Check which mode, managed or unmanaged
865     */
866    if (pInstance->InstParams.BufferMode == LVM_MANAGED_BUFFERS)
867    {
868        LVM_BufferManagedOut(hInstance,
869                             pOutData,
870                             pNumSamples);
871    }
872    else
873    {
874        LVM_BufferUnmanagedOut(hInstance,
875                               pNumSamples);
876    }
877}
878
879