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