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