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 #include <log/log.h>
29 
30 /****************************************************************************************/
31 /*                                                                                      */
32 /* FUNCTION:                 LVM_BufferManagedIn                                        */
33 /*                                                                                      */
34 /* DESCRIPTION:                                                                         */
35 /*    Full buffer management allowing the user to provide input and output buffers on   */
36 /*  any alignment and with any number of samples. The alignment is corrected within     */
37 /*  the buffer management and the samples are grouped in to blocks of the correct size  */
38 /*  before processing.                                                                  */
39 /*                                                                                      */
40 /* PARAMETERS:                                                                          */
41 /*    hInstance        -    Instance handle                                             */
42 /*    pInData            -    Pointer to the input data stream                          */
43 /*  *pToProcess        -    Pointer to pointer to the start of data processing          */
44 /*  *pProcessed        -    Pointer to pointer to the destination of the processed data */
45 /*    pNumSamples        -    Pointer to the number of samples to process               */
46 /*                                                                                      */
47 /* RETURNS:                                                                             */
48 /*    None                                                                              */
49 /*                                                                                      */
50 /* NOTES:                                                                               */
51 /*                                                                                      */
52 /****************************************************************************************/
53 #ifdef BUILD_FLOAT
LVM_BufferManagedIn(LVM_Handle_t hInstance,const LVM_FLOAT * pInData,LVM_FLOAT ** pToProcess,LVM_FLOAT ** pProcessed,LVM_UINT16 * pNumSamples)54 void LVM_BufferManagedIn(LVM_Handle_t       hInstance,
55                          const LVM_FLOAT    *pInData,
56                          LVM_FLOAT          **pToProcess,
57                          LVM_FLOAT          **pProcessed,
58                          LVM_UINT16         *pNumSamples)
59 {
60 
61     LVM_INT16        SampleCount;           /* Number of samples to be processed this call */
62     LVM_INT16        NumSamples;            /* Number of samples in scratch buffer */
63     LVM_FLOAT        *pStart;
64     LVM_Instance_t   *pInstance = (LVM_Instance_t  *)hInstance;
65     LVM_Buffer_t     *pBuffer;
66     LVM_FLOAT        *pDest;
67 #ifdef SUPPORT_MC
68     LVM_INT16        NumChannels = pInstance->NrChannels;
69 #else
70     LVM_INT16        NumChannels = 2;
71 #endif
72 
73     /*
74      * Set the processing address pointers
75      */
76     pBuffer     = pInstance->pBufferManagement;
77     pDest       = pBuffer->pScratch;
78     *pToProcess = pBuffer->pScratch;
79     *pProcessed = pBuffer->pScratch;
80 
81     /*
82      * Check if it is the first call of a block
83      */
84     if (pInstance->SamplesToProcess == 0)
85     {
86         /*
87          * First call for a new block of samples
88          */
89         pInstance->SamplesToProcess = (LVM_INT16)(*pNumSamples + pBuffer->InDelaySamples);
90         pInstance->pInputSamples    = (LVM_FLOAT *)pInData;
91         pBuffer->BufferState        = LVM_FIRSTCALL;
92     }
93     pStart = pInstance->pInputSamples;                 /* Pointer to the input samples */
94     pBuffer->SamplesToOutput  = 0;                     /* Samples to output is same as
95                                                           number read for inplace processing */
96 
97 
98     /*
99      * Calculate the number of samples to process this call and update the buffer state
100      */
101     if (pInstance->SamplesToProcess > pInstance->InternalBlockSize)
102     {
103         /*
104          * Process the maximum bock size of samples.
105          */
106         SampleCount = pInstance->InternalBlockSize;
107         NumSamples  = pInstance->InternalBlockSize;
108     }
109     else
110     {
111         /*
112          * Last call for the block, so calculate how many frames and samples to process
113           */
114         LVM_INT16   NumFrames;
115 
116         NumSamples  = pInstance->SamplesToProcess;
117         NumFrames    = (LVM_INT16)(NumSamples >> MIN_INTERNAL_BLOCKSHIFT);
118         SampleCount = (LVM_INT16)(NumFrames << MIN_INTERNAL_BLOCKSHIFT);
119 
120         /*
121          * Update the buffer state
122          */
123         if (pBuffer->BufferState == LVM_FIRSTCALL)
124         {
125             pBuffer->BufferState = LVM_FIRSTLASTCALL;
126         }
127         else
128         {
129             pBuffer->BufferState = LVM_LASTCALL;
130         }
131     }
132     *pNumSamples = (LVM_UINT16)SampleCount;  /* Set the number of samples to process this call */
133 
134 
135     /*
136      * Copy samples from the delay buffer as required
137      */
138     if (((pBuffer->BufferState == LVM_FIRSTCALL) ||
139         (pBuffer->BufferState == LVM_FIRSTLASTCALL)) &&
140         (pBuffer->InDelaySamples != 0))
141     {
142         Copy_Float(&pBuffer->InDelayBuffer[0],                             /* Source */
143                    pDest,                                                  /* Destination */
144                    (LVM_INT16)(NumChannels * pBuffer->InDelaySamples));    /* Number of delay \
145                                                                        samples, left and right */
146         NumSamples = (LVM_INT16)(NumSamples - pBuffer->InDelaySamples); /* Update sample count */
147         pDest += NumChannels * pBuffer->InDelaySamples;      /* Update the destination pointer */
148     }
149 
150 
151     /*
152      * Copy the rest of the samples for this call from the input buffer
153      */
154     if (NumSamples > 0)
155     {
156         Copy_Float(pStart,                                      /* Source */
157                    pDest,                                       /* Destination */
158                    (LVM_INT16)(NumChannels * NumSamples));      /* Number of input samples */
159         pStart += NumChannels * NumSamples;                     /* Update the input pointer */
160 
161         /*
162          * Update the input data pointer and samples to output
163          */
164         /* Update samples to output */
165         pBuffer->SamplesToOutput = (LVM_INT16)(pBuffer->SamplesToOutput + NumSamples);
166     }
167 
168 
169     /*
170       * Update the sample count and input pointer
171      */
172     /* Update the count of samples */
173     pInstance->SamplesToProcess  = (LVM_INT16)(pInstance->SamplesToProcess - SampleCount);
174     pInstance->pInputSamples     = pStart; /* Update input sample pointer */
175 
176 
177     /*
178      * Save samples to the delay buffer if any left unprocessed
179      */
180     if ((pBuffer->BufferState == LVM_FIRSTLASTCALL) ||
181         (pBuffer->BufferState == LVM_LASTCALL))
182     {
183         NumSamples = pInstance->SamplesToProcess;
184         pStart     = pBuffer->pScratch;                             /* Start of the buffer */
185         pStart    += NumChannels * SampleCount; /* Offset by the number of processed samples */
186         if (NumSamples != 0)
187         {
188             Copy_Float(pStart,                                         /* Source */
189                        &pBuffer->InDelayBuffer[0],                     /* Destination */
190                        (LVM_INT16)(NumChannels * NumSamples));   /* Number of input samples */
191         }
192 
193 
194         /*
195          * Update the delay sample count
196          */
197         pBuffer->InDelaySamples     = NumSamples;       /* Number of delay sample pairs */
198         pInstance->SamplesToProcess = 0;                            /* All Samples used */
199     }
200 }
201 #else
LVM_BufferManagedIn(LVM_Handle_t hInstance,const LVM_INT16 * pInData,LVM_INT16 ** pToProcess,LVM_INT16 ** pProcessed,LVM_UINT16 * pNumSamples)202 void LVM_BufferManagedIn(LVM_Handle_t       hInstance,
203                          const LVM_INT16    *pInData,
204                          LVM_INT16          **pToProcess,
205                          LVM_INT16          **pProcessed,
206                          LVM_UINT16         *pNumSamples)
207 {
208 
209     LVM_INT16        SampleCount;           /* Number of samples to be processed this call */
210     LVM_INT16        NumSamples;            /* Number of samples in scratch buffer */
211     LVM_INT16        *pStart;
212     LVM_Instance_t   *pInstance = (LVM_Instance_t  *)hInstance;
213     LVM_Buffer_t     *pBuffer;
214     LVM_INT16        *pDest;
215     LVM_INT16        NumChannels = 2;
216 
217     /*
218      * Set the processing address pointers
219      */
220     pBuffer     = pInstance->pBufferManagement;
221     pDest       = pBuffer->pScratch;
222     *pToProcess = pBuffer->pScratch;
223     *pProcessed = pBuffer->pScratch;
224 
225     /*
226      * Check if it is the first call of a block
227      */
228     if (pInstance->SamplesToProcess == 0)
229     {
230         /*
231          * First call for a new block of samples
232          */
233         pInstance->SamplesToProcess = (LVM_INT16)(*pNumSamples + pBuffer->InDelaySamples);
234         pInstance->pInputSamples    = (LVM_INT16 *)pInData;
235         pBuffer->BufferState        = LVM_FIRSTCALL;
236     }
237     pStart = pInstance->pInputSamples;                       /* Pointer to the input samples */
238     pBuffer->SamplesToOutput  = 0;                           /* Samples to output is same as number read for inplace processing */
239 
240 
241     /*
242      * Calculate the number of samples to process this call and update the buffer state
243      */
244     if (pInstance->SamplesToProcess > pInstance->InternalBlockSize)
245     {
246         /*
247          * Process the maximum bock size of samples.
248          */
249         SampleCount = pInstance->InternalBlockSize;
250         NumSamples  = pInstance->InternalBlockSize;
251     }
252     else
253     {
254         /*
255          * Last call for the block, so calculate how many frames and samples to process
256           */
257         LVM_INT16   NumFrames;
258 
259         NumSamples  = pInstance->SamplesToProcess;
260         NumFrames    = (LVM_INT16)(NumSamples >> MIN_INTERNAL_BLOCKSHIFT);
261         SampleCount = (LVM_INT16)(NumFrames << MIN_INTERNAL_BLOCKSHIFT);
262 
263         /*
264          * Update the buffer state
265          */
266         if (pBuffer->BufferState == LVM_FIRSTCALL)
267         {
268             pBuffer->BufferState = LVM_FIRSTLASTCALL;
269         }
270         else
271         {
272             pBuffer->BufferState = LVM_LASTCALL;
273         }
274     }
275     *pNumSamples = (LVM_UINT16)SampleCount;                        /* Set the number of samples to process this call */
276 
277 
278     /*
279      * Copy samples from the delay buffer as required
280      */
281     if (((pBuffer->BufferState == LVM_FIRSTCALL) ||
282         (pBuffer->BufferState == LVM_FIRSTLASTCALL)) &&
283         (pBuffer->InDelaySamples != 0))
284     {
285         Copy_16(&pBuffer->InDelayBuffer[0],                             /* Source */
286                 pDest,                                                  /* Destination */
287                 (LVM_INT16)(NumChannels*pBuffer->InDelaySamples));      /* Number of delay samples, left and right */
288         NumSamples = (LVM_INT16)(NumSamples - pBuffer->InDelaySamples); /* Update sample count */
289         pDest += NumChannels * pBuffer->InDelaySamples;                 /* Update the destination pointer */
290     }
291 
292 
293     /*
294      * Copy the rest of the samples for this call from the input buffer
295      */
296     if (NumSamples > 0)
297     {
298         Copy_16(pStart,                                             /* Source */
299                 pDest,                                              /* Destination */
300                 (LVM_INT16)(NumChannels*NumSamples));               /* Number of input samples */
301         pStart += NumChannels * NumSamples;                         /* Update the input pointer */
302 
303         /*
304          * Update the input data pointer and samples to output
305          */
306         pBuffer->SamplesToOutput = (LVM_INT16)(pBuffer->SamplesToOutput + NumSamples); /* Update samples to output */
307     }
308 
309 
310     /*
311       * Update the sample count and input pointer
312      */
313     pInstance->SamplesToProcess  = (LVM_INT16)(pInstance->SamplesToProcess - SampleCount);      /* Update the count of samples */
314     pInstance->pInputSamples     = pStart;                                                      /* Update input sample pointer */
315 
316 
317     /*
318      * Save samples to the delay buffer if any left unprocessed
319      */
320     if ((pBuffer->BufferState == LVM_FIRSTLASTCALL) ||
321         (pBuffer->BufferState == LVM_LASTCALL))
322     {
323         NumSamples = pInstance->SamplesToProcess;
324         pStart     = pBuffer->pScratch;                             /* Start of the buffer */
325         pStart    += NumChannels*SampleCount;                       /* Offset by the number of processed samples */
326         if (NumSamples != 0)
327         {
328             Copy_16(pStart,                                         /* Source */
329                     &pBuffer->InDelayBuffer[0],                     /* Destination */
330                     (LVM_INT16)(NumChannels*NumSamples));           /* Number of input samples */
331         }
332 
333 
334         /*
335          * Update the delay sample count
336          */
337         pBuffer->InDelaySamples     = NumSamples;                   /* Number of delay sample pairs */
338         pInstance->SamplesToProcess = 0;                            /* All Samples used */
339     }
340 }
341 #endif
342 
343 /****************************************************************************************/
344 /*                                                                                      */
345 /* FUNCTION:                 LVM_BufferUnmanagedIn                                      */
346 /*                                                                                      */
347 /* DESCRIPTION:                                                                         */
348 /*    This mode is selected by the user code and disables the buffer management with the */
349 /*  exception of the maximum block size processing. The user must ensure that the       */
350 /*  input and output buffers are 32-bit aligned and also that the number of samples to  */
351 /*    process is a correct multiple of samples.                                         */
352 /*                                                                                      */
353 /* PARAMETERS:                                                                          */
354 /*    hInstance        -    Instance handle                                             */
355 /*  *pToProcess        -    Pointer to the start of data processing                     */
356 /*  *pProcessed        -    Pointer to the destination of the processed data            */
357 /*    pNumSamples        -    Pointer to the number of samples to process               */
358 /*                                                                                      */
359 /* RETURNS:                                                                             */
360 /*    None                                                                              */
361 /*                                                                                      */
362 /* NOTES:                                                                               */
363 /*                                                                                      */
364 /****************************************************************************************/
365 #ifdef BUILD_FLOAT
LVM_BufferUnmanagedIn(LVM_Handle_t hInstance,LVM_FLOAT ** pToProcess,LVM_FLOAT ** pProcessed,LVM_UINT16 * pNumSamples)366 void LVM_BufferUnmanagedIn(LVM_Handle_t     hInstance,
367                            LVM_FLOAT        **pToProcess,
368                            LVM_FLOAT        **pProcessed,
369                            LVM_UINT16       *pNumSamples)
370 {
371 
372     LVM_Instance_t    *pInstance = (LVM_Instance_t  *)hInstance;
373 
374 
375     /*
376      * Check if this is the first call of a block
377      */
378     if (pInstance->SamplesToProcess == 0)
379     {
380         pInstance->SamplesToProcess = (LVM_INT16)*pNumSamples;    /* Get the number of samples
381                                                                                on first call */
382         pInstance->pInputSamples    = *pToProcess;                /* Get the I/O pointers */
383         pInstance->pOutputSamples    = *pProcessed;
384 
385 
386         /*
387          * Set te block size to process
388          */
389         if (pInstance->SamplesToProcess > pInstance->InternalBlockSize)
390         {
391             *pNumSamples = (LVM_UINT16)pInstance->InternalBlockSize;
392         }
393         else
394         {
395             *pNumSamples = (LVM_UINT16)pInstance->SamplesToProcess;
396         }
397     }
398 
399     /*
400      * Set the process pointers
401      */
402     *pToProcess = pInstance->pInputSamples;
403     *pProcessed = pInstance->pOutputSamples;
404 }
405 #else
LVM_BufferUnmanagedIn(LVM_Handle_t hInstance,LVM_INT16 ** pToProcess,LVM_INT16 ** pProcessed,LVM_UINT16 * pNumSamples)406 void LVM_BufferUnmanagedIn(LVM_Handle_t     hInstance,
407                            LVM_INT16        **pToProcess,
408                            LVM_INT16        **pProcessed,
409                            LVM_UINT16       *pNumSamples)
410 {
411 
412     LVM_Instance_t    *pInstance = (LVM_Instance_t  *)hInstance;
413 
414 
415     /*
416      * Check if this is the first call of a block
417      */
418     if (pInstance->SamplesToProcess == 0)
419     {
420         pInstance->SamplesToProcess = (LVM_INT16)*pNumSamples;       /* Get the number of samples on first call */
421         pInstance->pInputSamples    = *pToProcess;                   /* Get the I/O pointers */
422         pInstance->pOutputSamples    = *pProcessed;
423 
424 
425         /*
426          * Set te block size to process
427          */
428         if (pInstance->SamplesToProcess > pInstance->InternalBlockSize)
429         {
430             *pNumSamples = (LVM_UINT16)pInstance->InternalBlockSize;
431         }
432         else
433         {
434             *pNumSamples = (LVM_UINT16)pInstance->SamplesToProcess;
435         }
436     }
437 
438     /*
439      * Set the process pointers
440      */
441     *pToProcess = pInstance->pInputSamples;
442     *pProcessed = pInstance->pOutputSamples;
443 }
444 #endif
445 
446 /****************************************************************************************/
447 /*                                                                                      */
448 /* FUNCTION:                 LVM_BufferOptimisedIn                                      */
449 /*                                                                                      */
450 /* DESCRIPTION:                                                                         */
451 /*    Optimised buffer management for the case where the data is outplace processing,   */
452 /*    the output data is 32-bit aligned and there are sufficient samples to allow some  */
453 /*    processing directly in the output buffer. This saves one data copy per sample     */
454 /*    compared with the unoptimsed version.                                             */
455 /*                                                                                      */
456 /* PARAMETERS:                                                                          */
457 /*    hInstance        -    Instance handle                                             */
458 /*    pInData            -    Pointer to the input data stream                          */
459 /*  *pToProcess        -    Pointer to the start of data processing                     */
460 /*  *pProcessed        -    Pointer to the destination of the processed data            */
461 /*    pNumSamples        -    Pointer to the number of samples to process               */
462 /*                                                                                      */
463 /* RETURNS:                                                                             */
464 /*    None                                                                              */
465 /*                                                                                      */
466 /* NOTES:                                                                               */
467 /*                                                                                      */
468 /****************************************************************************************/
469 
470 #ifndef BUILD_FLOAT
LVM_BufferOptimisedIn(LVM_Handle_t hInstance,const LVM_INT16 * pInData,LVM_INT16 ** pToProcess,LVM_INT16 ** pProcessed,LVM_UINT16 * pNumSamples)471 void LVM_BufferOptimisedIn(LVM_Handle_t         hInstance,
472                            const LVM_INT16      *pInData,
473                            LVM_INT16            **pToProcess,
474                            LVM_INT16            **pProcessed,
475                            LVM_UINT16           *pNumSamples)
476 {
477 
478     LVM_Instance_t   *pInstance = (LVM_Instance_t  *)hInstance;
479     LVM_Buffer_t     *pBuffer    = pInstance->pBufferManagement;
480     LVM_INT16        *pDest;
481     LVM_INT16        SampleCount;
482     LVM_INT16        NumSamples;
483     LVM_INT16        NumFrames;
484 
485     /*
486      * Check if it is the first call for this block
487      */
488     if (pInstance->SamplesToProcess == 0)
489     {
490         /*
491          * First call for a new block of samples
492          */
493         pBuffer->BufferState = LVM_FIRSTCALL;
494         pInstance->pInputSamples    = (LVM_INT16 *)pInData;
495         pInstance->SamplesToProcess = (LVM_INT16)*pNumSamples;
496         pBuffer->SamplesToOutput    = (LVM_INT16)*pNumSamples;
497         pDest = *pProcessed;                                    /* The start of the output buffer */
498 
499 
500         /*
501          * Copy the already processed samples to the output buffer
502          */
503         if (pBuffer->OutDelaySamples != 0)
504         {
505             Copy_16(&pBuffer->OutDelayBuffer[0],                    /* Source */
506                     pDest,                                          /* Destination */
507                     (LVM_INT16)(2*pBuffer->OutDelaySamples));       /* Number of delay samples */
508             pDest += 2 * pBuffer->OutDelaySamples;                  /* Update the output pointer */
509             pBuffer->SamplesToOutput = (LVM_INT16)(pBuffer->SamplesToOutput - pBuffer->OutDelaySamples); /* Update the numbr of samples to output */
510         }
511         *pToProcess = pDest;                                    /* Set the address to start processing */
512         *pProcessed = pDest;                                    /* Process in the output buffer, now inplace */
513 
514         /*
515          * Copy the input delay buffer (unprocessed) samples to the output buffer
516          */
517         if (pBuffer->InDelaySamples != 0)
518         {
519             Copy_16(&pBuffer->InDelayBuffer[0],                     /* Source */
520                     pDest,                                          /* Destination */
521                     (LVM_INT16)(2*pBuffer->InDelaySamples));        /* Number of delay samples */
522             pDest += 2 * pBuffer->InDelaySamples;                   /* Update the output pointer */
523         }
524 
525 
526         /*
527          * Calculate how many input samples to process and copy
528          */
529         NumSamples    = (LVM_INT16)(*pNumSamples - pBuffer->OutDelaySamples);  /* Number that will fit in the output buffer */
530         if (NumSamples >= pInstance->InternalBlockSize)
531         {
532             NumSamples = pInstance->InternalBlockSize;
533         }
534         NumFrames      = (LVM_INT16)(NumSamples >> MIN_INTERNAL_BLOCKSHIFT);
535         SampleCount   = (LVM_INT16)(NumFrames << MIN_INTERNAL_BLOCKSHIFT);
536         *pNumSamples  = (LVM_UINT16)SampleCount;                                        /* The number of samples to process */
537         pBuffer->SamplesToOutput = (LVM_INT16)(pBuffer->SamplesToOutput - SampleCount); /* Update the number of samples to output */
538         SampleCount   = (LVM_INT16)(SampleCount - pBuffer->InDelaySamples);             /* The number of samples to copy from the input */
539 
540 
541         /*
542          * Copy samples from the input buffer and update counts and pointers
543          */
544         Copy_16(pInstance->pInputSamples,                           /* Source */
545                 pDest,                                              /* Destination */
546                 (LVM_INT16)(2*SampleCount));                        /* Number of input samples */
547         pInstance->pInputSamples += 2 * SampleCount;                /* Update the input pointer */
548         pInstance->pOutputSamples = pDest + (2 * SampleCount);      /* Update the output pointer */
549         pInstance->SamplesToProcess = (LVM_INT16)(pInstance->SamplesToProcess - SampleCount); /* Samples left in the input buffer */
550     }
551     else
552     {
553         /*
554          * Second or subsequent call in optimised mode
555          */
556         if (pBuffer->SamplesToOutput >= MIN_INTERNAL_BLOCKSIZE)
557         {
558             /*
559              * More samples can be processed directly in the output buffer
560              */
561             *pToProcess = pInstance->pOutputSamples;                /* Set the address to start processing */
562             *pProcessed = pInstance->pOutputSamples;                /* Process in the output buffer, now inplace */
563             NumSamples  = pBuffer->SamplesToOutput;                 /* Number that will fit in the output buffer */
564             if (NumSamples >= pInstance->InternalBlockSize)
565             {
566                 NumSamples = pInstance->InternalBlockSize;
567             }
568             NumFrames      = (LVM_INT16)(NumSamples >> MIN_INTERNAL_BLOCKSHIFT);
569             SampleCount   = (LVM_INT16)(NumFrames << MIN_INTERNAL_BLOCKSHIFT);
570             *pNumSamples  = (LVM_UINT16)SampleCount;            /* The number of samples to process */
571 
572 
573             /*
574              * Copy samples from the input buffer and update counts and pointers
575              */
576             Copy_16(pInstance->pInputSamples,                       /* Source */
577                     pInstance->pOutputSamples,                      /* Destination */
578                     (LVM_INT16)(2*SampleCount));                    /* Number of input samples */
579             pInstance->pInputSamples += 2 * SampleCount;            /* Update the input pointer */
580             pInstance->pOutputSamples += 2 * SampleCount;           /* Update the output pointer */
581             pInstance->SamplesToProcess = (LVM_INT16)(pInstance->SamplesToProcess - SampleCount);   /* Samples left in the input buffer */
582             pBuffer->SamplesToOutput = (LVM_INT16)(pBuffer->SamplesToOutput - SampleCount);         /* Number that will fit in the output buffer */
583         }
584         else
585         {
586             /*
587              * The remaining samples can not be processed in the output buffer
588              */
589             pBuffer->BufferState = LVM_LASTCALL;                    /* Indicate this is the last bock to process */
590             *pToProcess  = pBuffer->pScratch;                       /* Set the address to start processing */
591             *pProcessed  = pBuffer->pScratch;                       /* Process in the output buffer, now inplace */
592             NumSamples   = pInstance->SamplesToProcess;             /* Number left to be processed */
593             NumFrames     = (LVM_INT16)(NumSamples >> MIN_INTERNAL_BLOCKSHIFT);
594             SampleCount  = (LVM_INT16)(NumFrames << MIN_INTERNAL_BLOCKSHIFT);
595             *pNumSamples = (LVM_UINT16)SampleCount;                /* The number of samples to process */
596 
597 
598             /*
599              * Copy samples from the input buffer and update counts and pointers
600              */
601             Copy_16(pInstance->pInputSamples,                       /* Source */
602                     pBuffer->pScratch,                              /* Destination */
603                     (LVM_INT16)(2*SampleCount));                    /* Number of input samples */
604             pInstance->pInputSamples += 2 * SampleCount;            /* Update the input pointer */
605             pInstance->SamplesToProcess = (LVM_INT16)(pInstance->SamplesToProcess - SampleCount); /* Samples left in the input buffer */
606         }
607     }
608 }
609 #endif
610 /****************************************************************************************/
611 /*                                                                                      */
612 /* FUNCTION:                 LVM_BufferIn                                               */
613 /*                                                                                      */
614 /* DESCRIPTION:                                                                         */
615 /*    This function manages the data input, it has the following features:              */
616 /*        - Accepts data in 16-bit aligned memory                                       */
617 /*        - Copies the data to 32-bit aligned memory                                    */
618 /*        - Converts Mono inputs to Mono-in-Stereo                                      */
619 /*        - Accepts any number of samples as input, except 0                            */
620 /*        - Breaks the input sample stream in to blocks of the configured frame size or */
621 /*          multiples of the frame size                                                 */
622 /*        - Limits the processing block size to the maximum block size.                 */
623 /*        - Works with inplace or outplace processing automatically                     */
624 /*                                                                                      */
625 /*  To manage the data the function has a number of operating states:                   */
626 /*        LVM_FIRSTCALL        - The first call for this block of input samples         */
627 /*        LVM_MAXBLOCKCALL    - The current block is the maximum size. Only used for the */
628 /*                              second and subsequent blocks.                           */
629 /*        LVM_LASTCALL        - The last call for this block of input samples           */
630 /*        LVM_FIRSTLASTCALL    - This is the first and last call for this block of input*/
631 /*                              samples, this occurs when the number of samples to      */
632 /*                              process is less than the maximum block size.            */
633 /*                                                                                      */
634 /*    The function uses an internal delay buffer the size of the minimum frame, this is */
635 /*  used to temporarily hold samples when the number of samples to process is not a     */
636 /*  multiple of the frame size.                                                         */
637 /*                                                                                      */
638 /*    To ensure correct operation with inplace buffering the number of samples to output*/
639 /*  per call is calculated in this function and is set to the number of samples read    */
640 /*  from the input buffer.                                                              */
641 /*                                                                                      */
642 /*    The total number of samples to process is stored when the function is called for  */
643 /*  the first time. The value is overwritten by the size of the block to be processed   */
644 /*  in each call so the size of the processing blocks can be controlled. The number of  */
645 /*    samples actually processed for each block of input samples is always a multiple of*/
646 /*  the frame size so for any particular block of input samples the actual number of    */
647 /*  processed samples may not match the number of input samples, sometime it will be    */
648 /*  sometimes less. The average is the same and the difference is never more than the   */
649 /*  frame size.                                                                         */
650 /*                                                                                      */
651 /* PARAMETERS:                                                                          */
652 /*    hInstance        -    Instance handle                                             */
653 /*    pInData            -    Pointer to the input data stream                          */
654 /*  *pToProcess        -    Pointer to the start of data processing                     */
655 /*  *pProcessed        -    Pointer to the destination of the processed data            */
656 /*    pNumSamples        -    Pointer to the number of samples to process               */
657 /*                                                                                      */
658 /* RETURNS:                                                                             */
659 /*    None                                                                              */
660 /*                                                                                      */
661 /* NOTES:                                                                               */
662 /*                                                                                      */
663 /****************************************************************************************/
664 #ifdef BUILD_FLOAT
LVM_BufferIn(LVM_Handle_t hInstance,const LVM_FLOAT * pInData,LVM_FLOAT ** pToProcess,LVM_FLOAT ** pProcessed,LVM_UINT16 * pNumSamples)665 void LVM_BufferIn(LVM_Handle_t      hInstance,
666                   const LVM_FLOAT   *pInData,
667                   LVM_FLOAT         **pToProcess,
668                   LVM_FLOAT         **pProcessed,
669                   LVM_UINT16        *pNumSamples)
670 {
671 
672     LVM_Instance_t    *pInstance = (LVM_Instance_t  *)hInstance;
673 
674 
675     /*
676      * Check which mode, managed or unmanaged
677      */
678     if (pInstance->InstParams.BufferMode == LVM_MANAGED_BUFFERS)
679     {
680         LVM_BufferManagedIn(hInstance,
681                             pInData,
682                             pToProcess,
683                             pProcessed,
684                             pNumSamples);
685     }
686     else
687     {
688         LVM_BufferUnmanagedIn(hInstance,
689                               pToProcess,
690                               pProcessed,
691                               pNumSamples);
692     }
693 }
694 #else
LVM_BufferIn(LVM_Handle_t hInstance,const LVM_INT16 * pInData,LVM_INT16 ** pToProcess,LVM_INT16 ** pProcessed,LVM_UINT16 * pNumSamples)695 void LVM_BufferIn(LVM_Handle_t      hInstance,
696                   const LVM_INT16   *pInData,
697                   LVM_INT16         **pToProcess,
698                   LVM_INT16         **pProcessed,
699                   LVM_UINT16        *pNumSamples)
700 {
701 
702     LVM_Instance_t    *pInstance = (LVM_Instance_t  *)hInstance;
703 
704 
705     /*
706      * Check which mode, managed or unmanaged
707      */
708     if (pInstance->InstParams.BufferMode == LVM_MANAGED_BUFFERS)
709     {
710         LVM_BufferManagedIn(hInstance,
711                             pInData,
712                             pToProcess,
713                             pProcessed,
714                             pNumSamples);
715     }
716     else
717     {
718         LVM_BufferUnmanagedIn(hInstance,
719                               pToProcess,
720                               pProcessed,
721                               pNumSamples);
722     }
723 }
724 #endif
725 /****************************************************************************************/
726 /*                                                                                      */
727 /* FUNCTION:                 LVM_BufferManagedOut                                       */
728 /*                                                                                      */
729 /* DESCRIPTION:                                                                         */
730 /*  Full buffer management output. This works in conjunction with the managed input     */
731 /*  routine and ensures the correct number of samples are always output to the output   */
732 /*  buffer.                                                                             */
733 /*                                                                                      */
734 /* PARAMETERS:                                                                          */
735 /*    hInstance        - Instance handle                                                */
736 /*    pOutData        - Pointer to the output data stream                               */
737 /*    pNumSamples        - Pointer to the number of samples to process                  */
738 /*                                                                                      */
739 /* RETURNS:                                                                             */
740 /*    None                                                                              */
741 /*                                                                                      */
742 /* NOTES:                                                                               */
743 /*                                                                                      */
744 /****************************************************************************************/
745 #ifdef BUILD_FLOAT
LVM_BufferManagedOut(LVM_Handle_t hInstance,LVM_FLOAT * pOutData,LVM_UINT16 * pNumSamples)746 void LVM_BufferManagedOut(LVM_Handle_t        hInstance,
747                           LVM_FLOAT            *pOutData,
748                           LVM_UINT16        *pNumSamples)
749 {
750 
751     LVM_Instance_t  *pInstance  = (LVM_Instance_t  *)hInstance;
752     LVM_Buffer_t    *pBuffer    = pInstance->pBufferManagement;
753     LVM_INT16       SampleCount = (LVM_INT16)*pNumSamples;
754     LVM_INT16       NumSamples;
755     LVM_FLOAT       *pStart;
756     LVM_FLOAT       *pDest;
757 #ifdef SUPPORT_MC
758     LVM_INT32       NrChannels = pInstance->NrChannels;
759 #define NrFrames NumSamples  // alias for clarity
760 #define FrameCount SampleCount
761 #endif
762 
763     /*
764      * Set the pointers
765      */
766     NumSamples = pBuffer->SamplesToOutput;
767     pStart     = pBuffer->pScratch;
768 
769     /*
770      * check if it is the first call of a block
771       */
772     if ((pBuffer->BufferState == LVM_FIRSTCALL) ||
773         (pBuffer->BufferState == LVM_FIRSTLASTCALL))
774     {
775         /* First call for a new block */
776         pInstance->pOutputSamples = pOutData;                 /* Initialise the destination */
777     }
778     pDest = pInstance->pOutputSamples;                        /* Set the output address */
779 
780 
781     /*
782      * If the number of samples is non-zero then there are still samples to send to
783      * the output buffer
784      */
785     if ((NumSamples != 0) &&
786         (pBuffer->OutDelaySamples != 0))
787     {
788         /*
789          * Copy the delayed output buffer samples to the output
790          */
791         if (pBuffer->OutDelaySamples <= NumSamples)
792         {
793             /*
794              * Copy all output delay samples to the output
795              */
796 #ifdef SUPPORT_MC
797             Copy_Float(&pBuffer->OutDelayBuffer[0],                /* Source */
798                        pDest,                                      /* Destination */
799                        /* Number of delay samples */
800                        (LVM_INT16)(NrChannels * pBuffer->OutDelaySamples));
801 #else
802             Copy_Float(&pBuffer->OutDelayBuffer[0],                /* Source */
803                        pDest,                                      /* Destination */
804                        (LVM_INT16)(2 * pBuffer->OutDelaySamples)); /* Number of delay samples */
805 #endif
806 
807             /*
808              * Update the pointer and sample counts
809              */
810 #ifdef SUPPORT_MC
811             pDest += NrChannels * pBuffer->OutDelaySamples; /* Output sample pointer */
812 #else
813             pDest += 2 * pBuffer->OutDelaySamples; /* Output sample pointer */
814 #endif
815             NumSamples = (LVM_INT16)(NumSamples - pBuffer->OutDelaySamples); /* Samples left \
816                                                                                 to send */
817             pBuffer->OutDelaySamples = 0; /* No samples left in the buffer */
818         }
819         else
820         {
821             /*
822              * Copy only some of the ouput delay samples to the output
823              */
824 #ifdef SUPPORT_MC
825             Copy_Float(&pBuffer->OutDelayBuffer[0],                    /* Source */
826                        pDest,                                          /* Destination */
827                        (LVM_INT16)(NrChannels * NrFrames));       /* Number of delay samples */
828 #else
829             Copy_Float(&pBuffer->OutDelayBuffer[0],                    /* Source */
830                        pDest,                                          /* Destination */
831                        (LVM_INT16)(2 * NumSamples));       /* Number of delay samples */
832 #endif
833 
834             /*
835              * Update the pointer and sample counts
836              */
837 #ifdef SUPPORT_MC
838             pDest += NrChannels * NrFrames; /* Output sample pointer */
839 #else
840             pDest += 2 * NumSamples; /* Output sample pointer */
841 #endif
842             /* No samples left in the buffer */
843             pBuffer->OutDelaySamples = (LVM_INT16)(pBuffer->OutDelaySamples - NumSamples);
844 
845             /*
846              * Realign the delay buffer data to avoid using circular buffer management
847              */
848 #ifdef SUPPORT_MC
849             Copy_Float(&pBuffer->OutDelayBuffer[NrChannels * NrFrames],         /* Source */
850                        &pBuffer->OutDelayBuffer[0],                    /* Destination */
851                        /* Number of samples to move */
852                        (LVM_INT16)(NrChannels * pBuffer->OutDelaySamples));
853 #else
854             Copy_Float(&pBuffer->OutDelayBuffer[2 * NumSamples],         /* Source */
855                        &pBuffer->OutDelayBuffer[0],                    /* Destination */
856                        (LVM_INT16)(2 * pBuffer->OutDelaySamples)); /* Number of samples to move */
857 #endif
858             NumSamples = 0;                                /* Samples left to send */
859         }
860     }
861 
862 
863     /*
864      * Copy the processed results to the output
865      */
866     if ((NumSamples != 0) &&
867         (SampleCount != 0))
868     {
869         if (SampleCount <= NumSamples)
870         {
871             /*
872              * Copy all processed samples to the output
873              */
874 #ifdef SUPPORT_MC
875             Copy_Float(pStart,                                      /* Source */
876                        pDest,                                       /* Destination */
877                        (LVM_INT16)(NrChannels * FrameCount)); /* Number of processed samples */
878 #else
879             Copy_Float(pStart,                                      /* Source */
880                        pDest,                                       /* Destination */
881                        (LVM_INT16)(2 * SampleCount)); /* Number of processed samples */
882 #endif
883             /*
884              * Update the pointer and sample counts
885              */
886 #ifdef SUPPORT_MC
887             pDest      += NrChannels * FrameCount;                 /* Output sample pointer */
888 #else
889             pDest      += 2 * SampleCount;                          /* Output sample pointer */
890 #endif
891             NumSamples  = (LVM_INT16)(NumSamples - SampleCount);    /* Samples left to send */
892             SampleCount = 0; /* No samples left in the buffer */
893         }
894         else
895         {
896             /*
897              * Copy only some processed samples to the output
898              */
899 #ifdef SUPPORT_MC
900             Copy_Float(pStart,                                         /* Source */
901                        pDest,                                          /* Destination */
902                        (LVM_INT16)(NrChannels * NrFrames));  /* Number of processed samples */
903 #else
904             Copy_Float(pStart,                                         /* Source */
905                        pDest,                                          /* Destination */
906                        (LVM_INT16)(2 * NumSamples));     /* Number of processed samples */
907 #endif
908             /*
909              * Update the pointers and sample counts
910                */
911 #ifdef SUPPORT_MC
912             pStart      += NrChannels * NrFrames;               /* Processed sample pointer */
913             pDest       += NrChannels * NrFrames;               /* Output sample pointer */
914 #else
915             pStart      += 2 * NumSamples;                        /* Processed sample pointer */
916             pDest       += 2 * NumSamples;                        /* Output sample pointer */
917 #endif
918             SampleCount  = (LVM_INT16)(SampleCount - NumSamples); /* Processed samples left */
919             NumSamples   = 0;                                     /* Clear the sample count */
920         }
921     }
922 
923 
924     /*
925      * Copy the remaining processed data to the output delay buffer
926      */
927     if (SampleCount != 0)
928     {
929 #ifdef SUPPORT_MC
930         Copy_Float(pStart,                                                 /* Source */
931                    /* Destination */
932                    &pBuffer->OutDelayBuffer[NrChannels * pBuffer->OutDelaySamples],
933                    (LVM_INT16)(NrChannels * FrameCount));      /* Number of processed samples */
934 #else
935         Copy_Float(pStart,                                                 /* Source */
936                    &pBuffer->OutDelayBuffer[2 * pBuffer->OutDelaySamples], /* Destination */
937                    (LVM_INT16)(2 * SampleCount));               /* Number of processed samples */
938 #endif
939         /* Update the buffer count */
940         pBuffer->OutDelaySamples = (LVM_INT16)(pBuffer->OutDelaySamples + SampleCount);
941     }
942 
943     /*
944      * pointers, counts and set default buffer processing
945      */
946     pBuffer->SamplesToOutput  = NumSamples;                         /* Samples left to send */
947     pInstance->pOutputSamples = pDest;                              /* Output sample pointer */
948     pBuffer->BufferState      = LVM_MAXBLOCKCALL;                   /* Set for the default call \
949                                                                             block size */
950     /* This will terminate the loop when all samples processed */
951     *pNumSamples = (LVM_UINT16)pInstance->SamplesToProcess;
952 }
953 #else
LVM_BufferManagedOut(LVM_Handle_t hInstance,LVM_INT16 * pOutData,LVM_UINT16 * pNumSamples)954 void LVM_BufferManagedOut(LVM_Handle_t        hInstance,
955                           LVM_INT16            *pOutData,
956                           LVM_UINT16        *pNumSamples)
957 {
958 
959     LVM_Instance_t  *pInstance  = (LVM_Instance_t  *)hInstance;
960     LVM_Buffer_t    *pBuffer    = pInstance->pBufferManagement;
961     LVM_INT16       SampleCount = (LVM_INT16)*pNumSamples;
962     LVM_INT16       NumSamples;
963     LVM_INT16       *pStart;
964     LVM_INT16       *pDest;
965 
966 
967     /*
968      * Set the pointers
969      */
970     NumSamples = pBuffer->SamplesToOutput;
971     pStart     = pBuffer->pScratch;
972 
973 
974     /*
975      * check if it is the first call of a block
976       */
977     if ((pBuffer->BufferState == LVM_FIRSTCALL) ||
978         (pBuffer->BufferState == LVM_FIRSTLASTCALL))
979     {
980         /* First call for a new block */
981         pInstance->pOutputSamples = pOutData;                        /* Initialise the destination */
982     }
983     pDest = pInstance->pOutputSamples;                               /* Set the output address */
984 
985 
986     /*
987      * If the number of samples is non-zero then there are still samples to send to
988      * the output buffer
989      */
990     if ((NumSamples != 0) &&
991         (pBuffer->OutDelaySamples != 0))
992     {
993         /*
994          * Copy the delayed output buffer samples to the output
995          */
996         if (pBuffer->OutDelaySamples <= NumSamples)
997         {
998             /*
999              * Copy all output delay samples to the output
1000              */
1001             Copy_16(&pBuffer->OutDelayBuffer[0],                    /* Source */
1002                     pDest,                                          /* Detsination */
1003                     (LVM_INT16)(2*pBuffer->OutDelaySamples));       /* Number of delay samples */
1004 
1005             /*
1006              * Update the pointer and sample counts
1007              */
1008             pDest += 2*pBuffer->OutDelaySamples;                                /* Output sample pointer */
1009             NumSamples = (LVM_INT16)(NumSamples - pBuffer->OutDelaySamples);    /* Samples left to send */
1010             pBuffer->OutDelaySamples = 0;                                       /* No samples left in the buffer */
1011 
1012         }
1013         else
1014         {
1015             /*
1016              * Copy only some of the ouput delay samples to the output
1017              */
1018             Copy_16(&pBuffer->OutDelayBuffer[0],                    /* Source */
1019                     pDest,                                          /* Detsination */
1020                     (LVM_INT16)(2*NumSamples));                     /* Number of delay samples */
1021 
1022             /*
1023              * Update the pointer and sample counts
1024              */
1025             pDest += 2*NumSamples;                                                              /* Output sample pointer */
1026             pBuffer->OutDelaySamples = (LVM_INT16)(pBuffer->OutDelaySamples - NumSamples);      /* No samples left in the buffer */
1027 
1028 
1029             /*
1030              * Realign the delay buffer data to avoid using circular buffer management
1031              */
1032             Copy_16(&pBuffer->OutDelayBuffer[2*NumSamples],         /* Source */
1033                     &pBuffer->OutDelayBuffer[0],                    /* Destination */
1034                     (LVM_INT16)(2*pBuffer->OutDelaySamples));       /* Number of samples to move */
1035             NumSamples = 0;                                         /* Samples left to send */
1036         }
1037     }
1038 
1039 
1040     /*
1041      * Copy the processed results to the output
1042      */
1043     if ((NumSamples != 0) &&
1044         (SampleCount != 0))
1045     {
1046         if (SampleCount <= NumSamples)
1047         {
1048             /*
1049              * Copy all processed samples to the output
1050              */
1051             Copy_16(pStart,                                      /* Source */
1052                     pDest,                                       /* Detsination */
1053                     (LVM_INT16)(2*SampleCount));                 /* Number of processed samples */
1054 
1055             /*
1056              * Update the pointer and sample counts
1057              */
1058             pDest      += 2 * SampleCount;                          /* Output sample pointer */
1059             NumSamples  = (LVM_INT16)(NumSamples - SampleCount);    /* Samples left to send */
1060             SampleCount = 0;                                        /* No samples left in the buffer */
1061         }
1062         else
1063         {
1064             /*
1065              * Copy only some processed samples to the output
1066              */
1067             Copy_16(pStart,                                         /* Source */
1068                     pDest,                                          /* Destination */
1069                     (LVM_INT16)(2*NumSamples));                     /* Number of processed samples */
1070 
1071 
1072             /*
1073              * Update the pointers and sample counts
1074                */
1075             pStart      += 2 * NumSamples;                          /* Processed sample pointer */
1076             pDest        += 2 * NumSamples;                         /* Output sample pointer */
1077             SampleCount  = (LVM_INT16)(SampleCount - NumSamples);   /* Processed samples left */
1078             NumSamples   = 0;                                       /* Clear the sample count */
1079         }
1080     }
1081 
1082 
1083     /*
1084      * Copy the remaining processed data to the output delay buffer
1085      */
1086     if (SampleCount != 0)
1087     {
1088         Copy_16(pStart,                                                 /* Source */
1089                 &pBuffer->OutDelayBuffer[2*pBuffer->OutDelaySamples],   /* Destination */
1090                 (LVM_INT16)(2*SampleCount));                            /* Number of processed samples */
1091         pBuffer->OutDelaySamples = (LVM_INT16)(pBuffer->OutDelaySamples + SampleCount); /* Update the buffer count */
1092     }
1093 
1094 
1095     /*
1096      * pointers, counts and set default buffer processing
1097      */
1098     pBuffer->SamplesToOutput  = NumSamples;                         /* Samples left to send */
1099     pInstance->pOutputSamples = pDest;                              /* Output sample pointer */
1100     pBuffer->BufferState      = LVM_MAXBLOCKCALL;                   /* Set for the default call block size */
1101     *pNumSamples = (LVM_UINT16)pInstance->SamplesToProcess;         /* This will terminate the loop when all samples processed */
1102 }
1103 #endif
1104 
1105 /****************************************************************************************/
1106 /*                                                                                      */
1107 /* FUNCTION:                 LVM_BufferUnmanagedOut                                     */
1108 /*                                                                                      */
1109 /* DESCRIPTION:                                                                         */
1110 /*  This works in conjunction with the unmanaged input routine and updates the number   */
1111 /*    of samples left to be processed    and adjusts the buffer pointers.               */
1112 /*                                                                                      */
1113 /* PARAMETERS:                                                                          */
1114 /*    hInstance        - Instance handle                                                */
1115 /*    pNumSamples        - Pointer to the number of samples to process                  */
1116 /*                                                                                      */
1117 /* RETURNS:                                                                             */
1118 /*    None                                                                              */
1119 /*                                                                                      */
1120 /* NOTES:                                                                               */
1121 /*                                                                                      */
1122 /****************************************************************************************/
1123 
LVM_BufferUnmanagedOut(LVM_Handle_t hInstance,LVM_UINT16 * pNumSamples)1124 void LVM_BufferUnmanagedOut(LVM_Handle_t        hInstance,
1125                             LVM_UINT16          *pNumSamples)
1126 {
1127 
1128     LVM_Instance_t      *pInstance  = (LVM_Instance_t  *)hInstance;
1129 #ifdef SUPPORT_MC
1130     LVM_INT16           NumChannels = pInstance->NrChannels;
1131     if (NumChannels == 1)
1132     {
1133         /* Mono input is processed as stereo by LVM module */
1134         NumChannels = 2;
1135     }
1136 #undef NrFrames
1137 #define NrFrames (*pNumSamples) // alias for clarity
1138 #else
1139     LVM_INT16           NumChannels = 2;
1140 #endif
1141 
1142 
1143     /*
1144      * Update sample counts
1145      */
1146     pInstance->pInputSamples    += (LVM_INT16)(*pNumSamples * NumChannels); /* Update the I/O pointers */
1147 #ifdef SUPPORT_MC
1148     pInstance->pOutputSamples   += (LVM_INT16)(NrFrames * NumChannels);
1149 #else
1150     pInstance->pOutputSamples   += (LVM_INT16)(*pNumSamples * 2);
1151 #endif
1152     pInstance->SamplesToProcess  = (LVM_INT16)(pInstance->SamplesToProcess - *pNumSamples); /* Update the sample count */
1153 
1154     /*
1155      * Set te block size to process
1156      */
1157     if (pInstance->SamplesToProcess > pInstance->InternalBlockSize)
1158     {
1159         *pNumSamples = (LVM_UINT16)pInstance->InternalBlockSize;
1160     }
1161     else
1162     {
1163         *pNumSamples = (LVM_UINT16)pInstance->SamplesToProcess;
1164     }
1165 }
1166 
1167 
1168 /****************************************************************************************/
1169 /*                                                                                      */
1170 /* FUNCTION:                 LVM_BufferOptimisedOut                                     */
1171 /*                                                                                      */
1172 /* DESCRIPTION:                                                                         */
1173 /*  This works in conjunction with the optimised input routine and copies the last few  */
1174 /*  processed and unprocessed samples to their respective buffers.                      */
1175 /*                                                                                      */
1176 /* PARAMETERS:                                                                          */
1177 /*    hInstance        - Instance handle                                                */
1178 /*    pNumSamples        - Pointer to the number of samples to process                  */
1179 /*                                                                                      */
1180 /* RETURNS:                                                                             */
1181 /*    None                                                                              */
1182 /*                                                                                      */
1183 /* NOTES:                                                                               */
1184 /*                                                                                      */
1185 /****************************************************************************************/
1186 
1187 #ifndef BUILD_FLOAT
LVM_BufferOptimisedOut(LVM_Handle_t hInstance,LVM_UINT16 * pNumSamples)1188 void LVM_BufferOptimisedOut(LVM_Handle_t    hInstance,
1189                             LVM_UINT16        *pNumSamples)
1190 {
1191 
1192     LVM_Instance_t      *pInstance = (LVM_Instance_t  *)hInstance;
1193     LVM_Buffer_t        *pBuffer   = pInstance->pBufferManagement;
1194 
1195     /*
1196      * Check if it is the last block to process
1197      */
1198     if (pBuffer->BufferState == LVM_LASTCALL)
1199     {
1200         LVM_INT16    *pSrc = pBuffer->pScratch;
1201 
1202         /*
1203          * Copy the unprocessed samples to the input delay buffer
1204          */
1205         if (pInstance->SamplesToProcess != 0)
1206         {
1207             Copy_16(pInstance->pInputSamples,                       /* Source */
1208                     &pBuffer->InDelayBuffer[0],                     /* Destination */
1209                     (LVM_INT16)(2*pInstance->SamplesToProcess));    /* Number of input samples */
1210             pBuffer->InDelaySamples = pInstance->SamplesToProcess;
1211             pInstance->SamplesToProcess = 0;
1212         }
1213         else
1214         {
1215             pBuffer->InDelaySamples = 0;
1216         }
1217 
1218 
1219         /*
1220          * Fill the last empty spaces in the output buffer
1221          */
1222         if (pBuffer->SamplesToOutput != 0)
1223         {
1224             Copy_16(pSrc,                                           /* Source */
1225                     pInstance->pOutputSamples,                      /* Destination */
1226                     (LVM_INT16)(2*pBuffer->SamplesToOutput));       /* Number of input samples */
1227             *pNumSamples = (LVM_UINT16)(*pNumSamples - pBuffer->SamplesToOutput);
1228             pSrc += 2 * pBuffer->SamplesToOutput;                  /* Update scratch pointer */
1229             pBuffer->SamplesToOutput = 0;                          /* No more samples in this block */
1230         }
1231 
1232 
1233         /*
1234          * Save any remaining processed samples in the output delay buffer
1235          */
1236         if (*pNumSamples != 0)
1237         {
1238             Copy_16(pSrc,                                           /* Source */
1239                     &pBuffer->OutDelayBuffer[0],                    /* Destination */
1240                     (LVM_INT16)(2**pNumSamples));                   /* Number of input samples */
1241 
1242             pBuffer->OutDelaySamples = (LVM_INT16)*pNumSamples;
1243 
1244             *pNumSamples = 0;                                      /* No more samples in this block */
1245         }
1246         else
1247         {
1248             pBuffer->OutDelaySamples = 0;
1249         }
1250     }
1251 }
1252 #endif
1253 
1254 /****************************************************************************************/
1255 /*                                                                                      */
1256 /* FUNCTION:                 LVM_BufferOut                                              */
1257 /*                                                                                      */
1258 /* DESCRIPTION:                                                                         */
1259 /*  This function manages the data output, it has the following features:               */
1260 /*        - Output data to 16-bit aligned memory                                        */
1261 /*        - Reads data from 32-bit aligned memory                                       */
1262 /*        - Reads data only in blocks of frame size or multiples of frame size          */
1263 /*        - Writes the same number of samples as the LVM_BufferIn function reads        */
1264 /*        - Works with inplace or outplace processing automatically                     */
1265 /*                                                                                      */
1266 /*  To manage the data the function has a number of operating states:                   */
1267 /*        LVM_FIRSTCALL        - The first call for this block of input samples         */
1268 /*        LVM_FIRSTLASTCALL    - This is the first and last call for this block of input*/
1269 /*                              samples, this occurs when the number of samples to      */
1270 /*                              process is less than the maximum block size.            */
1271 /*                                                                                      */
1272 /*    The function uses an internal delay buffer the size of the minimum frame, this is */
1273 /*  used to temporarily hold samples when the number of samples to write is not a       */
1274 /*  multiple of the frame size.                                                         */
1275 /*                                                                                      */
1276 /*    To ensure correct operation with inplace buffering the number of samples to output*/
1277 /*  per call is always the same as the number of samples read from the input buffer.    */
1278 /*                                                                                      */
1279 /* PARAMETERS:                                                                          */
1280 /*    hInstance        - Instance handle                                                */
1281 /*    pOutData        - Pointer to the output data stream                               */
1282 /*    pNumSamples        - Pointer to the number of samples to process                  */
1283 /*                                                                                      */
1284 /* RETURNS:                                                                             */
1285 /*    None                                                                              */
1286 /*                                                                                      */
1287 /* NOTES:                                                                               */
1288 /*                                                                                      */
1289 /****************************************************************************************/
1290 #ifdef BUILD_FLOAT
LVM_BufferOut(LVM_Handle_t hInstance,LVM_FLOAT * pOutData,LVM_UINT16 * pNumSamples)1291 void LVM_BufferOut(LVM_Handle_t     hInstance,
1292                    LVM_FLOAT        *pOutData,
1293                    LVM_UINT16       *pNumSamples)
1294 {
1295 
1296     LVM_Instance_t    *pInstance  = (LVM_Instance_t  *)hInstance;
1297 
1298 
1299     /*
1300      * Check which mode, managed or unmanaged
1301      */
1302     if (pInstance->InstParams.BufferMode == LVM_MANAGED_BUFFERS)
1303     {
1304         LVM_BufferManagedOut(hInstance,
1305                              pOutData,
1306                              pNumSamples);
1307     }
1308     else
1309     {
1310         LVM_BufferUnmanagedOut(hInstance,
1311                                pNumSamples);
1312     }
1313 }
1314 #else
LVM_BufferOut(LVM_Handle_t hInstance,LVM_INT16 * pOutData,LVM_UINT16 * pNumSamples)1315 void LVM_BufferOut(LVM_Handle_t     hInstance,
1316                    LVM_INT16        *pOutData,
1317                    LVM_UINT16       *pNumSamples)
1318 {
1319 
1320     LVM_Instance_t    *pInstance  = (LVM_Instance_t  *)hInstance;
1321 
1322 
1323     /*
1324      * Check which mode, managed or unmanaged
1325      */
1326     if (pInstance->InstParams.BufferMode == LVM_MANAGED_BUFFERS)
1327     {
1328         LVM_BufferManagedOut(hInstance,
1329                              pOutData,
1330                              pNumSamples);
1331     }
1332     else
1333     {
1334         LVM_BufferUnmanagedOut(hInstance,
1335                                pNumSamples);
1336     }
1337 }
1338 #endif
1339