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 52void 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 217void 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 281void 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 475void 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 526void 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 696void 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 744void 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 847void 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