~ubuntu-branches/ubuntu/wily/sflphone/wily

« back to all changes in this revision

Viewing changes to daemon/libs/pjproject-2.0.1/third_party/portaudio/src/common/pa_process.c

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2014-01-28 18:23:36 UTC
  • mfrom: (1.1.11)
  • mto: This revision was merged to the branch mainline in revision 24.
  • Revision ID: package-import@ubuntu.com-20140128182336-3xenud1kbnwmf3mz
* New upstream release 
  - Fixes "New Upstream Release" (Closes: #735846)
  - Fixes "Ringtone does not stop" (Closes: #727164)
  - Fixes "[sflphone-kde] crash on startup" (Closes: #718178)
  - Fixes "sflphone GUI crashes when call is hung up" (Closes: #736583)
* Build-Depends: ensure GnuTLS 2.6
  - libucommon-dev (>= 6.0.7-1.1), libccrtp-dev (>= 2.0.6-3)
  - Fixes "FTBFS Build-Depends libgnutls{26,28}-dev" (Closes: #722040)
* Fix "boost 1.49 is going away" unversioned Build-Depends: (Closes: #736746)
* Add Build-Depends: libsndfile-dev, nepomuk-core-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * $Id: pa_process.c 1408 2009-03-13 16:41:39Z rossb $
3
 
 * Portable Audio I/O Library
4
 
 * streamCallback <-> host buffer processing adapter
5
 
 *
6
 
 * Based on the Open Source API proposed by Ross Bencina
7
 
 * Copyright (c) 1999-2002 Ross Bencina, Phil Burk
8
 
 *
9
 
 * Permission is hereby granted, free of charge, to any person obtaining
10
 
 * a copy of this software and associated documentation files
11
 
 * (the "Software"), to deal in the Software without restriction,
12
 
 * including without limitation the rights to use, copy, modify, merge,
13
 
 * publish, distribute, sublicense, and/or sell copies of the Software,
14
 
 * and to permit persons to whom the Software is furnished to do so,
15
 
 * subject to the following conditions:
16
 
 *
17
 
 * The above copyright notice and this permission notice shall be
18
 
 * included in all copies or substantial portions of the Software.
19
 
 *
20
 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
 
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
 
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23
 
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
24
 
 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
25
 
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26
 
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
 
 */
28
 
 
29
 
/*
30
 
 * The text above constitutes the entire PortAudio license; however,
31
 
 * the PortAudio community also makes the following non-binding requests:
32
 
 *
33
 
 * Any person wishing to distribute modifications to the Software is
34
 
 * requested to send the modifications to the original developer so that
35
 
 * they can be incorporated into the canonical version. It is also
36
 
 * requested that these non-binding requests be included along with the
37
 
 * license above.
38
 
 */
39
 
 
40
 
/** @file
41
 
 @ingroup common_src
42
 
 
43
 
 @brief Buffer Processor implementation.
44
 
 
45
 
 The code in this file is not optimised yet - although it's not clear that
46
 
 it needs to be. there may appear to be redundancies
47
 
 that could be factored into common functions, but the redundanceis are left
48
 
 intentionally as each appearance may have different optimisation possibilities.
49
 
 
50
 
 The optimisations which are planned involve only converting data in-place
51
 
 where possible, rather than copying to the temp buffer(s).
52
 
 
53
 
 Note that in the extreme case of being able to convert in-place, and there
54
 
 being no conversion necessary there should be some code which short-circuits
55
 
 the operation.
56
 
 
57
 
    @todo Consider cache tilings for intereave<->deinterleave.
58
 
 
59
 
    @todo specify and implement some kind of logical policy for handling the
60
 
        underflow and overflow stream flags when the underflow/overflow overlaps
61
 
        multiple user buffers/callbacks.
62
 
 
63
 
        @todo provide support for priming the buffers with data from the callback.
64
 
        The client interface is now implemented through PaUtil_SetNoInput()
65
 
        which sets bp->hostInputChannels[0][0].data to zero. However this is
66
 
        currently only implemented in NonAdaptingProcess(). It shouldn't be
67
 
        needed for AdaptingInputOnlyProcess() (no priming should ever be
68
 
        requested for AdaptingInputOnlyProcess()).
69
 
        Not sure if additional work should be required to make it work with
70
 
        AdaptingOutputOnlyProcess, but it definitely is required for
71
 
        AdaptingProcess.
72
 
 
73
 
    @todo implement PaUtil_SetNoOutput for AdaptingProcess
74
 
 
75
 
    @todo don't allocate temp buffers for blocking streams unless they are
76
 
        needed. At the moment they are needed, but perhaps for host APIs
77
 
        where the implementation passes a buffer to the host they could be
78
 
        used.
79
 
*/
80
 
 
81
 
 
82
 
#include <assert.h>
83
 
#include <string.h> /* memset() */
84
 
 
85
 
#include "pa_process.h"
86
 
#include "pa_util.h"
87
 
 
88
 
 
89
 
#define PA_FRAMES_PER_TEMP_BUFFER_WHEN_HOST_BUFFER_SIZE_IS_UNKNOWN_    1024
90
 
 
91
 
#define PA_MIN_( a, b ) ( ((a)<(b)) ? (a) : (b) )
92
 
 
93
 
 
94
 
/* greatest common divisor - PGCD in French */
95
 
static unsigned long GCD( unsigned long a, unsigned long b )
96
 
{
97
 
    return (b==0) ? a : GCD( b, a%b);
98
 
}
99
 
 
100
 
/* least common multiple - PPCM in French */
101
 
static unsigned long LCM( unsigned long a, unsigned long b )
102
 
{
103
 
    return (a*b) / GCD(a,b);
104
 
}
105
 
 
106
 
#define PA_MAX_( a, b ) (((a) > (b)) ? (a) : (b))
107
 
 
108
 
static unsigned long CalculateFrameShift( unsigned long M, unsigned long N )
109
 
{
110
 
    unsigned long result = 0;
111
 
    unsigned long i;
112
 
    unsigned long lcm;
113
 
 
114
 
    assert( M > 0 );
115
 
    assert( N > 0 );
116
 
 
117
 
    lcm = LCM( M, N );
118
 
    for( i = M; i < lcm; i += M )
119
 
        result = PA_MAX_( result, i % N );
120
 
 
121
 
    return result;
122
 
}
123
 
 
124
 
 
125
 
PaError PaUtil_InitializeBufferProcessor( PaUtilBufferProcessor* bp,
126
 
        int inputChannelCount, PaSampleFormat userInputSampleFormat,
127
 
        PaSampleFormat hostInputSampleFormat,
128
 
        int outputChannelCount, PaSampleFormat userOutputSampleFormat,
129
 
        PaSampleFormat hostOutputSampleFormat,
130
 
        double sampleRate,
131
 
        PaStreamFlags streamFlags,
132
 
        unsigned long framesPerUserBuffer,
133
 
        unsigned long framesPerHostBuffer,
134
 
        PaUtilHostBufferSizeMode hostBufferSizeMode,
135
 
        PaStreamCallback *streamCallback, void *userData )
136
 
{
137
 
    PaError result = paNoError;
138
 
    PaError bytesPerSample;
139
 
    unsigned long tempInputBufferSize, tempOutputBufferSize;
140
 
 
141
 
    if( streamFlags & paNeverDropInput )
142
 
    {
143
 
        /* paNeverDropInput is only valid for full-duplex callback streams, with an unspecified number of frames per buffer. */
144
 
        if( !streamCallback || !(inputChannelCount > 0 && outputChannelCount > 0) ||
145
 
                framesPerUserBuffer != paFramesPerBufferUnspecified )
146
 
            return paInvalidFlag;
147
 
    }
148
 
 
149
 
    /* initialize buffer ptrs to zero so they can be freed if necessary in error */
150
 
    bp->tempInputBuffer = 0;
151
 
    bp->tempInputBufferPtrs = 0;
152
 
    bp->tempOutputBuffer = 0;
153
 
    bp->tempOutputBufferPtrs = 0;
154
 
 
155
 
    bp->framesPerUserBuffer = framesPerUserBuffer;
156
 
    bp->framesPerHostBuffer = framesPerHostBuffer;
157
 
 
158
 
    bp->inputChannelCount = inputChannelCount;
159
 
    bp->outputChannelCount = outputChannelCount;
160
 
 
161
 
    bp->hostBufferSizeMode = hostBufferSizeMode;
162
 
 
163
 
    bp->hostInputChannels[0] = bp->hostInputChannels[1] = 0;
164
 
    bp->hostOutputChannels[0] = bp->hostOutputChannels[1] = 0;
165
 
 
166
 
    if( framesPerUserBuffer == 0 ) /* streamCallback will accept any buffer size */
167
 
    {
168
 
        bp->useNonAdaptingProcess = 1;
169
 
        bp->initialFramesInTempInputBuffer = 0;
170
 
        bp->initialFramesInTempOutputBuffer = 0;
171
 
 
172
 
        if( hostBufferSizeMode == paUtilFixedHostBufferSize
173
 
                || hostBufferSizeMode == paUtilBoundedHostBufferSize )
174
 
        {
175
 
            bp->framesPerTempBuffer = framesPerHostBuffer;
176
 
        }
177
 
        else /* unknown host buffer size */
178
 
        {
179
 
             bp->framesPerTempBuffer = PA_FRAMES_PER_TEMP_BUFFER_WHEN_HOST_BUFFER_SIZE_IS_UNKNOWN_;
180
 
        }
181
 
    }
182
 
    else
183
 
    {
184
 
        bp->framesPerTempBuffer = framesPerUserBuffer;
185
 
 
186
 
        if( hostBufferSizeMode == paUtilFixedHostBufferSize
187
 
                && framesPerHostBuffer % framesPerUserBuffer == 0 )
188
 
        {
189
 
            bp->useNonAdaptingProcess = 1;
190
 
            bp->initialFramesInTempInputBuffer = 0;
191
 
            bp->initialFramesInTempOutputBuffer = 0;
192
 
        }
193
 
        else
194
 
        {
195
 
            bp->useNonAdaptingProcess = 0;
196
 
 
197
 
            if( inputChannelCount > 0 && outputChannelCount > 0 )
198
 
            {
199
 
                /* full duplex */
200
 
                if( hostBufferSizeMode == paUtilFixedHostBufferSize )
201
 
                {
202
 
                    unsigned long frameShift =
203
 
                        CalculateFrameShift( framesPerHostBuffer, framesPerUserBuffer );
204
 
 
205
 
                    if( framesPerUserBuffer > framesPerHostBuffer )
206
 
                    {
207
 
                        bp->initialFramesInTempInputBuffer = frameShift;
208
 
                        bp->initialFramesInTempOutputBuffer = 0;
209
 
                    }
210
 
                    else
211
 
                    {
212
 
                        bp->initialFramesInTempInputBuffer = 0;
213
 
                        bp->initialFramesInTempOutputBuffer = frameShift;
214
 
                    }
215
 
                }
216
 
                else /* variable host buffer size, add framesPerUserBuffer latency */
217
 
                {
218
 
                    bp->initialFramesInTempInputBuffer = 0;
219
 
                    bp->initialFramesInTempOutputBuffer = framesPerUserBuffer;
220
 
                }
221
 
            }
222
 
            else
223
 
            {
224
 
                /* half duplex */
225
 
                bp->initialFramesInTempInputBuffer = 0;
226
 
                bp->initialFramesInTempOutputBuffer = 0;
227
 
            }
228
 
        }
229
 
    }
230
 
 
231
 
 
232
 
    bp->framesInTempInputBuffer = bp->initialFramesInTempInputBuffer;
233
 
    bp->framesInTempOutputBuffer = bp->initialFramesInTempOutputBuffer;
234
 
 
235
 
 
236
 
    if( inputChannelCount > 0 )
237
 
    {
238
 
        bytesPerSample = Pa_GetSampleSize( hostInputSampleFormat );
239
 
        if( bytesPerSample > 0 )
240
 
        {
241
 
            bp->bytesPerHostInputSample = bytesPerSample;
242
 
        }
243
 
        else
244
 
        {
245
 
            result = bytesPerSample;
246
 
            goto error;
247
 
        }
248
 
 
249
 
        bytesPerSample = Pa_GetSampleSize( userInputSampleFormat );
250
 
        if( bytesPerSample > 0 )
251
 
        {
252
 
            bp->bytesPerUserInputSample = bytesPerSample;
253
 
        }
254
 
        else
255
 
        {
256
 
            result = bytesPerSample;
257
 
            goto error;
258
 
        }
259
 
 
260
 
        bp->inputConverter =
261
 
            PaUtil_SelectConverter( hostInputSampleFormat, userInputSampleFormat, streamFlags );
262
 
 
263
 
        bp->inputZeroer = PaUtil_SelectZeroer( hostInputSampleFormat );
264
 
 
265
 
        bp->userInputIsInterleaved = (userInputSampleFormat & paNonInterleaved)?0:1;
266
 
 
267
 
 
268
 
        tempInputBufferSize =
269
 
            bp->framesPerTempBuffer * bp->bytesPerUserInputSample * inputChannelCount;
270
 
 
271
 
        bp->tempInputBuffer = PaUtil_AllocateMemory( tempInputBufferSize );
272
 
        if( bp->tempInputBuffer == 0 )
273
 
        {
274
 
            result = paInsufficientMemory;
275
 
            goto error;
276
 
        }
277
 
 
278
 
        if( bp->framesInTempInputBuffer > 0 )
279
 
            memset( bp->tempInputBuffer, 0, tempInputBufferSize );
280
 
 
281
 
        if( userInputSampleFormat & paNonInterleaved )
282
 
        {
283
 
            bp->tempInputBufferPtrs =
284
 
                (void **)PaUtil_AllocateMemory( sizeof(void*)*inputChannelCount );
285
 
            if( bp->tempInputBufferPtrs == 0 )
286
 
            {
287
 
                result = paInsufficientMemory;
288
 
                goto error;
289
 
            }
290
 
        }
291
 
 
292
 
        bp->hostInputChannels[0] = (PaUtilChannelDescriptor*)
293
 
                PaUtil_AllocateMemory( sizeof(PaUtilChannelDescriptor) * inputChannelCount * 2);
294
 
        if( bp->hostInputChannels[0] == 0 )
295
 
        {
296
 
            result = paInsufficientMemory;
297
 
            goto error;
298
 
        }
299
 
 
300
 
        bp->hostInputChannels[1] = &bp->hostInputChannels[0][inputChannelCount];
301
 
    }
302
 
 
303
 
    if( outputChannelCount > 0 )
304
 
    {
305
 
        bytesPerSample = Pa_GetSampleSize( hostOutputSampleFormat );
306
 
        if( bytesPerSample > 0 )
307
 
        {
308
 
            bp->bytesPerHostOutputSample = bytesPerSample;
309
 
        }
310
 
        else
311
 
        {
312
 
            result = bytesPerSample;
313
 
            goto error;
314
 
        }
315
 
 
316
 
        bytesPerSample = Pa_GetSampleSize( userOutputSampleFormat );
317
 
        if( bytesPerSample > 0 )
318
 
        {
319
 
            bp->bytesPerUserOutputSample = bytesPerSample;
320
 
        }
321
 
        else
322
 
        {
323
 
            result = bytesPerSample;
324
 
            goto error;
325
 
        }
326
 
 
327
 
        bp->outputConverter =
328
 
            PaUtil_SelectConverter( userOutputSampleFormat, hostOutputSampleFormat, streamFlags );
329
 
 
330
 
        bp->outputZeroer = PaUtil_SelectZeroer( hostOutputSampleFormat );
331
 
 
332
 
        bp->userOutputIsInterleaved = (userOutputSampleFormat & paNonInterleaved)?0:1;
333
 
 
334
 
        tempOutputBufferSize =
335
 
                bp->framesPerTempBuffer * bp->bytesPerUserOutputSample * outputChannelCount;
336
 
 
337
 
        bp->tempOutputBuffer = PaUtil_AllocateMemory( tempOutputBufferSize );
338
 
        if( bp->tempOutputBuffer == 0 )
339
 
        {
340
 
            result = paInsufficientMemory;
341
 
            goto error;
342
 
        }
343
 
 
344
 
        if( bp->framesInTempOutputBuffer > 0 )
345
 
            memset( bp->tempOutputBuffer, 0, tempOutputBufferSize );
346
 
 
347
 
        if( userOutputSampleFormat & paNonInterleaved )
348
 
        {
349
 
            bp->tempOutputBufferPtrs =
350
 
                (void **)PaUtil_AllocateMemory( sizeof(void*)*outputChannelCount );
351
 
            if( bp->tempOutputBufferPtrs == 0 )
352
 
            {
353
 
                result = paInsufficientMemory;
354
 
                goto error;
355
 
            }
356
 
        }
357
 
 
358
 
        bp->hostOutputChannels[0] = (PaUtilChannelDescriptor*)
359
 
                PaUtil_AllocateMemory( sizeof(PaUtilChannelDescriptor)*outputChannelCount * 2 );
360
 
        if( bp->hostOutputChannels[0] == 0 )
361
 
        {
362
 
            result = paInsufficientMemory;
363
 
            goto error;
364
 
        }
365
 
 
366
 
        bp->hostOutputChannels[1] = &bp->hostOutputChannels[0][outputChannelCount];
367
 
    }
368
 
 
369
 
    PaUtil_InitializeTriangularDitherState( &bp->ditherGenerator );
370
 
 
371
 
    bp->samplePeriod = 1. / sampleRate;
372
 
 
373
 
    bp->streamCallback = streamCallback;
374
 
    bp->userData = userData;
375
 
 
376
 
    return result;
377
 
 
378
 
error:
379
 
    if( bp->tempInputBuffer )
380
 
        PaUtil_FreeMemory( bp->tempInputBuffer );
381
 
 
382
 
    if( bp->tempInputBufferPtrs )
383
 
        PaUtil_FreeMemory( bp->tempInputBufferPtrs );
384
 
 
385
 
    if( bp->hostInputChannels[0] )
386
 
        PaUtil_FreeMemory( bp->hostInputChannels[0] );
387
 
 
388
 
    if( bp->tempOutputBuffer )
389
 
        PaUtil_FreeMemory( bp->tempOutputBuffer );
390
 
 
391
 
    if( bp->tempOutputBufferPtrs )
392
 
        PaUtil_FreeMemory( bp->tempOutputBufferPtrs );
393
 
 
394
 
    if( bp->hostOutputChannels[0] )
395
 
        PaUtil_FreeMemory( bp->hostOutputChannels[0] );
396
 
 
397
 
    return result;
398
 
}
399
 
 
400
 
 
401
 
void PaUtil_TerminateBufferProcessor( PaUtilBufferProcessor* bp )
402
 
{
403
 
    if( bp->tempInputBuffer )
404
 
        PaUtil_FreeMemory( bp->tempInputBuffer );
405
 
 
406
 
    if( bp->tempInputBufferPtrs )
407
 
        PaUtil_FreeMemory( bp->tempInputBufferPtrs );
408
 
 
409
 
    if( bp->hostInputChannels[0] )
410
 
        PaUtil_FreeMemory( bp->hostInputChannels[0] );
411
 
 
412
 
    if( bp->tempOutputBuffer )
413
 
        PaUtil_FreeMemory( bp->tempOutputBuffer );
414
 
 
415
 
    if( bp->tempOutputBufferPtrs )
416
 
        PaUtil_FreeMemory( bp->tempOutputBufferPtrs );
417
 
 
418
 
    if( bp->hostOutputChannels[0] )
419
 
        PaUtil_FreeMemory( bp->hostOutputChannels[0] );
420
 
}
421
 
 
422
 
 
423
 
void PaUtil_ResetBufferProcessor( PaUtilBufferProcessor* bp )
424
 
{
425
 
    unsigned long tempInputBufferSize, tempOutputBufferSize;
426
 
 
427
 
    bp->framesInTempInputBuffer = bp->initialFramesInTempInputBuffer;
428
 
    bp->framesInTempOutputBuffer = bp->initialFramesInTempOutputBuffer;
429
 
 
430
 
    if( bp->framesInTempInputBuffer > 0 )
431
 
    {
432
 
        tempInputBufferSize =
433
 
            bp->framesPerTempBuffer * bp->bytesPerUserInputSample * bp->inputChannelCount;
434
 
        memset( bp->tempInputBuffer, 0, tempInputBufferSize );
435
 
    }
436
 
 
437
 
    if( bp->framesInTempOutputBuffer > 0 )
438
 
    {
439
 
        tempOutputBufferSize =
440
 
            bp->framesPerTempBuffer * bp->bytesPerUserOutputSample * bp->outputChannelCount;
441
 
        memset( bp->tempOutputBuffer, 0, tempOutputBufferSize );
442
 
    }
443
 
}
444
 
 
445
 
 
446
 
unsigned long PaUtil_GetBufferProcessorInputLatency( PaUtilBufferProcessor* bp )
447
 
{
448
 
    return bp->initialFramesInTempInputBuffer;
449
 
}
450
 
 
451
 
 
452
 
unsigned long PaUtil_GetBufferProcessorOutputLatency( PaUtilBufferProcessor* bp )
453
 
{
454
 
    return bp->initialFramesInTempOutputBuffer;
455
 
}
456
 
 
457
 
 
458
 
void PaUtil_SetInputFrameCount( PaUtilBufferProcessor* bp,
459
 
        unsigned long frameCount )
460
 
{
461
 
    if( frameCount == 0 )
462
 
        bp->hostInputFrameCount[0] = bp->framesPerHostBuffer;
463
 
    else
464
 
        bp->hostInputFrameCount[0] = frameCount;
465
 
}
466
 
 
467
 
 
468
 
void PaUtil_SetNoInput( PaUtilBufferProcessor* bp )
469
 
{
470
 
    assert( bp->inputChannelCount > 0 );
471
 
 
472
 
    bp->hostInputChannels[0][0].data = 0;
473
 
}
474
 
 
475
 
 
476
 
void PaUtil_SetInputChannel( PaUtilBufferProcessor* bp,
477
 
        unsigned int channel, void *data, unsigned int stride )
478
 
{
479
 
    assert( channel < bp->inputChannelCount );
480
 
 
481
 
    bp->hostInputChannels[0][channel].data = data;
482
 
    bp->hostInputChannels[0][channel].stride = stride;
483
 
}
484
 
 
485
 
 
486
 
void PaUtil_SetInterleavedInputChannels( PaUtilBufferProcessor* bp,
487
 
        unsigned int firstChannel, void *data, unsigned int channelCount )
488
 
{
489
 
    unsigned int i;
490
 
    unsigned int channel = firstChannel;
491
 
    unsigned char *p = (unsigned char*)data;
492
 
 
493
 
    if( channelCount == 0 )
494
 
        channelCount = bp->inputChannelCount;
495
 
 
496
 
    assert( firstChannel < bp->inputChannelCount );
497
 
    assert( firstChannel + channelCount <= bp->inputChannelCount );
498
 
 
499
 
    for( i=0; i< channelCount; ++i )
500
 
    {
501
 
        bp->hostInputChannels[0][channel+i].data = p;
502
 
        p += bp->bytesPerHostInputSample;
503
 
        bp->hostInputChannels[0][channel+i].stride = channelCount;
504
 
    }
505
 
}
506
 
 
507
 
 
508
 
void PaUtil_SetNonInterleavedInputChannel( PaUtilBufferProcessor* bp,
509
 
        unsigned int channel, void *data )
510
 
{
511
 
    assert( channel < bp->inputChannelCount );
512
 
 
513
 
    bp->hostInputChannels[0][channel].data = data;
514
 
    bp->hostInputChannels[0][channel].stride = 1;
515
 
}
516
 
 
517
 
 
518
 
void PaUtil_Set2ndInputFrameCount( PaUtilBufferProcessor* bp,
519
 
        unsigned long frameCount )
520
 
{
521
 
    bp->hostInputFrameCount[1] = frameCount;
522
 
}
523
 
 
524
 
 
525
 
void PaUtil_Set2ndInputChannel( PaUtilBufferProcessor* bp,
526
 
        unsigned int channel, void *data, unsigned int stride )
527
 
{
528
 
    assert( channel < bp->inputChannelCount );
529
 
 
530
 
    bp->hostInputChannels[1][channel].data = data;
531
 
    bp->hostInputChannels[1][channel].stride = stride;
532
 
}
533
 
 
534
 
 
535
 
void PaUtil_Set2ndInterleavedInputChannels( PaUtilBufferProcessor* bp,
536
 
        unsigned int firstChannel, void *data, unsigned int channelCount )
537
 
{
538
 
    unsigned int i;
539
 
    unsigned int channel = firstChannel;
540
 
    unsigned char *p = (unsigned char*)data;
541
 
 
542
 
    if( channelCount == 0 )
543
 
        channelCount = bp->inputChannelCount;
544
 
 
545
 
    assert( firstChannel < bp->inputChannelCount );
546
 
    assert( firstChannel + channelCount <= bp->inputChannelCount );
547
 
 
548
 
    for( i=0; i< channelCount; ++i )
549
 
    {
550
 
        bp->hostInputChannels[1][channel+i].data = p;
551
 
        p += bp->bytesPerHostInputSample;
552
 
        bp->hostInputChannels[1][channel+i].stride = channelCount;
553
 
    }
554
 
}
555
 
 
556
 
 
557
 
void PaUtil_Set2ndNonInterleavedInputChannel( PaUtilBufferProcessor* bp,
558
 
        unsigned int channel, void *data )
559
 
{
560
 
    assert( channel < bp->inputChannelCount );
561
 
 
562
 
    bp->hostInputChannels[1][channel].data = data;
563
 
    bp->hostInputChannels[1][channel].stride = 1;
564
 
}
565
 
 
566
 
 
567
 
void PaUtil_SetOutputFrameCount( PaUtilBufferProcessor* bp,
568
 
        unsigned long frameCount )
569
 
{
570
 
    if( frameCount == 0 )
571
 
        bp->hostOutputFrameCount[0] = bp->framesPerHostBuffer;
572
 
    else
573
 
        bp->hostOutputFrameCount[0] = frameCount;
574
 
}
575
 
 
576
 
 
577
 
void PaUtil_SetNoOutput( PaUtilBufferProcessor* bp )
578
 
{
579
 
    assert( bp->outputChannelCount > 0 );
580
 
 
581
 
    bp->hostOutputChannels[0][0].data = 0;
582
 
}
583
 
 
584
 
 
585
 
void PaUtil_SetOutputChannel( PaUtilBufferProcessor* bp,
586
 
        unsigned int channel, void *data, unsigned int stride )
587
 
{
588
 
    assert( channel < bp->outputChannelCount );
589
 
    assert( data != NULL );
590
 
 
591
 
    bp->hostOutputChannels[0][channel].data = data;
592
 
    bp->hostOutputChannels[0][channel].stride = stride;
593
 
}
594
 
 
595
 
 
596
 
void PaUtil_SetInterleavedOutputChannels( PaUtilBufferProcessor* bp,
597
 
        unsigned int firstChannel, void *data, unsigned int channelCount )
598
 
{
599
 
    unsigned int i;
600
 
    unsigned int channel = firstChannel;
601
 
    unsigned char *p = (unsigned char*)data;
602
 
 
603
 
    if( channelCount == 0 )
604
 
        channelCount = bp->outputChannelCount;
605
 
 
606
 
    assert( firstChannel < bp->outputChannelCount );
607
 
    assert( firstChannel + channelCount <= bp->outputChannelCount );
608
 
 
609
 
    for( i=0; i< channelCount; ++i )
610
 
    {
611
 
        PaUtil_SetOutputChannel( bp, channel + i, p, channelCount );
612
 
        p += bp->bytesPerHostOutputSample;
613
 
    }
614
 
}
615
 
 
616
 
 
617
 
void PaUtil_SetNonInterleavedOutputChannel( PaUtilBufferProcessor* bp,
618
 
        unsigned int channel, void *data )
619
 
{
620
 
    assert( channel < bp->outputChannelCount );
621
 
 
622
 
    PaUtil_SetOutputChannel( bp, channel, data, 1 );
623
 
}
624
 
 
625
 
 
626
 
void PaUtil_Set2ndOutputFrameCount( PaUtilBufferProcessor* bp,
627
 
        unsigned long frameCount )
628
 
{
629
 
    bp->hostOutputFrameCount[1] = frameCount;
630
 
}
631
 
 
632
 
 
633
 
void PaUtil_Set2ndOutputChannel( PaUtilBufferProcessor* bp,
634
 
        unsigned int channel, void *data, unsigned int stride )
635
 
{
636
 
    assert( channel < bp->outputChannelCount );
637
 
    assert( data != NULL );
638
 
 
639
 
    bp->hostOutputChannels[1][channel].data = data;
640
 
    bp->hostOutputChannels[1][channel].stride = stride;
641
 
}
642
 
 
643
 
 
644
 
void PaUtil_Set2ndInterleavedOutputChannels( PaUtilBufferProcessor* bp,
645
 
        unsigned int firstChannel, void *data, unsigned int channelCount )
646
 
{
647
 
    unsigned int i;
648
 
    unsigned int channel = firstChannel;
649
 
    unsigned char *p = (unsigned char*)data;
650
 
 
651
 
    if( channelCount == 0 )
652
 
        channelCount = bp->outputChannelCount;
653
 
 
654
 
    assert( firstChannel < bp->outputChannelCount );
655
 
    assert( firstChannel + channelCount <= bp->outputChannelCount );
656
 
 
657
 
    for( i=0; i< channelCount; ++i )
658
 
    {
659
 
        PaUtil_Set2ndOutputChannel( bp, channel + i, p, channelCount );
660
 
        p += bp->bytesPerHostOutputSample;
661
 
    }
662
 
}
663
 
 
664
 
 
665
 
void PaUtil_Set2ndNonInterleavedOutputChannel( PaUtilBufferProcessor* bp,
666
 
        unsigned int channel, void *data )
667
 
{
668
 
    assert( channel < bp->outputChannelCount );
669
 
 
670
 
    PaUtil_Set2ndOutputChannel( bp, channel, data, 1 );
671
 
}
672
 
 
673
 
 
674
 
void PaUtil_BeginBufferProcessing( PaUtilBufferProcessor* bp,
675
 
        PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags callbackStatusFlags )
676
 
{
677
 
    bp->timeInfo = timeInfo;
678
 
 
679
 
    /* the first streamCallback will be called to process samples which are
680
 
        currently in the input buffer before the ones starting at the timeInfo time */
681
 
 
682
 
    bp->timeInfo->inputBufferAdcTime -= bp->framesInTempInputBuffer * bp->samplePeriod;
683
 
 
684
 
    /* We just pass through timeInfo->currentTime provided by the caller. This is
685
 
        not strictly conformant to the word of the spec, since the buffer processor
686
 
        might call the callback multiple times, and we never refresh currentTime. */
687
 
 
688
 
    /* the first streamCallback will be called to generate samples which will be
689
 
        outputted after the frames currently in the output buffer have been
690
 
        outputted. */
691
 
    bp->timeInfo->outputBufferDacTime += bp->framesInTempOutputBuffer * bp->samplePeriod;
692
 
 
693
 
    bp->callbackStatusFlags = callbackStatusFlags;
694
 
 
695
 
    bp->hostInputFrameCount[1] = 0;
696
 
    bp->hostOutputFrameCount[1] = 0;
697
 
}
698
 
 
699
 
 
700
 
/*
701
 
    NonAdaptingProcess() is a simple buffer copying adaptor that can handle
702
 
    both full and half duplex copies. It processes framesToProcess frames,
703
 
    broken into blocks bp->framesPerTempBuffer long.
704
 
    This routine can be used when the streamCallback doesn't care what length
705
 
    the buffers are, or when framesToProcess is an integer multiple of
706
 
    bp->framesPerTempBuffer, in which case streamCallback will always be called
707
 
    with bp->framesPerTempBuffer samples.
708
 
*/
709
 
static unsigned long NonAdaptingProcess( PaUtilBufferProcessor *bp,
710
 
        int *streamCallbackResult,
711
 
        PaUtilChannelDescriptor *hostInputChannels,
712
 
        PaUtilChannelDescriptor *hostOutputChannels,
713
 
        unsigned long framesToProcess )
714
 
{
715
 
    void *userInput, *userOutput;
716
 
    unsigned char *srcBytePtr, *destBytePtr;
717
 
    unsigned int srcSampleStrideSamples; /* stride from one sample to the next within a channel, in samples */
718
 
    unsigned int srcChannelStrideBytes; /* stride from one channel to the next, in bytes */
719
 
    unsigned int destSampleStrideSamples; /* stride from one sample to the next within a channel, in samples */
720
 
    unsigned int destChannelStrideBytes; /* stride from one channel to the next, in bytes */
721
 
    unsigned int i;
722
 
    unsigned long frameCount;
723
 
    unsigned long framesToGo = framesToProcess;
724
 
    unsigned long framesProcessed = 0;
725
 
 
726
 
 
727
 
    if( *streamCallbackResult == paContinue )
728
 
    {
729
 
        do
730
 
        {
731
 
            frameCount = PA_MIN_( bp->framesPerTempBuffer, framesToGo );
732
 
 
733
 
            /* configure user input buffer and convert input data (host -> user) */
734
 
            if( bp->inputChannelCount == 0 )
735
 
            {
736
 
                /* no input */
737
 
                userInput = 0;
738
 
            }
739
 
            else /* there are input channels */
740
 
            {
741
 
                /*
742
 
                    could use more elaborate logic here and sometimes process
743
 
                    buffers in-place.
744
 
                */
745
 
 
746
 
                destBytePtr = (unsigned char *)bp->tempInputBuffer;
747
 
 
748
 
                if( bp->userInputIsInterleaved )
749
 
                {
750
 
                    destSampleStrideSamples = bp->inputChannelCount;
751
 
                    destChannelStrideBytes = bp->bytesPerUserInputSample;
752
 
                    userInput = bp->tempInputBuffer;
753
 
                }
754
 
                else /* user input is not interleaved */
755
 
                {
756
 
                    destSampleStrideSamples = 1;
757
 
                    destChannelStrideBytes = frameCount * bp->bytesPerUserInputSample;
758
 
 
759
 
                    /* setup non-interleaved ptrs */
760
 
                    for( i=0; i<bp->inputChannelCount; ++i )
761
 
                    {
762
 
                        bp->tempInputBufferPtrs[i] = ((unsigned char*)bp->tempInputBuffer) +
763
 
                            i * bp->bytesPerUserInputSample * frameCount;
764
 
                    }
765
 
 
766
 
                    userInput = bp->tempInputBufferPtrs;
767
 
                }
768
 
 
769
 
                if( !bp->hostInputChannels[0][0].data )
770
 
                {
771
 
                    /* no input was supplied (see PaUtil_SetNoInput), so
772
 
                        zero the input buffer */
773
 
 
774
 
                    for( i=0; i<bp->inputChannelCount; ++i )
775
 
                    {
776
 
                        bp->inputZeroer( destBytePtr, destSampleStrideSamples, frameCount );
777
 
                        destBytePtr += destChannelStrideBytes;  /* skip to next destination channel */
778
 
                    }
779
 
                }
780
 
                else
781
 
                {
782
 
                    for( i=0; i<bp->inputChannelCount; ++i )
783
 
                    {
784
 
                        bp->inputConverter( destBytePtr, destSampleStrideSamples,
785
 
                                                hostInputChannels[i].data,
786
 
                                                hostInputChannels[i].stride,
787
 
                                                frameCount, &bp->ditherGenerator );
788
 
 
789
 
                        destBytePtr += destChannelStrideBytes;  /* skip to next destination channel */
790
 
 
791
 
                        /* advance src ptr for next iteration */
792
 
                        hostInputChannels[i].data = ((unsigned char*)hostInputChannels[i].data) +
793
 
                                frameCount * hostInputChannels[i].stride * bp->bytesPerHostInputSample;
794
 
                    }
795
 
                }
796
 
            }
797
 
 
798
 
            /* configure user output buffer */
799
 
            if( bp->outputChannelCount == 0 )
800
 
            {
801
 
                /* no output */
802
 
                userOutput = 0;
803
 
            }
804
 
            else /* there are output channels */
805
 
            {
806
 
                if( bp->userOutputIsInterleaved )
807
 
                {
808
 
                    userOutput = bp->tempOutputBuffer;
809
 
                }
810
 
                else /* user output is not interleaved */
811
 
                {
812
 
                    for( i = 0; i < bp->outputChannelCount; ++i )
813
 
                    {
814
 
                        bp->tempOutputBufferPtrs[i] = ((unsigned char*)bp->tempOutputBuffer) +
815
 
                            i * bp->bytesPerUserOutputSample * frameCount;
816
 
                    }
817
 
 
818
 
                    userOutput = bp->tempOutputBufferPtrs;
819
 
                }
820
 
            }
821
 
 
822
 
            *streamCallbackResult = bp->streamCallback( userInput, userOutput,
823
 
                    frameCount, bp->timeInfo, bp->callbackStatusFlags, bp->userData );
824
 
 
825
 
            if( *streamCallbackResult == paAbort )
826
 
            {
827
 
                /* callback returned paAbort, don't advance framesProcessed
828
 
                        and framesToGo, they will be handled below */
829
 
            }
830
 
            else
831
 
            {
832
 
                bp->timeInfo->inputBufferAdcTime += frameCount * bp->samplePeriod;
833
 
                bp->timeInfo->outputBufferDacTime += frameCount * bp->samplePeriod;
834
 
 
835
 
                /* convert output data (user -> host) */
836
 
 
837
 
                if( bp->outputChannelCount != 0 && bp->hostOutputChannels[0][0].data )
838
 
                {
839
 
                    /*
840
 
                        could use more elaborate logic here and sometimes process
841
 
                        buffers in-place.
842
 
                    */
843
 
 
844
 
                    srcBytePtr = (unsigned char *)bp->tempOutputBuffer;
845
 
 
846
 
                    if( bp->userOutputIsInterleaved )
847
 
                    {
848
 
                        srcSampleStrideSamples = bp->outputChannelCount;
849
 
                        srcChannelStrideBytes = bp->bytesPerUserOutputSample;
850
 
                    }
851
 
                    else /* user output is not interleaved */
852
 
                    {
853
 
                        srcSampleStrideSamples = 1;
854
 
                        srcChannelStrideBytes = frameCount * bp->bytesPerUserOutputSample;
855
 
                    }
856
 
 
857
 
                    for( i=0; i<bp->outputChannelCount; ++i )
858
 
                    {
859
 
                        bp->outputConverter(    hostOutputChannels[i].data,
860
 
                                                hostOutputChannels[i].stride,
861
 
                                                srcBytePtr, srcSampleStrideSamples,
862
 
                                                frameCount, &bp->ditherGenerator );
863
 
 
864
 
                        srcBytePtr += srcChannelStrideBytes;  /* skip to next source channel */
865
 
 
866
 
                        /* advance dest ptr for next iteration */
867
 
                        hostOutputChannels[i].data = ((unsigned char*)hostOutputChannels[i].data) +
868
 
                                frameCount * hostOutputChannels[i].stride * bp->bytesPerHostOutputSample;
869
 
                    }
870
 
                }
871
 
 
872
 
                framesProcessed += frameCount;
873
 
 
874
 
                framesToGo -= frameCount;
875
 
            }
876
 
        }
877
 
        while( framesToGo > 0  && *streamCallbackResult == paContinue );
878
 
    }
879
 
 
880
 
    if( framesToGo > 0 )
881
 
    {
882
 
        /* zero any remaining frames output. There will only be remaining frames
883
 
            if the callback has returned paComplete or paAbort */
884
 
 
885
 
        frameCount = framesToGo;
886
 
 
887
 
        if( bp->outputChannelCount != 0 && bp->hostOutputChannels[0][0].data )
888
 
        {
889
 
            for( i=0; i<bp->outputChannelCount; ++i )
890
 
            {
891
 
                bp->outputZeroer(   hostOutputChannels[i].data,
892
 
                                    hostOutputChannels[i].stride,
893
 
                                    frameCount );
894
 
 
895
 
                /* advance dest ptr for next iteration */
896
 
                hostOutputChannels[i].data = ((unsigned char*)hostOutputChannels[i].data) +
897
 
                        frameCount * hostOutputChannels[i].stride * bp->bytesPerHostOutputSample;
898
 
            }
899
 
        }
900
 
 
901
 
        framesProcessed += frameCount;
902
 
    }
903
 
 
904
 
    return framesProcessed;
905
 
}
906
 
 
907
 
 
908
 
/*
909
 
    AdaptingInputOnlyProcess() is a half duplex input buffer processor. It
910
 
    converts data from the input buffers into the temporary input buffer,
911
 
    when the temporary input buffer is full, it calls the streamCallback.
912
 
*/
913
 
static unsigned long AdaptingInputOnlyProcess( PaUtilBufferProcessor *bp,
914
 
        int *streamCallbackResult,
915
 
        PaUtilChannelDescriptor *hostInputChannels,
916
 
        unsigned long framesToProcess )
917
 
{
918
 
    void *userInput, *userOutput;
919
 
    unsigned char *destBytePtr;
920
 
    unsigned int destSampleStrideSamples; /* stride from one sample to the next within a channel, in samples */
921
 
    unsigned int destChannelStrideBytes; /* stride from one channel to the next, in bytes */
922
 
    unsigned int i;
923
 
    unsigned long frameCount;
924
 
    unsigned long framesToGo = framesToProcess;
925
 
    unsigned long framesProcessed = 0;
926
 
 
927
 
    userOutput = 0;
928
 
 
929
 
    do
930
 
    {
931
 
        frameCount = ( bp->framesInTempInputBuffer + framesToGo > bp->framesPerUserBuffer )
932
 
                ? ( bp->framesPerUserBuffer - bp->framesInTempInputBuffer )
933
 
                : framesToGo;
934
 
 
935
 
        /* convert frameCount samples into temp buffer */
936
 
 
937
 
        if( bp->userInputIsInterleaved )
938
 
        {
939
 
            destBytePtr = ((unsigned char*)bp->tempInputBuffer) +
940
 
                    bp->bytesPerUserInputSample * bp->inputChannelCount *
941
 
                    bp->framesInTempInputBuffer;
942
 
 
943
 
            destSampleStrideSamples = bp->inputChannelCount;
944
 
            destChannelStrideBytes = bp->bytesPerUserInputSample;
945
 
 
946
 
            userInput = bp->tempInputBuffer;
947
 
        }
948
 
        else /* user input is not interleaved */
949
 
        {
950
 
            destBytePtr = ((unsigned char*)bp->tempInputBuffer) +
951
 
                    bp->bytesPerUserInputSample * bp->framesInTempInputBuffer;
952
 
 
953
 
            destSampleStrideSamples = 1;
954
 
            destChannelStrideBytes = bp->framesPerUserBuffer * bp->bytesPerUserInputSample;
955
 
 
956
 
            /* setup non-interleaved ptrs */
957
 
            for( i=0; i<bp->inputChannelCount; ++i )
958
 
            {
959
 
                bp->tempInputBufferPtrs[i] = ((unsigned char*)bp->tempInputBuffer) +
960
 
                    i * bp->bytesPerUserInputSample * bp->framesPerUserBuffer;
961
 
            }
962
 
 
963
 
            userInput = bp->tempInputBufferPtrs;
964
 
        }
965
 
 
966
 
        for( i=0; i<bp->inputChannelCount; ++i )
967
 
        {
968
 
            bp->inputConverter( destBytePtr, destSampleStrideSamples,
969
 
                                    hostInputChannels[i].data,
970
 
                                    hostInputChannels[i].stride,
971
 
                                    frameCount, &bp->ditherGenerator );
972
 
 
973
 
            destBytePtr += destChannelStrideBytes;  /* skip to next destination channel */
974
 
 
975
 
            /* advance src ptr for next iteration */
976
 
            hostInputChannels[i].data = ((unsigned char*)hostInputChannels[i].data) +
977
 
                    frameCount * hostInputChannels[i].stride * bp->bytesPerHostInputSample;
978
 
        }
979
 
 
980
 
        bp->framesInTempInputBuffer += frameCount;
981
 
 
982
 
        if( bp->framesInTempInputBuffer == bp->framesPerUserBuffer )
983
 
        {
984
 
            /**
985
 
            @todo (non-critical optimisation)
986
 
            The conditional below implements the continue/complete/abort mechanism
987
 
            simply by continuing on iterating through the input buffer, but not
988
 
            passing the data to the callback. With care, the outer loop could be
989
 
            terminated earlier, thus some unneeded conversion cycles would be
990
 
            saved.
991
 
            */
992
 
            if( *streamCallbackResult == paContinue )
993
 
            {
994
 
                bp->timeInfo->outputBufferDacTime = 0;
995
 
 
996
 
                *streamCallbackResult = bp->streamCallback( userInput, userOutput,
997
 
                        bp->framesPerUserBuffer, bp->timeInfo,
998
 
                        bp->callbackStatusFlags, bp->userData );
999
 
 
1000
 
                bp->timeInfo->inputBufferAdcTime += bp->framesPerUserBuffer * bp->samplePeriod;
1001
 
            }
1002
 
 
1003
 
            bp->framesInTempInputBuffer = 0;
1004
 
        }
1005
 
 
1006
 
        framesProcessed += frameCount;
1007
 
 
1008
 
        framesToGo -= frameCount;
1009
 
    }while( framesToGo > 0 );
1010
 
 
1011
 
    return framesProcessed;
1012
 
}
1013
 
 
1014
 
 
1015
 
/*
1016
 
    AdaptingOutputOnlyProcess() is a half duplex output buffer processor.
1017
 
    It converts data from the temporary output buffer, to the output buffers,
1018
 
    when the temporary output buffer is empty, it calls the streamCallback.
1019
 
*/
1020
 
static unsigned long AdaptingOutputOnlyProcess( PaUtilBufferProcessor *bp,
1021
 
        int *streamCallbackResult,
1022
 
        PaUtilChannelDescriptor *hostOutputChannels,
1023
 
        unsigned long framesToProcess )
1024
 
{
1025
 
    void *userInput, *userOutput;
1026
 
    unsigned char *srcBytePtr;
1027
 
    unsigned int srcSampleStrideSamples; /* stride from one sample to the next within a channel, in samples */
1028
 
    unsigned int srcChannelStrideBytes;  /* stride from one channel to the next, in bytes */
1029
 
    unsigned int i;
1030
 
    unsigned long frameCount;
1031
 
    unsigned long framesToGo = framesToProcess;
1032
 
    unsigned long framesProcessed = 0;
1033
 
 
1034
 
    do
1035
 
    {
1036
 
        if( bp->framesInTempOutputBuffer == 0 && *streamCallbackResult == paContinue )
1037
 
        {
1038
 
            userInput = 0;
1039
 
 
1040
 
            /* setup userOutput */
1041
 
            if( bp->userOutputIsInterleaved )
1042
 
            {
1043
 
                userOutput = bp->tempOutputBuffer;
1044
 
            }
1045
 
            else /* user output is not interleaved */
1046
 
            {
1047
 
                for( i = 0; i < bp->outputChannelCount; ++i )
1048
 
                {
1049
 
                    bp->tempOutputBufferPtrs[i] = ((unsigned char*)bp->tempOutputBuffer) +
1050
 
                            i * bp->framesPerUserBuffer * bp->bytesPerUserOutputSample;
1051
 
                }
1052
 
 
1053
 
                userOutput = bp->tempOutputBufferPtrs;
1054
 
            }
1055
 
 
1056
 
            bp->timeInfo->inputBufferAdcTime = 0;
1057
 
 
1058
 
            *streamCallbackResult = bp->streamCallback( userInput, userOutput,
1059
 
                    bp->framesPerUserBuffer, bp->timeInfo,
1060
 
                    bp->callbackStatusFlags, bp->userData );
1061
 
 
1062
 
            if( *streamCallbackResult == paAbort )
1063
 
            {
1064
 
                /* if the callback returned paAbort, we disregard its output */
1065
 
            }
1066
 
            else
1067
 
            {
1068
 
                bp->timeInfo->outputBufferDacTime += bp->framesPerUserBuffer * bp->samplePeriod;
1069
 
 
1070
 
                bp->framesInTempOutputBuffer = bp->framesPerUserBuffer;
1071
 
            }
1072
 
        }
1073
 
 
1074
 
        if( bp->framesInTempOutputBuffer > 0 )
1075
 
        {
1076
 
            /* convert frameCount frames from user buffer to host buffer */
1077
 
 
1078
 
            frameCount = PA_MIN_( bp->framesInTempOutputBuffer, framesToGo );
1079
 
 
1080
 
            if( bp->userOutputIsInterleaved )
1081
 
            {
1082
 
                srcBytePtr = ((unsigned char*)bp->tempOutputBuffer) +
1083
 
                        bp->bytesPerUserOutputSample * bp->outputChannelCount *
1084
 
                        (bp->framesPerUserBuffer - bp->framesInTempOutputBuffer);
1085
 
 
1086
 
                srcSampleStrideSamples = bp->outputChannelCount;
1087
 
                srcChannelStrideBytes = bp->bytesPerUserOutputSample;
1088
 
            }
1089
 
            else /* user output is not interleaved */
1090
 
            {
1091
 
                srcBytePtr = ((unsigned char*)bp->tempOutputBuffer) +
1092
 
                        bp->bytesPerUserOutputSample *
1093
 
                        (bp->framesPerUserBuffer - bp->framesInTempOutputBuffer);
1094
 
 
1095
 
                srcSampleStrideSamples = 1;
1096
 
                srcChannelStrideBytes = bp->framesPerUserBuffer * bp->bytesPerUserOutputSample;
1097
 
            }
1098
 
 
1099
 
            for( i=0; i<bp->outputChannelCount; ++i )
1100
 
            {
1101
 
                bp->outputConverter(    hostOutputChannels[i].data,
1102
 
                                        hostOutputChannels[i].stride,
1103
 
                                        srcBytePtr, srcSampleStrideSamples,
1104
 
                                        frameCount, &bp->ditherGenerator );
1105
 
 
1106
 
                srcBytePtr += srcChannelStrideBytes;  /* skip to next source channel */
1107
 
 
1108
 
                /* advance dest ptr for next iteration */
1109
 
                hostOutputChannels[i].data = ((unsigned char*)hostOutputChannels[i].data) +
1110
 
                        frameCount * hostOutputChannels[i].stride * bp->bytesPerHostOutputSample;
1111
 
            }
1112
 
 
1113
 
            bp->framesInTempOutputBuffer -= frameCount;
1114
 
        }
1115
 
        else
1116
 
        {
1117
 
            /* no more user data is available because the callback has returned
1118
 
                paComplete or paAbort. Fill the remainder of the host buffer
1119
 
                with zeros.
1120
 
            */
1121
 
 
1122
 
            frameCount = framesToGo;
1123
 
 
1124
 
            for( i=0; i<bp->outputChannelCount; ++i )
1125
 
            {
1126
 
                bp->outputZeroer(   hostOutputChannels[i].data,
1127
 
                                    hostOutputChannels[i].stride,
1128
 
                                    frameCount );
1129
 
 
1130
 
                /* advance dest ptr for next iteration */
1131
 
                hostOutputChannels[i].data = ((unsigned char*)hostOutputChannels[i].data) +
1132
 
                        frameCount * hostOutputChannels[i].stride * bp->bytesPerHostOutputSample;
1133
 
            }
1134
 
        }
1135
 
 
1136
 
        framesProcessed += frameCount;
1137
 
 
1138
 
        framesToGo -= frameCount;
1139
 
 
1140
 
    }while( framesToGo > 0 );
1141
 
 
1142
 
    return framesProcessed;
1143
 
}
1144
 
 
1145
 
/* CopyTempOutputBuffersToHostOutputBuffers is called from AdaptingProcess to copy frames from
1146
 
        tempOutputBuffer to hostOutputChannels. This includes data conversion
1147
 
        and interleaving.
1148
 
*/
1149
 
static void CopyTempOutputBuffersToHostOutputBuffers( PaUtilBufferProcessor *bp)
1150
 
{
1151
 
    unsigned long maxFramesToCopy;
1152
 
    PaUtilChannelDescriptor *hostOutputChannels;
1153
 
    unsigned int frameCount;
1154
 
    unsigned char *srcBytePtr;
1155
 
    unsigned int srcSampleStrideSamples; /* stride from one sample to the next within a channel, in samples */
1156
 
    unsigned int srcChannelStrideBytes; /* stride from one channel to the next, in bytes */
1157
 
    unsigned int i;
1158
 
 
1159
 
     /* copy frames from user to host output buffers */
1160
 
     while( bp->framesInTempOutputBuffer > 0 &&
1161
 
             ((bp->hostOutputFrameCount[0] + bp->hostOutputFrameCount[1]) > 0) )
1162
 
     {
1163
 
         maxFramesToCopy = bp->framesInTempOutputBuffer;
1164
 
 
1165
 
         /* select the output buffer set (1st or 2nd) */
1166
 
         if( bp->hostOutputFrameCount[0] > 0 )
1167
 
         {
1168
 
             hostOutputChannels = bp->hostOutputChannels[0];
1169
 
             frameCount = PA_MIN_( bp->hostOutputFrameCount[0], maxFramesToCopy );
1170
 
         }
1171
 
         else
1172
 
         {
1173
 
             hostOutputChannels = bp->hostOutputChannels[1];
1174
 
             frameCount = PA_MIN_( bp->hostOutputFrameCount[1], maxFramesToCopy );
1175
 
         }
1176
 
 
1177
 
         if( bp->userOutputIsInterleaved )
1178
 
         {
1179
 
             srcBytePtr = ((unsigned char*)bp->tempOutputBuffer) +
1180
 
                     bp->bytesPerUserOutputSample * bp->outputChannelCount *
1181
 
                     (bp->framesPerUserBuffer - bp->framesInTempOutputBuffer);
1182
 
 
1183
 
             srcSampleStrideSamples = bp->outputChannelCount;
1184
 
             srcChannelStrideBytes = bp->bytesPerUserOutputSample;
1185
 
         }
1186
 
         else /* user output is not interleaved */
1187
 
         {
1188
 
             srcBytePtr = ((unsigned char*)bp->tempOutputBuffer) +
1189
 
                     bp->bytesPerUserOutputSample *
1190
 
                     (bp->framesPerUserBuffer - bp->framesInTempOutputBuffer);
1191
 
 
1192
 
             srcSampleStrideSamples = 1;
1193
 
             srcChannelStrideBytes = bp->framesPerUserBuffer * bp->bytesPerUserOutputSample;
1194
 
         }
1195
 
 
1196
 
         for( i=0; i<bp->outputChannelCount; ++i )
1197
 
         {
1198
 
             assert( hostOutputChannels[i].data != NULL );
1199
 
             bp->outputConverter(    hostOutputChannels[i].data,
1200
 
                                     hostOutputChannels[i].stride,
1201
 
                                     srcBytePtr, srcSampleStrideSamples,
1202
 
                                     frameCount, &bp->ditherGenerator );
1203
 
 
1204
 
             srcBytePtr += srcChannelStrideBytes;  /* skip to next source channel */
1205
 
 
1206
 
             /* advance dest ptr for next iteration */
1207
 
             hostOutputChannels[i].data = ((unsigned char*)hostOutputChannels[i].data) +
1208
 
                     frameCount * hostOutputChannels[i].stride * bp->bytesPerHostOutputSample;
1209
 
         }
1210
 
 
1211
 
         if( bp->hostOutputFrameCount[0] > 0 )
1212
 
             bp->hostOutputFrameCount[0] -= frameCount;
1213
 
         else
1214
 
             bp->hostOutputFrameCount[1] -= frameCount;
1215
 
 
1216
 
         bp->framesInTempOutputBuffer -= frameCount;
1217
 
     }
1218
 
}
1219
 
 
1220
 
/*
1221
 
    AdaptingProcess is a full duplex adapting buffer processor. It converts
1222
 
    data from the temporary output buffer into the host output buffers, then
1223
 
    from the host input buffers into the temporary input buffers. Calling the
1224
 
    streamCallback when necessary.
1225
 
    When processPartialUserBuffers is 0, all available input data will be
1226
 
    consumed and all available output space will be filled. When
1227
 
    processPartialUserBuffers is non-zero, as many full user buffers
1228
 
    as possible will be processed, but partial buffers will not be consumed.
1229
 
*/
1230
 
static unsigned long AdaptingProcess( PaUtilBufferProcessor *bp,
1231
 
        int *streamCallbackResult, int processPartialUserBuffers )
1232
 
{
1233
 
    void *userInput, *userOutput;
1234
 
    unsigned long framesProcessed = 0;
1235
 
    unsigned long framesAvailable;
1236
 
    unsigned long endProcessingMinFrameCount;
1237
 
    unsigned long maxFramesToCopy;
1238
 
    PaUtilChannelDescriptor *hostInputChannels, *hostOutputChannels;
1239
 
    unsigned int frameCount;
1240
 
    unsigned char *destBytePtr;
1241
 
    unsigned int destSampleStrideSamples; /* stride from one sample to the next within a channel, in samples */
1242
 
    unsigned int destChannelStrideBytes; /* stride from one channel to the next, in bytes */
1243
 
    unsigned int i, j;
1244
 
 
1245
 
 
1246
 
    framesAvailable = bp->hostInputFrameCount[0] + bp->hostInputFrameCount[1];/* this is assumed to be the same as the output buffer's frame count */
1247
 
 
1248
 
    if( processPartialUserBuffers )
1249
 
        endProcessingMinFrameCount = 0;
1250
 
    else
1251
 
        endProcessingMinFrameCount = (bp->framesPerUserBuffer - 1);
1252
 
 
1253
 
    /* Fill host output with remaining frames in user output (tempOutputBuffer) */
1254
 
    CopyTempOutputBuffersToHostOutputBuffers( bp );
1255
 
 
1256
 
    while( framesAvailable > endProcessingMinFrameCount )
1257
 
    {
1258
 
 
1259
 
        if( bp->framesInTempOutputBuffer == 0 && *streamCallbackResult != paContinue )
1260
 
        {
1261
 
            /* the callback will not be called any more, so zero what remains
1262
 
                of the host output buffers */
1263
 
 
1264
 
            for( i=0; i<2; ++i )
1265
 
            {
1266
 
                frameCount = bp->hostOutputFrameCount[i];
1267
 
                if( frameCount > 0 )
1268
 
                {
1269
 
                    hostOutputChannels = bp->hostOutputChannels[i];
1270
 
 
1271
 
                    for( j=0; j<bp->outputChannelCount; ++j )
1272
 
                    {
1273
 
                        bp->outputZeroer(   hostOutputChannels[j].data,
1274
 
                                            hostOutputChannels[j].stride,
1275
 
                                            frameCount );
1276
 
 
1277
 
                        /* advance dest ptr for next iteration  */
1278
 
                        hostOutputChannels[j].data = ((unsigned char*)hostOutputChannels[j].data) +
1279
 
                                frameCount * hostOutputChannels[j].stride * bp->bytesPerHostOutputSample;
1280
 
                    }
1281
 
                    bp->hostOutputFrameCount[i] = 0;
1282
 
                }
1283
 
            }
1284
 
        }
1285
 
 
1286
 
 
1287
 
        /* copy frames from host to user input buffers */
1288
 
        while( bp->framesInTempInputBuffer < bp->framesPerUserBuffer &&
1289
 
                ((bp->hostInputFrameCount[0] + bp->hostInputFrameCount[1]) > 0) )
1290
 
        {
1291
 
            maxFramesToCopy = bp->framesPerUserBuffer - bp->framesInTempInputBuffer;
1292
 
 
1293
 
            /* select the input buffer set (1st or 2nd) */
1294
 
            if( bp->hostInputFrameCount[0] > 0 )
1295
 
            {
1296
 
                hostInputChannels = bp->hostInputChannels[0];
1297
 
                frameCount = PA_MIN_( bp->hostInputFrameCount[0], maxFramesToCopy );
1298
 
            }
1299
 
            else
1300
 
            {
1301
 
                hostInputChannels = bp->hostInputChannels[1];
1302
 
                frameCount = PA_MIN_( bp->hostInputFrameCount[1], maxFramesToCopy );
1303
 
            }
1304
 
 
1305
 
            /* configure conversion destination pointers */
1306
 
            if( bp->userInputIsInterleaved )
1307
 
            {
1308
 
                destBytePtr = ((unsigned char*)bp->tempInputBuffer) +
1309
 
                        bp->bytesPerUserInputSample * bp->inputChannelCount *
1310
 
                        bp->framesInTempInputBuffer;
1311
 
 
1312
 
                destSampleStrideSamples = bp->inputChannelCount;
1313
 
                destChannelStrideBytes = bp->bytesPerUserInputSample;
1314
 
            }
1315
 
            else /* user input is not interleaved */
1316
 
            {
1317
 
                destBytePtr = ((unsigned char*)bp->tempInputBuffer) +
1318
 
                        bp->bytesPerUserInputSample * bp->framesInTempInputBuffer;
1319
 
 
1320
 
                destSampleStrideSamples = 1;
1321
 
                destChannelStrideBytes = bp->framesPerUserBuffer * bp->bytesPerUserInputSample;
1322
 
            }
1323
 
 
1324
 
            for( i=0; i<bp->inputChannelCount; ++i )
1325
 
            {
1326
 
                bp->inputConverter( destBytePtr, destSampleStrideSamples,
1327
 
                                        hostInputChannels[i].data,
1328
 
                                        hostInputChannels[i].stride,
1329
 
                                        frameCount, &bp->ditherGenerator );
1330
 
 
1331
 
                destBytePtr += destChannelStrideBytes;  /* skip to next destination channel */
1332
 
 
1333
 
                /* advance src ptr for next iteration */
1334
 
                hostInputChannels[i].data = ((unsigned char*)hostInputChannels[i].data) +
1335
 
                        frameCount * hostInputChannels[i].stride * bp->bytesPerHostInputSample;
1336
 
            }
1337
 
 
1338
 
            if( bp->hostInputFrameCount[0] > 0 )
1339
 
                bp->hostInputFrameCount[0] -= frameCount;
1340
 
            else
1341
 
                bp->hostInputFrameCount[1] -= frameCount;
1342
 
 
1343
 
            bp->framesInTempInputBuffer += frameCount;
1344
 
 
1345
 
            /* update framesAvailable and framesProcessed based on input consumed
1346
 
                unless something is very wrong this will also correspond to the
1347
 
                amount of output generated */
1348
 
            framesAvailable -= frameCount;
1349
 
            framesProcessed += frameCount;
1350
 
        }
1351
 
 
1352
 
        /* call streamCallback */
1353
 
        if( bp->framesInTempInputBuffer == bp->framesPerUserBuffer &&
1354
 
            bp->framesInTempOutputBuffer == 0 )
1355
 
        {
1356
 
            if( *streamCallbackResult == paContinue )
1357
 
            {
1358
 
                /* setup userInput */
1359
 
                if( bp->userInputIsInterleaved )
1360
 
                {
1361
 
                    userInput = bp->tempInputBuffer;
1362
 
                }
1363
 
                else /* user input is not interleaved */
1364
 
                {
1365
 
                    for( i = 0; i < bp->inputChannelCount; ++i )
1366
 
                    {
1367
 
                        bp->tempInputBufferPtrs[i] = ((unsigned char*)bp->tempInputBuffer) +
1368
 
                                i * bp->framesPerUserBuffer * bp->bytesPerUserInputSample;
1369
 
                    }
1370
 
 
1371
 
                    userInput = bp->tempInputBufferPtrs;
1372
 
                }
1373
 
 
1374
 
                /* setup userOutput */
1375
 
                if( bp->userOutputIsInterleaved )
1376
 
                {
1377
 
                    userOutput = bp->tempOutputBuffer;
1378
 
                }
1379
 
                else /* user output is not interleaved */
1380
 
                {
1381
 
                    for( i = 0; i < bp->outputChannelCount; ++i )
1382
 
                    {
1383
 
                        bp->tempOutputBufferPtrs[i] = ((unsigned char*)bp->tempOutputBuffer) +
1384
 
                                i * bp->framesPerUserBuffer * bp->bytesPerUserOutputSample;
1385
 
                    }
1386
 
 
1387
 
                    userOutput = bp->tempOutputBufferPtrs;
1388
 
                }
1389
 
 
1390
 
                /* call streamCallback */
1391
 
 
1392
 
                *streamCallbackResult = bp->streamCallback( userInput, userOutput,
1393
 
                        bp->framesPerUserBuffer, bp->timeInfo,
1394
 
                        bp->callbackStatusFlags, bp->userData );
1395
 
 
1396
 
                bp->timeInfo->inputBufferAdcTime += bp->framesPerUserBuffer * bp->samplePeriod;
1397
 
                bp->timeInfo->outputBufferDacTime += bp->framesPerUserBuffer * bp->samplePeriod;
1398
 
 
1399
 
                bp->framesInTempInputBuffer = 0;
1400
 
 
1401
 
                if( *streamCallbackResult == paAbort )
1402
 
                    bp->framesInTempOutputBuffer = 0;
1403
 
                else
1404
 
                    bp->framesInTempOutputBuffer = bp->framesPerUserBuffer;
1405
 
            }
1406
 
            else
1407
 
            {
1408
 
                /* paComplete or paAbort has already been called. */
1409
 
 
1410
 
                bp->framesInTempInputBuffer = 0;
1411
 
            }
1412
 
        }
1413
 
 
1414
 
        /* copy frames from user (tempOutputBuffer) to host output buffers (hostOutputChannels)
1415
 
           Means to process the user output provided by the callback. Has to be called after
1416
 
            each callback. */
1417
 
        CopyTempOutputBuffersToHostOutputBuffers( bp );
1418
 
 
1419
 
    }
1420
 
 
1421
 
    return framesProcessed;
1422
 
}
1423
 
 
1424
 
 
1425
 
unsigned long PaUtil_EndBufferProcessing( PaUtilBufferProcessor* bp, int *streamCallbackResult )
1426
 
{
1427
 
    unsigned long framesToProcess, framesToGo;
1428
 
    unsigned long framesProcessed = 0;
1429
 
 
1430
 
    if( bp->inputChannelCount != 0 && bp->outputChannelCount != 0
1431
 
            && bp->hostInputChannels[0][0].data /* input was supplied (see PaUtil_SetNoInput) */
1432
 
            && bp->hostOutputChannels[0][0].data /* output was supplied (see PaUtil_SetNoOutput) */ )
1433
 
    {
1434
 
        assert( (bp->hostInputFrameCount[0] + bp->hostInputFrameCount[1]) ==
1435
 
                (bp->hostOutputFrameCount[0] + bp->hostOutputFrameCount[1]) );
1436
 
    }
1437
 
 
1438
 
    assert( *streamCallbackResult == paContinue
1439
 
            || *streamCallbackResult == paComplete
1440
 
            || *streamCallbackResult == paAbort ); /* don't forget to pass in a valid callback result value */
1441
 
 
1442
 
    if( bp->useNonAdaptingProcess )
1443
 
    {
1444
 
        if( bp->inputChannelCount != 0 && bp->outputChannelCount != 0 )
1445
 
        {
1446
 
            /* full duplex non-adapting process, splice buffers if they are
1447
 
                different lengths */
1448
 
 
1449
 
            framesToGo = bp->hostOutputFrameCount[0] + bp->hostOutputFrameCount[1]; /* relies on assert above for input/output equivalence */
1450
 
 
1451
 
            do{
1452
 
                unsigned long noInputInputFrameCount;
1453
 
                unsigned long *hostInputFrameCount;
1454
 
                PaUtilChannelDescriptor *hostInputChannels;
1455
 
                unsigned long noOutputOutputFrameCount;
1456
 
                unsigned long *hostOutputFrameCount;
1457
 
                PaUtilChannelDescriptor *hostOutputChannels;
1458
 
                unsigned long framesProcessedThisIteration;
1459
 
 
1460
 
                if( !bp->hostInputChannels[0][0].data )
1461
 
                {
1462
 
                    /* no input was supplied (see PaUtil_SetNoInput)
1463
 
                        NonAdaptingProcess knows how to deal with this
1464
 
                    */
1465
 
                    noInputInputFrameCount = framesToGo;
1466
 
                    hostInputFrameCount = &noInputInputFrameCount;
1467
 
                    hostInputChannels = 0;
1468
 
                }
1469
 
                else if( bp->hostInputFrameCount[0] != 0 )
1470
 
                {
1471
 
                    hostInputFrameCount = &bp->hostInputFrameCount[0];
1472
 
                    hostInputChannels = bp->hostInputChannels[0];
1473
 
                }
1474
 
                else
1475
 
                {
1476
 
                    hostInputFrameCount = &bp->hostInputFrameCount[1];
1477
 
                    hostInputChannels = bp->hostInputChannels[1];
1478
 
                }
1479
 
 
1480
 
                if( !bp->hostOutputChannels[0][0].data )
1481
 
                {
1482
 
                    /* no output was supplied (see PaUtil_SetNoOutput)
1483
 
                        NonAdaptingProcess knows how to deal with this
1484
 
                    */
1485
 
                    noOutputOutputFrameCount = framesToGo;
1486
 
                    hostOutputFrameCount = &noOutputOutputFrameCount;
1487
 
                    hostOutputChannels = 0;
1488
 
                }
1489
 
                if( bp->hostOutputFrameCount[0] != 0 )
1490
 
                {
1491
 
                    hostOutputFrameCount = &bp->hostOutputFrameCount[0];
1492
 
                    hostOutputChannels = bp->hostOutputChannels[0];
1493
 
                }
1494
 
                else
1495
 
                {
1496
 
                    hostOutputFrameCount = &bp->hostOutputFrameCount[1];
1497
 
                    hostOutputChannels = bp->hostOutputChannels[1];
1498
 
                }
1499
 
 
1500
 
                framesToProcess = PA_MIN_( *hostInputFrameCount,
1501
 
                                       *hostOutputFrameCount );
1502
 
 
1503
 
                assert( framesToProcess != 0 );
1504
 
 
1505
 
                framesProcessedThisIteration = NonAdaptingProcess( bp, streamCallbackResult,
1506
 
                        hostInputChannels, hostOutputChannels,
1507
 
                        framesToProcess );
1508
 
 
1509
 
                *hostInputFrameCount -= framesProcessedThisIteration;
1510
 
                *hostOutputFrameCount -= framesProcessedThisIteration;
1511
 
 
1512
 
                framesProcessed += framesProcessedThisIteration;
1513
 
                framesToGo -= framesProcessedThisIteration;
1514
 
 
1515
 
            }while( framesToGo > 0 );
1516
 
        }
1517
 
        else
1518
 
        {
1519
 
            /* half duplex non-adapting process, just process 1st and 2nd buffer */
1520
 
            /* process first buffer */
1521
 
 
1522
 
            framesToProcess = (bp->inputChannelCount != 0)
1523
 
                            ? bp->hostInputFrameCount[0]
1524
 
                            : bp->hostOutputFrameCount[0];
1525
 
 
1526
 
            framesProcessed = NonAdaptingProcess( bp, streamCallbackResult,
1527
 
                        bp->hostInputChannels[0], bp->hostOutputChannels[0],
1528
 
                        framesToProcess );
1529
 
 
1530
 
            /* process second buffer if provided */
1531
 
 
1532
 
            framesToProcess = (bp->inputChannelCount != 0)
1533
 
                            ? bp->hostInputFrameCount[1]
1534
 
                            : bp->hostOutputFrameCount[1];
1535
 
            if( framesToProcess > 0 )
1536
 
            {
1537
 
                framesProcessed += NonAdaptingProcess( bp, streamCallbackResult,
1538
 
                    bp->hostInputChannels[1], bp->hostOutputChannels[1],
1539
 
                    framesToProcess );
1540
 
            }
1541
 
        }
1542
 
    }
1543
 
    else /* block adaption necessary*/
1544
 
    {
1545
 
 
1546
 
        if( bp->inputChannelCount != 0 && bp->outputChannelCount != 0 )
1547
 
        {
1548
 
            /* full duplex */
1549
 
 
1550
 
            if( bp->hostBufferSizeMode == paUtilVariableHostBufferSizePartialUsageAllowed  )
1551
 
            {
1552
 
                framesProcessed = AdaptingProcess( bp, streamCallbackResult,
1553
 
                        0 /* dont process partial user buffers */ );
1554
 
            }
1555
 
            else
1556
 
            {
1557
 
                framesProcessed = AdaptingProcess( bp, streamCallbackResult,
1558
 
                        1 /* process partial user buffers */ );
1559
 
            }
1560
 
        }
1561
 
        else if( bp->inputChannelCount != 0 )
1562
 
        {
1563
 
            /* input only */
1564
 
            framesToProcess = bp->hostInputFrameCount[0];
1565
 
 
1566
 
            framesProcessed = AdaptingInputOnlyProcess( bp, streamCallbackResult,
1567
 
                        bp->hostInputChannels[0], framesToProcess );
1568
 
 
1569
 
            framesToProcess = bp->hostInputFrameCount[1];
1570
 
            if( framesToProcess > 0 )
1571
 
            {
1572
 
                framesProcessed += AdaptingInputOnlyProcess( bp, streamCallbackResult,
1573
 
                        bp->hostInputChannels[1], framesToProcess );
1574
 
            }
1575
 
        }
1576
 
        else
1577
 
        {
1578
 
            /* output only */
1579
 
            framesToProcess = bp->hostOutputFrameCount[0];
1580
 
 
1581
 
            framesProcessed = AdaptingOutputOnlyProcess( bp, streamCallbackResult,
1582
 
                        bp->hostOutputChannels[0], framesToProcess );
1583
 
 
1584
 
            framesToProcess = bp->hostOutputFrameCount[1];
1585
 
            if( framesToProcess > 0 )
1586
 
            {
1587
 
                framesProcessed += AdaptingOutputOnlyProcess( bp, streamCallbackResult,
1588
 
                        bp->hostOutputChannels[1], framesToProcess );
1589
 
            }
1590
 
        }
1591
 
    }
1592
 
 
1593
 
    return framesProcessed;
1594
 
}
1595
 
 
1596
 
 
1597
 
int PaUtil_IsBufferProcessorOutputEmpty( PaUtilBufferProcessor* bp )
1598
 
{
1599
 
    return (bp->framesInTempOutputBuffer) ? 0 : 1;
1600
 
}
1601
 
 
1602
 
 
1603
 
unsigned long PaUtil_CopyInput( PaUtilBufferProcessor* bp,
1604
 
        void **buffer, unsigned long frameCount )
1605
 
{
1606
 
    PaUtilChannelDescriptor *hostInputChannels;
1607
 
    unsigned int framesToCopy;
1608
 
    unsigned char *destBytePtr;
1609
 
    void **nonInterleavedDestPtrs;
1610
 
    unsigned int destSampleStrideSamples; /* stride from one sample to the next within a channel, in samples */
1611
 
    unsigned int destChannelStrideBytes; /* stride from one channel to the next, in bytes */
1612
 
    unsigned int i;
1613
 
 
1614
 
    hostInputChannels = bp->hostInputChannels[0];
1615
 
    framesToCopy = PA_MIN_( bp->hostInputFrameCount[0], frameCount );
1616
 
 
1617
 
    if( bp->userInputIsInterleaved )
1618
 
    {
1619
 
        destBytePtr = (unsigned char*)*buffer;
1620
 
 
1621
 
        destSampleStrideSamples = bp->inputChannelCount;
1622
 
        destChannelStrideBytes = bp->bytesPerUserInputSample;
1623
 
 
1624
 
        for( i=0; i<bp->inputChannelCount; ++i )
1625
 
        {
1626
 
            bp->inputConverter( destBytePtr, destSampleStrideSamples,
1627
 
                                hostInputChannels[i].data,
1628
 
                                hostInputChannels[i].stride,
1629
 
                                framesToCopy, &bp->ditherGenerator );
1630
 
 
1631
 
            destBytePtr += destChannelStrideBytes;  /* skip to next source channel */
1632
 
 
1633
 
            /* advance dest ptr for next iteration */
1634
 
            hostInputChannels[i].data = ((unsigned char*)hostInputChannels[i].data) +
1635
 
                    framesToCopy * hostInputChannels[i].stride * bp->bytesPerHostInputSample;
1636
 
        }
1637
 
 
1638
 
        /* advance callers dest pointer (buffer) */
1639
 
        *buffer = ((unsigned char *)*buffer) +
1640
 
                framesToCopy * bp->inputChannelCount * bp->bytesPerUserInputSample;
1641
 
    }
1642
 
    else
1643
 
    {
1644
 
        /* user input is not interleaved */
1645
 
 
1646
 
        nonInterleavedDestPtrs = (void**)*buffer;
1647
 
 
1648
 
        destSampleStrideSamples = 1;
1649
 
 
1650
 
        for( i=0; i<bp->inputChannelCount; ++i )
1651
 
        {
1652
 
            destBytePtr = (unsigned char*)nonInterleavedDestPtrs[i];
1653
 
 
1654
 
            bp->inputConverter( destBytePtr, destSampleStrideSamples,
1655
 
                                hostInputChannels[i].data,
1656
 
                                hostInputChannels[i].stride,
1657
 
                                framesToCopy, &bp->ditherGenerator );
1658
 
 
1659
 
            /* advance callers dest pointer (nonInterleavedDestPtrs[i]) */
1660
 
            destBytePtr += bp->bytesPerUserInputSample * framesToCopy;
1661
 
            nonInterleavedDestPtrs[i] = destBytePtr;
1662
 
 
1663
 
            /* advance dest ptr for next iteration */
1664
 
            hostInputChannels[i].data = ((unsigned char*)hostInputChannels[i].data) +
1665
 
                    framesToCopy * hostInputChannels[i].stride * bp->bytesPerHostInputSample;
1666
 
        }
1667
 
    }
1668
 
 
1669
 
    bp->hostInputFrameCount[0] -= framesToCopy;
1670
 
 
1671
 
    return framesToCopy;
1672
 
}
1673
 
 
1674
 
unsigned long PaUtil_CopyOutput( PaUtilBufferProcessor* bp,
1675
 
        const void ** buffer, unsigned long frameCount )
1676
 
{
1677
 
    PaUtilChannelDescriptor *hostOutputChannels;
1678
 
    unsigned int framesToCopy;
1679
 
    unsigned char *srcBytePtr;
1680
 
    void **nonInterleavedSrcPtrs;
1681
 
    unsigned int srcSampleStrideSamples; /* stride from one sample to the next within a channel, in samples */
1682
 
    unsigned int srcChannelStrideBytes; /* stride from one channel to the next, in bytes */
1683
 
    unsigned int i;
1684
 
 
1685
 
    hostOutputChannels = bp->hostOutputChannels[0];
1686
 
    framesToCopy = PA_MIN_( bp->hostOutputFrameCount[0], frameCount );
1687
 
 
1688
 
    if( bp->userOutputIsInterleaved )
1689
 
    {
1690
 
        srcBytePtr = (unsigned char*)*buffer;
1691
 
 
1692
 
        srcSampleStrideSamples = bp->outputChannelCount;
1693
 
        srcChannelStrideBytes = bp->bytesPerUserOutputSample;
1694
 
 
1695
 
        for( i=0; i<bp->outputChannelCount; ++i )
1696
 
        {
1697
 
            bp->outputConverter(    hostOutputChannels[i].data,
1698
 
                                    hostOutputChannels[i].stride,
1699
 
                                    srcBytePtr, srcSampleStrideSamples,
1700
 
                                    framesToCopy, &bp->ditherGenerator );
1701
 
 
1702
 
            srcBytePtr += srcChannelStrideBytes;  /* skip to next source channel */
1703
 
 
1704
 
            /* advance dest ptr for next iteration */
1705
 
            hostOutputChannels[i].data = ((unsigned char*)hostOutputChannels[i].data) +
1706
 
                    framesToCopy * hostOutputChannels[i].stride * bp->bytesPerHostOutputSample;
1707
 
        }
1708
 
 
1709
 
        /* advance callers source pointer (buffer) */
1710
 
        *buffer = ((unsigned char *)*buffer) +
1711
 
                framesToCopy * bp->outputChannelCount * bp->bytesPerUserOutputSample;
1712
 
 
1713
 
    }
1714
 
    else
1715
 
    {
1716
 
        /* user output is not interleaved */
1717
 
 
1718
 
        nonInterleavedSrcPtrs = (void**)*buffer;
1719
 
 
1720
 
        srcSampleStrideSamples = 1;
1721
 
 
1722
 
        for( i=0; i<bp->outputChannelCount; ++i )
1723
 
        {
1724
 
            srcBytePtr = (unsigned char*)nonInterleavedSrcPtrs[i];
1725
 
 
1726
 
            bp->outputConverter(    hostOutputChannels[i].data,
1727
 
                                    hostOutputChannels[i].stride,
1728
 
                                    srcBytePtr, srcSampleStrideSamples,
1729
 
                                    framesToCopy, &bp->ditherGenerator );
1730
 
 
1731
 
 
1732
 
            /* advance callers source pointer (nonInterleavedSrcPtrs[i]) */
1733
 
            srcBytePtr += bp->bytesPerUserOutputSample * framesToCopy;
1734
 
            nonInterleavedSrcPtrs[i] = srcBytePtr;
1735
 
 
1736
 
            /* advance dest ptr for next iteration */
1737
 
            hostOutputChannels[i].data = ((unsigned char*)hostOutputChannels[i].data) +
1738
 
                    framesToCopy * hostOutputChannels[i].stride * bp->bytesPerHostOutputSample;
1739
 
        }
1740
 
    }
1741
 
 
1742
 
    bp->hostOutputFrameCount[0] += framesToCopy;
1743
 
 
1744
 
    return framesToCopy;
1745
 
}
1746
 
 
1747
 
 
1748
 
unsigned long PaUtil_ZeroOutput( PaUtilBufferProcessor* bp, unsigned long frameCount )
1749
 
{
1750
 
    PaUtilChannelDescriptor *hostOutputChannels;
1751
 
    unsigned int framesToZero;
1752
 
    unsigned int i;
1753
 
 
1754
 
    hostOutputChannels = bp->hostOutputChannels[0];
1755
 
    framesToZero = PA_MIN_( bp->hostOutputFrameCount[0], frameCount );
1756
 
 
1757
 
    for( i=0; i<bp->outputChannelCount; ++i )
1758
 
    {
1759
 
        bp->outputZeroer(   hostOutputChannels[i].data,
1760
 
                            hostOutputChannels[i].stride,
1761
 
                            framesToZero );
1762
 
 
1763
 
 
1764
 
        /* advance dest ptr for next iteration */
1765
 
        hostOutputChannels[i].data = ((unsigned char*)hostOutputChannels[i].data) +
1766
 
                framesToZero * hostOutputChannels[i].stride * bp->bytesPerHostOutputSample;
1767
 
    }
1768
 
 
1769
 
    bp->hostOutputFrameCount[0] += framesToZero;
1770
 
 
1771
 
    return framesToZero;
1772
 
}