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