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