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