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