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 
LVM_BufferManagedIn(LVM_Handle_t hInstance,const LVM_INT16 * pInData,LVM_INT16 ** pToProcess,LVM_INT16 ** pProcessed,LVM_UINT16 * pNumSamples)52 void LVM_BufferManagedIn(LVM_Handle_t       hInstance,
53                          const LVM_INT16    *pInData,
54                          LVM_INT16          **pToProcess,
55                          LVM_INT16          **pProcessed,
56                          LVM_UINT16         *pNumSamples)
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 
LVM_BufferUnmanagedIn(LVM_Handle_t hInstance,LVM_INT16 ** pToProcess,LVM_INT16 ** pProcessed,LVM_UINT16 * pNumSamples)217 void 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 
LVM_BufferOptimisedIn(LVM_Handle_t hInstance,const LVM_INT16 * pInData,LVM_INT16 ** pToProcess,LVM_INT16 ** pProcessed,LVM_UINT16 * pNumSamples)281 void LVM_BufferOptimisedIn(LVM_Handle_t         hInstance,
282                            const LVM_INT16      *pInData,
283                            LVM_INT16            **pToProcess,
284                            LVM_INT16            **pProcessed,
285                            LVM_UINT16           *pNumSamples)
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 
LVM_BufferIn(LVM_Handle_t hInstance,const LVM_INT16 * pInData,LVM_INT16 ** pToProcess,LVM_INT16 ** pProcessed,LVM_UINT16 * pNumSamples)475 void LVM_BufferIn(LVM_Handle_t      hInstance,
476                   const LVM_INT16   *pInData,
477                   LVM_INT16         **pToProcess,
478                   LVM_INT16         **pProcessed,
479                   LVM_UINT16        *pNumSamples)
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 
LVM_BufferManagedOut(LVM_Handle_t hInstance,LVM_INT16 * pOutData,LVM_UINT16 * pNumSamples)526 void 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 
LVM_BufferUnmanagedOut(LVM_Handle_t hInstance,LVM_UINT16 * pNumSamples)696 void 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 
LVM_BufferOptimisedOut(LVM_Handle_t hInstance,LVM_UINT16 * pNumSamples)744 void 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 
LVM_BufferOut(LVM_Handle_t hInstance,LVM_INT16 * pOutData,LVM_UINT16 * pNumSamples)847 void 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