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
LVM_BufferManagedIn(LVM_Handle_t hInstance,const LVM_INT16 * pInData,LVM_INT16 ** pToProcess,LVM_INT16 ** pProcessed,LVM_UINT16 * pNumSamples)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
LVM_BufferUnmanagedIn(LVM_Handle_t hInstance,LVM_INT16 ** pToProcess,LVM_INT16 ** pProcessed,LVM_UINT16 * pNumSamples)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
LVM_BufferOptimisedIn(LVM_Handle_t hInstance,const LVM_INT16 * pInData,LVM_INT16 ** pToProcess,LVM_INT16 ** pProcessed,LVM_UINT16 * pNumSamples)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
LVM_BufferIn(LVM_Handle_t hInstance,const LVM_INT16 * pInData,LVM_INT16 ** pToProcess,LVM_INT16 ** pProcessed,LVM_UINT16 * pNumSamples)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
LVM_BufferManagedOut(LVM_Handle_t hInstance,LVM_INT16 * pOutData,LVM_UINT16 * pNumSamples)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
LVM_BufferUnmanagedOut(LVM_Handle_t hInstance,LVM_UINT16 * pNumSamples)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
LVM_BufferOptimisedOut(LVM_Handle_t hInstance,LVM_UINT16 * pNumSamples)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
LVM_BufferOut(LVM_Handle_t hInstance,LVM_INT16 * pOutData,LVM_UINT16 * pNumSamples)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