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