aboutsummaryrefslogtreecommitdiff
path: root/pd/portaudio/pa_common
diff options
context:
space:
mode:
Diffstat (limited to 'pd/portaudio/pa_common')
-rw-r--r--pd/portaudio/pa_common/pa_cpuload.c96
-rw-r--r--pd/portaudio/pa_common/pa_cpuload.h63
-rw-r--r--pd/portaudio/pa_common/pa_dither.c203
-rw-r--r--pd/portaudio/pa_common/pa_dither.h91
-rw-r--r--pd/portaudio/pa_common/pa_endianness.h111
-rw-r--r--pd/portaudio/pa_common/pa_front.c1974
-rw-r--r--pd/portaudio/pa_common/pa_hostapi.h244
-rw-r--r--pd/portaudio/pa_common/pa_process.c1740
-rw-r--r--pd/portaudio/pa_common/pa_process.h733
-rw-r--r--pd/portaudio/pa_common/pa_skeleton.c807
-rw-r--r--pd/portaudio/pa_common/pa_stream.c141
-rw-r--r--pd/portaudio/pa_common/pa_stream.h196
-rw-r--r--pd/portaudio/pa_common/pa_trace.c88
-rw-r--r--pd/portaudio/pa_common/pa_trace.h70
-rw-r--r--pd/portaudio/pa_common/pa_util.h167
-rw-r--r--pd/portaudio/pa_common/portaudio.h1128
16 files changed, 7852 insertions, 0 deletions
diff --git a/pd/portaudio/pa_common/pa_cpuload.c b/pd/portaudio/pa_common/pa_cpuload.c
new file mode 100644
index 00000000..e70fbf4e
--- /dev/null
+++ b/pd/portaudio/pa_common/pa_cpuload.c
@@ -0,0 +1,96 @@
+/*
+ * $Id: pa_cpuload.c,v 1.1.2.14 2004/01/08 22:01:12 rossbencina Exp $
+ * Portable Audio I/O Library CPU Load measurement functions
+ * Portable CPU load measurement facility.
+ *
+ * Based on the Open Source API proposed by Ross Bencina
+ * Copyright (c) 2002 Ross Bencina
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/** @file
+ @brief Functions to assist in measuring the CPU utilization of a callback
+ stream. Used to implement the Pa_GetStreamCpuLoad() function.
+
+ @todo Dynamically calculate the coefficients used to smooth the CPU Load
+ Measurements over time to provide a uniform characterisation of CPU Load
+ independent of rate at which PaUtil_BeginCpuLoadMeasurement /
+ PaUtil_EndCpuLoadMeasurement are called.
+*/
+
+
+#include "pa_cpuload.h"
+
+#include <assert.h>
+
+#include "pa_util.h" /* for PaUtil_GetTime() */
+
+
+void PaUtil_InitializeCpuLoadMeasurer( PaUtilCpuLoadMeasurer* measurer, double sampleRate )
+{
+ assert( sampleRate > 0 );
+
+ measurer->samplingPeriod = 1. / sampleRate;
+ measurer->averageLoad = 0.;
+}
+
+void PaUtil_ResetCpuLoadMeasurer( PaUtilCpuLoadMeasurer* measurer )
+{
+ measurer->averageLoad = 0.;
+}
+
+void PaUtil_BeginCpuLoadMeasurement( PaUtilCpuLoadMeasurer* measurer )
+{
+ measurer->measurementStartTime = PaUtil_GetTime();
+}
+
+
+void PaUtil_EndCpuLoadMeasurement( PaUtilCpuLoadMeasurer* measurer, unsigned long framesProcessed )
+{
+ double measurementEndTime, secondsFor100Percent, measuredLoad;
+
+ if( framesProcessed > 0 ){
+ measurementEndTime = PaUtil_GetTime();
+
+ assert( framesProcessed > 0 );
+ secondsFor100Percent = framesProcessed * measurer->samplingPeriod;
+
+ measuredLoad = (measurementEndTime - measurer->measurementStartTime) / secondsFor100Percent;
+
+ /* Low pass filter the calculated CPU load to reduce jitter using a simple IIR low pass filter. */
+ /** FIXME @todo these coefficients shouldn't be hardwired */
+#define LOWPASS_COEFFICIENT_0 (0.9)
+#define LOWPASS_COEFFICIENT_1 (0.99999 - LOWPASS_COEFFICIENT_0)
+
+ measurer->averageLoad = (LOWPASS_COEFFICIENT_0 * measurer->averageLoad) +
+ (LOWPASS_COEFFICIENT_1 * measuredLoad);
+ }
+}
+
+
+double PaUtil_GetCpuLoad( PaUtilCpuLoadMeasurer* measurer )
+{
+ return measurer->averageLoad;
+}
diff --git a/pd/portaudio/pa_common/pa_cpuload.h b/pd/portaudio/pa_common/pa_cpuload.h
new file mode 100644
index 00000000..f77d9199
--- /dev/null
+++ b/pd/portaudio/pa_common/pa_cpuload.h
@@ -0,0 +1,63 @@
+#ifndef PA_CPULOAD_H
+#define PA_CPULOAD_H
+/*
+ * $Id: pa_cpuload.h,v 1.1.2.10 2004/01/08 22:01:12 rossbencina Exp $
+ * Portable Audio I/O Library CPU Load measurement functions
+ * Portable CPU load measurement facility.
+ *
+ * Based on the Open Source API proposed by Ross Bencina
+ * Copyright (c) 2002 Ross Bencina
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/** @file
+ @brief Functions to assist in measuring the CPU utilization of a callback
+ stream. Used to implement the Pa_GetStreamCpuLoad() function.
+*/
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+
+typedef struct {
+ double samplingPeriod;
+ double measurementStartTime;
+ double averageLoad;
+} PaUtilCpuLoadMeasurer; /**< @todo need better name than measurer */
+
+void PaUtil_InitializeCpuLoadMeasurer( PaUtilCpuLoadMeasurer* measurer, double sampleRate );
+void PaUtil_BeginCpuLoadMeasurement( PaUtilCpuLoadMeasurer* measurer );
+void PaUtil_EndCpuLoadMeasurement( PaUtilCpuLoadMeasurer* measurer, unsigned long framesProcessed );
+void PaUtil_ResetCpuLoadMeasurer( PaUtilCpuLoadMeasurer* measurer );
+double PaUtil_GetCpuLoad( PaUtilCpuLoadMeasurer* measurer );
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* PA_CPULOAD_H */
diff --git a/pd/portaudio/pa_common/pa_dither.c b/pd/portaudio/pa_common/pa_dither.c
new file mode 100644
index 00000000..eb6bec38
--- /dev/null
+++ b/pd/portaudio/pa_common/pa_dither.c
@@ -0,0 +1,203 @@
+/*
+ * $Id: pa_dither.c,v 1.1.2.5 2003/09/20 21:06:19 rossbencina Exp $
+ * Portable Audio I/O Library triangular dither generator
+ *
+ * Based on the Open Source API proposed by Ross Bencina
+ * Copyright (c) 1999-2002 Phil Burk, Ross Bencina
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/** @file
+ @brief Functions for generating dither noise
+*/
+
+
+#include "pa_dither.h"
+
+#define PA_DITHER_BITS_ (15)
+
+
+void PaUtil_InitializeTriangularDitherState( PaUtilTriangularDitherGenerator *state )
+{
+ state->previous = 0;
+ state->randSeed1 = 22222;
+ state->randSeed2 = 5555555;
+}
+
+
+signed long PaUtil_Generate16BitTriangularDither( PaUtilTriangularDitherGenerator *state )
+{
+ signed long current, highPass;
+
+ /* Generate two random numbers. */
+ state->randSeed1 = (state->randSeed1 * 196314165) + 907633515;
+ state->randSeed2 = (state->randSeed2 * 196314165) + 907633515;
+
+ /* Generate triangular distribution about 0.
+ * Shift before adding to prevent overflow which would skew the distribution.
+ * Also shift an extra bit for the high pass filter.
+ */
+#define DITHER_SHIFT_ ((32 - PA_DITHER_BITS_) + 1)
+ current = (((signed long)state->randSeed1)>>DITHER_SHIFT_) +
+ (((signed long)state->randSeed2)>>DITHER_SHIFT_);
+
+ /* High pass filter to reduce audibility. */
+ highPass = current - state->previous;
+ state->previous = current;
+ return highPass;
+}
+
+
+/* Multiply by PA_FLOAT_DITHER_SCALE_ to get a float between -2.0 and +1.99999 */
+#define PA_FLOAT_DITHER_SCALE_ (1.0f / ((1<<PA_DITHER_BITS_)-1))
+static const float const_float_dither_scale_ = PA_FLOAT_DITHER_SCALE_;
+
+float PaUtil_GenerateFloatTriangularDither( PaUtilTriangularDitherGenerator *state )
+{
+ signed long current, highPass;
+
+ /* Generate two random numbers. */
+ state->randSeed1 = (state->randSeed1 * 196314165) + 907633515;
+ state->randSeed2 = (state->randSeed2 * 196314165) + 907633515;
+
+ /* Generate triangular distribution about 0.
+ * Shift before adding to prevent overflow which would skew the distribution.
+ * Also shift an extra bit for the high pass filter.
+ */
+#define DITHER_SHIFT_ ((32 - PA_DITHER_BITS_) + 1)
+ current = (((signed long)state->randSeed1)>>DITHER_SHIFT_) +
+ (((signed long)state->randSeed2)>>DITHER_SHIFT_);
+
+ /* High pass filter to reduce audibility. */
+ highPass = current - state->previous;
+ state->previous = current;
+ return ((float)highPass) * const_float_dither_scale_;
+}
+
+
+/*
+The following alternate dither algorithms (from musicdsp.org) could be
+considered
+*/
+
+/*Noise shaped dither (March 2000)
+-------------------
+
+This is a simple implementation of highpass triangular-PDF dither with
+2nd-order noise shaping, for use when truncating floating point audio
+data to fixed point.
+
+The noise shaping lowers the noise floor by 11dB below 5kHz (@ 44100Hz
+sample rate) compared to triangular-PDF dither. The code below assumes
+input data is in the range +1 to -1 and doesn't check for overloads!
+
+To save time when generating dither for multiple channels you can do
+things like this: r3=(r1 & 0x7F)<<8; instead of calling rand() again.
+
+
+
+ int r1, r2; //rectangular-PDF random numbers
+ float s1, s2; //error feedback buffers
+ float s = 0.5f; //set to 0.0f for no noise shaping
+ float w = pow(2.0,bits-1); //word length (usually bits=16)
+ float wi= 1.0f/w;
+ float d = wi / RAND_MAX; //dither amplitude (2 lsb)
+ float o = wi * 0.5f; //remove dc offset
+ float in, tmp;
+ int out;
+
+
+//for each sample...
+
+ r2=r1; //can make HP-TRI dither by
+ r1=rand(); //subtracting previous rand()
+
+ in += s * (s1 + s1 - s2); //error feedback
+ tmp = in + o + d * (float)(r1 - r2); //dc offset and dither
+
+ out = (int)(w * tmp); //truncate downwards
+ if(tmp<0.0f) out--; //this is faster than floor()
+
+ s2 = s1;
+ s1 = in - wi * (float)out; //error
+
+
+
+--
+paul.kellett@maxim.abel.co.uk
+http://www.maxim.abel.co.uk
+*/
+
+
+/*
+16-to-8-bit first-order dither
+
+Type : First order error feedforward dithering code
+References : Posted by Jon Watte
+
+Notes :
+This is about as simple a dithering algorithm as you can implement, but it's
+likely to sound better than just truncating to N bits.
+
+Note that you might not want to carry forward the full difference for infinity.
+It's probably likely that the worst performance hit comes from the saturation
+conditionals, which can be avoided with appropriate instructions on many DSPs
+and integer SIMD type instructions, or CMOV.
+
+Last, if sound quality is paramount (such as when going from > 16 bits to 16
+bits) you probably want to use a higher-order dither function found elsewhere
+on this site.
+
+
+Code :
+// This code will down-convert and dither a 16-bit signed short
+// mono signal into an 8-bit unsigned char signal, using a first
+// order forward-feeding error term dither.
+
+#define uchar unsigned char
+
+void dither_one_channel_16_to_8( short * input, uchar * output, int count, int * memory )
+{
+ int m = *memory;
+ while( count-- > 0 ) {
+ int i = *input++;
+ i += m;
+ int j = i + 32768 - 128;
+ uchar o;
+ if( j < 0 ) {
+ o = 0;
+ }
+ else if( j > 65535 ) {
+ o = 255;
+ }
+ else {
+ o = (uchar)((j>>8)&0xff);
+ }
+ m = ((j-32768+128)-i);
+ *output++ = o;
+ }
+ *memory = m;
+}
+*/
diff --git a/pd/portaudio/pa_common/pa_dither.h b/pd/portaudio/pa_common/pa_dither.h
new file mode 100644
index 00000000..70369e18
--- /dev/null
+++ b/pd/portaudio/pa_common/pa_dither.h
@@ -0,0 +1,91 @@
+#ifndef PA_DITHER_H
+#define PA_DITHER_H
+/*
+ * $Id: pa_dither.h,v 1.1.2.4 2003/09/20 21:06:19 rossbencina Exp $
+ * Portable Audio I/O Library triangular dither generator
+ *
+ * Based on the Open Source API proposed by Ross Bencina
+ * Copyright (c) 1999-2002 Phil Burk, Ross Bencina
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/** @file
+ @brief Functions for generating dither noise
+*/
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+
+/** @brief State needed to generate a dither signal */
+typedef struct PaUtilTriangularDitherGenerator{
+ unsigned long previous;
+ unsigned long randSeed1;
+ unsigned long randSeed2;
+} PaUtilTriangularDitherGenerator;
+
+
+/** @brief Initialize dither state */
+void PaUtil_InitializeTriangularDitherState( PaUtilTriangularDitherGenerator *ditherState );
+
+
+/**
+ @brief Calculate 2 LSB dither signal with a triangular distribution.
+ Ranged for adding to a 1 bit right-shifted 32 bit integer
+ prior to >>15. eg:
+<pre>
+ signed long in = *
+ signed long dither = PaUtil_Generate16BitTriangularDither( ditherState );
+ signed short out = (signed short)(((in>>1) + dither) >> 15);
+</pre>
+ @return
+ A signed long with a range of +32767 to -32768
+*/
+signed long PaUtil_Generate16BitTriangularDither( PaUtilTriangularDitherGenerator *ditherState );
+
+
+/**
+ @brief Calculate 2 LSB dither signal with a triangular distribution.
+ Ranged for adding to a pre-scaled float.
+<pre>
+ float in = *
+ float dither = PaUtil_GenerateFloatTriangularDither( ditherState );
+ // use smaller scaler to prevent overflow when we add the dither
+ signed short out = (signed short)(in*(32766.0f) + dither );
+</pre>
+ @return
+ A float with a range of -2.0 to +1.99999.
+*/
+float PaUtil_GenerateFloatTriangularDither( PaUtilTriangularDitherGenerator *ditherState );
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* PA_DITHER_H */
diff --git a/pd/portaudio/pa_common/pa_endianness.h b/pd/portaudio/pa_common/pa_endianness.h
new file mode 100644
index 00000000..052bced6
--- /dev/null
+++ b/pd/portaudio/pa_common/pa_endianness.h
@@ -0,0 +1,111 @@
+#ifndef PA_ENDIANNESS_H
+#define PA_ENDIANNESS_H
+/*
+ * $Id: pa_endianness.h,v 1.1.2.3 2003/09/20 21:06:19 rossbencina Exp $
+ * Portable Audio I/O Library current platform endianness macros
+ *
+ * Based on the Open Source API proposed by Ross Bencina
+ * Copyright (c) 1999-2002 Phil Burk, Ross Bencina
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/** @file
+ @brief Configure endianness symbols for the target processor.
+
+ Arrange for either the PA_LITTLE_ENDIAN or PA_BIG_ENDIAN preprocessor symbols
+ to be defined. The one that is defined reflects the endianness of the target
+ platform and may be used to implement conditional compilation of byte-order
+ dependent code.
+
+ If either PA_LITTLE_ENDIAN or PA_BIG_ENDIAN is defined already, then no attempt
+ is made to override that setting. This may be useful if you have a better way
+ of determining the platform's endianness. The autoconf mechanism uses this for
+ example.
+
+ A PA_VALIDATE_ENDIANNESS macro is provided to compare the compile time
+ and runtime endiannes and raise an assertion if they don't match.
+*/
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+
+#if defined(PA_LITTLE_ENDIAN) || defined(PA_BIG_ENDIAN)
+ /* endianness define has been set externally, such as by autoconf */
+
+ #if defined(PA_LITTLE_ENDIAN) && defined(PA_BIG_ENDIAN)
+ #error both PA_LITTLE_ENDIAN and PA_BIG_ENDIAN have been defined externally to pa_endianness.h - only one endianness at a time please
+ #endif
+
+#else
+ /* endianness define has not been set externally */
+
+ /* set PA_LITTLE_ENDIAN or PA_BIG_ENDIAN by testing well known platform specific defines */
+
+ #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
+
+ #define PA_LITTLE_ENDIAN /* win32, assume intel byte order */
+
+ #else
+
+#endif
+
+ #if !defined(PA_LITTLE_ENDIAN) && !defined(PA_BIG_ENDIAN)
+ /*
+ If the following error is raised, you either need to modify the code above
+ to automatically determine the endianness from other symbols defined on your
+ platform, or define either PA_LITTLE_ENDIAN or PA_BIG_ENDIAN externally.
+ */
+ #error pa_endianness.h was unable to automatically determine the endianness of the target platform
+ #endif
+
+#endif
+
+/* PA_VALIDATE_ENDIANNESS compares the compile time and runtime endianness,
+ and raises an assertion if they don't match. <assert.h> must be included in
+ the context in which this macro is used.
+*/
+#if defined(PA_LITTLE_ENDIAN)
+ #define PA_VALIDATE_ENDIANNESS \
+ { \
+ const long nativeOne = 1; \
+ assert( "PortAudio: compile time and runtime endianness don't match" && (((char *)&nativeOne)[0]) == 1 ); \
+ }
+#elif defined(PA_BIG_ENDIAN)
+ #define PA_VALIDATE_ENDIANNESS \
+ { \
+ const long nativeOne = 1; \
+ assert( "PortAudio: compile time and runtime endianness don't match" && (((char *)&nativeOne)[0]) == 0 ); \
+ }
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* PA_ENDIANNESS_H */
diff --git a/pd/portaudio/pa_common/pa_front.c b/pd/portaudio/pa_common/pa_front.c
new file mode 100644
index 00000000..655c3bd0
--- /dev/null
+++ b/pd/portaudio/pa_common/pa_front.c
@@ -0,0 +1,1974 @@
+/*
+ * $Id: pa_front.c,v 1.1.2.50 2004/02/13 07:50:20 rossbencina Exp $
+ * Portable Audio I/O Library Multi-Host API front end
+ * Validate function parameters and manage multiple host APIs.
+ *
+ * Based on the Open Source API proposed by Ross Bencina
+ * Copyright (c) 1999-2002 Ross Bencina, Phil Burk
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/* doxygen index page */
+/** @mainpage
+
+PortAudio is an open-source cross-platform ‘C’ library for audio input
+and output. It is designed to simplify the porting of audio applications
+between various platforms, and also to simplify the development of audio
+software in general by hiding the complexities of device interfacing.
+
+See the PortAudio website for further information http://www.portaudio.com/
+
+This documentation pertains to PortAudio V19, API version 2.0 which is
+currently under development. API version 2.0 differs in a number of ways from
+previous versions, please consult the enhancement proposals for further details:
+http://www.portaudio.com/docs/proposals/index.html
+
+This documentation is under construction. Things you might be interested in
+include:
+
+- The PortAudio API 2.0, as documented in portaudio.h
+
+- The <a href="todo.html">TODO List</a>
+
+Feel free to pick an item off TODO list and fix/implement it. You may want to
+enquire about status on the PortAudio mailing list first.
+*/
+
+
+/** @file
+ @brief Implements public PortAudio API, checks some errors, forwards to
+ host API implementations.
+
+ Implements the functions defined in the PortAudio API, checks for
+ some parameter and state inconsistencies and forwards API requests to
+ specific Host API implementations (via the interface declared in
+ pa_hostapi.h), and Streams (via the interface declared in pa_stream.h).
+
+ This file handles initialization and termination of Host API
+ implementations via initializers stored in the paHostApiInitializers
+ global variable.
+
+ Some utility functions declared in pa_util.h are implemented in this file.
+
+ All PortAudio API functions can be conditionally compiled with logging code.
+ To compile with logging, define the PA_LOG_API_CALLS precompiler symbol.
+
+ @todo Consider adding host API specific error text in Pa_GetErrorText() for
+ paUnanticipatedHostError
+
+ @todo Consider adding a new error code for when (inputParameters == NULL)
+ && (outputParameters == NULL)
+
+ @todo review whether Pa_CloseStream() should call the interface's
+ CloseStream function if aborting the stream returns an error code.
+
+ @todo Create new error codes if a NULL buffer pointer, or a
+ zero frame count is passed to Pa_ReadStream or Pa_WriteStream.
+*/
+
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <memory.h>
+#include <string.h>
+#include <assert.h> /* needed by PA_VALIDATE_ENDIANNESS */
+
+#include "portaudio.h"
+#include "pa_util.h"
+#include "pa_endianness.h"
+#include "pa_hostapi.h"
+#include "pa_stream.h"
+
+#include "pa_trace.h"
+
+
+#define PA_VERSION_ 1899
+#define PA_VERSION_TEXT_ "PortAudio V19-devel"
+
+
+
+/* #define PA_LOG_API_CALLS */
+
+/*
+ The basic format for log messages is described below. If you need to
+ add any log messages, please follow this format.
+
+ Function entry (void function):
+
+ "FunctionName called.\n"
+
+ Function entry (non void function):
+
+ "FunctionName called:\n"
+ "\tParam1Type param1: param1Value\n"
+ "\tParam2Type param2: param2Value\n" (etc...)
+
+
+ Function exit (no return value):
+
+ "FunctionName returned.\n"
+
+ Function exit (simple return value):
+
+ "FunctionName returned:\n"
+ "\tReturnType: returnValue\n\n"
+
+ If the return type is an error code, the error text is displayed in ()
+
+ If the return type is not an error code, but has taken a special value
+ because an error occurred, then the reason for the error is shown in []
+
+ If the return type is a struct ptr, the struct is dumped.
+
+ See the code below for examples
+*/
+
+
+int Pa_GetVersion( void )
+{
+ return PA_VERSION_;
+}
+
+
+const char* Pa_GetVersionText( void )
+{
+ return PA_VERSION_TEXT_;
+}
+
+
+
+#define PA_LAST_HOST_ERROR_TEXT_LENGTH_ 1024
+
+static char lastHostErrorText_[ PA_LAST_HOST_ERROR_TEXT_LENGTH_ + 1 ] = {0};
+
+static PaHostErrorInfo lastHostErrorInfo_ = { (PaHostApiTypeId)-1, 0, lastHostErrorText_ };
+
+
+void PaUtil_SetLastHostErrorInfo( PaHostApiTypeId hostApiType, long errorCode,
+ const char *errorText )
+{
+ lastHostErrorInfo_.hostApiType = hostApiType;
+ lastHostErrorInfo_.errorCode = errorCode;
+
+ strncpy( lastHostErrorText_, errorText, PA_LAST_HOST_ERROR_TEXT_LENGTH_ );
+}
+
+
+void PaUtil_DebugPrint( const char *format, ... )
+{
+ va_list ap;
+
+ va_start( ap, format );
+ vfprintf( stderr, format, ap );
+ va_end( ap );
+
+ fflush( stderr );
+}
+
+
+static PaUtilHostApiRepresentation **hostApis_ = 0;
+static int hostApisCount_ = 0;
+static int initializationCount_ = 0;
+static int deviceCount_ = 0;
+
+PaUtilStreamRepresentation *firstOpenStream_ = NULL;
+
+
+#define PA_IS_INITIALISED_ (initializationCount_ != 0)
+
+
+static int CountHostApiInitializers( void )
+{
+ int result = 0;
+
+ while( paHostApiInitializers[ result ] != 0 )
+ ++result;
+ return result;
+}
+
+
+static void TerminateHostApis( void )
+{
+ /* terminate in reverse order from initialization */
+
+ while( hostApisCount_ > 0 )
+ {
+ --hostApisCount_;
+ hostApis_[hostApisCount_]->Terminate( hostApis_[hostApisCount_] );
+ }
+ hostApisCount_ = 0;
+ deviceCount_ = 0;
+
+ if( hostApis_ != 0 )
+ PaUtil_FreeMemory( hostApis_ );
+ hostApis_ = 0;
+}
+
+
+static PaError InitializeHostApis( void )
+{
+ PaError result = paNoError;
+ int i, initializerCount, baseDeviceIndex;
+
+ initializerCount = CountHostApiInitializers();
+
+ hostApis_ = (PaUtilHostApiRepresentation**)PaUtil_AllocateMemory(
+ sizeof(PaUtilHostApiRepresentation*) * initializerCount );
+ if( !hostApis_ )
+ {
+ result = paInsufficientMemory;
+ goto error;
+ }
+
+ hostApisCount_ = 0;
+ deviceCount_ = 0;
+ baseDeviceIndex = 0;
+
+ for( i=0; i< initializerCount; ++i )
+ {
+ hostApis_[hostApisCount_] = NULL;
+ result = paHostApiInitializers[i]( &hostApis_[hostApisCount_], hostApisCount_ );
+ if( result != paNoError )
+ goto error;
+
+ if( hostApis_[hostApisCount_] )
+ {
+
+ hostApis_[hostApisCount_]->privatePaFrontInfo.baseDeviceIndex = baseDeviceIndex;
+
+ if( hostApis_[hostApisCount_]->info.defaultInputDevice != paNoDevice )
+ hostApis_[hostApisCount_]->info.defaultInputDevice += baseDeviceIndex;
+
+ if( hostApis_[hostApisCount_]->info.defaultOutputDevice != paNoDevice )
+ hostApis_[hostApisCount_]->info.defaultOutputDevice += baseDeviceIndex;
+
+ baseDeviceIndex += hostApis_[hostApisCount_]->info.deviceCount;
+ deviceCount_ += hostApis_[hostApisCount_]->info.deviceCount;
+
+ ++hostApisCount_;
+ }
+ }
+
+ return result;
+
+error:
+ TerminateHostApis();
+ return result;
+}
+
+
+/*
+ FindHostApi() finds the index of the host api to which
+ <device> belongs and returns it. if <hostSpecificDeviceIndex> is
+ non-null, the host specific device index is returned in it.
+ returns -1 if <device> is out of range.
+
+*/
+static int FindHostApi( PaDeviceIndex device, int *hostSpecificDeviceIndex )
+{
+ int i=0;
+
+ if( !PA_IS_INITIALISED_ )
+ return -1;
+
+ if( device < 0 )
+ return -1;
+
+ while( i < hostApisCount_
+ && device >= hostApis_[i]->info.deviceCount )
+ {
+
+ device -= hostApis_[i]->info.deviceCount;
+ ++i;
+ }
+
+ if( i >= hostApisCount_ )
+ return -1;
+
+ if( hostSpecificDeviceIndex )
+ *hostSpecificDeviceIndex = device;
+
+ return i;
+}
+
+
+static void AddOpenStream( PaStream* stream )
+{
+ ((PaUtilStreamRepresentation*)stream)->nextOpenStream = firstOpenStream_;
+ firstOpenStream_ = (PaUtilStreamRepresentation*)stream;
+}
+
+
+static void RemoveOpenStream( PaStream* stream )
+{
+ PaUtilStreamRepresentation *previous = NULL;
+ PaUtilStreamRepresentation *current = firstOpenStream_;
+
+ while( current != NULL )
+ {
+ if( ((PaStream*)current) == stream )
+ {
+ if( previous == NULL )
+ {
+ firstOpenStream_ = current->nextOpenStream;
+ }
+ else
+ {
+ previous->nextOpenStream = current->nextOpenStream;
+ }
+ return;
+ }
+ else
+ {
+ previous = current;
+ current = current->nextOpenStream;
+ }
+ }
+}
+
+
+static void CloseOpenStreams( void )
+{
+ /* we call Pa_CloseStream() here to ensure that the same destruction
+ logic is used for automatically closed streams */
+
+ while( firstOpenStream_ != NULL )
+ Pa_CloseStream( firstOpenStream_ );
+}
+
+
+PaError Pa_Initialize( void )
+{
+ PaError result;
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint( "Pa_Initialize called.\n" );
+#endif
+
+ if( PA_IS_INITIALISED_ )
+ {
+ ++initializationCount_;
+ result = paNoError;
+ }
+ else
+ {
+ PA_VALIDATE_ENDIANNESS;
+
+ PaUtil_InitializeClock();
+ PaUtil_ResetTraceMessages();
+
+ result = InitializeHostApis();
+ if( result == paNoError )
+ ++initializationCount_;
+ }
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint( "Pa_Initialize returned:\n" );
+ PaUtil_DebugPrint( "\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
+#endif
+
+ return result;
+}
+
+
+PaError Pa_Terminate( void )
+{
+ PaError result;
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_Terminate called.\n" );
+#endif
+
+ if( PA_IS_INITIALISED_ )
+ {
+ if( --initializationCount_ == 0 )
+ {
+ CloseOpenStreams();
+
+ TerminateHostApis();
+
+ PaUtil_DumpTraceMessages();
+ }
+ result = paNoError;
+ }
+ else
+ {
+ result= paNotInitialized;
+ }
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_Terminate returned:\n" );
+ PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
+#endif
+
+ return result;
+}
+
+
+const PaHostErrorInfo* Pa_GetLastHostErrorInfo( void )
+{
+ return &lastHostErrorInfo_;
+}
+
+
+const char *Pa_GetErrorText( PaError errorCode )
+{
+ const char *result;
+
+ switch( errorCode )
+ {
+ case paNoError: result = "Success"; break;
+ case paNotInitialized: result = "PortAudio not initialized"; break;
+ /** @todo could catenate the last host error text to result in the case of paUnanticipatedHostError */
+ case paUnanticipatedHostError: result = "Unanticipated host error"; break;
+ case paInvalidChannelCount: result = "Invalid number of channels"; break;
+ case paInvalidSampleRate: result = "Invalid sample rate"; break;
+ case paInvalidDevice: result = "Invalid device"; break;
+ case paInvalidFlag: result = "Invalid flag"; break;
+ case paSampleFormatNotSupported: result = "Sample format not supported"; break;
+ case paBadIODeviceCombination: result = "Illegal combination of I/O devices"; break;
+ case paInsufficientMemory: result = "Insufficient memory"; break;
+ case paBufferTooBig: result = "Buffer too big"; break;
+ case paBufferTooSmall: result = "Buffer too small"; break;
+ case paNullCallback: result = "No callback routine specified"; break;
+ case paBadStreamPtr: result = "Invalid stream pointer"; break;
+ case paTimedOut: result = "Wait timed out"; break;
+ case paInternalError: result = "Internal PortAudio error"; break;
+ case paDeviceUnavailable: result = "Device unavailable"; break;
+ case paIncompatibleHostApiSpecificStreamInfo: result = "Incompatible host API specific stream info"; break;
+ case paStreamIsStopped: result = "Stream is stopped"; break;
+ case paStreamIsNotStopped: result = "Stream is not stopped"; break;
+ case paInputOverflowed: result = "Input overflowed"; break;
+ case paOutputUnderflowed: result = "Output underflowed"; break;
+ case paHostApiNotFound: result = "Host API not found"; break;
+ case paInvalidHostApi: result = "Invalid host API"; break;
+ case paCanNotReadFromACallbackStream: result = "Can't read from a callback stream"; break;
+ case paCanNotWriteToACallbackStream: result = "Can't write to a callback stream"; break;
+ case paCanNotReadFromAnOutputOnlyStream: result = "Can't read from an output only stream"; break;
+ case paCanNotWriteToAnInputOnlyStream: result = "Can't write to an input only stream"; break;
+ default: result = "Illegal error number"; break;
+ }
+ return result;
+}
+
+
+PaHostApiIndex Pa_HostApiTypeIdToHostApiIndex( PaHostApiTypeId type )
+{
+ PaHostApiIndex result;
+ int i;
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_HostApiTypeIdToHostApiIndex called:\n" );
+ PaUtil_DebugPrint("\tPaHostApiTypeId type: %d\n", type );
+#endif
+
+ if( !PA_IS_INITIALISED_ )
+ {
+ result = paNotInitialized;
+ }
+ else
+ {
+ result = paHostApiNotFound;
+
+ for( i=0; i < hostApisCount_; ++i )
+ {
+ if( hostApis_[i]->info.type == type )
+ {
+ result = i;
+ break;
+ }
+ }
+ }
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_HostApiTypeIdToHostApiIndex returned:\n" );
+ if( result < 0 )
+ PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
+ else
+ PaUtil_DebugPrint("\tPaHostApiIndex: %d\n\n", result );
+#endif
+
+ return result;
+}
+
+
+PaError PaUtil_GetHostApiRepresentation( struct PaUtilHostApiRepresentation **hostApi,
+ PaHostApiTypeId type )
+{
+ PaError result;
+ int i;
+
+ if( !PA_IS_INITIALISED_ )
+ {
+ result = paNotInitialized;
+ }
+ else
+ {
+ result = paHostApiNotFound;
+
+ for( i=0; i < hostApisCount_; ++i )
+ {
+ if( hostApis_[i]->info.type == type )
+ {
+ *hostApi = hostApis_[i];
+ result = paNoError;
+ break;
+ }
+ }
+ }
+
+ return result;
+}
+
+
+PaError PaUtil_DeviceIndexToHostApiDeviceIndex(
+ PaDeviceIndex *hostApiDevice, PaDeviceIndex device, struct PaUtilHostApiRepresentation *hostApi )
+{
+ PaError result;
+ PaDeviceIndex x;
+
+ x = device - hostApi->privatePaFrontInfo.baseDeviceIndex;
+
+ if( x < 0 || x >= hostApi->info.deviceCount )
+ {
+ result = paInvalidDevice;
+ }
+ else
+ {
+ *hostApiDevice = x;
+ result = paNoError;
+ }
+
+ return result;
+}
+
+
+PaHostApiIndex Pa_GetHostApiCount( void )
+{
+ int result;
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetHostApiCount called.\n" );
+#endif
+
+ if( !PA_IS_INITIALISED_ )
+ {
+ result = paNotInitialized;
+ }
+ else
+ {
+ result = hostApisCount_;
+ }
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetHostApiCount returned:\n" );
+ if( result < 0 )
+ PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
+ else
+ PaUtil_DebugPrint("\tPaHostApiIndex %d\n\n", result );
+#endif
+
+ return result;
+}
+
+
+PaHostApiIndex Pa_GetDefaultHostApi( void )
+{
+ int result;
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetDefaultHostApi called.\n" );
+#endif
+
+ if( !PA_IS_INITIALISED_ )
+ {
+ result = paNotInitialized;
+ }
+ else
+ {
+ result = paDefaultHostApiIndex;
+
+ /* internal consistency check: make sure that the default host api
+ index is within range */
+
+ if( result < 0 || result >= hostApisCount_ )
+ {
+ result = paInternalError;
+ }
+ }
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetDefaultHostApi returned:\n" );
+ if( result < 0 )
+ PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
+ else
+ PaUtil_DebugPrint("\tPaHostApiIndex %d\n\n", result );
+#endif
+
+ return result;
+}
+
+
+const PaHostApiInfo* Pa_GetHostApiInfo( PaHostApiIndex hostApi )
+{
+ PaHostApiInfo *info;
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetHostApiInfo called:\n" );
+ PaUtil_DebugPrint("\tPaHostApiIndex hostApi: %d\n", hostApi );
+#endif
+
+ if( !PA_IS_INITIALISED_ )
+ {
+ info = NULL;
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetHostApiInfo returned:\n" );
+ PaUtil_DebugPrint("\tPaHostApiInfo*: NULL [ PortAudio not initialized ]\n\n" );
+#endif
+
+ }
+ else if( hostApi < 0 || hostApi >= hostApisCount_ )
+ {
+ info = NULL;
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetHostApiInfo returned:\n" );
+ PaUtil_DebugPrint("\tPaHostApiInfo*: NULL [ hostApi out of range ]\n\n" );
+#endif
+
+ }
+ else
+ {
+ info = &hostApis_[hostApi]->info;
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetHostApiInfo returned:\n" );
+ PaUtil_DebugPrint("\tPaHostApiInfo*: 0x%p\n", info );
+ PaUtil_DebugPrint("\t{" );
+ PaUtil_DebugPrint("\t\tint structVersion: %d\n", info->structVersion );
+ PaUtil_DebugPrint("\t\tPaHostApiTypeId type: %d\n", info->type );
+ PaUtil_DebugPrint("\t\tconst char *name: %s\n\n", info->name );
+ PaUtil_DebugPrint("\t}\n\n" );
+#endif
+
+ }
+
+ return info;
+}
+
+
+PaDeviceIndex Pa_HostApiDeviceIndexToDeviceIndex( PaHostApiIndex hostApi, int hostApiDeviceIndex )
+{
+ PaDeviceIndex result;
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_HostApiDeviceIndexToPaDeviceIndex called:\n" );
+ PaUtil_DebugPrint("\tPaHostApiIndex hostApi: %d\n", hostApi );
+ PaUtil_DebugPrint("\tint hostApiDeviceIndex: %d\n", hostApiDeviceIndex );
+#endif
+
+ if( !PA_IS_INITIALISED_ )
+ {
+ result = paNotInitialized;
+ }
+ else
+ {
+ if( hostApi < 0 || hostApi >= hostApisCount_ )
+ {
+ result = paInvalidHostApi;
+ }
+ else
+ {
+ if( hostApiDeviceIndex < 0 ||
+ hostApiDeviceIndex >= hostApis_[hostApi]->info.deviceCount )
+ {
+ result = paInvalidDevice;
+ }
+ else
+ {
+ result = hostApis_[hostApi]->privatePaFrontInfo.baseDeviceIndex + hostApiDeviceIndex;
+ }
+ }
+ }
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_HostApiDeviceIndexToPaDeviceIndex returned:\n" );
+ if( result < 0 )
+ PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
+ else
+ PaUtil_DebugPrint("\tPaDeviceIndex: %d\n\n", result );
+#endif
+
+ return result;
+}
+
+
+PaDeviceIndex Pa_GetDeviceCount( void )
+{
+ PaDeviceIndex result;
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetDeviceCount called.\n" );
+#endif
+
+ if( !PA_IS_INITIALISED_ )
+ {
+ result = paNotInitialized;
+ }
+ else
+ {
+ result = deviceCount_;
+ }
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetDeviceCount returned:\n" );
+ if( result < 0 )
+ PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
+ else
+ PaUtil_DebugPrint("\tPaDeviceIndex: %d\n\n", result );
+#endif
+
+ return result;
+}
+
+
+PaDeviceIndex Pa_GetDefaultInputDevice( void )
+{
+ PaHostApiIndex hostApi;
+ PaDeviceIndex result;
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetDefaultInputDevice called.\n" );
+#endif
+
+ hostApi = Pa_GetDefaultHostApi();
+ if( hostApi < 0 )
+ {
+ result = paNoDevice;
+ }
+ else
+ {
+ result = hostApis_[hostApi]->info.defaultInputDevice;
+ }
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetDefaultInputDevice returned:\n" );
+ PaUtil_DebugPrint("\tPaDeviceIndex: %d\n\n", result );
+#endif
+
+ return result;
+}
+
+
+PaDeviceIndex Pa_GetDefaultOutputDevice( void )
+{
+ PaHostApiIndex hostApi;
+ PaDeviceIndex result;
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetDefaultOutputDevice called.\n" );
+#endif
+
+ hostApi = Pa_GetDefaultHostApi();
+ if( hostApi < 0 )
+ {
+ result = paNoDevice;
+ }
+ else
+ {
+ result = hostApis_[hostApi]->info.defaultOutputDevice;
+ }
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetDefaultOutputDevice returned:\n" );
+ PaUtil_DebugPrint("\tPaDeviceIndex: %d\n\n", result );
+#endif
+
+ return result;
+}
+
+
+const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceIndex device )
+{
+ int hostSpecificDeviceIndex;
+ int hostApiIndex = FindHostApi( device, &hostSpecificDeviceIndex );
+ PaDeviceInfo *result;
+
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetDeviceInfo called:\n" );
+ PaUtil_DebugPrint("\tPaDeviceIndex device: %d\n", device );
+#endif
+
+ if( hostApiIndex < 0 )
+ {
+ result = NULL;
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetDeviceInfo returned:\n" );
+ PaUtil_DebugPrint("\tPaDeviceInfo* NULL [ invalid device index ]\n\n" );
+#endif
+
+ }
+ else
+ {
+ result = hostApis_[hostApiIndex]->deviceInfos[ hostSpecificDeviceIndex ];
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetDeviceInfo returned:\n" );
+ PaUtil_DebugPrint("\tPaDeviceInfo*: 0x%p:\n", result );
+ PaUtil_DebugPrint("\t{\n" );
+
+ PaUtil_DebugPrint("\t\tint structVersion: %d\n", result->structVersion );
+ PaUtil_DebugPrint("\t\tconst char *name: %s\n", result->name );
+ PaUtil_DebugPrint("\t\tPaHostApiIndex hostApi: %d\n", result->hostApi );
+ PaUtil_DebugPrint("\t\tint maxInputChannels: %d\n", result->maxInputChannels );
+ PaUtil_DebugPrint("\t\tint maxOutputChannels: %d\n", result->maxOutputChannels );
+ PaUtil_DebugPrint("\t}\n\n" );
+#endif
+
+ }
+
+ return result;
+}
+
+
+/*
+ SampleFormatIsValid() returns 1 if sampleFormat is a sample format
+ defined in portaudio.h, or 0 otherwise.
+*/
+static int SampleFormatIsValid( PaSampleFormat format )
+{
+ switch( format & ~paNonInterleaved )
+ {
+ case paFloat32: return 1;
+ case paInt16: return 1;
+ case paInt32: return 1;
+ case paInt24: return 1;
+ case paInt8: return 1;
+ case paUInt8: return 1;
+ case paCustomFormat: return 1;
+ default: return 0;
+ }
+}
+
+/*
+ NOTE: make sure this validation list is kept syncronised with the one in
+ pa_hostapi.h
+
+ ValidateOpenStreamParameters() checks that parameters to Pa_OpenStream()
+ conform to the expected values as described below. This function is
+ also designed to be used with the proposed Pa_IsFormatSupported() function.
+
+ There are basically two types of validation that could be performed:
+ Generic conformance validation, and device capability mismatch
+ validation. This function performs only generic conformance validation.
+ Validation that would require knowledge of device capabilities is
+ not performed because of potentially complex relationships between
+ combinations of parameters - for example, even if the sampleRate
+ seems ok, it might not be for a duplex stream - we have no way of
+ checking this in an API-neutral way, so we don't try.
+
+ On success the function returns PaNoError and fills in hostApi,
+ hostApiInputDeviceID, and hostApiOutputDeviceID fields. On failure
+ the function returns an error code indicating the first encountered
+ parameter error.
+
+
+ If ValidateOpenStreamParameters() returns paNoError, the following
+ assertions are guaranteed to be true.
+
+ - at least one of inputParameters & outputParmeters is valid (not NULL)
+
+ - if inputParameters & outputParmeters are both valid, that
+ inputParameters->device & outputParmeters->device both use the same host api
+
+ PaDeviceIndex inputParameters->device
+ - is within range (0 to Pa_GetDeviceCount-1) Or:
+ - is paUseHostApiSpecificDeviceSpecification and
+ inputParameters->hostApiSpecificStreamInfo is non-NULL and refers
+ to a valid host api
+
+ int inputParameters->channelCount
+ - if inputParameters->device is not paUseHostApiSpecificDeviceSpecification, channelCount is > 0
+ - upper bound is NOT validated against device capabilities
+
+ PaSampleFormat inputParameters->sampleFormat
+ - is one of the sample formats defined in portaudio.h
+
+ void *inputParameters->hostApiSpecificStreamInfo
+ - if supplied its hostApi field matches the input device's host Api
+
+ PaDeviceIndex outputParmeters->device
+ - is within range (0 to Pa_GetDeviceCount-1)
+
+ int outputParmeters->channelCount
+ - if inputDevice is valid, channelCount is > 0
+ - upper bound is NOT validated against device capabilities
+
+ PaSampleFormat outputParmeters->sampleFormat
+ - is one of the sample formats defined in portaudio.h
+
+ void *outputParmeters->hostApiSpecificStreamInfo
+ - if supplied its hostApi field matches the output device's host Api
+
+ double sampleRate
+ - is not an 'absurd' rate (less than 1000. or greater than 200000.)
+ - sampleRate is NOT validated against device capabilities
+
+ PaStreamFlags streamFlags
+ - unused platform neutral flags are zero
+ - paNeverDropInput is only used for full-duplex callback streams with
+ variable buffer size (paFramesPerBufferUnspecified)
+*/
+static PaError ValidateOpenStreamParameters(
+ const PaStreamParameters *inputParameters,
+ const PaStreamParameters *outputParameters,
+ double sampleRate,
+ unsigned long framesPerBuffer,
+ PaStreamFlags streamFlags,
+ PaStreamCallback *streamCallback,
+ PaUtilHostApiRepresentation **hostApi,
+ PaDeviceIndex *hostApiInputDevice,
+ PaDeviceIndex *hostApiOutputDevice )
+{
+ int inputHostApiIndex = -1, /* Surpress uninitialised var warnings: compiler does */
+ outputHostApiIndex = -1; /* not see that if inputParameters and outputParame- */
+ /* ters are both nonzero, these indices are set. */
+
+ if( (inputParameters == NULL) && (outputParameters == NULL) )
+ {
+ return paInvalidDevice; /** @todo should be a new error code "invalid device parameters" or something */
+ }
+ else
+ {
+ if( inputParameters == NULL )
+ {
+ *hostApiInputDevice = paNoDevice;
+ }
+ else if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
+ {
+ if( inputParameters->hostApiSpecificStreamInfo )
+ {
+ inputHostApiIndex = Pa_HostApiTypeIdToHostApiIndex(
+ ((PaUtilHostApiSpecificStreamInfoHeader*)inputParameters->hostApiSpecificStreamInfo)->hostApiType );
+
+ if( inputHostApiIndex != -1 )
+ {
+ *hostApiInputDevice = paUseHostApiSpecificDeviceSpecification;
+ *hostApi = hostApis_[inputHostApiIndex];
+ }
+ else
+ {
+ return paInvalidDevice;
+ }
+ }
+ else
+ {
+ return paInvalidDevice;
+ }
+ }
+ else
+ {
+ if( inputParameters->device < 0 || inputParameters->device >= deviceCount_ )
+ return paInvalidDevice;
+
+ inputHostApiIndex = FindHostApi( inputParameters->device, hostApiInputDevice );
+ if( inputHostApiIndex < 0 )
+ return paInternalError;
+
+ *hostApi = hostApis_[inputHostApiIndex];
+
+ if( inputParameters->channelCount <= 0 )
+ return paInvalidChannelCount;
+
+ if( !SampleFormatIsValid( inputParameters->sampleFormat ) )
+ return paSampleFormatNotSupported;
+
+ if( inputParameters->hostApiSpecificStreamInfo != NULL )
+ {
+ if( ((PaUtilHostApiSpecificStreamInfoHeader*)inputParameters->hostApiSpecificStreamInfo)->hostApiType
+ != (*hostApi)->info.type )
+ return paIncompatibleHostApiSpecificStreamInfo;
+ }
+ }
+
+ if( outputParameters == NULL )
+ {
+ *hostApiOutputDevice = paNoDevice;
+ }
+ else if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )
+ {
+ if( outputParameters->hostApiSpecificStreamInfo )
+ {
+ outputHostApiIndex = Pa_HostApiTypeIdToHostApiIndex(
+ ((PaUtilHostApiSpecificStreamInfoHeader*)outputParameters->hostApiSpecificStreamInfo)->hostApiType );
+
+ if( outputHostApiIndex != -1 )
+ {
+ *hostApiOutputDevice = paUseHostApiSpecificDeviceSpecification;
+ *hostApi = hostApis_[outputHostApiIndex];
+ }
+ else
+ {
+ return paInvalidDevice;
+ }
+ }
+ else
+ {
+ return paInvalidDevice;
+ }
+ }
+ else
+ {
+ if( outputParameters->device < 0 || outputParameters->device >= deviceCount_ )
+ return paInvalidDevice;
+
+ outputHostApiIndex = FindHostApi( outputParameters->device, hostApiOutputDevice );
+ if( outputHostApiIndex < 0 )
+ return paInternalError;
+
+ *hostApi = hostApis_[outputHostApiIndex];
+
+ if( outputParameters->channelCount <= 0 )
+ return paInvalidChannelCount;
+
+ if( !SampleFormatIsValid( outputParameters->sampleFormat ) )
+ return paSampleFormatNotSupported;
+
+ if( outputParameters->hostApiSpecificStreamInfo != NULL )
+ {
+ if( ((PaUtilHostApiSpecificStreamInfoHeader*)outputParameters->hostApiSpecificStreamInfo)->hostApiType
+ != (*hostApi)->info.type )
+ return paIncompatibleHostApiSpecificStreamInfo;
+ }
+ }
+
+ if( (inputParameters != NULL) && (outputParameters != NULL) )
+ {
+ /* ensure that both devices use the same API */
+ if( inputHostApiIndex != outputHostApiIndex )
+ return paBadIODeviceCombination;
+ }
+ }
+
+
+ /* Check for absurd sample rates. */
+ if( (sampleRate < 1000.0) || (sampleRate > 200000.0) )
+ return paInvalidSampleRate;
+
+ if( ((streamFlags & ~paPlatformSpecificFlags) & ~(paClipOff | paDitherOff | paNeverDropInput | paPrimeOutputBuffersUsingStreamCallback ) ) != 0 )
+ return paInvalidFlag;
+
+ if( streamFlags & paNeverDropInput )
+ {
+ /* must be a callback stream */
+ if( !streamCallback )
+ return paInvalidFlag;
+
+ /* must be a full duplex stream */
+ if( (inputParameters == NULL) || (outputParameters == NULL) )
+ return paInvalidFlag;
+
+ /* must use paFramesPerBufferUnspecified */
+ if( framesPerBuffer != paFramesPerBufferUnspecified )
+ return paInvalidFlag;
+ }
+
+ return paNoError;
+}
+
+
+PaError Pa_IsFormatSupported( const PaStreamParameters *inputParameters,
+ const PaStreamParameters *outputParameters,
+ double sampleRate )
+{
+ PaError result;
+ PaUtilHostApiRepresentation *hostApi;
+ PaDeviceIndex hostApiInputDevice, hostApiOutputDevice;
+ PaStreamParameters hostApiInputParameters, hostApiOutputParameters;
+ PaStreamParameters *hostApiInputParametersPtr, *hostApiOutputParametersPtr;
+
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_IsFormatSupported called:\n" );
+
+ if( inputParameters == NULL ){
+ PaUtil_DebugPrint("\tPaStreamParameters *inputParameters: NULL\n" );
+ }else{
+ PaUtil_DebugPrint("\tPaStreamParameters *inputParameters: 0x%p\n", inputParameters );
+ PaUtil_DebugPrint("\tPaDeviceIndex inputParameters->device: %d\n", inputParameters->device );
+ PaUtil_DebugPrint("\tint inputParameters->channelCount: %d\n", inputParameters->channelCount );
+ PaUtil_DebugPrint("\tPaSampleFormat inputParameters->sampleFormat: %d\n", inputParameters->sampleFormat );
+ PaUtil_DebugPrint("\tPaTime inputParameters->suggestedLatency: %f\n", inputParameters->suggestedLatency );
+ PaUtil_DebugPrint("\tvoid *inputParameters->hostApiSpecificStreamInfo: 0x%p\n", inputParameters->hostApiSpecificStreamInfo );
+ }
+
+ if( outputParameters == NULL ){
+ PaUtil_DebugPrint("\tPaStreamParameters *outputParameters: NULL\n" );
+ }else{
+ PaUtil_DebugPrint("\tPaStreamParameters *outputParameters: 0x%p\n", outputParameters );
+ PaUtil_DebugPrint("\tPaDeviceIndex outputParameters->device: %d\n", outputParameters->device );
+ PaUtil_DebugPrint("\tint outputParameters->channelCount: %d\n", outputParameters->channelCount );
+ PaUtil_DebugPrint("\tPaSampleFormat outputParameters->sampleFormat: %d\n", outputParameters->sampleFormat );
+ PaUtil_DebugPrint("\tPaTime outputParameters->suggestedLatency: %f\n", outputParameters->suggestedLatency );
+ PaUtil_DebugPrint("\tvoid *outputParameters->hostApiSpecificStreamInfo: 0x%p\n", outputParameters->hostApiSpecificStreamInfo );
+ }
+
+ PaUtil_DebugPrint("\tdouble sampleRate: %g\n", sampleRate );
+#endif
+
+ if( !PA_IS_INITIALISED_ )
+ {
+ result = paNotInitialized;
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_IsFormatSupported returned:\n" );
+ PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
+#endif
+ return result;
+ }
+
+ result = ValidateOpenStreamParameters( inputParameters,
+ outputParameters,
+ sampleRate, 0, paNoFlag, 0,
+ &hostApi,
+ &hostApiInputDevice,
+ &hostApiOutputDevice );
+ if( result != paNoError )
+ {
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_IsFormatSupported returned:\n" );
+ PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
+#endif
+ return result;
+ }
+
+
+ if( inputParameters )
+ {
+ hostApiInputParameters.device = hostApiInputDevice;
+ hostApiInputParameters.channelCount = inputParameters->channelCount;
+ hostApiInputParameters.sampleFormat = inputParameters->sampleFormat;
+ hostApiInputParameters.suggestedLatency = inputParameters->suggestedLatency;
+ hostApiInputParameters.hostApiSpecificStreamInfo = inputParameters->hostApiSpecificStreamInfo;
+ hostApiInputParametersPtr = &hostApiInputParameters;
+ }
+ else
+ {
+ hostApiInputParametersPtr = NULL;
+ }
+
+ if( outputParameters )
+ {
+ hostApiOutputParameters.device = hostApiOutputDevice;
+ hostApiOutputParameters.channelCount = outputParameters->channelCount;
+ hostApiOutputParameters.sampleFormat = outputParameters->sampleFormat;
+ hostApiOutputParameters.suggestedLatency = outputParameters->suggestedLatency;
+ hostApiOutputParameters.hostApiSpecificStreamInfo = outputParameters->hostApiSpecificStreamInfo;
+ hostApiOutputParametersPtr = &hostApiOutputParameters;
+ }
+ else
+ {
+ hostApiOutputParametersPtr = NULL;
+ }
+
+ result = hostApi->IsFormatSupported( hostApi,
+ hostApiInputParametersPtr, hostApiOutputParametersPtr,
+ sampleRate );
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_OpenStream returned:\n" );
+ if( result == paFormatIsSupported )
+ PaUtil_DebugPrint("\tPaError: 0 [ paFormatIsSupported ]\n\n" );
+ else
+ PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
+#endif
+
+ return result;
+}
+
+
+PaError Pa_OpenStream( PaStream** stream,
+ const PaStreamParameters *inputParameters,
+ const PaStreamParameters *outputParameters,
+ double sampleRate,
+ unsigned long framesPerBuffer,
+ PaStreamFlags streamFlags,
+ PaStreamCallback *streamCallback,
+ void *userData )
+{
+ PaError result;
+ PaUtilHostApiRepresentation *hostApi;
+ PaDeviceIndex hostApiInputDevice, hostApiOutputDevice;
+ PaStreamParameters hostApiInputParameters, hostApiOutputParameters;
+ PaStreamParameters *hostApiInputParametersPtr, *hostApiOutputParametersPtr;
+
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_OpenStream called:\n" );
+ PaUtil_DebugPrint("\tPaStream** stream: 0x%p\n", stream );
+
+ if( inputParameters == NULL ){
+ PaUtil_DebugPrint("\tPaStreamParameters *inputParameters: NULL\n" );
+ }else{
+ PaUtil_DebugPrint("\tPaStreamParameters *inputParameters: 0x%p\n", inputParameters );
+ PaUtil_DebugPrint("\tPaDeviceIndex inputParameters->device: %d\n", inputParameters->device );
+ PaUtil_DebugPrint("\tint inputParameters->channelCount: %d\n", inputParameters->channelCount );
+ PaUtil_DebugPrint("\tPaSampleFormat inputParameters->sampleFormat: %d\n", inputParameters->sampleFormat );
+ PaUtil_DebugPrint("\tPaTime inputParameters->suggestedLatency: %f\n", inputParameters->suggestedLatency );
+ PaUtil_DebugPrint("\tvoid *inputParameters->hostApiSpecificStreamInfo: 0x%p\n", inputParameters->hostApiSpecificStreamInfo );
+ }
+
+ if( outputParameters == NULL ){
+ PaUtil_DebugPrint("\tPaStreamParameters *outputParameters: NULL\n" );
+ }else{
+ PaUtil_DebugPrint("\tPaStreamParameters *outputParameters: 0x%p\n", outputParameters );
+ PaUtil_DebugPrint("\tPaDeviceIndex outputParameters->device: %d\n", outputParameters->device );
+ PaUtil_DebugPrint("\tint outputParameters->channelCount: %d\n", outputParameters->channelCount );
+ PaUtil_DebugPrint("\tPaSampleFormat outputParameters->sampleFormat: %d\n", outputParameters->sampleFormat );
+ PaUtil_DebugPrint("\tPaTime outputParameters->suggestedLatency: %f\n", outputParameters->suggestedLatency );
+ PaUtil_DebugPrint("\tvoid *outputParameters->hostApiSpecificStreamInfo: 0x%p\n", outputParameters->hostApiSpecificStreamInfo );
+ }
+
+ PaUtil_DebugPrint("\tdouble sampleRate: %g\n", sampleRate );
+ PaUtil_DebugPrint("\tunsigned long framesPerBuffer: %d\n", framesPerBuffer );
+ PaUtil_DebugPrint("\tPaStreamFlags streamFlags: 0x%x\n", streamFlags );
+ PaUtil_DebugPrint("\tPaStreamCallback *streamCallback: 0x%p\n", streamCallback );
+ PaUtil_DebugPrint("\tvoid *userData: 0x%p\n", userData );
+#endif
+
+ if( !PA_IS_INITIALISED_ )
+ {
+ result = paNotInitialized;
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_OpenStream returned:\n" );
+ PaUtil_DebugPrint("\t*(PaStream** stream): undefined\n" );
+ PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
+#endif
+ return result;
+ }
+
+ /* Check for parameter errors.
+ NOTE: make sure this validation list is kept syncronised with the one
+ in pa_hostapi.h
+ */
+
+ if( stream == NULL )
+ {
+ result = paBadStreamPtr;
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_OpenStream returned:\n" );
+ PaUtil_DebugPrint("\t*(PaStream** stream): undefined\n" );
+ PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
+#endif
+ return result;
+ }
+
+ result = ValidateOpenStreamParameters( inputParameters,
+ outputParameters,
+ sampleRate, framesPerBuffer,
+ streamFlags, streamCallback,
+ &hostApi,
+ &hostApiInputDevice,
+ &hostApiOutputDevice );
+ if( result != paNoError )
+ {
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_OpenStream returned:\n" );
+ PaUtil_DebugPrint("\t*(PaStream** stream): undefined\n" );
+ PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
+#endif
+ return result;
+ }
+
+
+ if( inputParameters )
+ {
+ hostApiInputParameters.device = hostApiInputDevice;
+ hostApiInputParameters.channelCount = inputParameters->channelCount;
+ hostApiInputParameters.sampleFormat = inputParameters->sampleFormat;
+ hostApiInputParameters.suggestedLatency = inputParameters->suggestedLatency;
+ hostApiInputParameters.hostApiSpecificStreamInfo = inputParameters->hostApiSpecificStreamInfo;
+ hostApiInputParametersPtr = &hostApiInputParameters;
+ }
+ else
+ {
+ hostApiInputParametersPtr = NULL;
+ }
+
+ if( outputParameters )
+ {
+ hostApiOutputParameters.device = hostApiOutputDevice;
+ hostApiOutputParameters.channelCount = outputParameters->channelCount;
+ hostApiOutputParameters.sampleFormat = outputParameters->sampleFormat;
+ hostApiOutputParameters.suggestedLatency = outputParameters->suggestedLatency;
+ hostApiOutputParameters.hostApiSpecificStreamInfo = outputParameters->hostApiSpecificStreamInfo;
+ hostApiOutputParametersPtr = &hostApiOutputParameters;
+ }
+ else
+ {
+ hostApiOutputParametersPtr = NULL;
+ }
+
+ result = hostApi->OpenStream( hostApi, stream,
+ hostApiInputParametersPtr, hostApiOutputParametersPtr,
+ sampleRate, framesPerBuffer, streamFlags, streamCallback, userData );
+
+ if( result == paNoError )
+ AddOpenStream( *stream );
+
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_OpenStream returned:\n" );
+ PaUtil_DebugPrint("\t*(PaStream** stream): 0x%p\n", *stream );
+ PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
+#endif
+
+ return result;
+}
+
+
+PaError Pa_OpenDefaultStream( PaStream** stream,
+ int inputChannelCount,
+ int outputChannelCount,
+ PaSampleFormat sampleFormat,
+ double sampleRate,
+ unsigned long framesPerBuffer,
+ PaStreamCallback *streamCallback,
+ void *userData )
+{
+ PaError result;
+ PaStreamParameters hostApiInputParameters, hostApiOutputParameters;
+ PaStreamParameters *hostApiInputParametersPtr, *hostApiOutputParametersPtr;
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_OpenDefaultStream called:\n" );
+ PaUtil_DebugPrint("\tPaStream** stream: 0x%p\n", stream );
+ PaUtil_DebugPrint("\tint inputChannelCount: %d\n", inputChannelCount );
+ PaUtil_DebugPrint("\tint outputChannelCount: %d\n", outputChannelCount );
+ PaUtil_DebugPrint("\tPaSampleFormat sampleFormat: %d\n", sampleFormat );
+ PaUtil_DebugPrint("\tdouble sampleRate: %g\n", sampleRate );
+ PaUtil_DebugPrint("\tunsigned long framesPerBuffer: %d\n", framesPerBuffer );
+ PaUtil_DebugPrint("\tPaStreamCallback *streamCallback: 0x%p\n", streamCallback );
+ PaUtil_DebugPrint("\tvoid *userData: 0x%p\n", userData );
+#endif
+
+
+ if( inputChannelCount > 0 )
+ {
+ hostApiInputParameters.device = Pa_GetDefaultInputDevice();
+ hostApiInputParameters.channelCount = inputChannelCount;
+ hostApiInputParameters.sampleFormat = sampleFormat;
+ /* defaultHighInputLatency is used below instead of
+ defaultLowInputLatency because it is more important for the default
+ stream to work reliably than it is for it to work with the lowest
+ latency.
+ */
+ hostApiInputParameters.suggestedLatency =
+ Pa_GetDeviceInfo( hostApiInputParameters.device )->defaultHighInputLatency;
+ hostApiInputParameters.hostApiSpecificStreamInfo = NULL;
+ hostApiInputParametersPtr = &hostApiInputParameters;
+ }
+ else
+ {
+ hostApiInputParametersPtr = NULL;
+ }
+
+ if( outputChannelCount > 0 )
+ {
+ hostApiOutputParameters.device = Pa_GetDefaultOutputDevice();
+ hostApiOutputParameters.channelCount = outputChannelCount;
+ hostApiOutputParameters.sampleFormat = sampleFormat;
+ /* defaultHighOutputLatency is used below instead of
+ defaultLowOutputLatency because it is more important for the default
+ stream to work reliably than it is for it to work with the lowest
+ latency.
+ */
+ hostApiOutputParameters.suggestedLatency =
+ Pa_GetDeviceInfo( hostApiOutputParameters.device )->defaultHighOutputLatency;
+ hostApiOutputParameters.hostApiSpecificStreamInfo = NULL;
+ hostApiOutputParametersPtr = &hostApiOutputParameters;
+ }
+ else
+ {
+ hostApiOutputParametersPtr = NULL;
+ }
+
+
+ result = Pa_OpenStream(
+ stream, hostApiInputParametersPtr, hostApiOutputParametersPtr,
+ sampleRate, framesPerBuffer, paNoFlag, streamCallback, userData );
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_OpenDefaultStream returned:\n" );
+ PaUtil_DebugPrint("\t*(PaStream** stream): 0x%p", *stream );
+ PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
+#endif
+
+ return result;
+}
+
+
+PaError PaUtil_ValidateStreamPointer( PaStream* stream )
+{
+ if( !PA_IS_INITIALISED_ ) return paNotInitialized;
+
+ if( stream == NULL ) return paBadStreamPtr;
+
+ if( ((PaUtilStreamRepresentation*)stream)->magic != PA_STREAM_MAGIC )
+ return paBadStreamPtr;
+
+ return paNoError;
+}
+
+
+PaError Pa_CloseStream( PaStream* stream )
+{
+ PaUtilStreamInterface *interface;
+ PaError result = PaUtil_ValidateStreamPointer( stream );
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_CloseStream called:\n" );
+ PaUtil_DebugPrint("\tPaStream* stream: 0x%p\n", stream );
+#endif
+
+ /* always remove the open stream from our list, even if this function
+ eventually returns an error. Otherwise CloseOpenStreams() will
+ get stuck in an infinite loop */
+ RemoveOpenStream( stream ); /* be sure to call this _before_ closing the stream */
+
+ if( result == paNoError )
+ {
+ interface = PA_STREAM_INTERFACE(stream);
+
+ /* abort the stream if it isn't stopped */
+ result = interface->IsStopped( stream );
+ if( result == 1 )
+ result = paNoError;
+ else if( result == 0 )
+ result = interface->Abort( stream );
+
+ if( result == paNoError ) /** @todo REVIEW: shouldn't we close anyway? */
+ result = interface->Close( stream );
+ }
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_CloseStream returned:\n" );
+ PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
+#endif
+
+ return result;
+}
+
+
+PaError Pa_SetStreamFinishedCallback( PaStream *stream, PaStreamFinishedCallback* streamFinishedCallback )
+{
+ PaError result = PaUtil_ValidateStreamPointer( stream );
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_SetStreamFinishedCallback called:\n" );
+ PaUtil_DebugPrint("\tPaStream* stream: 0x%p\n", stream );
+ PaUtil_DebugPrint("\tPaStreamFinishedCallback* streamFinishedCallback: 0x%p\n", streamFinishedCallback );
+#endif
+
+ if( result == paNoError )
+ {
+ result = PA_STREAM_INTERFACE(stream)->IsStopped( stream );
+ if( result == 0 )
+ {
+ result = paStreamIsNotStopped ;
+ }
+ if( result == 1 )
+ {
+ PA_STREAM_REP( stream )->streamFinishedCallback = streamFinishedCallback;
+ result = paNoError;
+ }
+ }
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_SetStreamFinishedCallback returned:\n" );
+ PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
+#endif
+
+ return result;
+
+}
+
+
+PaError Pa_StartStream( PaStream *stream )
+{
+ PaError result = PaUtil_ValidateStreamPointer( stream );
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_StartStream called:\n" );
+ PaUtil_DebugPrint("\tPaStream* stream: 0x%p\n", stream );
+#endif
+
+ if( result == paNoError )
+ {
+ result = PA_STREAM_INTERFACE(stream)->IsStopped( stream );
+ if( result == 0 )
+ {
+ result = paStreamIsNotStopped ;
+ }
+ else if( result == 1 )
+ {
+ result = PA_STREAM_INTERFACE(stream)->Start( stream );
+ }
+ }
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_StartStream returned:\n" );
+ PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
+#endif
+
+ return result;
+}
+
+
+PaError Pa_StopStream( PaStream *stream )
+{
+ PaError result = PaUtil_ValidateStreamPointer( stream );
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_StopStream called\n" );
+ PaUtil_DebugPrint("\tPaStream* stream: 0x%p\n", stream );
+#endif
+
+ if( result == paNoError )
+ {
+ result = PA_STREAM_INTERFACE(stream)->IsStopped( stream );
+ if( result == 0 )
+ {
+ result = PA_STREAM_INTERFACE(stream)->Stop( stream );
+ }
+ else if( result == 1 )
+ {
+ result = paStreamIsStopped;
+ }
+ }
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_StopStream returned:\n" );
+ PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
+#endif
+
+ return result;
+}
+
+
+PaError Pa_AbortStream( PaStream *stream )
+{
+ PaError result = PaUtil_ValidateStreamPointer( stream );
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_AbortStream called:\n" );
+ PaUtil_DebugPrint("\tPaStream* stream: 0x%p\n", stream );
+#endif
+
+ if( result == paNoError )
+ {
+ result = PA_STREAM_INTERFACE(stream)->IsStopped( stream );
+ if( result == 0 )
+ {
+ result = PA_STREAM_INTERFACE(stream)->Abort( stream );
+ }
+ else if( result == 1 )
+ {
+ result = paStreamIsStopped;
+ }
+ }
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_AbortStream returned:\n" );
+ PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
+#endif
+
+ return result;
+}
+
+
+PaError Pa_IsStreamStopped( PaStream *stream )
+{
+ PaError result = PaUtil_ValidateStreamPointer( stream );
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_IsStreamStopped called:\n" );
+ PaUtil_DebugPrint("\tPaStream* stream: 0x%p\n", stream );
+#endif
+
+ if( result == paNoError )
+ result = PA_STREAM_INTERFACE(stream)->IsStopped( stream );
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_IsStreamStopped returned:\n" );
+ PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
+#endif
+
+ return result;
+}
+
+
+PaError Pa_IsStreamActive( PaStream *stream )
+{
+ PaError result = PaUtil_ValidateStreamPointer( stream );
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_IsStreamActive called:\n" );
+ PaUtil_DebugPrint("\tPaStream* stream: 0x%p\n", stream );
+#endif
+
+ if( result == paNoError )
+ result = PA_STREAM_INTERFACE(stream)->IsActive( stream );
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_IsStreamActive returned:\n" );
+ PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
+#endif
+
+ return result;
+}
+
+
+const PaStreamInfo* Pa_GetStreamInfo( PaStream *stream )
+{
+ PaError error = PaUtil_ValidateStreamPointer( stream );
+ const PaStreamInfo *result;
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetStreamInfo called:\n" );
+ PaUtil_DebugPrint("\tPaStream* stream: 0x%p\n", stream );
+#endif
+
+ if( error != paNoError )
+ {
+ result = 0;
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetStreamInfo returned:\n" );
+ PaUtil_DebugPrint("\tconst PaStreamInfo*: 0 [PaError error:%d ( %s )]\n\n", result, error, Pa_GetErrorText( error ) );
+#endif
+
+ }
+ else
+ {
+ result = &PA_STREAM_REP( stream )->streamInfo;
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetStreamInfo returned:\n" );
+ PaUtil_DebugPrint("\tconst PaStreamInfo*: 0x%p:\n", result );
+ PaUtil_DebugPrint("\t{" );
+
+ PaUtil_DebugPrint("\t\tint structVersion: %d\n", result->structVersion );
+ PaUtil_DebugPrint("\t\tPaTime inputLatency: %f\n", result->inputLatency );
+ PaUtil_DebugPrint("\t\tPaTime outputLatency: %f\n", result->outputLatency );
+ PaUtil_DebugPrint("\t\tdouble sampleRate: %f\n", result->sampleRate );
+ PaUtil_DebugPrint("\t}\n\n" );
+#endif
+
+ }
+
+ return result;
+}
+
+
+PaTime Pa_GetStreamTime( PaStream *stream )
+{
+ PaError error = PaUtil_ValidateStreamPointer( stream );
+ PaTime result;
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetStreamTime called:\n" );
+ PaUtil_DebugPrint("\tPaStream* stream: 0x%p\n", stream );
+#endif
+
+ if( error != paNoError )
+ {
+ result = 0;
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetStreamTime returned:\n" );
+ PaUtil_DebugPrint("\tPaTime: 0 [PaError error:%d ( %s )]\n\n", result, error, Pa_GetErrorText( error ) );
+#endif
+
+ }
+ else
+ {
+ result = PA_STREAM_INTERFACE(stream)->GetTime( stream );
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetStreamTime returned:\n" );
+ PaUtil_DebugPrint("\tPaTime: %g\n\n", result );
+#endif
+
+ }
+
+ return result;
+}
+
+
+double Pa_GetStreamCpuLoad( PaStream* stream )
+{
+ PaError error = PaUtil_ValidateStreamPointer( stream );
+ double result;
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetStreamCpuLoad called:\n" );
+ PaUtil_DebugPrint("\tPaStream* stream: 0x%p\n", stream );
+#endif
+
+ if( error != paNoError )
+ {
+
+ result = 0.0;
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetStreamCpuLoad returned:\n" );
+ PaUtil_DebugPrint("\tdouble: 0.0 [PaError error: %d ( %s )]\n\n", error, Pa_GetErrorText( error ) );
+#endif
+
+ }
+ else
+ {
+ result = PA_STREAM_INTERFACE(stream)->GetCpuLoad( stream );
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetStreamCpuLoad returned:\n" );
+ PaUtil_DebugPrint("\tdouble: %g\n\n", result );
+#endif
+
+ }
+
+ return result;
+}
+
+
+PaError Pa_ReadStream( PaStream* stream,
+ void *buffer,
+ unsigned long frames )
+{
+ PaError result = PaUtil_ValidateStreamPointer( stream );
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_ReadStream called:\n" );
+ PaUtil_DebugPrint("\tPaStream* stream: 0x%p\n", stream );
+#endif
+
+ if( result == paNoError )
+ {
+ if( frames == 0 )
+ {
+ result = paInternalError; /** @todo should return a different error code */
+ }
+ else if( buffer == 0 )
+ {
+ result = paInternalError; /** @todo should return a different error code */
+ }
+ else
+ {
+ result = PA_STREAM_INTERFACE(stream)->IsStopped( stream );
+ if( result == 0 )
+ {
+ result = PA_STREAM_INTERFACE(stream)->Read( stream, buffer, frames );
+ }
+ else if( result == 1 )
+ {
+ result = paStreamIsStopped;
+ }
+ }
+ }
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_ReadStream returned:\n" );
+ PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
+#endif
+
+ return result;
+}
+
+
+PaError Pa_WriteStream( PaStream* stream,
+ const void *buffer,
+ unsigned long frames )
+{
+ PaError result = PaUtil_ValidateStreamPointer( stream );
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_WriteStream called:\n" );
+ PaUtil_DebugPrint("\tPaStream* stream: 0x%p\n", stream );
+#endif
+
+ if( result == paNoError )
+ {
+ if( frames == 0 )
+ {
+ result = paInternalError; /** @todo should return a different error code */
+ }
+ else if( buffer == 0 )
+ {
+ result = paInternalError; /** @todo should return a different error code */
+ }
+ else
+ {
+ result = PA_STREAM_INTERFACE(stream)->IsStopped( stream );
+ if( result == 0 )
+ {
+ result = PA_STREAM_INTERFACE(stream)->Write( stream, buffer, frames );
+ }
+ else if( result == 1 )
+ {
+ result = paStreamIsStopped;
+ }
+ }
+ }
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_WriteStream returned:\n" );
+ PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
+#endif
+
+ return result;
+}
+
+signed long Pa_GetStreamReadAvailable( PaStream* stream )
+{
+ PaError error = PaUtil_ValidateStreamPointer( stream );
+ signed long result;
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetStreamReadAvailable called:\n" );
+ PaUtil_DebugPrint("\tPaStream* stream: 0x%p\n", stream );
+#endif
+
+ if( error != paNoError )
+ {
+ result = 0;
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetStreamReadAvailable returned:\n" );
+ PaUtil_DebugPrint("\tunsigned long: 0 [ PaError error: %d ( %s ) ]\n\n", error, Pa_GetErrorText( error ) );
+#endif
+
+ }
+ else
+ {
+ result = PA_STREAM_INTERFACE(stream)->GetReadAvailable( stream );
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetStreamReadAvailable returned:\n" );
+ PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
+#endif
+
+ }
+
+ return result;
+}
+
+
+signed long Pa_GetStreamWriteAvailable( PaStream* stream )
+{
+ PaError error = PaUtil_ValidateStreamPointer( stream );
+ signed long result;
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetStreamWriteAvailable called:\n" );
+ PaUtil_DebugPrint("\tPaStream* stream: 0x%p\n", stream );
+#endif
+
+ if( error != paNoError )
+ {
+ result = 0;
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetStreamWriteAvailable returned:\n" );
+ PaUtil_DebugPrint("\tunsigned long: 0 [ PaError error: %d ( %s ) ]\n\n", error, Pa_GetErrorText( error ) );
+#endif
+
+ }
+ else
+ {
+ result = PA_STREAM_INTERFACE(stream)->GetWriteAvailable( stream );
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetStreamWriteAvailable returned:\n" );
+ PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
+#endif
+
+ }
+
+ return result;
+}
+
+
+PaError Pa_GetSampleSize( PaSampleFormat format )
+{
+ int result;
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetSampleSize called:\n" );
+ PaUtil_DebugPrint("\tPaSampleFormat format: %d\n", format );
+#endif
+
+ switch( format & ~paNonInterleaved )
+ {
+
+ case paUInt8:
+ case paInt8:
+ result = 1;
+ break;
+
+ case paInt16:
+ result = 2;
+ break;
+
+ case paInt24:
+ result = 3;
+ break;
+
+ case paFloat32:
+ case paInt32:
+ result = 4;
+ break;
+
+ default:
+ result = paSampleFormatNotSupported;
+ break;
+ }
+
+#ifdef PA_LOG_API_CALLS
+ PaUtil_DebugPrint("Pa_GetSampleSize returned:\n" );
+ if( result > 0 )
+ PaUtil_DebugPrint("\tint: %d\n\n", result );
+ else
+ PaUtil_DebugPrint("\tPaError: %d ( %s )\n\n", result, Pa_GetErrorText( result ) );
+#endif
+
+ return (PaError) result;
+}
+
diff --git a/pd/portaudio/pa_common/pa_hostapi.h b/pd/portaudio/pa_common/pa_hostapi.h
new file mode 100644
index 00000000..d0550706
--- /dev/null
+++ b/pd/portaudio/pa_common/pa_hostapi.h
@@ -0,0 +1,244 @@
+#ifndef PA_HOSTAPI_H
+#define PA_HOSTAPI_H
+/*
+ * $Id: pa_hostapi.h,v 1.1.2.14 2004/01/08 22:01:12 rossbencina Exp $
+ * Portable Audio I/O Library
+ * host api representation
+ *
+ * Based on the Open Source API proposed by Ross Bencina
+ * Copyright (c) 1999-2002 Ross Bencina, Phil Burk
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/** @file
+ @brief Interface used by pa_front to virtualize functions which operate on
+ host APIs.
+*/
+
+
+#include "portaudio.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+
+/** **FOR THE USE OF pa_front.c ONLY**
+ Do NOT use fields in this structure, they my change at any time.
+ Use functions defined in pa_util.h if you think you need functionality
+ which can be derived from here.
+*/
+typedef struct PaUtilPrivatePaFrontHostApiInfo {
+
+
+ unsigned long baseDeviceIndex;
+}PaUtilPrivatePaFrontHostApiInfo;
+
+
+/** The common header for all data structures whose pointers are passed through
+ the hostApiSpecificStreamInfo field of the PaStreamParameters structure.
+ Note that in order to keep the public PortAudio interface clean, this structure
+ is not used explicitly when declaring hostApiSpecificStreamInfo data structures.
+ However, some code in pa_front depends on the first 3 members being equivalent
+ with this structure.
+ @see PaStreamParameters
+*/
+typedef struct PaUtilHostApiSpecificStreamInfoHeader
+{
+ unsigned long size; /**< size of whole structure including this header */
+ PaHostApiTypeId hostApiType; /**< host API for which this data is intended */
+ unsigned long version; /**< structure version */
+} PaUtilHostApiSpecificStreamInfoHeader;
+
+
+
+/** A structure representing the interface to a host API. Contains both
+ concrete data and pointers to functions which implement the interface.
+*/
+typedef struct PaUtilHostApiRepresentation {
+ PaUtilPrivatePaFrontHostApiInfo privatePaFrontInfo;
+
+ /** The host api implementation should populate the info field. In the
+ case of info.defaultInputDevice and info.defaultOutputDevice the
+ values stored should be 0 based indices within the host api's own
+ device index range (0 to deviceCount). These values will be converted
+ to global device indices by pa_front after PaUtilHostApiInitializer()
+ returns.
+ */
+ PaHostApiInfo info;
+
+ PaDeviceInfo** deviceInfos;
+
+ /**
+ (*Terminate)() is guaranteed to be called with a valid <hostApi>
+ parameter, which was previously returned from the same implementation's
+ initializer.
+ */
+ void (*Terminate)( struct PaUtilHostApiRepresentation *hostApi );
+
+ /**
+ The inputParameters and outputParameters pointers should not be saved
+ as they will not remain valid after OpenStream is called.
+
+
+ The following guarantees are made about parameters to (*OpenStream)():
+
+ [NOTE: the following list up to *END PA FRONT VALIDATIONS* should be
+ kept in sync with the one for ValidateOpenStreamParameters and
+ Pa_OpenStream in pa_front.c]
+
+ PaHostApiRepresentation *hostApi
+ - is valid for this implementation
+
+ PaStream** stream
+ - is non-null
+
+ - at least one of inputParameters & outputParmeters is valid (not NULL)
+
+ - if inputParameters & outputParmeters are both valid, that
+ inputParameters->device & outputParmeters->device both use the same host api
+
+ PaDeviceIndex inputParameters->device
+ - is within range (0 to Pa_CountDevices-1) Or:
+ - is paUseHostApiSpecificDeviceSpecification and
+ inputParameters->hostApiSpecificStreamInfo is non-NULL and refers
+ to a valid host api
+
+ int inputParameters->numChannels
+ - if inputParameters->device is not paUseHostApiSpecificDeviceSpecification, numInputChannels is > 0
+ - upper bound is NOT validated against device capabilities
+
+ PaSampleFormat inputParameters->sampleFormat
+ - is one of the sample formats defined in portaudio.h
+
+ void *inputParameters->hostApiSpecificStreamInfo
+ - if supplied its hostApi field matches the input device's host Api
+
+ PaDeviceIndex outputParmeters->device
+ - is within range (0 to Pa_CountDevices-1)
+
+ int outputParmeters->numChannels
+ - if inputDevice is valid, numInputChannels is > 0
+ - upper bound is NOT validated against device capabilities
+
+ PaSampleFormat outputParmeters->sampleFormat
+ - is one of the sample formats defined in portaudio.h
+
+ void *outputParmeters->hostApiSpecificStreamInfo
+ - if supplied its hostApi field matches the output device's host Api
+
+ double sampleRate
+ - is not an 'absurd' rate (less than 1000. or greater than 200000.)
+ - sampleRate is NOT validated against device capabilities
+
+ PaStreamFlags streamFlags
+ - unused platform neutral flags are zero
+ - paNeverDropInput is only used for full-duplex callback streams
+ with variable buffer size (paFramesPerBufferUnspecified)
+
+ [*END PA FRONT VALIDATIONS*]
+
+
+ The following validations MUST be performed by (*OpenStream)():
+
+ - check that input device can support numInputChannels
+
+ - check that input device can support inputSampleFormat, or that
+ we have the capability to convert from outputSampleFormat to
+ a native format
+
+ - if inputStreamInfo is supplied, validate its contents,
+ or return an error if no inputStreamInfo is expected
+
+ - check that output device can support numOutputChannels
+
+ - check that output device can support outputSampleFormat, or that
+ we have the capability to convert from outputSampleFormat to
+ a native format
+
+ - if outputStreamInfo is supplied, validate its contents,
+ or return an error if no outputStreamInfo is expected
+
+ - if a full duplex stream is requested, check that the combination
+ of input and output parameters is supported
+
+ - check that the device supports sampleRate
+
+ - alter sampleRate to a close allowable rate if necessary
+
+ - validate inputLatency and outputLatency
+
+ - validate any platform specific flags, if flags are supplied they
+ must be valid.
+ */
+ PaError (*OpenStream)( struct PaUtilHostApiRepresentation *hostApi,
+ PaStream** stream,
+ const PaStreamParameters *inputParameters,
+ const PaStreamParameters *outputParameters,
+ double sampleRate,
+ unsigned long framesPerCallback,
+ PaStreamFlags streamFlags,
+ PaStreamCallback *streamCallback,
+ void *userData );
+
+
+ PaError (*IsFormatSupported)( struct PaUtilHostApiRepresentation *hostApi,
+ const PaStreamParameters *inputParameters,
+ const PaStreamParameters *outputParameters,
+ double sampleRate );
+} PaUtilHostApiRepresentation;
+
+
+/** Prototype for the initialization function which must be implemented by every
+ host API.
+
+ @see paHostApiInitializers
+*/
+typedef PaError PaUtilHostApiInitializer( PaUtilHostApiRepresentation**, PaHostApiIndex );
+
+
+/** paHostApiInitializers is a NULL-terminated array of host API initialization
+ functions. These functions are called by pa_front to initialize the host APIs
+ when the client calls Pa_Initialize().
+
+ There is a platform specific file which defines paHostApiInitializers for that
+ platform, pa_win/pa_win_hostapis.c contains the Win32 definitions for example.
+*/
+extern PaUtilHostApiInitializer *paHostApiInitializers[];
+
+
+/** The index of the default host API in the paHostApiInitializers array.
+
+ There is a platform specific file which defines paDefaultHostApiIndex for that
+ platform, see pa_win/pa_win_hostapis.c for example.
+*/
+extern int paDefaultHostApiIndex;
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* PA_HOSTAPI_H */
diff --git a/pd/portaudio/pa_common/pa_process.c b/pd/portaudio/pa_common/pa_process.c
new file mode 100644
index 00000000..acbd9536
--- /dev/null
+++ b/pd/portaudio/pa_common/pa_process.c
@@ -0,0 +1,1740 @@
+/*
+ * $Id: pa_process.c,v 1.1.2.45 2004/05/11 13:40:42 rossbencina Exp $
+ * Portable Audio I/O Library
+ * streamCallback <-> host buffer processing adapter
+ *
+ * Based on the Open Source API proposed by Ross Bencina
+ * Copyright (c) 1999-2002 Ross Bencina, Phil Burk
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/** @file
+ @brief Buffer Processor implementation.
+
+ The code in this file is not optimised yet - although it's not clear that
+ it needs to be. there may appear to be redundancies
+ that could be factored into common functions, but the redundanceis are left
+ intentionally as each appearance may have different optimisation possibilities.
+
+ The optimisations which are planned involve only converting data in-place
+ where possible, rather than copying to the temp buffer(s).
+
+ Note that in the extreme case of being able to convert in-place, and there
+ being no conversion necessary there should be some code which short-circuits
+ the operation.
+
+ @todo Consider cache tilings for intereave<->deinterleave.
+
+ @todo implement timeInfo->currentTime int PaUtil_BeginBufferProcessing()
+
+ @todo specify and implement some kind of logical policy for handling the
+ underflow and overflow stream flags when the underflow/overflow overlaps
+ multiple user buffers/callbacks.
+
+ @todo provide support for priming the buffers with data from the callback.
+ The client interface is now implemented through PaUtil_SetNoInput()
+ which sets bp->hostInputChannels[0][0].data to zero. However this is
+ currently only implemented in NonAdaptingProcess(). It shouldn't be
+ needed for AdaptingInputOnlyProcess() (no priming should ever be
+ requested for AdaptingInputOnlyProcess()).
+ Not sure if additional work should be required to make it work with
+ AdaptingOutputOnlyProcess, but it definitely is required for
+ AdaptingProcess.
+
+ @todo implement PaUtil_SetNoOutput for AdaptingProcess
+
+ @todo don't allocate temp buffers for blocking streams unless they are
+ needed. At the moment they are needed, but perhaps for host APIs
+ where the implementation passes a buffer to the host they could be
+ used.
+*/
+
+
+#include <assert.h>
+#include <string.h> /* memset() */
+
+#include "pa_process.h"
+#include "pa_util.h"
+
+
+#define PA_FRAMES_PER_TEMP_BUFFER_WHEN_HOST_BUFFER_SIZE_IS_UNKNOWN_ 1024
+
+#define PA_MIN_( a, b ) ( ((a)<(b)) ? (a) : (b) )
+
+
+/* greatest common divisor - PGCD in French */
+static unsigned long GCD( unsigned long a, unsigned long b )
+{
+ return (b==0) ? a : GCD( b, a%b);
+}
+
+/* least common multiple - PPCM in French */
+static unsigned long LCM( unsigned long a, unsigned long b )
+{
+ return (a*b) / GCD(a,b);
+}
+
+#define PA_MAX_( a, b ) (((a) > (b)) ? (a) : (b))
+
+static unsigned long CalculateFrameShift( unsigned long M, unsigned long N )
+{
+ unsigned long result = 0;
+ unsigned long i;
+ unsigned long lcm;
+
+ assert( M > 0 );
+ assert( N > 0 );
+
+ lcm = LCM( M, N );
+ for( i = M; i < lcm; i += M )
+ result = PA_MAX_( result, i % N );
+
+ return result;
+}
+
+
+PaError PaUtil_InitializeBufferProcessor( PaUtilBufferProcessor* bp,
+ int inputChannelCount, PaSampleFormat userInputSampleFormat,
+ PaSampleFormat hostInputSampleFormat,
+ int outputChannelCount, PaSampleFormat userOutputSampleFormat,
+ PaSampleFormat hostOutputSampleFormat,
+ double sampleRate,
+ PaStreamFlags streamFlags,
+ unsigned long framesPerUserBuffer,
+ unsigned long framesPerHostBuffer,
+ PaUtilHostBufferSizeMode hostBufferSizeMode,
+ PaStreamCallback *streamCallback, void *userData )
+{
+ PaError result = paNoError;
+ PaError bytesPerSample;
+ unsigned long tempInputBufferSize, tempOutputBufferSize;
+
+ /* initialize buffer ptrs to zero so they can be freed if necessary in error */
+ bp->tempInputBuffer = 0;
+ bp->tempInputBufferPtrs = 0;
+ bp->tempOutputBuffer = 0;
+ bp->tempOutputBufferPtrs = 0;
+
+ bp->framesPerUserBuffer = framesPerUserBuffer;
+ bp->framesPerHostBuffer = framesPerHostBuffer;
+
+ bp->inputChannelCount = inputChannelCount;
+ bp->outputChannelCount = outputChannelCount;
+
+ bp->hostBufferSizeMode = hostBufferSizeMode;
+
+ bp->hostInputChannels[0] = 0;
+ bp->hostOutputChannels[0] = 0;
+
+ if( framesPerUserBuffer == 0 ) /* streamCallback will accept any buffer size */
+ {
+ bp->useNonAdaptingProcess = 1;
+ bp->initialFramesInTempInputBuffer = 0;
+ bp->initialFramesInTempOutputBuffer = 0;
+
+ if( hostBufferSizeMode == paUtilFixedHostBufferSize
+ || hostBufferSizeMode == paUtilBoundedHostBufferSize )
+ {
+ bp->framesPerTempBuffer = framesPerHostBuffer;
+ }
+ else /* unknown host buffer size */
+ {
+ bp->framesPerTempBuffer = PA_FRAMES_PER_TEMP_BUFFER_WHEN_HOST_BUFFER_SIZE_IS_UNKNOWN_;
+ }
+ }
+ else
+ {
+ bp->framesPerTempBuffer = framesPerUserBuffer;
+
+ if( hostBufferSizeMode == paUtilFixedHostBufferSize
+ && framesPerHostBuffer % framesPerUserBuffer == 0 )
+ {
+ bp->useNonAdaptingProcess = 1;
+ bp->initialFramesInTempInputBuffer = 0;
+ bp->initialFramesInTempOutputBuffer = 0;
+ }
+ else
+ {
+ bp->useNonAdaptingProcess = 0;
+
+ if( inputChannelCount > 0 && outputChannelCount > 0 )
+ {
+ /* full duplex */
+ if( hostBufferSizeMode == paUtilFixedHostBufferSize )
+ {
+ unsigned long frameShift =
+ CalculateFrameShift( framesPerHostBuffer, framesPerUserBuffer );
+
+ if( framesPerUserBuffer > framesPerHostBuffer )
+ {
+ bp->initialFramesInTempInputBuffer = frameShift;
+ bp->initialFramesInTempOutputBuffer = 0;
+ }
+ else
+ {
+ bp->initialFramesInTempInputBuffer = 0;
+ bp->initialFramesInTempOutputBuffer = frameShift;
+ }
+ }
+ else /* variable host buffer size, add framesPerUserBuffer latency */
+ {
+ bp->initialFramesInTempInputBuffer = 0;
+ bp->initialFramesInTempOutputBuffer = framesPerUserBuffer;
+ }
+ }
+ else
+ {
+ /* half duplex */
+ bp->initialFramesInTempInputBuffer = 0;
+ bp->initialFramesInTempOutputBuffer = 0;
+ }
+ }
+ }
+
+
+ bp->framesInTempInputBuffer = bp->initialFramesInTempInputBuffer;
+ bp->framesInTempOutputBuffer = bp->initialFramesInTempOutputBuffer;
+
+
+ if( inputChannelCount > 0 )
+ {
+ bytesPerSample = Pa_GetSampleSize( hostInputSampleFormat );
+ if( bytesPerSample > 0 )
+ {
+ bp->bytesPerHostInputSample = bytesPerSample;
+ }
+ else
+ {
+ result = bytesPerSample;
+ goto error;
+ }
+
+ bytesPerSample = Pa_GetSampleSize( userInputSampleFormat );
+ if( bytesPerSample > 0 )
+ {
+ bp->bytesPerUserInputSample = bytesPerSample;
+ }
+ else
+ {
+ result = bytesPerSample;
+ goto error;
+ }
+
+ bp->inputConverter =
+ PaUtil_SelectConverter( hostInputSampleFormat, userInputSampleFormat, streamFlags );
+
+ bp->inputZeroer = PaUtil_SelectZeroer( hostInputSampleFormat );
+
+ bp->userInputIsInterleaved = (userInputSampleFormat & paNonInterleaved)?0:1;
+
+
+ tempInputBufferSize =
+ bp->framesPerTempBuffer * bp->bytesPerUserInputSample * inputChannelCount;
+
+ bp->tempInputBuffer = PaUtil_AllocateMemory( tempInputBufferSize );
+ if( bp->tempInputBuffer == 0 )
+ {
+ result = paInsufficientMemory;
+ goto error;
+ }
+
+ if( bp->framesInTempInputBuffer > 0 )
+ memset( bp->tempInputBuffer, 0, tempInputBufferSize );
+
+ if( userInputSampleFormat & paNonInterleaved )
+ {
+ bp->tempInputBufferPtrs =
+ (void **)PaUtil_AllocateMemory( sizeof(void*)*inputChannelCount );
+ if( bp->tempInputBufferPtrs == 0 )
+ {
+ result = paInsufficientMemory;
+ goto error;
+ }
+ }
+
+ bp->hostInputChannels[0] = (PaUtilChannelDescriptor*)
+ PaUtil_AllocateMemory( sizeof(PaUtilChannelDescriptor) * inputChannelCount * 2);
+ if( bp->hostInputChannels[0] == 0 )
+ {
+ result = paInsufficientMemory;
+ goto error;
+ }
+
+ bp->hostInputChannels[1] = &bp->hostInputChannels[0][inputChannelCount];
+ }
+
+ if( outputChannelCount > 0 )
+ {
+ bytesPerSample = Pa_GetSampleSize( hostOutputSampleFormat );
+ if( bytesPerSample > 0 )
+ {
+ bp->bytesPerHostOutputSample = bytesPerSample;
+ }
+ else
+ {
+ result = bytesPerSample;
+ goto error;
+ }
+
+ bytesPerSample = Pa_GetSampleSize( userOutputSampleFormat );
+ if( bytesPerSample > 0 )
+ {
+ bp->bytesPerUserOutputSample = bytesPerSample;
+ }
+ else
+ {
+ result = bytesPerSample;
+ goto error;
+ }
+
+ bp->outputConverter =
+ PaUtil_SelectConverter( userOutputSampleFormat, hostOutputSampleFormat, streamFlags );
+
+ bp->outputZeroer = PaUtil_SelectZeroer( hostOutputSampleFormat );
+
+ bp->userOutputIsInterleaved = (userOutputSampleFormat & paNonInterleaved)?0:1;
+
+ tempOutputBufferSize =
+ bp->framesPerTempBuffer * bp->bytesPerUserOutputSample * outputChannelCount;
+
+ bp->tempOutputBuffer = PaUtil_AllocateMemory( tempOutputBufferSize );
+ if( bp->tempOutputBuffer == 0 )
+ {
+ result = paInsufficientMemory;
+ goto error;
+ }
+
+ if( bp->framesInTempOutputBuffer > 0 )
+ memset( bp->tempOutputBuffer, 0, tempOutputBufferSize );
+
+ if( userOutputSampleFormat & paNonInterleaved )
+ {
+ bp->tempOutputBufferPtrs =
+ (void **)PaUtil_AllocateMemory( sizeof(void*)*outputChannelCount );
+ if( bp->tempOutputBufferPtrs == 0 )
+ {
+ result = paInsufficientMemory;
+ goto error;
+ }
+ }
+
+ bp->hostOutputChannels[0] = (PaUtilChannelDescriptor*)
+ PaUtil_AllocateMemory( sizeof(PaUtilChannelDescriptor)*outputChannelCount * 2 );
+ if( bp->hostOutputChannels[0] == 0 )
+ {
+ result = paInsufficientMemory;
+ goto error;
+ }
+
+ bp->hostOutputChannels[1] = &bp->hostOutputChannels[0][outputChannelCount];
+ }
+
+ PaUtil_InitializeTriangularDitherState( &bp->ditherGenerator );
+
+ bp->samplePeriod = 1. / sampleRate;
+
+ bp->streamCallback = streamCallback;
+ bp->userData = userData;
+
+ return result;
+
+error:
+ if( bp->tempInputBuffer )
+ PaUtil_FreeMemory( bp->tempInputBuffer );
+
+ if( bp->tempInputBufferPtrs )
+ PaUtil_FreeMemory( bp->tempInputBufferPtrs );
+
+ if( bp->hostInputChannels[0] )
+ PaUtil_FreeMemory( bp->hostInputChannels[0] );
+
+ if( bp->tempOutputBuffer )
+ PaUtil_FreeMemory( bp->tempOutputBuffer );
+
+ if( bp->tempOutputBufferPtrs )
+ PaUtil_FreeMemory( bp->tempOutputBufferPtrs );
+
+ if( bp->hostOutputChannels[0] )
+ PaUtil_FreeMemory( bp->hostOutputChannels[0] );
+
+ return result;
+}
+
+
+void PaUtil_TerminateBufferProcessor( PaUtilBufferProcessor* bp )
+{
+ if( bp->tempInputBuffer )
+ PaUtil_FreeMemory( bp->tempInputBuffer );
+
+ if( bp->tempInputBufferPtrs )
+ PaUtil_FreeMemory( bp->tempInputBufferPtrs );
+
+ if( bp->hostInputChannels[0] )
+ PaUtil_FreeMemory( bp->hostInputChannels[0] );
+
+ if( bp->tempOutputBuffer )
+ PaUtil_FreeMemory( bp->tempOutputBuffer );
+
+ if( bp->tempOutputBufferPtrs )
+ PaUtil_FreeMemory( bp->tempOutputBufferPtrs );
+
+ if( bp->hostOutputChannels[0] )
+ PaUtil_FreeMemory( bp->hostOutputChannels[0] );
+}
+
+
+void PaUtil_ResetBufferProcessor( PaUtilBufferProcessor* bp )
+{
+ unsigned long tempInputBufferSize, tempOutputBufferSize;
+
+ bp->framesInTempInputBuffer = bp->initialFramesInTempInputBuffer;
+ bp->framesInTempOutputBuffer = bp->initialFramesInTempOutputBuffer;
+
+ if( bp->framesInTempInputBuffer > 0 )
+ {
+ tempInputBufferSize =
+ bp->framesPerTempBuffer * bp->bytesPerUserInputSample * bp->inputChannelCount;
+ memset( bp->tempInputBuffer, 0, tempInputBufferSize );
+ }
+
+ if( bp->framesInTempOutputBuffer > 0 )
+ {
+ tempOutputBufferSize =
+ bp->framesPerTempBuffer * bp->bytesPerUserOutputSample * bp->outputChannelCount;
+ memset( bp->tempOutputBuffer, 0, tempOutputBufferSize );
+ }
+}
+
+
+unsigned long PaUtil_GetBufferProcessorInputLatency( PaUtilBufferProcessor* bp )
+{
+ return bp->initialFramesInTempInputBuffer;
+}
+
+
+unsigned long PaUtil_GetBufferProcessorOutputLatency( PaUtilBufferProcessor* bp )
+{
+ return bp->initialFramesInTempOutputBuffer;
+}
+
+
+void PaUtil_SetInputFrameCount( PaUtilBufferProcessor* bp,
+ unsigned long frameCount )
+{
+ if( frameCount == 0 )
+ bp->hostInputFrameCount[0] = bp->framesPerHostBuffer;
+ else
+ bp->hostInputFrameCount[0] = frameCount;
+}
+
+
+void PaUtil_SetNoInput( PaUtilBufferProcessor* bp )
+{
+ assert( bp->inputChannelCount > 0 );
+
+ bp->hostInputChannels[0][0].data = 0;
+}
+
+
+void PaUtil_SetInputChannel( PaUtilBufferProcessor* bp,
+ unsigned int channel, void *data, unsigned int stride )
+{
+ assert( channel < bp->inputChannelCount );
+
+ bp->hostInputChannels[0][channel].data = data;
+ bp->hostInputChannels[0][channel].stride = stride;
+}
+
+
+void PaUtil_SetInterleavedInputChannels( PaUtilBufferProcessor* bp,
+ unsigned int firstChannel, void *data, unsigned int channelCount )
+{
+ unsigned int i;
+ unsigned int channel = firstChannel;
+ unsigned char *p = (unsigned char*)data;
+
+ if( channelCount == 0 )
+ channelCount = bp->inputChannelCount;
+
+ assert( firstChannel < bp->inputChannelCount );
+ assert( firstChannel + channelCount <= bp->inputChannelCount );
+
+ for( i=0; i< channelCount; ++i )
+ {
+ bp->hostInputChannels[0][channel+i].data = p;
+ p += bp->bytesPerHostInputSample;
+ bp->hostInputChannels[0][channel+i].stride = channelCount;
+ }
+}
+
+
+void PaUtil_SetNonInterleavedInputChannel( PaUtilBufferProcessor* bp,
+ unsigned int channel, void *data )
+{
+ assert( channel < bp->inputChannelCount );
+
+ bp->hostInputChannels[0][channel].data = data;
+ bp->hostInputChannels[0][channel].stride = 1;
+}
+
+
+void PaUtil_Set2ndInputFrameCount( PaUtilBufferProcessor* bp,
+ unsigned long frameCount )
+{
+ bp->hostInputFrameCount[1] = frameCount;
+}
+
+
+void PaUtil_Set2ndInputChannel( PaUtilBufferProcessor* bp,
+ unsigned int channel, void *data, unsigned int stride )
+{
+ assert( channel < bp->inputChannelCount );
+
+ bp->hostInputChannels[1][channel].data = data;
+ bp->hostInputChannels[1][channel].stride = stride;
+}
+
+
+void PaUtil_Set2ndInterleavedInputChannels( PaUtilBufferProcessor* bp,
+ unsigned int firstChannel, void *data, unsigned int channelCount )
+{
+ unsigned int i;
+ unsigned int channel = firstChannel;
+ unsigned char *p = (unsigned char*)data;
+
+ if( channelCount == 0 )
+ channelCount = bp->inputChannelCount;
+
+ assert( firstChannel < bp->inputChannelCount );
+ assert( firstChannel + channelCount <= bp->inputChannelCount );
+
+ for( i=0; i< channelCount; ++i )
+ {
+ bp->hostInputChannels[1][channel+i].data = p;
+ p += bp->bytesPerHostInputSample;
+ bp->hostInputChannels[1][channel+i].stride = channelCount;
+ }
+}
+
+
+void PaUtil_Set2ndNonInterleavedInputChannel( PaUtilBufferProcessor* bp,
+ unsigned int channel, void *data )
+{
+ assert( channel < bp->inputChannelCount );
+
+ bp->hostInputChannels[1][channel].data = data;
+ bp->hostInputChannels[1][channel].stride = 1;
+}
+
+
+void PaUtil_SetOutputFrameCount( PaUtilBufferProcessor* bp,
+ unsigned long frameCount )
+{
+ if( frameCount == 0 )
+ bp->hostOutputFrameCount[0] = bp->framesPerHostBuffer;
+ else
+ bp->hostOutputFrameCount[0] = frameCount;
+}
+
+
+void PaUtil_SetNoOutput( PaUtilBufferProcessor* bp )
+{
+ assert( bp->outputChannelCount > 0 );
+
+ bp->hostOutputChannels[0][0].data = 0;
+}
+
+
+void PaUtil_SetOutputChannel( PaUtilBufferProcessor* bp,
+ unsigned int channel, void *data, unsigned int stride )
+{
+ assert( channel < bp->outputChannelCount );
+
+ bp->hostOutputChannels[0][channel].data = data;
+ bp->hostOutputChannels[0][channel].stride = stride;
+}
+
+
+void PaUtil_SetInterleavedOutputChannels( PaUtilBufferProcessor* bp,
+ unsigned int firstChannel, void *data, unsigned int channelCount )
+{
+ unsigned int i;
+ unsigned int channel = firstChannel;
+ unsigned char *p = (unsigned char*)data;
+
+ if( channelCount == 0 )
+ channelCount = bp->outputChannelCount;
+
+ assert( firstChannel < bp->outputChannelCount );
+ assert( firstChannel + channelCount <= bp->outputChannelCount );
+
+ for( i=0; i< channelCount; ++i )
+ {
+ bp->hostOutputChannels[0][channel+i].data = p;
+ p += bp->bytesPerHostOutputSample;
+ bp->hostOutputChannels[0][channel+i].stride = channelCount;
+ }
+}
+
+
+void PaUtil_SetNonInterleavedOutputChannel( PaUtilBufferProcessor* bp,
+ unsigned int channel, void *data )
+{
+ assert( channel < bp->outputChannelCount );
+
+ bp->hostOutputChannels[0][channel].data = data;
+ bp->hostOutputChannels[0][channel].stride = 1;
+}
+
+
+void PaUtil_Set2ndOutputFrameCount( PaUtilBufferProcessor* bp,
+ unsigned long frameCount )
+{
+ bp->hostOutputFrameCount[1] = frameCount;
+}
+
+
+void PaUtil_Set2ndOutputChannel( PaUtilBufferProcessor* bp,
+ unsigned int channel, void *data, unsigned int stride )
+{
+ assert( channel < bp->outputChannelCount );
+
+ bp->hostOutputChannels[1][channel].data = data;
+ bp->hostOutputChannels[1][channel].stride = stride;
+}
+
+
+void PaUtil_Set2ndInterleavedOutputChannels( PaUtilBufferProcessor* bp,
+ unsigned int firstChannel, void *data, unsigned int channelCount )
+{
+ unsigned int i;
+ unsigned int channel = firstChannel;
+ unsigned char *p = (unsigned char*)data;
+
+ if( channelCount == 0 )
+ channelCount = bp->outputChannelCount;
+
+ assert( firstChannel < bp->outputChannelCount );
+ assert( firstChannel + channelCount <= bp->outputChannelCount );
+
+ for( i=0; i< channelCount; ++i )
+ {
+ bp->hostOutputChannels[1][channel+i].data = p;
+ p += bp->bytesPerHostOutputSample;
+ bp->hostOutputChannels[1][channel+i].stride = channelCount;
+ }
+}
+
+
+void PaUtil_Set2ndNonInterleavedOutputChannel( PaUtilBufferProcessor* bp,
+ unsigned int channel, void *data )
+{
+ assert( channel < bp->outputChannelCount );
+
+ bp->hostOutputChannels[1][channel].data = data;
+ bp->hostOutputChannels[1][channel].stride = 1;
+}
+
+
+void PaUtil_BeginBufferProcessing( PaUtilBufferProcessor* bp,
+ PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags callbackStatusFlags )
+{
+ bp->timeInfo = timeInfo;
+
+ /* the first streamCallback will be called to process samples which are
+ currently in the input buffer before the ones starting at the timeInfo time */
+
+ bp->timeInfo->inputBufferAdcTime -= bp->framesInTempInputBuffer * bp->samplePeriod;
+
+ bp->timeInfo->currentTime = 0; /** FIXME: @todo time info currentTime not implemented */
+
+ /* the first streamCallback will be called to generate samples which will be
+ outputted after the frames currently in the output buffer have been
+ outputted. */
+ bp->timeInfo->outputBufferDacTime += bp->framesInTempOutputBuffer * bp->samplePeriod;
+
+ bp->callbackStatusFlags = callbackStatusFlags;
+
+ bp->hostInputFrameCount[1] = 0;
+ bp->hostOutputFrameCount[1] = 0;
+}
+
+
+/*
+ NonAdaptingProcess() is a simple buffer copying adaptor that can handle
+ both full and half duplex copies. It processes framesToProcess frames,
+ broken into blocks bp->framesPerTempBuffer long.
+ This routine can be used when the streamCallback doesn't care what length
+ the buffers are, or when framesToProcess is an integer multiple of
+ bp->framesPerTempBuffer, in which case streamCallback will always be called
+ with bp->framesPerTempBuffer samples.
+*/
+static unsigned long NonAdaptingProcess( PaUtilBufferProcessor *bp,
+ int *streamCallbackResult,
+ PaUtilChannelDescriptor *hostInputChannels,
+ PaUtilChannelDescriptor *hostOutputChannels,
+ unsigned long framesToProcess )
+{
+ void *userInput, *userOutput;
+ unsigned char *srcBytePtr, *destBytePtr;
+ unsigned int srcSampleStrideSamples; /* stride from one sample to the next within a channel, in samples */
+ unsigned int srcChannelStrideBytes; /* stride from one channel to the next, in bytes */
+ unsigned int destSampleStrideSamples; /* stride from one sample to the next within a channel, in samples */
+ unsigned int destChannelStrideBytes; /* stride from one channel to the next, in bytes */
+ unsigned int i;
+ unsigned long frameCount;
+ unsigned long framesToGo = framesToProcess;
+ unsigned long framesProcessed = 0;
+
+
+ if( *streamCallbackResult == paContinue )
+ {
+ do
+ {
+ frameCount = PA_MIN_( bp->framesPerTempBuffer, framesToGo );
+
+ /* configure user input buffer and convert input data (host -> user) */
+ if( bp->inputChannelCount == 0 )
+ {
+ /* no input */
+ userInput = 0;
+ }
+ else /* there are input channels */
+ {
+ /*
+ could use more elaborate logic here and sometimes process
+ buffers in-place.
+ */
+
+ destBytePtr = (unsigned char *)bp->tempInputBuffer;
+
+ if( bp->userInputIsInterleaved )
+ {
+ destSampleStrideSamples = bp->inputChannelCount;
+ destChannelStrideBytes = bp->bytesPerUserInputSample;
+ userInput = bp->tempInputBuffer;
+ }
+ else /* user input is not interleaved */
+ {
+ destSampleStrideSamples = 1;
+ destChannelStrideBytes = frameCount * bp->bytesPerUserInputSample;
+
+ /* setup non-interleaved ptrs */
+ for( i=0; i<bp->inputChannelCount; ++i )
+ {
+ bp->tempInputBufferPtrs[i] = ((unsigned char*)bp->tempInputBuffer) +
+ i * bp->bytesPerUserInputSample * frameCount;
+ }
+
+ userInput = bp->tempInputBufferPtrs;
+ }
+
+ if( !bp->hostInputChannels[0][0].data )
+ {
+ /* no input was supplied (see PaUtil_SetNoInput), so
+ zero the input buffer */
+
+ for( i=0; i<bp->inputChannelCount; ++i )
+ {
+ bp->inputZeroer( destBytePtr, destSampleStrideSamples, frameCount );
+ destBytePtr += destChannelStrideBytes; /* skip to next destination channel */
+ }
+ }
+ else
+ {
+ for( i=0; i<bp->inputChannelCount; ++i )
+ {
+ bp->inputConverter( destBytePtr, destSampleStrideSamples,
+ hostInputChannels[i].data,
+ hostInputChannels[i].stride,
+ frameCount, &bp->ditherGenerator );
+
+ destBytePtr += destChannelStrideBytes; /* skip to next destination channel */
+
+ /* advance src ptr for next iteration */
+ hostInputChannels[i].data = ((unsigned char*)hostInputChannels[i].data) +
+ frameCount * hostInputChannels[i].stride * bp->bytesPerHostInputSample;
+ }
+ }
+ }
+
+ /* configure user output buffer */
+ if( bp->outputChannelCount == 0 )
+ {
+ /* no output */
+ userOutput = 0;
+ }
+ else /* there are output channels */
+ {
+ if( bp->userOutputIsInterleaved )
+ {
+ userOutput = bp->tempOutputBuffer;
+ }
+ else /* user output is not interleaved */
+ {
+ for( i = 0; i < bp->outputChannelCount; ++i )
+ {
+ bp->tempOutputBufferPtrs[i] = ((unsigned char*)bp->tempOutputBuffer) +
+ i * bp->bytesPerUserOutputSample * frameCount;
+ }
+
+ userOutput = bp->tempOutputBufferPtrs;
+ }
+ }
+
+ *streamCallbackResult = bp->streamCallback( userInput, userOutput,
+ frameCount, bp->timeInfo, bp->callbackStatusFlags, bp->userData );
+
+ if( *streamCallbackResult == paAbort )
+ {
+ /* callback returned paAbort, don't advance framesProcessed
+ and framesToGo, they will be handled below */
+ }
+ else
+ {
+ bp->timeInfo->inputBufferAdcTime += frameCount * bp->samplePeriod;
+ bp->timeInfo->outputBufferDacTime += frameCount * bp->samplePeriod;
+
+ /* convert output data (user -> host) */
+ if( bp->outputChannelCount != 0 )
+ {
+ if( !bp->hostOutputChannels[0][0].data )
+ {
+ /* do nothing, this are no host output buffers */
+ }
+ else
+ {
+ /*
+ could use more elaborate logic here and sometimes process
+ buffers in-place.
+ */
+
+ srcBytePtr = (unsigned char *)bp->tempOutputBuffer;
+
+ if( bp->userOutputIsInterleaved )
+ {
+ srcSampleStrideSamples = bp->outputChannelCount;
+ srcChannelStrideBytes = bp->bytesPerUserOutputSample;
+ }
+ else /* user output is not interleaved */
+ {
+ srcSampleStrideSamples = 1;
+ srcChannelStrideBytes = frameCount * bp->bytesPerUserOutputSample;
+ }
+
+ for( i=0; i<bp->outputChannelCount; ++i )
+ {
+ bp->outputConverter( hostOutputChannels[i].data,
+ hostOutputChannels[i].stride,
+ srcBytePtr, srcSampleStrideSamples,
+ frameCount, &bp->ditherGenerator );
+
+ srcBytePtr += srcChannelStrideBytes; /* skip to next source channel */
+
+ /* advance dest ptr for next iteration */
+ hostOutputChannels[i].data = ((unsigned char*)hostOutputChannels[i].data) +
+ frameCount * hostOutputChannels[i].stride * bp->bytesPerHostOutputSample;
+ }
+ }
+ }
+
+ framesProcessed += frameCount;
+
+ framesToGo -= frameCount;
+ }
+ }
+ while( framesToGo > 0 && *streamCallbackResult == paContinue );
+ }
+
+ if( framesToGo > 0 )
+ {
+ /* zero any remaining frames. There will only be remaining frames
+ if the callback has returned paComplete or paAbort */
+
+ frameCount = framesToGo;
+
+ if( bp->hostOutputChannels[0][0].data )
+ {
+ for( i=0; i<bp->outputChannelCount; ++i )
+ {
+ bp->outputZeroer( hostOutputChannels[i].data,
+ hostOutputChannels[i].stride,
+ frameCount );
+
+ /* advance dest ptr for next iteration */
+ hostOutputChannels[i].data = ((unsigned char*)hostOutputChannels[i].data) +
+ frameCount * hostOutputChannels[i].stride * bp->bytesPerHostOutputSample;
+ }
+ }
+
+ framesProcessed += frameCount;
+ }
+
+ return framesProcessed;
+}
+
+
+/*
+ AdaptingInputOnlyProcess() is a half duplex input buffer processor. It
+ converts data from the input buffers into the temporary input buffer,
+ when the temporary input buffer is full, it calls the streamCallback.
+*/
+static unsigned long AdaptingInputOnlyProcess( PaUtilBufferProcessor *bp,
+ int *streamCallbackResult,
+ PaUtilChannelDescriptor *hostInputChannels,
+ unsigned long framesToProcess )
+{
+ void *userInput, *userOutput;
+ unsigned char *destBytePtr;
+ unsigned int destSampleStrideSamples; /* stride from one sample to the next within a channel, in samples */
+ unsigned int destChannelStrideBytes; /* stride from one channel to the next, in bytes */
+ unsigned int i;
+ unsigned long frameCount;
+ unsigned long framesToGo = framesToProcess;
+ unsigned long framesProcessed = 0;
+
+ userOutput = 0;
+
+ do
+ {
+ frameCount = ( bp->framesInTempInputBuffer + framesToGo > bp->framesPerUserBuffer )
+ ? ( bp->framesPerUserBuffer - bp->framesInTempInputBuffer )
+ : framesToGo;
+
+ /* convert frameCount samples into temp buffer */
+
+ if( bp->userInputIsInterleaved )
+ {
+ destBytePtr = ((unsigned char*)bp->tempInputBuffer) +
+ bp->bytesPerUserInputSample * bp->inputChannelCount *
+ bp->framesInTempInputBuffer;
+
+ destSampleStrideSamples = bp->inputChannelCount;
+ destChannelStrideBytes = bp->bytesPerUserInputSample;
+
+ userInput = bp->tempInputBuffer;
+ }
+ else /* user input is not interleaved */
+ {
+ destBytePtr = ((unsigned char*)bp->tempInputBuffer) +
+ bp->bytesPerUserInputSample * bp->framesInTempInputBuffer;
+
+ destSampleStrideSamples = 1;
+ destChannelStrideBytes = bp->framesPerUserBuffer * bp->bytesPerUserInputSample;
+
+ /* setup non-interleaved ptrs */
+ for( i=0; i<bp->inputChannelCount; ++i )
+ {
+ bp->tempInputBufferPtrs[i] = ((unsigned char*)bp->tempInputBuffer) +
+ i * bp->bytesPerUserInputSample * bp->framesPerUserBuffer;
+ }
+
+ userInput = bp->tempInputBufferPtrs;
+ }
+
+ for( i=0; i<bp->inputChannelCount; ++i )
+ {
+ bp->inputConverter( destBytePtr, destSampleStrideSamples,
+ hostInputChannels[i].data,
+ hostInputChannels[i].stride,
+ frameCount, &bp->ditherGenerator );
+
+ destBytePtr += destChannelStrideBytes; /* skip to next destination channel */
+
+ /* advance src ptr for next iteration */
+ hostInputChannels[i].data = ((unsigned char*)hostInputChannels[i].data) +
+ frameCount * hostInputChannels[i].stride * bp->bytesPerHostInputSample;
+ }
+
+ bp->framesInTempInputBuffer += frameCount;
+
+ if( bp->framesInTempInputBuffer == bp->framesPerUserBuffer )
+ {
+ /**
+ @todo (non-critical optimisation)
+ The conditional below implements the continue/complete/abort mechanism
+ simply by continuing on iterating through the input buffer, but not
+ passing the data to the callback. With care, the outer loop could be
+ terminated earlier, thus some unneeded conversion cycles would be
+ saved.
+ */
+ if( *streamCallbackResult == paContinue )
+ {
+ bp->timeInfo->outputBufferDacTime = 0;
+
+ *streamCallbackResult = bp->streamCallback( userInput, userOutput,
+ bp->framesPerUserBuffer, bp->timeInfo,
+ bp->callbackStatusFlags, bp->userData );
+
+ bp->timeInfo->inputBufferAdcTime += frameCount * bp->samplePeriod;
+ }
+
+ bp->framesInTempInputBuffer = 0;
+ }
+
+ framesProcessed += frameCount;
+
+ framesToGo -= frameCount;
+ }while( framesToGo > 0 );
+
+ return framesProcessed;
+}
+
+
+/*
+ AdaptingOutputOnlyProcess() is a half duplex output buffer processor.
+ It converts data from the temporary output buffer, to the output buffers,
+ when the temporary output buffer is empty, it calls the streamCallback.
+*/
+static unsigned long AdaptingOutputOnlyProcess( PaUtilBufferProcessor *bp,
+ int *streamCallbackResult,
+ PaUtilChannelDescriptor *hostOutputChannels,
+ unsigned long framesToProcess )
+{
+ void *userInput, *userOutput;
+ unsigned char *srcBytePtr;
+ unsigned int srcSampleStrideSamples; /* stride from one sample to the next within a channel, in samples */
+ unsigned int srcChannelStrideBytes; /* stride from one channel to the next, in bytes */
+ unsigned int i;
+ unsigned long frameCount;
+ unsigned long framesToGo = framesToProcess;
+ unsigned long framesProcessed = 0;
+
+ do
+ {
+ if( bp->framesInTempOutputBuffer == 0 && *streamCallbackResult == paContinue )
+ {
+ userInput = 0;
+
+ /* setup userOutput */
+ if( bp->userOutputIsInterleaved )
+ {
+ userOutput = bp->tempOutputBuffer;
+ }
+ else /* user output is not interleaved */
+ {
+ for( i = 0; i < bp->outputChannelCount; ++i )
+ {
+ bp->tempOutputBufferPtrs[i] = ((unsigned char*)bp->tempOutputBuffer) +
+ i * bp->framesPerUserBuffer * bp->bytesPerUserOutputSample;
+ }
+
+ userOutput = bp->tempOutputBufferPtrs;
+ }
+
+ bp->timeInfo->inputBufferAdcTime = 0;
+
+ *streamCallbackResult = bp->streamCallback( userInput, userOutput,
+ bp->framesPerUserBuffer, bp->timeInfo,
+ bp->callbackStatusFlags, bp->userData );
+
+ if( *streamCallbackResult == paAbort )
+ {
+ /* if the callback returned paAbort, we disregard its output */
+ }
+ else
+ {
+ bp->timeInfo->outputBufferDacTime += bp->framesPerUserBuffer * bp->samplePeriod;
+
+ bp->framesInTempOutputBuffer = bp->framesPerUserBuffer;
+ }
+ }
+
+ if( bp->framesInTempOutputBuffer > 0 )
+ {
+ /* convert frameCount frames from user buffer to host buffer */
+
+ frameCount = PA_MIN_( bp->framesInTempOutputBuffer, framesToGo );
+
+ if( bp->userOutputIsInterleaved )
+ {
+ srcBytePtr = ((unsigned char*)bp->tempOutputBuffer) +
+ bp->bytesPerUserOutputSample * bp->outputChannelCount *
+ (bp->framesPerUserBuffer - bp->framesInTempOutputBuffer);
+
+ srcSampleStrideSamples = bp->outputChannelCount;
+ srcChannelStrideBytes = bp->bytesPerUserOutputSample;
+ }
+ else /* user output is not interleaved */
+ {
+ srcBytePtr = ((unsigned char*)bp->tempOutputBuffer) +
+ bp->bytesPerUserOutputSample *
+ (bp->framesPerUserBuffer - bp->framesInTempOutputBuffer);
+
+ srcSampleStrideSamples = 1;
+ srcChannelStrideBytes = bp->framesPerUserBuffer * bp->bytesPerUserOutputSample;
+ }
+
+ for( i=0; i<bp->outputChannelCount; ++i )
+ {
+ bp->outputConverter( hostOutputChannels[i].data,
+ hostOutputChannels[i].stride,
+ srcBytePtr, srcSampleStrideSamples,
+ frameCount, &bp->ditherGenerator );
+
+ srcBytePtr += srcChannelStrideBytes; /* skip to next source channel */
+
+ /* advance dest ptr for next iteration */
+ hostOutputChannels[i].data = ((unsigned char*)hostOutputChannels[i].data) +
+ frameCount * hostOutputChannels[i].stride * bp->bytesPerHostOutputSample;
+ }
+
+ bp->framesInTempOutputBuffer -= frameCount;
+ }
+ else
+ {
+ /* no more user data is available because the callback has returned
+ paComplete or paAbort. Fill the remainder of the host buffer
+ with zeros.
+ */
+
+ frameCount = framesToGo;
+
+ for( i=0; i<bp->outputChannelCount; ++i )
+ {
+ bp->outputZeroer( hostOutputChannels[i].data,
+ hostOutputChannels[i].stride,
+ frameCount );
+
+ /* advance dest ptr for next iteration */
+ hostOutputChannels[i].data = ((unsigned char*)hostOutputChannels[i].data) +
+ frameCount * hostOutputChannels[i].stride * bp->bytesPerHostOutputSample;
+ }
+ }
+
+ framesProcessed += frameCount;
+
+ framesToGo -= frameCount;
+
+ }while( framesToGo > 0 );
+
+ return framesProcessed;
+}
+
+
+/*
+ AdaptingProcess is a full duplex adapting buffer processor. It converts
+ data from the temporary output buffer into the host output buffers, then
+ from the host input buffers into the temporary input buffers. Calling the
+ streamCallback when necessary.
+ When processPartialUserBuffers is 0, all available input data will be
+ consumed and all available output space will be filled. When
+ processPartialUserBuffers is non-zero, as many full user buffers
+ as possible will be processed, but partial buffers will not be consumed.
+*/
+static unsigned long AdaptingProcess( PaUtilBufferProcessor *bp,
+ int *streamCallbackResult, int processPartialUserBuffers )
+{
+ void *userInput, *userOutput;
+ unsigned long framesProcessed = 0;
+ unsigned long framesAvailable;
+ unsigned long endProcessingMinFrameCount;
+ unsigned long maxFramesToCopy;
+ PaUtilChannelDescriptor *hostInputChannels, *hostOutputChannels;
+ unsigned int frameCount;
+ unsigned char *srcBytePtr, *destBytePtr;
+ unsigned int srcSampleStrideSamples; /* stride from one sample to the next within a channel, in samples */
+ unsigned int srcChannelStrideBytes; /* stride from one channel to the next, in bytes */
+ unsigned int destSampleStrideSamples; /* stride from one sample to the next within a channel, in samples */
+ unsigned int destChannelStrideBytes; /* stride from one channel to the next, in bytes */
+ unsigned int i, j;
+
+
+ framesAvailable = bp->hostInputFrameCount[0] + bp->hostInputFrameCount[1];/* this is assumed to be the same as the output buffer's frame count */
+
+ if( processPartialUserBuffers )
+ endProcessingMinFrameCount = 0;
+ else
+ endProcessingMinFrameCount = (bp->framesPerUserBuffer - 1);
+
+ while( framesAvailable > endProcessingMinFrameCount )
+ {
+ /* copy frames from user to host output buffers */
+ while( bp->framesInTempOutputBuffer > 0 &&
+ ((bp->hostOutputFrameCount[0] + bp->hostOutputFrameCount[1]) > 0) )
+ {
+ maxFramesToCopy = bp->framesInTempOutputBuffer;
+
+ /* select the output buffer set (1st or 2nd) */
+ if( bp->hostOutputFrameCount[0] > 0 )
+ {
+ hostOutputChannels = bp->hostOutputChannels[0];
+ frameCount = PA_MIN_( bp->hostOutputFrameCount[0], maxFramesToCopy );
+ }
+ else
+ {
+ hostOutputChannels = bp->hostOutputChannels[1];
+ frameCount = PA_MIN_( bp->hostOutputFrameCount[1], maxFramesToCopy );
+ }
+
+ if( bp->userOutputIsInterleaved )
+ {
+ srcBytePtr = ((unsigned char*)bp->tempOutputBuffer) +
+ bp->bytesPerUserOutputSample * bp->outputChannelCount *
+ (bp->framesPerUserBuffer - bp->framesInTempOutputBuffer);
+
+ srcSampleStrideSamples = bp->outputChannelCount;
+ srcChannelStrideBytes = bp->bytesPerUserOutputSample;
+ }
+ else /* user output is not interleaved */
+ {
+ srcBytePtr = ((unsigned char*)bp->tempOutputBuffer) +
+ bp->bytesPerUserOutputSample *
+ (bp->framesPerUserBuffer - bp->framesInTempOutputBuffer);
+
+ srcSampleStrideSamples = 1;
+ srcChannelStrideBytes = bp->framesPerUserBuffer * bp->bytesPerUserOutputSample;
+ }
+
+ for( i=0; i<bp->outputChannelCount; ++i )
+ {
+ bp->outputConverter( hostOutputChannels[i].data,
+ hostOutputChannels[i].stride,
+ srcBytePtr, srcSampleStrideSamples,
+ frameCount, &bp->ditherGenerator );
+
+ srcBytePtr += srcChannelStrideBytes; /* skip to next source channel */
+
+ /* advance dest ptr for next iteration */
+ hostOutputChannels[i].data = ((unsigned char*)hostOutputChannels[i].data) +
+ frameCount * hostOutputChannels[i].stride * bp->bytesPerHostOutputSample;
+ }
+
+ if( bp->hostOutputFrameCount[0] > 0 )
+ bp->hostOutputFrameCount[0] -= frameCount;
+ else
+ bp->hostOutputFrameCount[1] -= frameCount;
+
+ bp->framesInTempOutputBuffer -= frameCount;
+ }
+
+ if( bp->framesInTempOutputBuffer == 0 && *streamCallbackResult != paContinue )
+ {
+ /* the callback will not be called any more, so zero what remains
+ of the host output buffers */
+
+ for( i=0; i<2; ++i )
+ {
+ frameCount = bp->hostOutputFrameCount[i];
+ if( frameCount > 0 )
+ {
+ hostOutputChannels = bp->hostOutputChannels[i];
+
+ for( j=0; j<bp->outputChannelCount; ++j )
+ {
+ bp->outputZeroer( hostOutputChannels[j].data,
+ hostOutputChannels[j].stride,
+ frameCount );
+
+ /* advance dest ptr for next iteration */
+ hostOutputChannels[j].data = ((unsigned char*)hostOutputChannels[j].data) +
+ frameCount * hostOutputChannels[j].stride * bp->bytesPerHostOutputSample;
+ }
+ bp->hostOutputFrameCount[i] = 0;
+ }
+ }
+ }
+
+
+ /* copy frames from host to user input buffers */
+ while( bp->framesInTempInputBuffer < bp->framesPerUserBuffer &&
+ ((bp->hostInputFrameCount[0] + bp->hostInputFrameCount[1]) > 0) )
+ {
+ maxFramesToCopy = bp->framesPerUserBuffer - bp->framesInTempInputBuffer;
+
+ /* select the input buffer set (1st or 2nd) */
+ if( bp->hostInputFrameCount[0] > 0 )
+ {
+ hostInputChannels = bp->hostInputChannels[0];
+ frameCount = PA_MIN_( bp->hostInputFrameCount[0], maxFramesToCopy );
+ }
+ else
+ {
+ hostInputChannels = bp->hostInputChannels[1];
+ frameCount = PA_MIN_( bp->hostInputFrameCount[1], maxFramesToCopy );
+ }
+
+ /* configure conversion destination pointers */
+ if( bp->userInputIsInterleaved )
+ {
+ destBytePtr = ((unsigned char*)bp->tempInputBuffer) +
+ bp->bytesPerUserInputSample * bp->inputChannelCount *
+ bp->framesInTempInputBuffer;
+
+ destSampleStrideSamples = bp->inputChannelCount;
+ destChannelStrideBytes = bp->bytesPerUserInputSample;
+ }
+ else /* user input is not interleaved */
+ {
+ destBytePtr = ((unsigned char*)bp->tempInputBuffer) +
+ bp->bytesPerUserInputSample * bp->framesInTempInputBuffer;
+
+ destSampleStrideSamples = 1;
+ destChannelStrideBytes = bp->framesPerUserBuffer * bp->bytesPerUserInputSample;
+ }
+
+ for( i=0; i<bp->inputChannelCount; ++i )
+ {
+ bp->inputConverter( destBytePtr, destSampleStrideSamples,
+ hostInputChannels[i].data,
+ hostInputChannels[i].stride,
+ frameCount, &bp->ditherGenerator );
+
+ destBytePtr += destChannelStrideBytes; /* skip to next destination channel */
+
+ /* advance src ptr for next iteration */
+ hostInputChannels[i].data = ((unsigned char*)hostInputChannels[i].data) +
+ frameCount * hostInputChannels[i].stride * bp->bytesPerHostInputSample;
+ }
+
+ if( bp->hostInputFrameCount[0] > 0 )
+ bp->hostInputFrameCount[0] -= frameCount;
+ else
+ bp->hostInputFrameCount[1] -= frameCount;
+
+ bp->framesInTempInputBuffer += frameCount;
+
+ /* update framesAvailable and framesProcessed based on input consumed
+ unless something is very wrong this will also correspond to the
+ amount of output generated */
+ framesAvailable -= frameCount;
+ framesProcessed += frameCount;
+ }
+
+ /* call streamCallback */
+ if( bp->framesInTempInputBuffer == bp->framesPerUserBuffer &&
+ bp->framesInTempOutputBuffer == 0 )
+ {
+ if( *streamCallbackResult == paContinue )
+ {
+ /* setup userInput */
+ if( bp->userInputIsInterleaved )
+ {
+ userInput = bp->tempInputBuffer;
+ }
+ else /* user input is not interleaved */
+ {
+ for( i = 0; i < bp->inputChannelCount; ++i )
+ {
+ bp->tempInputBufferPtrs[i] = ((unsigned char*)bp->tempInputBuffer) +
+ i * bp->framesPerUserBuffer * bp->bytesPerUserInputSample;
+ }
+
+ userInput = bp->tempInputBufferPtrs;
+ }
+
+ /* setup userOutput */
+ if( bp->userOutputIsInterleaved )
+ {
+ userOutput = bp->tempOutputBuffer;
+ }
+ else /* user output is not interleaved */
+ {
+ for( i = 0; i < bp->outputChannelCount; ++i )
+ {
+ bp->tempOutputBufferPtrs[i] = ((unsigned char*)bp->tempOutputBuffer) +
+ i * bp->framesPerUserBuffer * bp->bytesPerUserOutputSample;
+ }
+
+ userOutput = bp->tempOutputBufferPtrs;
+ }
+
+ /* call streamCallback */
+
+ *streamCallbackResult = bp->streamCallback( userInput, userOutput,
+ bp->framesPerUserBuffer, bp->timeInfo,
+ bp->callbackStatusFlags, bp->userData );
+
+ bp->timeInfo->inputBufferAdcTime += bp->framesPerUserBuffer * bp->samplePeriod;
+ bp->timeInfo->outputBufferDacTime += bp->framesPerUserBuffer * bp->samplePeriod;
+
+ bp->framesInTempInputBuffer = 0;
+
+ if( *streamCallbackResult == paAbort )
+ bp->framesInTempOutputBuffer = 0;
+ else
+ bp->framesInTempOutputBuffer = bp->framesPerUserBuffer;
+ }
+ else
+ {
+ /* paComplete or paAbort has already been called. */
+
+ bp->framesInTempInputBuffer = 0;
+ }
+ }
+ }
+
+ return framesProcessed;
+}
+
+
+unsigned long PaUtil_EndBufferProcessing( PaUtilBufferProcessor* bp, int *streamCallbackResult )
+{
+ unsigned long framesToProcess, framesToGo;
+ unsigned long framesProcessed = 0;
+
+ if( bp->inputChannelCount != 0 && bp->outputChannelCount != 0
+ && bp->hostInputChannels[0][0].data /* input was supplied (see PaUtil_SetNoInput) */
+ && bp->hostOutputChannels[0][0].data /* output was supplied (see PaUtil_SetNoOutput) */ )
+ {
+ assert( (bp->hostInputFrameCount[0] + bp->hostInputFrameCount[1]) ==
+ (bp->hostOutputFrameCount[0] + bp->hostOutputFrameCount[1]) );
+ }
+
+ assert( *streamCallbackResult == paContinue
+ || *streamCallbackResult == paComplete
+ || *streamCallbackResult == paAbort ); /* don't forget to pass in a valid callback result value */
+
+ if( bp->useNonAdaptingProcess )
+ {
+ if( bp->inputChannelCount != 0 && bp->outputChannelCount != 0 )
+ {
+ /* full duplex non-adapting process, splice buffers if they are
+ different lengths */
+
+ framesToGo = bp->hostOutputFrameCount[0] + bp->hostOutputFrameCount[1]; /* relies on assert above for input/output equivalence */
+
+ do{
+ unsigned long noInputInputFrameCount;
+ unsigned long *hostInputFrameCount;
+ PaUtilChannelDescriptor *hostInputChannels;
+ unsigned long noOutputOutputFrameCount;
+ unsigned long *hostOutputFrameCount;
+ PaUtilChannelDescriptor *hostOutputChannels;
+ unsigned long framesProcessedThisIteration;
+
+ if( !bp->hostInputChannels[0][0].data )
+ {
+ /* no input was supplied (see PaUtil_SetNoInput)
+ NonAdaptingProcess knows how to deal with this
+ */
+ noInputInputFrameCount = framesToGo;
+ hostInputFrameCount = &noInputInputFrameCount;
+ hostInputChannels = 0;
+ }
+ else if( bp->hostInputFrameCount[0] != 0 )
+ {
+ hostInputFrameCount = &bp->hostInputFrameCount[0];
+ hostInputChannels = bp->hostInputChannels[0];
+ }
+ else
+ {
+ hostInputFrameCount = &bp->hostInputFrameCount[1];
+ hostInputChannels = bp->hostInputChannels[1];
+ }
+
+ if( !bp->hostOutputChannels[0][0].data )
+ {
+ /* no output was supplied (see PaUtil_SetNoOutput)
+ NonAdaptingProcess knows how to deal with this
+ */
+ noOutputOutputFrameCount = framesToGo;
+ hostOutputFrameCount = &noOutputOutputFrameCount;
+ hostOutputChannels = 0;
+ }
+ if( bp->hostOutputFrameCount[0] != 0 )
+ {
+ hostOutputFrameCount = &bp->hostOutputFrameCount[0];
+ hostOutputChannels = bp->hostOutputChannels[0];
+ }
+ else
+ {
+ hostOutputFrameCount = &bp->hostOutputFrameCount[1];
+ hostOutputChannels = bp->hostOutputChannels[1];
+ }
+
+ framesToProcess = PA_MIN_( *hostInputFrameCount,
+ *hostOutputFrameCount );
+
+ assert( framesToProcess != 0 );
+
+ framesProcessedThisIteration = NonAdaptingProcess( bp, streamCallbackResult,
+ hostInputChannels, hostOutputChannels,
+ framesToProcess );
+
+ *hostInputFrameCount -= framesProcessedThisIteration;
+ *hostOutputFrameCount -= framesProcessedThisIteration;
+
+ framesProcessed += framesProcessedThisIteration;
+ framesToGo -= framesProcessedThisIteration;
+
+ }while( framesToGo > 0 );
+ }
+ else
+ {
+ /* half duplex non-adapting process, just process 1st and 2nd buffer */
+ /* process first buffer */
+
+ framesToProcess = (bp->inputChannelCount != 0)
+ ? bp->hostInputFrameCount[0]
+ : bp->hostOutputFrameCount[0];
+
+ framesProcessed = NonAdaptingProcess( bp, streamCallbackResult,
+ bp->hostInputChannels[0], bp->hostOutputChannels[0],
+ framesToProcess );
+
+ /* process second buffer if provided */
+
+ framesToProcess = (bp->inputChannelCount != 0)
+ ? bp->hostInputFrameCount[1]
+ : bp->hostOutputFrameCount[1];
+ if( framesToProcess > 0 )
+ {
+ framesProcessed += NonAdaptingProcess( bp, streamCallbackResult,
+ bp->hostInputChannels[1], bp->hostOutputChannels[1],
+ framesToProcess );
+ }
+ }
+ }
+ else /* block adaption necessary*/
+ {
+
+ if( bp->inputChannelCount != 0 && bp->outputChannelCount != 0 )
+ {
+ /* full duplex */
+
+ if( bp->hostBufferSizeMode == paUtilVariableHostBufferSizePartialUsageAllowed )
+ {
+ framesProcessed = AdaptingProcess( bp, streamCallbackResult,
+ 0 /* dont process partial user buffers */ );
+ }
+ else
+ {
+ framesProcessed = AdaptingProcess( bp, streamCallbackResult,
+ 1 /* process partial user buffers */ );
+ }
+ }
+ else if( bp->inputChannelCount != 0 )
+ {
+ /* input only */
+ framesToProcess = bp->hostInputFrameCount[0];
+
+ framesProcessed = AdaptingInputOnlyProcess( bp, streamCallbackResult,
+ bp->hostInputChannels[0], framesToProcess );
+
+ framesToProcess = bp->hostInputFrameCount[1];
+ if( framesToProcess > 0 )
+ {
+ framesProcessed += AdaptingInputOnlyProcess( bp, streamCallbackResult,
+ bp->hostInputChannels[1], framesToProcess );
+ }
+ }
+ else
+ {
+ /* output only */
+ framesToProcess = bp->hostOutputFrameCount[0];
+
+ framesProcessed = AdaptingOutputOnlyProcess( bp, streamCallbackResult,
+ bp->hostOutputChannels[0], framesToProcess );
+
+ framesToProcess = bp->hostOutputFrameCount[1];
+ if( framesToProcess > 0 )
+ {
+ framesProcessed += AdaptingOutputOnlyProcess( bp, streamCallbackResult,
+ bp->hostOutputChannels[1], framesToProcess );
+ }
+ }
+ }
+
+ return framesProcessed;
+}
+
+
+int PaUtil_IsBufferProcessorOuputEmpty( PaUtilBufferProcessor* bp )
+{
+ return (bp->framesInTempOutputBuffer) ? 0 : 1;
+}
+
+
+unsigned long PaUtil_CopyInput( PaUtilBufferProcessor* bp,
+ void **buffer, unsigned long frameCount )
+{
+ PaUtilChannelDescriptor *hostInputChannels;
+ unsigned int framesToCopy;
+ unsigned char *destBytePtr;
+ void **nonInterleavedDestPtrs;
+ unsigned int destSampleStrideSamples; /* stride from one sample to the next within a channel, in samples */
+ unsigned int destChannelStrideBytes; /* stride from one channel to the next, in bytes */
+ unsigned int i;
+
+ hostInputChannels = bp->hostInputChannels[0];
+ framesToCopy = PA_MIN_( bp->hostInputFrameCount[0], frameCount );
+
+ if( bp->userInputIsInterleaved )
+ {
+ destBytePtr = (unsigned char*)*buffer;
+
+ destSampleStrideSamples = bp->inputChannelCount;
+ destChannelStrideBytes = bp->bytesPerUserInputSample;
+
+ for( i=0; i<bp->inputChannelCount; ++i )
+ {
+ bp->inputConverter( destBytePtr, destSampleStrideSamples,
+ hostInputChannels[i].data,
+ hostInputChannels[i].stride,
+ framesToCopy, &bp->ditherGenerator );
+
+ destBytePtr += destChannelStrideBytes; /* skip to next source channel */
+
+ /* advance dest ptr for next iteration */
+ hostInputChannels[i].data = ((unsigned char*)hostInputChannels[i].data) +
+ framesToCopy * hostInputChannels[i].stride * bp->bytesPerHostInputSample;
+ }
+
+ /* advance callers dest pointer (buffer) */
+ *buffer = ((unsigned char *)*buffer) +
+ framesToCopy * bp->inputChannelCount * bp->bytesPerUserInputSample;
+ }
+ else
+ {
+ /* user input is not interleaved */
+
+ nonInterleavedDestPtrs = (void**)*buffer;
+
+ destSampleStrideSamples = 1;
+
+ for( i=0; i<bp->inputChannelCount; ++i )
+ {
+ destBytePtr = (unsigned char*)nonInterleavedDestPtrs[i];
+
+ bp->inputConverter( destBytePtr, destSampleStrideSamples,
+ hostInputChannels[i].data,
+ hostInputChannels[i].stride,
+ framesToCopy, &bp->ditherGenerator );
+
+ /* advance callers dest pointer (nonInterleavedDestPtrs[i]) */
+ destBytePtr += bp->bytesPerUserInputSample * framesToCopy;
+ nonInterleavedDestPtrs[i] = destBytePtr;
+
+ /* advance dest ptr for next iteration */
+ hostInputChannels[i].data = ((unsigned char*)hostInputChannels[i].data) +
+ framesToCopy * hostInputChannels[i].stride * bp->bytesPerHostInputSample;
+ }
+ }
+
+ bp->hostInputFrameCount[0] -= framesToCopy;
+
+ return framesToCopy;
+}
+
+unsigned long PaUtil_CopyOutput( PaUtilBufferProcessor* bp,
+ const void ** buffer, unsigned long frameCount )
+{
+ PaUtilChannelDescriptor *hostOutputChannels;
+ unsigned int framesToCopy;
+ unsigned char *srcBytePtr;
+ void **nonInterleavedSrcPtrs;
+ unsigned int srcSampleStrideSamples; /* stride from one sample to the next within a channel, in samples */
+ unsigned int srcChannelStrideBytes; /* stride from one channel to the next, in bytes */
+ unsigned int i;
+
+ hostOutputChannels = bp->hostOutputChannels[0];
+ framesToCopy = PA_MIN_( bp->hostOutputFrameCount[0], frameCount );
+
+ if( bp->userOutputIsInterleaved )
+ {
+ srcBytePtr = (unsigned char*)*buffer;
+
+ srcSampleStrideSamples = bp->outputChannelCount;
+ srcChannelStrideBytes = bp->bytesPerUserOutputSample;
+
+ for( i=0; i<bp->outputChannelCount; ++i )
+ {
+ bp->outputConverter( hostOutputChannels[i].data,
+ hostOutputChannels[i].stride,
+ srcBytePtr, srcSampleStrideSamples,
+ framesToCopy, &bp->ditherGenerator );
+
+ srcBytePtr += srcChannelStrideBytes; /* skip to next source channel */
+
+ /* advance dest ptr for next iteration */
+ hostOutputChannels[i].data = ((unsigned char*)hostOutputChannels[i].data) +
+ framesToCopy * hostOutputChannels[i].stride * bp->bytesPerHostOutputSample;
+ }
+
+ /* advance callers source pointer (buffer) */
+ *buffer = ((unsigned char *)*buffer) +
+ framesToCopy * bp->outputChannelCount * bp->bytesPerUserOutputSample;
+
+ }
+ else
+ {
+ /* user output is not interleaved */
+
+ nonInterleavedSrcPtrs = (void**)*buffer;
+
+ srcSampleStrideSamples = 1;
+
+ for( i=0; i<bp->outputChannelCount; ++i )
+ {
+ srcBytePtr = (unsigned char*)nonInterleavedSrcPtrs[i];
+
+ bp->outputConverter( hostOutputChannels[i].data,
+ hostOutputChannels[i].stride,
+ srcBytePtr, srcSampleStrideSamples,
+ framesToCopy, &bp->ditherGenerator );
+
+
+ /* advance callers source pointer (nonInterleavedSrcPtrs[i]) */
+ srcBytePtr += bp->bytesPerUserOutputSample * framesToCopy;
+ nonInterleavedSrcPtrs[i] = srcBytePtr;
+
+ /* advance dest ptr for next iteration */
+ hostOutputChannels[i].data = ((unsigned char*)hostOutputChannels[i].data) +
+ framesToCopy * hostOutputChannels[i].stride * bp->bytesPerHostOutputSample;
+ }
+ }
+
+ bp->hostOutputFrameCount[0] += framesToCopy;
+
+ return framesToCopy;
+}
+
+
+unsigned long PaUtil_ZeroOutput( PaUtilBufferProcessor* bp, unsigned long frameCount )
+{
+ PaUtilChannelDescriptor *hostOutputChannels;
+ unsigned int framesToZero;
+ unsigned int i;
+
+ hostOutputChannels = bp->hostOutputChannels[0];
+ framesToZero = PA_MIN_( bp->hostOutputFrameCount[0], frameCount );
+
+ for( i=0; i<bp->outputChannelCount; ++i )
+ {
+ bp->outputZeroer( hostOutputChannels[i].data,
+ hostOutputChannels[i].stride,
+ framesToZero );
+
+
+ /* advance dest ptr for next iteration */
+ hostOutputChannels[i].data = ((unsigned char*)hostOutputChannels[i].data) +
+ framesToZero * hostOutputChannels[i].stride * bp->bytesPerHostOutputSample;
+ }
+
+ bp->hostOutputFrameCount[0] += framesToZero;
+
+ return framesToZero;
+}
diff --git a/pd/portaudio/pa_common/pa_process.h b/pd/portaudio/pa_common/pa_process.h
new file mode 100644
index 00000000..a54eccd7
--- /dev/null
+++ b/pd/portaudio/pa_common/pa_process.h
@@ -0,0 +1,733 @@
+#ifndef PA_PROCESS_H
+#define PA_PROCESS_H
+/*
+ * $Id: pa_process.h,v 1.1.2.27 2004/05/28 21:13:10 aknudsen Exp $
+ * Portable Audio I/O Library callback buffer processing adapters
+ *
+ * Based on the Open Source API proposed by Ross Bencina
+ * Copyright (c) 1999-2002 Phil Burk, Ross Bencina
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/** @file
+ @brief Buffer Processor prototypes. A Buffer Processor performs buffer length
+ adaption, coordinates sample format conversion, and interleaves/deinterleaves
+ channels.
+
+ <h3>Overview</h3>
+
+ The "Buffer Processor" (PaUtilBufferProcessor) manages conversion of audio
+ data from host buffers to user buffers and back again. Where required, the
+ buffer processor takes care of converting between host and user sample formats,
+ interleaving and deinterleaving multichannel buffers, and adapting between host
+ and user buffers with different lengths. The buffer processor may be used with
+ full and half duplex streams, for both callback streams and blocking read/write
+ streams.
+
+ One of the important capabilities provided by the buffer processor is
+ the ability to adapt between user and host buffer sizes of different lengths
+ with minimum latency. Although this task is relatively easy to perform when
+ the host buffer size is an integer multiple of the user buffer size, the
+ problem is more complicated when this is not the case - especially for
+ full-duplex callback streams. Where necessary the adaption is implemented by
+ internally buffering some input and/or output data. The buffer adation
+ algorithm used by the buffer processor was originally implemented by
+ Stephan Letz for the ASIO version of PortAudio, and is described in his
+ Callback_adaption_.pdf which is included in the distribution.
+
+ The buffer processor performs sample conversion using the functions provided
+ by pa_converters.c.
+
+ The following sections provide an overview of how to use the buffer processor.
+ Interested readers are advised to consult the host API implementations for
+ examples of buffer processor usage.
+
+
+ <h4>Initialization, resetting and termination</h4>
+
+ When a stream is opened, the buffer processor should be initialized using
+ PaUtil_InitializeBufferProcessor. This function initializes internal state
+ and allocates temporary buffers as neccesary according to the supplied
+ configuration parameters. Some of the parameters correspond to those requested
+ by the user in their call to Pa_OpenStream(), others reflect the requirements
+ of the host API implementation - they indicate host buffer sizes, formats,
+ and the type of buffering which the Host API uses. The buffer processor should
+ be initialized for callback streams and blocking read/write streams.
+
+ Call PaUtil_ResetBufferProcessor to clear any sample data which is present
+ in the buffer processor before starting to use it (for example when
+ Pa_StartStream is called).
+
+ When the buffer processor is no longer used call
+ PaUtil_TerminateBufferProcessor.
+
+
+ <h4>Using the buffer processor for a callback stream</h4>
+
+ The buffer processor's role in a callback stream is to take host input buffers
+ process them with the stream callback, and fill host output buffers. For a
+ full duplex stream, the buffer processor handles input and output simultaneously
+ due to the requirements of the minimum-latency buffer adation algorithm.
+
+ When a host buffer becomes available, the implementation should call
+ the buffer processor to process the buffer. The buffer processor calls the
+ stream callback to consume and/or produce audio data as necessary. The buffer
+ processor will convert sample formats, interleave/deinterleave channels,
+ and slice or chunk the data to the appropriate buffer lengths according to
+ the requirements of the stream callback and the host API.
+
+ To process a host buffer (or a pair of host buffers for a full-duplex stream)
+ use the following calling sequence:
+
+ -# Call PaUtil_BeginBufferProcessing
+ -# For a stream which takes input:
+ - Call PaUtil_SetInputFrameCount with the number of frames in the host input
+ buffer.
+ - Call one of the following functions one or more times to tell the
+ buffer processor about the host input buffer(s): PaUtil_SetInputChannel,
+ PaUtil_SetInterleavedInputChannels, PaUtil_SetNonInterleavedInputChannel.
+ Which function you call will depend on whether the host buffer(s) are
+ interleaved or not.
+ - If the available host data is split accross two buffers (for example a
+ data range at the end of a circular buffer and another range at the
+ beginning of the circular buffer), also call
+ PaUtil_Set2ndInputFrameCount, PaUtil_Set2ndInputChannel,
+ PaUtil_Set2ndInterleavedInputChannels,
+ PaUtil_Set2ndNonInterleavedInputChannel as necessary to tell the buffer
+ processor about the second buffer.
+ -# For a stream which generates output:
+ - Call PaUtil_SetOutputFrameCount with the number of frames in the host
+ output buffer.
+ - Call one of the following functions one or more times to tell the
+ buffer processor about the host output buffer(s): PaUtil_SetOutputChannel,
+ PaUtil_SetInterleavedOutputChannels, PaUtil_SetNonInterleavedOutputChannel.
+ Which function you call will depend on whether the host buffer(s) are
+ interleaved or not.
+ - If the available host output buffer space is split accross two buffers
+ (for example a data range at the end of a circular buffer and another
+ range at the beginning of the circular buffer), call
+ PaUtil_Set2ndOutputFrameCount, PaUtil_Set2ndOutputChannel,
+ PaUtil_Set2ndInterleavedOutputChannels,
+ PaUtil_Set2ndNonInterleavedOutputChannel as necessary to tell the buffer
+ processor about the second buffer.
+ -# Call PaUtil_EndBufferProcessing, this function performs the actual data
+ conversion and processing.
+
+
+ <h4>Using the buffer processor for a blocking read/write stream</h4>
+
+ Blocking read/write streams use the buffer processor to convert and copy user
+ output data to a host buffer, and to convert and copy host input data to
+ the user's buffer. The buffer processor does not perform any buffer adaption.
+ When using the buffer processor in a blocking read/write stream the input and
+ output conversion are performed separately by the PaUtil_CopyInput and
+ PaUtil_CopyOutput functions.
+
+ To copy data from a host input buffer to the buffer(s) which the user supplies
+ to Pa_ReadStream, use the following calling sequence.
+
+ - Repeat the following three steps until the user buffer(s) have been filled
+ with samples from the host input buffers:
+ -# Call PaUtil_SetInputFrameCount with the number of frames in the host
+ input buffer.
+ -# Call one of the following functions one or more times to tell the
+ buffer processor about the host input buffer(s): PaUtil_SetInputChannel,
+ PaUtil_SetInterleavedInputChannels, PaUtil_SetNonInterleavedInputChannel.
+ Which function you call will depend on whether the host buffer(s) are
+ interleaved or not.
+ -# Call PaUtil_CopyInput with the user buffer pointer (or a copy of the
+ array of buffer pointers for a non-interleaved stream) passed to
+ Pa_ReadStream, along with the number of frames in the user buffer(s).
+ Be careful to pass a <i>copy</i> of the user buffer pointers to
+ PaUtil_CopyInput because PaUtil_CopyInput advances the pointers to
+ the start of the next region to copy.
+ - PaUtil_CopyInput will not copy more data than is available in the
+ host buffer(s), so the above steps need to be repeated until the user
+ buffer(s) are full.
+
+
+ To copy data to the host output buffer from the user buffers(s) supplied
+ to Pa_WriteStream use the following calling sequence.
+
+ - Repeat the following three steps until all frames from the user buffer(s)
+ have been copied to the host API:
+ -# Call PaUtil_SetOutputFrameCount with the number of frames in the host
+ output buffer.
+ -# Call one of the following functions one or more times to tell the
+ buffer processor about the host output buffer(s): PaUtil_SetOutputChannel,
+ PaUtil_SetInterleavedOutputChannels, PaUtil_SetNonInterleavedOutputChannel.
+ Which function you call will depend on whether the host buffer(s) are
+ interleaved or not.
+ -# Call PaUtil_CopyOutput with the user buffer pointer (or a copy of the
+ array of buffer pointers for a non-interleaved stream) passed to
+ Pa_WriteStream, along with the number of frames in the user buffer(s).
+ Be careful to pass a <i>copy</i> of the user buffer pointers to
+ PaUtil_CopyOutput because PaUtil_CopyOutput advances the pointers to
+ the start of the next region to copy.
+ - PaUtil_CopyOutput will not copy more data than fits in the host buffer(s),
+ so the above steps need to be repeated until all user data is copied.
+*/
+
+
+#include "portaudio.h"
+#include "pa_converters.h"
+#include "pa_dither.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+
+/** @brief Mode flag passed to PaUtil_InitializeBufferProcessor indicating the type
+ of buffering that the host API uses.
+
+ The mode used depends on whether the host API or the implementation manages
+ the buffers, and how these buffers are used (scatter gather, circular buffer).
+*/
+typedef enum {
+/** The host buffer size is a fixed known size. */
+ paUtilFixedHostBufferSize,
+
+/** The host buffer size may vary, but has a known maximum size. */
+ paUtilBoundedHostBufferSize,
+
+/** Nothing is known about the host buffer size. */
+ paUtilUnknownHostBufferSize,
+
+/** The host buffer size varies, and the client does not require the buffer
+ processor to consume all of the input and fill all of the output buffer. This
+ is useful when the implementation has access to the host API's circular buffer
+ and only needs to consume/fill some of it, not necessarily all of it, with each
+ call to the buffer processor. This is the only mode where
+ PaUtil_EndBufferProcessing() may not consume the whole buffer.
+*/
+ paUtilVariableHostBufferSizePartialUsageAllowed
+}PaUtilHostBufferSizeMode;
+
+
+/** @brief An auxilliary data structure used internally by the buffer processor
+ to represent host input and output buffers. */
+typedef struct PaUtilChannelDescriptor{
+ void *data;
+ unsigned int stride; /**< stride in samples, not bytes */
+}PaUtilChannelDescriptor;
+
+
+/** @brief The main buffer processor data structure.
+
+ Allocate one of these, initialize it with PaUtil_InitializeBufferProcessor
+ and terminate it with PaUtil_TerminateBufferProcessor.
+*/
+typedef struct {
+ unsigned long framesPerUserBuffer;
+ unsigned long framesPerHostBuffer;
+
+ PaUtilHostBufferSizeMode hostBufferSizeMode;
+ int useNonAdaptingProcess;
+ unsigned long framesPerTempBuffer;
+
+ unsigned int inputChannelCount;
+ unsigned int bytesPerHostInputSample;
+ unsigned int bytesPerUserInputSample;
+ int userInputIsInterleaved;
+ PaUtilConverter *inputConverter;
+ PaUtilZeroer *inputZeroer;
+
+ unsigned int outputChannelCount;
+ unsigned int bytesPerHostOutputSample;
+ unsigned int bytesPerUserOutputSample;
+ int userOutputIsInterleaved;
+ PaUtilConverter *outputConverter;
+ PaUtilZeroer *outputZeroer;
+
+ unsigned long initialFramesInTempInputBuffer;
+ unsigned long initialFramesInTempOutputBuffer;
+
+ void *tempInputBuffer; /**< used for slips, block adaption, and conversion. */
+ void **tempInputBufferPtrs; /**< storage for non-interleaved buffer pointers, NULL for interleaved user input */
+ unsigned long framesInTempInputBuffer; /**< frames remaining in input buffer from previous adaption iteration */
+
+ void *tempOutputBuffer; /**< used for slips, block adaption, and conversion. */
+ void **tempOutputBufferPtrs; /**< storage for non-interleaved buffer pointers, NULL for interleaved user output */
+ unsigned long framesInTempOutputBuffer; /**< frames remaining in input buffer from previous adaption iteration */
+
+ PaStreamCallbackTimeInfo *timeInfo;
+
+ PaStreamCallbackFlags callbackStatusFlags;
+
+ unsigned long hostInputFrameCount[2];
+ PaUtilChannelDescriptor *hostInputChannels[2];
+ unsigned long hostOutputFrameCount[2];
+ PaUtilChannelDescriptor *hostOutputChannels[2];
+
+ PaUtilTriangularDitherGenerator ditherGenerator;
+
+ double samplePeriod;
+
+ PaStreamCallback *streamCallback;
+ void *userData;
+} PaUtilBufferProcessor;
+
+
+/** @name Initialization, termination, resetting and info */
+/*@{*/
+
+/** Initialize a buffer processor's representation stored in a
+ PaUtilBufferProcessor structure. Be sure to call
+ PaUtil_TerminateBufferProcessor after finishing with a buffer processor.
+
+ @param bufferProcessor The buffer processor structure to initialize.
+
+ @param inputChannelCount The number of input channels as passed to
+ Pa_OpenStream or 0 for an output-only stream.
+
+ @param userInputSampleFormat Format of user input samples, as passed to
+ Pa_OpenStream. This parameter is ignored for ouput-only streams.
+
+ @param hostInputSampleFormat Format of host input samples. This parameter is
+ ignored for output-only streams. See note about host buffer interleave below.
+
+ @param outputChannelCount The number of output channels as passed to
+ Pa_OpenStream or 0 for an input-only stream.
+
+ @param userOutputSampleFormat Format of user output samples, as passed to
+ Pa_OpenStream. This parameter is ignored for input-only streams.
+
+ @param hostOutputSampleFormat Format of host output samples. This parameter is
+ ignored for input-only streams. See note about host buffer interleave below.
+
+ @param sampleRate Sample rate of the stream. The more accurate this is the
+ better - it is used for updating time stamps when adapting buffers.
+
+ @param streamFlags Stream flags as passed to Pa_OpenStream, this parameter is
+ used for selecting special sample conversion options such as clipping and
+ dithering.
+
+ @param framesPerUserBuffer Number of frames per user buffer, as requested
+ by the framesPerBuffer parameter to Pa_OpenStream. This parameter may be
+ zero to indicate that the user will accept any (and varying) buffer sizes.
+
+ @param framesPerHostBuffer Specifies the number of frames per host buffer
+ for the fixed buffer size mode, and the maximum number of frames
+ per host buffer for the bounded host buffer size mode. It is ignored for
+ the other modes.
+
+ @param hostBufferSizeMode A mode flag indicating the size variability of
+ host buffers that will be passed to the buffer processor. See
+ PaUtilHostBufferSizeMode for further details.
+
+ @param streamCallback The user stream callback passed to Pa_OpenStream.
+
+ @param userData The user data field passed to Pa_OpenStream.
+
+ @note The interleave flag is ignored for host buffer formats. Host
+ interleave is determined by the use of different SetInput and SetOutput
+ functions.
+
+ @return An error code indicating whether the initialization was successful.
+ If the error code is not PaNoError, the buffer processor was not initialized
+ and should not be used.
+
+ @see Pa_OpenStream, PaUtilHostBufferSizeMode, PaUtil_TerminateBufferProcessor
+*/
+PaError PaUtil_InitializeBufferProcessor( PaUtilBufferProcessor* bufferProcessor,
+ int inputChannelCount, PaSampleFormat userInputSampleFormat,
+ PaSampleFormat hostInputSampleFormat,
+ int outputChannelCount, PaSampleFormat userOutputSampleFormat,
+ PaSampleFormat hostOutputSampleFormat,
+ double sampleRate,
+ PaStreamFlags streamFlags,
+ unsigned long framesPerUserBuffer, /* 0 indicates don't care */
+ unsigned long framesPerHostBuffer,
+ PaUtilHostBufferSizeMode hostBufferSizeMode,
+ PaStreamCallback *streamCallback, void *userData );
+
+
+/** Terminate a buffer processor's representation. Deallocates any temporary
+ buffers allocated by PaUtil_InitializeBufferProcessor.
+
+ @param bufferProcessor The buffer processor structure to terminate.
+
+ @see PaUtil_InitializeBufferProcessor.
+*/
+void PaUtil_TerminateBufferProcessor( PaUtilBufferProcessor* bufferProcessor );
+
+
+/** Clear any internally buffered data. If you call
+ PaUtil_InitializeBufferProcessor in your OpenStream routine, make sure you
+ call PaUtil_ResetBufferProcessor in your StartStream call.
+
+ @param bufferProcessor The buffer processor to reset.
+*/
+void PaUtil_ResetBufferProcessor( PaUtilBufferProcessor* bufferProcessor );
+
+
+/** Retrieve the input latency of a buffer processor.
+
+ @param bufferProcessor The buffer processor examine.
+
+ @return The input latency introduced by the buffer processor, in frames.
+
+ @see PaUtil_GetBufferProcessorOutputLatency
+*/
+unsigned long PaUtil_GetBufferProcessorInputLatency( PaUtilBufferProcessor* bufferProcessor );
+
+/** Retrieve the output latency of a buffer processor.
+
+ @param bufferProcessor The buffer processor examine.
+
+ @return The output latency introduced by the buffer processor, in frames.
+
+ @see PaUtil_GetBufferProcessorInputLatency
+*/
+unsigned long PaUtil_GetBufferProcessorOutputLatency( PaUtilBufferProcessor* bufferProcessor );
+
+/*@}*/
+
+
+/** @name Host buffer pointer configuration
+
+ Functions to set host input and output buffers, used by both callback streams
+ and blocking read/write streams.
+*/
+/*@{*/
+
+
+/** Set the number of frames in the input host buffer(s) specified by the
+ PaUtil_Set*InputChannel functions.
+
+ @param bufferProcessor The buffer processor.
+
+ @param frameCount The number of host input frames. A 0 frameCount indicates to
+ use the framesPerHostBuffer value passed to PaUtil_InitializeBufferProcessor.
+
+ @see PaUtil_SetNoInput, PaUtil_SetInputChannel,
+ PaUtil_SetInterleavedInputChannels, PaUtil_SetNonInterleavedInputChannel
+*/
+void PaUtil_SetInputFrameCount( PaUtilBufferProcessor* bufferProcessor,
+ unsigned long frameCount );
+
+
+/** Indicate that no input is avalable. This function should be used when
+ priming the output of a full-duplex stream opened with the
+ paPrimeOutputBuffersUsingStreamCallback flag. Note that it is not necessary
+ to call this or any othe PaUtil_Set*Input* functions for ouput-only streams.
+
+ @param bufferProcessor The buffer processor.
+*/
+void PaUtil_SetNoInput( PaUtilBufferProcessor* bufferProcessor );
+
+
+/** Provide the buffer processor with a pointer to a host input channel.
+
+ @param bufferProcessor The buffer processor.
+ @param channel The channel number.
+ @param data The buffer.
+ @param stride The stride from one sample to the next, in samples. For
+ interleaved host buffers, the stride will usually be the same as the number of
+ channels in the buffer.
+*/
+void PaUtil_SetInputChannel( PaUtilBufferProcessor* bufferProcessor,
+ unsigned int channel, void *data, unsigned int stride );
+
+
+/** Provide the buffer processor with a pointer to an number of interleaved
+ host input channels.
+
+ @param bufferProcessor The buffer processor.
+ @param firstChannel The first channel number.
+ @param data The buffer.
+ @param channelCount The number of interleaved channels in the buffer. If
+ channelCount is zero, the number of channels specified to
+ PaUtil_InitializeBufferProcessor will be used.
+*/
+void PaUtil_SetInterleavedInputChannels( PaUtilBufferProcessor* bufferProcessor,
+ unsigned int firstChannel, void *data, unsigned int channelCount );
+
+
+/** Provide the buffer processor with a pointer to one non-interleaved host
+ output channel.
+
+ @param bufferProcessor The buffer processor.
+ @param channel The channel number.
+ @param data The buffer.
+*/
+void PaUtil_SetNonInterleavedInputChannel( PaUtilBufferProcessor* bufferProcessor,
+ unsigned int channel, void *data );
+
+
+/** Use for the second buffer half when the input buffer is split in two halves.
+ @see PaUtil_SetInputFrameCount
+*/
+void PaUtil_Set2ndInputFrameCount( PaUtilBufferProcessor* bufferProcessor,
+ unsigned long frameCount );
+
+/** Use for the second buffer half when the input buffer is split in two halves.
+ @see PaUtil_SetInputChannel
+*/
+void PaUtil_Set2ndInputChannel( PaUtilBufferProcessor* bufferProcessor,
+ unsigned int channel, void *data, unsigned int stride );
+
+/** Use for the second buffer half when the input buffer is split in two halves.
+ @see PaUtil_SetInterleavedInputChannels
+*/
+void PaUtil_Set2ndInterleavedInputChannels( PaUtilBufferProcessor* bufferProcessor,
+ unsigned int firstChannel, void *data, unsigned int channelCount );
+
+/** Use for the second buffer half when the input buffer is split in two halves.
+ @see PaUtil_SetNonInterleavedInputChannel
+*/
+void PaUtil_Set2ndNonInterleavedInputChannel( PaUtilBufferProcessor* bufferProcessor,
+ unsigned int channel, void *data );
+
+
+/** Set the number of frames in the output host buffer(s) specified by the
+ PaUtil_Set*OutputChannel functions.
+
+ @param bufferProcessor The buffer processor.
+
+ @param frameCount The number of host output frames. A 0 frameCount indicates to
+ use the framesPerHostBuffer value passed to PaUtil_InitializeBufferProcessor.
+
+ @see PaUtil_SetOutputChannel, PaUtil_SetInterleavedOutputChannels,
+ PaUtil_SetNonInterleavedOutputChannel
+*/
+void PaUtil_SetOutputFrameCount( PaUtilBufferProcessor* bufferProcessor,
+ unsigned long frameCount );
+
+
+/** Indicate that the output will be discarded. This function should be used
+ when implementing the paNeverDropInput mode for full duplex streams.
+
+ @param bufferProcessor The buffer processor.
+*/
+void PaUtil_SetNoOutput( PaUtilBufferProcessor* bufferProcessor );
+
+
+/** Provide the buffer processor with a pointer to a host output channel.
+
+ @param bufferProcessor The buffer processor.
+ @param channel The channel number.
+ @param data The buffer.
+ @param stride The stride from one sample to the next, in samples. For
+ interleaved host buffers, the stride will usually be the same as the number of
+ channels in the buffer.
+*/
+void PaUtil_SetOutputChannel( PaUtilBufferProcessor* bufferProcessor,
+ unsigned int channel, void *data, unsigned int stride );
+
+
+/** Provide the buffer processor with a pointer to an number of interleaved
+ host output channels.
+
+ @param bufferProcessor The buffer processor.
+ @param firstChannel The first channel number.
+ @param data The buffer.
+ @param channelCount The number of interleaved channels in the buffer. If
+ channelCount is zero, the number of channels specified to
+ PaUtil_InitializeBufferProcessor will be used.
+*/
+void PaUtil_SetInterleavedOutputChannels( PaUtilBufferProcessor* bufferProcessor,
+ unsigned int firstChannel, void *data, unsigned int channelCount );
+
+
+/** Provide the buffer processor with a pointer to one non-interleaved host
+ output channel.
+
+ @param bufferProcessor The buffer processor.
+ @param channel The channel number.
+ @param data The buffer.
+*/
+void PaUtil_SetNonInterleavedOutputChannel( PaUtilBufferProcessor* bufferProcessor,
+ unsigned int channel, void *data );
+
+
+/** Use for the second buffer half when the output buffer is split in two halves.
+ @see PaUtil_SetOutputFrameCount
+*/
+void PaUtil_Set2ndOutputFrameCount( PaUtilBufferProcessor* bufferProcessor,
+ unsigned long frameCount );
+
+/** Use for the second buffer half when the output buffer is split in two halves.
+ @see PaUtil_SetOutputChannel
+*/
+void PaUtil_Set2ndOutputChannel( PaUtilBufferProcessor* bufferProcessor,
+ unsigned int channel, void *data, unsigned int stride );
+
+/** Use for the second buffer half when the output buffer is split in two halves.
+ @see PaUtil_SetInterleavedOutputChannels
+*/
+void PaUtil_Set2ndInterleavedOutputChannels( PaUtilBufferProcessor* bufferProcessor,
+ unsigned int firstChannel, void *data, unsigned int channelCount );
+
+/** Use for the second buffer half when the output buffer is split in two halves.
+ @see PaUtil_SetNonInterleavedOutputChannel
+*/
+void PaUtil_Set2ndNonInterleavedOutputChannel( PaUtilBufferProcessor* bufferProcessor,
+ unsigned int channel, void *data );
+
+/*@}*/
+
+
+/** @name Buffer processing functions for callback streams
+*/
+/*@{*/
+
+/** Commence processing a host buffer (or a pair of host buffers in the
+ full-duplex case) for a callback stream.
+
+ @param bufferProcessor The buffer processor.
+
+ @param timeInfo Timing information for the first sample of the host
+ buffer(s). This information may be adjusted when buffer adaption is being
+ performed.
+
+ @param callbackStatusFlags Flags indicating whether underruns and overruns
+ have occurred since the last time the buffer processor was called.
+*/
+void PaUtil_BeginBufferProcessing( PaUtilBufferProcessor* bufferProcessor,
+ PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags callbackStatusFlags );
+
+
+/** Finish processing a host buffer (or a pair of host buffers in the
+ full-duplex case) for a callback stream.
+
+ @param bufferProcessor The buffer processor.
+
+ @param callbackResult On input, indicates a previous callback result, and on
+ exit, the result of the user stream callback, if it is called.
+ On entry callbackResult should contain one of { paContinue, paComplete, or
+ paAbort}. If paComplete is passed, the stream callback will not be called
+ but any audio that was generated by previous stream callbacks will be copied
+ to the output buffer(s). You can check whether the buffer processor's internal
+ buffer is empty by calling PaUtil_IsBufferProcessorOuputEmpty.
+
+ If the stream callback is called its result is stored in *callbackResult. If
+ the stream callback returns paComplete or paAbort, all output buffers will be
+ full of valid data - some of which may be zeros to acount for data that
+ wasn't generated by the terminating callback.
+
+ @return The number of frames processed. This usually corresponds to the
+ number of frames specified by the PaUtil_Set*FrameCount functions, exept in
+ the paUtilVariableHostBufferSizePartialUsageAllowed buffer size mode when a
+ smaller value may be returned.
+*/
+unsigned long PaUtil_EndBufferProcessing( PaUtilBufferProcessor* bufferProcessor,
+ int *callbackResult );
+
+
+/** Determine whether any callback generated output remains in the bufffer
+ processor's internal buffers. This method may be used to determine when to
+ continue calling PaUtil_EndBufferProcessing() after the callback has returned
+ a callbackResult of paComplete.
+
+ @param bufferProcessor The buffer processor.
+
+ @return Returns non-zero when callback generated output remains in the internal
+ buffer and zero (0) when there internal buffer contains no callback generated
+ data.
+*/
+int PaUtil_IsBufferProcessorOuputEmpty( PaUtilBufferProcessor* bufferProcessor );
+
+/*@}*/
+
+
+/** @name Buffer processing functions for blocking read/write streams
+*/
+/*@{*/
+
+/** Copy samples from host input channels set up by the PaUtil_Set*InputChannels
+ functions to a user supplied buffer. This function is intended for use with
+ blocking read/write streams. Copies the minimum of the number of
+ user frames (specified by the frameCount parameter) and the number of available
+ host frames (specified in a previous call to SetInputFrameCount()).
+
+ @param bufferProcessor The buffer processor.
+
+ @param buffer A pointer to the user buffer pointer, or a pointer to a pointer
+ to an array of user buffer pointers for a non-interleaved stream. It is
+ important that this parameter points to a copy of the user buffer pointers,
+ not to the actual user buffer pointers, because this function updates the
+ pointers before returning.
+
+ @param frameCount The number of frames of data in the buffer(s) pointed to by
+ the buffer parameter.
+
+ @return The number of frames copied. The buffer pointer(s) pointed to by the
+ buffer parameter are advanced to point to the frame(s) following the last one
+ filled.
+*/
+unsigned long PaUtil_CopyInput( PaUtilBufferProcessor* bufferProcessor,
+ void **buffer, unsigned long frameCount );
+
+
+/* Copy samples from a user supplied buffer to host output channels set up by
+ the PaUtil_Set*OutputChannels functions. This function is intended for use with
+ blocking read/write streams. Copies the minimum of the number of
+ user frames (specified by the frameCount parameter) and the number of
+ host frames (specified in a previous call to SetOutputFrameCount()).
+
+ @param bufferProcessor The buffer processor.
+
+ @param buffer A pointer to the user buffer pointer, or a pointer to a pointer
+ to an array of user buffer pointers for a non-interleaved stream. It is
+ important that this parameter points to a copy of the user buffer pointers,
+ not to the actual user buffer pointers, because this function updates the
+ pointers before returning.
+
+ @param frameCount The number of frames of data in the buffer(s) pointed to by
+ the buffer parameter.
+
+ @return The number of frames copied. The buffer pointer(s) pointed to by the
+ buffer parameter are advanced to point to the frame(s) following the last one
+ copied.
+*/
+unsigned long PaUtil_CopyOutput( PaUtilBufferProcessor* bufferProcessor,
+ const void ** buffer, unsigned long frameCount );
+
+
+/* Zero samples in host output channels set up by the PaUtil_Set*OutputChannels
+ functions. This function is useful for flushing streams.
+ Zeros the minimum of frameCount and the number of host frames specified in a
+ previous call to SetOutputFrameCount().
+
+ @param bufferProcessor The buffer processor.
+
+ @param frameCount The maximum number of frames to zero.
+
+ @return The number of frames zeroed.
+*/
+unsigned long PaUtil_ZeroOutput( PaUtilBufferProcessor* bufferProcessor,
+ unsigned long frameCount );
+
+
+/*@}*/
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* PA_PROCESS_H */
diff --git a/pd/portaudio/pa_common/pa_skeleton.c b/pd/portaudio/pa_common/pa_skeleton.c
new file mode 100644
index 00000000..ebc1f501
--- /dev/null
+++ b/pd/portaudio/pa_common/pa_skeleton.c
@@ -0,0 +1,807 @@
+/*
+ * $Id: pa_skeleton.c,v 1.1.2.39 2003/11/26 14:56:09 rossbencina Exp $
+ * Portable Audio I/O Library skeleton implementation
+ * demonstrates how to use the common functions to implement support
+ * for a host API
+ *
+ * Based on the Open Source API proposed by Ross Bencina
+ * Copyright (c) 1999-2002 Ross Bencina, Phil Burk
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/** @file
+ @brief Skeleton implementation of support for a host API.
+
+ @note This file is provided as a starting point for implementing support for
+ a new host API. IMPLEMENT ME comments are used to indicate functionality
+ which much be customised for each implementation.
+*/
+
+
+#include <string.h> /* strlen() */
+
+#include "pa_util.h"
+#include "pa_allocation.h"
+#include "pa_hostapi.h"
+#include "pa_stream.h"
+#include "pa_cpuload.h"
+#include "pa_process.h"
+
+
+/* prototypes for functions declared in this file */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+PaError PaSkeleton_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex index );
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+static void Terminate( struct PaUtilHostApiRepresentation *hostApi );
+static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
+ const PaStreamParameters *inputParameters,
+ const PaStreamParameters *outputParameters,
+ double sampleRate );
+static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
+ PaStream** s,
+ const PaStreamParameters *inputParameters,
+ const PaStreamParameters *outputParameters,
+ double sampleRate,
+ unsigned long framesPerBuffer,
+ PaStreamFlags streamFlags,
+ PaStreamCallback *streamCallback,
+ void *userData );
+static PaError CloseStream( PaStream* stream );
+static PaError StartStream( PaStream *stream );
+static PaError StopStream( PaStream *stream );
+static PaError AbortStream( PaStream *stream );
+static PaError IsStreamStopped( PaStream *s );
+static PaError IsStreamActive( PaStream *stream );
+static PaTime GetStreamTime( PaStream *stream );
+static double GetStreamCpuLoad( PaStream* stream );
+static PaError ReadStream( PaStream* stream, void *buffer, unsigned long frames );
+static PaError WriteStream( PaStream* stream, const void *buffer, unsigned long frames );
+static signed long GetStreamReadAvailable( PaStream* stream );
+static signed long GetStreamWriteAvailable( PaStream* stream );
+
+
+/* IMPLEMENT ME: a macro like the following one should be used for reporting
+ host errors */
+#define PA_SKELETON_SET_LAST_HOST_ERROR( errorCode, errorText ) \
+ PaUtil_SetLastHostErrorInfo( paInDevelopment, errorCode, errorText )
+
+/* PaSkeletonHostApiRepresentation - host api datastructure specific to this implementation */
+
+typedef struct
+{
+ PaUtilHostApiRepresentation inheritedHostApiRep;
+ PaUtilStreamInterface callbackStreamInterface;
+ PaUtilStreamInterface blockingStreamInterface;
+
+ PaUtilAllocationGroup *allocations;
+
+ /* implementation specific data goes here */
+}
+PaSkeletonHostApiRepresentation; /* IMPLEMENT ME: rename this */
+
+
+PaError PaSkeleton_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex )
+{
+ PaError result = paNoError;
+ int i, deviceCount;
+ PaSkeletonHostApiRepresentation *skeletonHostApi;
+ PaDeviceInfo *deviceInfoArray;
+
+ skeletonHostApi = (PaSkeletonHostApiRepresentation*)PaUtil_AllocateMemory( sizeof(PaSkeletonHostApiRepresentation) );
+ if( !skeletonHostApi )
+ {
+ result = paInsufficientMemory;
+ goto error;
+ }
+
+ skeletonHostApi->allocations = PaUtil_CreateAllocationGroup();
+ if( !skeletonHostApi->allocations )
+ {
+ result = paInsufficientMemory;
+ goto error;
+ }
+
+ *hostApi = &skeletonHostApi->inheritedHostApiRep;
+ (*hostApi)->info.structVersion = 1;
+ (*hostApi)->info.type = paInDevelopment; /* IMPLEMENT ME: change to correct type id */
+ (*hostApi)->info.name = "skeleton implementation"; /* IMPLEMENT ME: change to correct name */
+
+ (*hostApi)->info.defaultInputDevice = paNoDevice; /* IMPLEMENT ME */
+ (*hostApi)->info.defaultOutputDevice = paNoDevice; /* IMPLEMENT ME */
+
+ (*hostApi)->info.deviceCount = 0;
+
+ deviceCount = 0; /* IMPLEMENT ME */
+
+ if( deviceCount > 0 )
+ {
+ (*hostApi)->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory(
+ skeletonHostApi->allocations, sizeof(PaDeviceInfo*) * deviceCount );
+ if( !(*hostApi)->deviceInfos )
+ {
+ result = paInsufficientMemory;
+ goto error;
+ }
+
+ /* allocate all device info structs in a contiguous block */
+ deviceInfoArray = (PaDeviceInfo*)PaUtil_GroupAllocateMemory(
+ skeletonHostApi->allocations, sizeof(PaDeviceInfo) * deviceCount );
+ if( !deviceInfoArray )
+ {
+ result = paInsufficientMemory;
+ goto error;
+ }
+
+ for( i=0; i < deviceCount; ++i )
+ {
+ PaDeviceInfo *deviceInfo = &deviceInfoArray[i];
+ deviceInfo->structVersion = 2;
+ deviceInfo->hostApi = hostApiIndex;
+ deviceInfo->name = 0; /* IMPLEMENT ME: allocate block and copy name eg:
+ deviceName = (char*)PaUtil_GroupAllocateMemory( skeletonHostApi->allocations, strlen(srcName) + 1 );
+ if( !deviceName )
+ {
+ result = paInsufficientMemory;
+ goto error;
+ }
+ strcpy( deviceName, srcName );
+ deviceInfo->name = deviceName;
+ */
+
+ deviceInfo->maxInputChannels = 0; /* IMPLEMENT ME */
+ deviceInfo->maxOutputChannels = 0; /* IMPLEMENT ME */
+
+ deviceInfo->defaultLowInputLatency = 0.; /* IMPLEMENT ME */
+ deviceInfo->defaultLowOutputLatency = 0.; /* IMPLEMENT ME */
+ deviceInfo->defaultHighInputLatency = 0.; /* IMPLEMENT ME */
+ deviceInfo->defaultHighOutputLatency = 0.; /* IMPLEMENT ME */
+
+ deviceInfo->defaultSampleRate = 0.; /* IMPLEMENT ME */
+
+ (*hostApi)->deviceInfos[i] = deviceInfo;
+ ++(*hostApi)->info.deviceCount;
+ }
+ }
+
+ (*hostApi)->Terminate = Terminate;
+ (*hostApi)->OpenStream = OpenStream;
+ (*hostApi)->IsFormatSupported = IsFormatSupported;
+
+ PaUtil_InitializeStreamInterface( &skeletonHostApi->callbackStreamInterface, CloseStream, StartStream,
+ StopStream, AbortStream, IsStreamStopped, IsStreamActive,
+ GetStreamTime, GetStreamCpuLoad,
+ PaUtil_DummyRead, PaUtil_DummyWrite,
+ PaUtil_DummyGetReadAvailable, PaUtil_DummyGetWriteAvailable );
+
+ PaUtil_InitializeStreamInterface( &skeletonHostApi->blockingStreamInterface, CloseStream, StartStream,
+ StopStream, AbortStream, IsStreamStopped, IsStreamActive,
+ GetStreamTime, PaUtil_DummyGetCpuLoad,
+ ReadStream, WriteStream, GetStreamReadAvailable, GetStreamWriteAvailable );
+
+ return result;
+
+error:
+ if( skeletonHostApi )
+ {
+ if( skeletonHostApi->allocations )
+ {
+ PaUtil_FreeAllAllocations( skeletonHostApi->allocations );
+ PaUtil_DestroyAllocationGroup( skeletonHostApi->allocations );
+ }
+
+ PaUtil_FreeMemory( skeletonHostApi );
+ }
+ return result;
+}
+
+
+static void Terminate( struct PaUtilHostApiRepresentation *hostApi )
+{
+ PaSkeletonHostApiRepresentation *skeletonHostApi = (PaSkeletonHostApiRepresentation*)hostApi;
+
+ /*
+ IMPLEMENT ME:
+ - clean up any resources not handled by the allocation group
+ */
+
+ if( skeletonHostApi->allocations )
+ {
+ PaUtil_FreeAllAllocations( skeletonHostApi->allocations );
+ PaUtil_DestroyAllocationGroup( skeletonHostApi->allocations );
+ }
+
+ PaUtil_FreeMemory( skeletonHostApi );
+}
+
+
+static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
+ const PaStreamParameters *inputParameters,
+ const PaStreamParameters *outputParameters,
+ double sampleRate )
+{
+ int inputChannelCount, outputChannelCount;
+ PaSampleFormat inputSampleFormat, outputSampleFormat;
+
+ if( inputParameters )
+ {
+ inputChannelCount = inputParameters->channelCount;
+ inputSampleFormat = inputParameters->sampleFormat;
+
+ /* all standard sample formats are supported by the buffer adapter,
+ this implementation doesn't support any custom sample formats */
+ if( inputSampleFormat & paCustomFormat )
+ return paSampleFormatNotSupported;
+
+ /* unless alternate device specification is supported, reject the use of
+ paUseHostApiSpecificDeviceSpecification */
+
+ if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
+ return paInvalidDevice;
+
+ /* check that input device can support inputChannelCount */
+ if( inputChannelCount > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels )
+ return paInvalidChannelCount;
+
+ /* validate inputStreamInfo */
+ if( inputParameters->hostApiSpecificStreamInfo )
+ return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
+ }
+ else
+ {
+ inputChannelCount = 0;
+ }
+
+ if( outputParameters )
+ {
+ outputChannelCount = outputParameters->channelCount;
+ outputSampleFormat = outputParameters->sampleFormat;
+
+ /* all standard sample formats are supported by the buffer adapter,
+ this implementation doesn't support any custom sample formats */
+ if( outputSampleFormat & paCustomFormat )
+ return paSampleFormatNotSupported;
+
+ /* unless alternate device specification is supported, reject the use of
+ paUseHostApiSpecificDeviceSpecification */
+
+ if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )
+ return paInvalidDevice;
+
+ /* check that output device can support outputChannelCount */
+ if( outputChannelCount > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels )
+ return paInvalidChannelCount;
+
+ /* validate outputStreamInfo */
+ if( outputParameters->hostApiSpecificStreamInfo )
+ return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
+ }
+ else
+ {
+ outputChannelCount = 0;
+ }
+
+ /*
+ IMPLEMENT ME:
+
+ - if a full duplex stream is requested, check that the combination
+ of input and output parameters is supported if necessary
+
+ - check that the device supports sampleRate
+
+ Because the buffer adapter handles conversion between all standard
+ sample formats, the following checks are only required if paCustomFormat
+ is implemented, or under some other unusual conditions.
+
+ - check that input device can support inputSampleFormat, or that
+ we have the capability to convert from inputSampleFormat to
+ a native format
+
+ - check that output device can support outputSampleFormat, or that
+ we have the capability to convert from outputSampleFormat to
+ a native format
+ */
+
+
+ /* suppress unused variable warnings */
+ (void) sampleRate;
+
+ return paFormatIsSupported;
+}
+
+/* PaSkeletonStream - a stream data structure specifically for this implementation */
+
+typedef struct PaSkeletonStream
+{ /* IMPLEMENT ME: rename this */
+ PaUtilStreamRepresentation streamRepresentation;
+ PaUtilCpuLoadMeasurer cpuLoadMeasurer;
+ PaUtilBufferProcessor bufferProcessor;
+
+ /* IMPLEMENT ME:
+ - implementation specific data goes here
+ */
+ unsigned long framesPerHostCallback; /* just an example */
+}
+PaSkeletonStream;
+
+/* see pa_hostapi.h for a list of validity guarantees made about OpenStream parameters */
+
+static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi,
+ PaStream** s,
+ const PaStreamParameters *inputParameters,
+ const PaStreamParameters *outputParameters,
+ double sampleRate,
+ unsigned long framesPerBuffer,
+ PaStreamFlags streamFlags,
+ PaStreamCallback *streamCallback,
+ void *userData )
+{
+ PaError result = paNoError;
+ PaSkeletonHostApiRepresentation *skeletonHostApi = (PaSkeletonHostApiRepresentation*)hostApi;
+ PaSkeletonStream *stream = 0;
+ unsigned long framesPerHostBuffer = framesPerBuffer; /* these may not be equivalent for all implementations */
+ int inputChannelCount, outputChannelCount;
+ PaSampleFormat inputSampleFormat, outputSampleFormat;
+ PaSampleFormat hostInputSampleFormat, hostOutputSampleFormat;
+
+
+ if( inputParameters )
+ {
+ inputChannelCount = inputParameters->channelCount;
+ inputSampleFormat = inputParameters->sampleFormat;
+
+ /* unless alternate device specification is supported, reject the use of
+ paUseHostApiSpecificDeviceSpecification */
+
+ if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
+ return paInvalidDevice;
+
+ /* check that input device can support inputChannelCount */
+ if( inputChannelCount > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels )
+ return paInvalidChannelCount;
+
+ /* validate inputStreamInfo */
+ if( inputParameters->hostApiSpecificStreamInfo )
+ return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
+
+ /* IMPLEMENT ME - establish which host formats are available */
+ hostInputSampleFormat =
+ PaUtil_SelectClosestAvailableFormat( paInt16 /* native formats */, inputSampleFormat );
+ }
+ else
+ {
+ inputChannelCount = 0;
+ inputSampleFormat = hostInputSampleFormat = paInt16; /* Surpress 'uninitialised var' warnings. */
+ }
+
+ if( outputParameters )
+ {
+ outputChannelCount = outputParameters->channelCount;
+ outputSampleFormat = outputParameters->sampleFormat;
+
+ /* unless alternate device specification is supported, reject the use of
+ paUseHostApiSpecificDeviceSpecification */
+
+ if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )
+ return paInvalidDevice;
+
+ /* check that output device can support inputChannelCount */
+ if( outputChannelCount > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels )
+ return paInvalidChannelCount;
+
+ /* validate outputStreamInfo */
+ if( outputParameters->hostApiSpecificStreamInfo )
+ return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */
+
+ /* IMPLEMENT ME - establish which host formats are available */
+ hostOutputSampleFormat =
+ PaUtil_SelectClosestAvailableFormat( paInt16 /* native formats */, outputSampleFormat );
+ }
+ else
+ {
+ outputChannelCount = 0;
+ outputSampleFormat = hostOutputSampleFormat = paInt16; /* Surpress 'uninitialized var' warnings. */
+ }
+
+ /*
+ IMPLEMENT ME:
+
+ ( the following two checks are taken care of by PaUtil_InitializeBufferProcessor() FIXME - checks needed? )
+
+ - check that input device can support inputSampleFormat, or that
+ we have the capability to convert from outputSampleFormat to
+ a native format
+
+ - check that output device can support outputSampleFormat, or that
+ we have the capability to convert from outputSampleFormat to
+ a native format
+
+ - if a full duplex stream is requested, check that the combination
+ of input and output parameters is supported
+
+ - check that the device supports sampleRate
+
+ - alter sampleRate to a close allowable rate if possible / necessary
+
+ - validate suggestedInputLatency and suggestedOutputLatency parameters,
+ use default values where necessary
+ */
+
+
+
+
+ /* validate platform specific flags */
+ if( (streamFlags & paPlatformSpecificFlags) != 0 )
+ return paInvalidFlag; /* unexpected platform specific flag */
+
+
+ stream = (PaSkeletonStream*)PaUtil_AllocateMemory( sizeof(PaSkeletonStream) );
+ if( !stream )
+ {
+ result = paInsufficientMemory;
+ goto error;
+ }
+
+ if( streamCallback )
+ {
+ PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
+ &skeletonHostApi->callbackStreamInterface, streamCallback, userData );
+ }
+ else
+ {
+ PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,
+ &skeletonHostApi->blockingStreamInterface, streamCallback, userData );
+ }
+
+ PaUtil_InitializeCpuLoadMeasurer( &stream->cpuLoadMeasurer, sampleRate );
+
+
+ /* we assume a fixed host buffer size in this example, but the buffer processor
+ can also support bounded and unknown host buffer sizes by passing
+ paUtilBoundedHostBufferSize or paUtilUnknownHostBufferSize instead of
+ paUtilFixedHostBufferSize below. */
+
+ result = PaUtil_InitializeBufferProcessor( &stream->bufferProcessor,
+ inputChannelCount, inputSampleFormat, hostInputSampleFormat,
+ outputChannelCount, outputSampleFormat, hostOutputSampleFormat,
+ sampleRate, streamFlags, framesPerBuffer,
+ framesPerHostBuffer, paUtilFixedHostBufferSize,
+ streamCallback, userData );
+ if( result != paNoError )
+ goto error;
+
+
+ /*
+ IMPLEMENT ME: initialise the following fields with estimated or actual
+ values.
+ */
+ stream->streamRepresentation.streamInfo.inputLatency =
+ PaUtil_GetBufferProcessorInputLatency(&stream->bufferProcessor);
+ stream->streamRepresentation.streamInfo.outputLatency =
+ PaUtil_GetBufferProcessorOutputLatency(&stream->bufferProcessor);
+ stream->streamRepresentation.streamInfo.sampleRate = sampleRate;
+
+
+ /*
+ IMPLEMENT ME:
+ - additional stream setup + opening
+ */
+
+ stream->framesPerHostCallback = framesPerHostBuffer;
+
+ *s = (PaStream*)stream;
+
+ return result;
+
+error:
+ if( stream )
+ PaUtil_FreeMemory( stream );
+
+ return result;
+}
+
+/*
+ ExampleHostProcessingLoop() illustrates the kind of processing which may
+ occur in a host implementation.
+
+*/
+static void ExampleHostProcessingLoop( void *inputBuffer, void *outputBuffer, void *userData )
+{
+ PaSkeletonStream *stream = (PaSkeletonStream*)userData;
+ PaStreamCallbackTimeInfo timeInfo = {0,0,0}; /* IMPLEMENT ME */
+ int callbackResult;
+ unsigned long framesProcessed;
+
+ PaUtil_BeginCpuLoadMeasurement( &stream->cpuLoadMeasurer );
+
+ /*
+ IMPLEMENT ME:
+ - generate timing information
+ - handle buffer slips
+ */
+
+ /*
+ If you need to byte swap or shift inputBuffer to convert it into a
+ portaudio format, do it here.
+ */
+
+
+
+ PaUtil_BeginBufferProcessing( &stream->bufferProcessor, &timeInfo, 0 /* IMPLEMENT ME: pass underflow/overflow flags when necessary */ );
+
+ /*
+ depending on whether the host buffers are interleaved, non-interleaved
+ or a mixture, you will want to call PaUtil_SetInterleaved*Channels(),
+ PaUtil_SetNonInterleaved*Channel() or PaUtil_Set*Channel() here.
+ */
+
+ PaUtil_SetInputFrameCount( &stream->bufferProcessor, 0 /* default to host buffer size */ );
+ PaUtil_SetInterleavedInputChannels( &stream->bufferProcessor,
+ 0, /* first channel of inputBuffer is channel 0 */
+ inputBuffer,
+ 0 ); /* 0 - use inputChannelCount passed to init buffer processor */
+
+ PaUtil_SetOutputFrameCount( &stream->bufferProcessor, 0 /* default to host buffer size */ );
+ PaUtil_SetInterleavedOutputChannels( &stream->bufferProcessor,
+ 0, /* first channel of outputBuffer is channel 0 */
+ outputBuffer,
+ 0 ); /* 0 - use outputChannelCount passed to init buffer processor */
+
+ /* you must pass a valid value of callback result to PaUtil_EndBufferProcessing()
+ in general you would pass paContinue for normal operation, and
+ paComplete to drain the buffer processor's internal output buffer.
+ You can check whether the buffer processor's output buffer is empty
+ using PaUtil_IsBufferProcessorOuputEmpty( bufferProcessor )
+ */
+ callbackResult = paContinue;
+ framesProcessed = PaUtil_EndBufferProcessing( &stream->bufferProcessor, &callbackResult );
+
+
+ /*
+ If you need to byte swap or shift outputBuffer to convert it to
+ host format, do it here.
+ */
+
+ PaUtil_EndCpuLoadMeasurement( &stream->cpuLoadMeasurer, framesProcessed );
+
+
+ if( callbackResult == paContinue )
+ {
+ /* nothing special to do */
+ }
+ else if( callbackResult == paAbort )
+ {
+ /* IMPLEMENT ME - finish playback immediately */
+
+ /* once finished, call the finished callback */
+ if( stream->streamRepresentation.streamFinishedCallback != 0 )
+ stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData );
+ }
+ else
+ {
+ /* User callback has asked us to stop with paComplete or other non-zero value */
+
+ /* IMPLEMENT ME - finish playback once currently queued audio has completed */
+
+ /* once finished, call the finished callback */
+ if( stream->streamRepresentation.streamFinishedCallback != 0 )
+ stream->streamRepresentation.streamFinishedCallback( stream->streamRepresentation.userData );
+ }
+}
+
+
+/*
+ When CloseStream() is called, the multi-api layer ensures that
+ the stream has already been stopped or aborted.
+*/
+static PaError CloseStream( PaStream* s )
+{
+ PaError result = paNoError;
+ PaSkeletonStream *stream = (PaSkeletonStream*)s;
+
+ /*
+ IMPLEMENT ME:
+ - additional stream closing + cleanup
+ */
+
+ PaUtil_TerminateBufferProcessor( &stream->bufferProcessor );
+ PaUtil_TerminateStreamRepresentation( &stream->streamRepresentation );
+ PaUtil_FreeMemory( stream );
+
+ return result;
+}
+
+
+static PaError StartStream( PaStream *s )
+{
+ PaError result = paNoError;
+ PaSkeletonStream *stream = (PaSkeletonStream*)s;
+
+ PaUtil_ResetBufferProcessor( &stream->bufferProcessor );
+
+ /* IMPLEMENT ME, see portaudio.h for required behavior */
+
+ /* suppress unused function warning. the code in ExampleHostProcessingLoop or
+ something similar should be implemented to feed samples to and from the
+ host after StartStream() is called.
+ */
+ (void) ExampleHostProcessingLoop;
+
+ return result;
+}
+
+
+static PaError StopStream( PaStream *s )
+{
+ PaError result = paNoError;
+ PaSkeletonStream *stream = (PaSkeletonStream*)s;
+
+ /* suppress unused variable warnings */
+ (void) stream;
+
+ /* IMPLEMENT ME, see portaudio.h for required behavior */
+
+ return result;
+}
+
+
+static PaError AbortStream( PaStream *s )
+{
+ PaError result = paNoError;
+ PaSkeletonStream *stream = (PaSkeletonStream*)s;
+
+ /* suppress unused variable warnings */
+ (void) stream;
+
+ /* IMPLEMENT ME, see portaudio.h for required behavior */
+
+ return result;
+}
+
+
+static PaError IsStreamStopped( PaStream *s )
+{
+ PaSkeletonStream *stream = (PaSkeletonStream*)s;
+
+ /* suppress unused variable warnings */
+ (void) stream;
+
+ /* IMPLEMENT ME, see portaudio.h for required behavior */
+
+ return 0;
+}
+
+
+static PaError IsStreamActive( PaStream *s )
+{
+ PaSkeletonStream *stream = (PaSkeletonStream*)s;
+
+ /* suppress unused variable warnings */
+ (void) stream;
+
+ /* IMPLEMENT ME, see portaudio.h for required behavior */
+
+ return 0;
+}
+
+
+static PaTime GetStreamTime( PaStream *s )
+{
+ PaSkeletonStream *stream = (PaSkeletonStream*)s;
+
+ /* suppress unused variable warnings */
+ (void) stream;
+
+ /* IMPLEMENT ME, see portaudio.h for required behavior*/
+
+ return 0;
+}
+
+
+static double GetStreamCpuLoad( PaStream* s )
+{
+ PaSkeletonStream *stream = (PaSkeletonStream*)s;
+
+ return PaUtil_GetCpuLoad( &stream->cpuLoadMeasurer );
+}
+
+
+/*
+ As separate stream interfaces are used for blocking and callback
+ streams, the following functions can be guaranteed to only be called
+ for blocking streams.
+*/
+
+static PaError ReadStream( PaStream* s,
+ void *buffer,
+ unsigned long frames )
+{
+ PaSkeletonStream *stream = (PaSkeletonStream*)s;
+
+ /* suppress unused variable warnings */
+ (void) buffer;
+ (void) frames;
+ (void) stream;
+
+ /* IMPLEMENT ME, see portaudio.h for required behavior*/
+
+ return paNoError;
+}
+
+
+static PaError WriteStream( PaStream* s,
+ const void *buffer,
+ unsigned long frames )
+{
+ PaSkeletonStream *stream = (PaSkeletonStream*)s;
+
+ /* suppress unused variable warnings */
+ (void) buffer;
+ (void) frames;
+ (void) stream;
+
+ /* IMPLEMENT ME, see portaudio.h for required behavior*/
+
+ return paNoError;
+}
+
+
+static signed long GetStreamReadAvailable( PaStream* s )
+{
+ PaSkeletonStream *stream = (PaSkeletonStream*)s;
+
+ /* suppress unused variable warnings */
+ (void) stream;
+
+ /* IMPLEMENT ME, see portaudio.h for required behavior*/
+
+ return 0;
+}
+
+
+static signed long GetStreamWriteAvailable( PaStream* s )
+{
+ PaSkeletonStream *stream = (PaSkeletonStream*)s;
+
+ /* suppress unused variable warnings */
+ (void) stream;
+
+ /* IMPLEMENT ME, see portaudio.h for required behavior*/
+
+ return 0;
+}
+
+
+
+
diff --git a/pd/portaudio/pa_common/pa_stream.c b/pd/portaudio/pa_common/pa_stream.c
new file mode 100644
index 00000000..044dde29
--- /dev/null
+++ b/pd/portaudio/pa_common/pa_stream.c
@@ -0,0 +1,141 @@
+/*
+ * $Id: pa_stream.c,v 1.1.2.12 2003/09/20 21:31:00 rossbencina Exp $
+ * Portable Audio I/O Library
+ *
+ *
+ * Based on the Open Source API proposed by Ross Bencina
+ * Copyright (c) 2002 Ross Bencina
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/** @file
+ @brief Interface used by pa_front to virtualize functions which operate on
+ streams.
+*/
+
+
+#include "pa_stream.h"
+
+
+void PaUtil_InitializeStreamInterface( PaUtilStreamInterface *streamInterface,
+ PaError (*Close)( PaStream* ),
+ PaError (*Start)( PaStream* ),
+ PaError (*Stop)( PaStream* ),
+ PaError (*Abort)( PaStream* ),
+ PaError (*IsStopped)( PaStream* ),
+ PaError (*IsActive)( PaStream* ),
+ PaTime (*GetTime)( PaStream* ),
+ double (*GetCpuLoad)( PaStream* ),
+ PaError (*Read)( PaStream*, void *, unsigned long ),
+ PaError (*Write)( PaStream*, const void *, unsigned long ),
+ signed long (*GetReadAvailable)( PaStream* ),
+ signed long (*GetWriteAvailable)( PaStream* ) )
+{
+ streamInterface->Close = Close;
+ streamInterface->Start = Start;
+ streamInterface->Stop = Stop;
+ streamInterface->Abort = Abort;
+ streamInterface->IsStopped = IsStopped;
+ streamInterface->IsActive = IsActive;
+ streamInterface->GetTime = GetTime;
+ streamInterface->GetCpuLoad = GetCpuLoad;
+ streamInterface->Read = Read;
+ streamInterface->Write = Write;
+ streamInterface->GetReadAvailable = GetReadAvailable;
+ streamInterface->GetWriteAvailable = GetWriteAvailable;
+}
+
+
+void PaUtil_InitializeStreamRepresentation( PaUtilStreamRepresentation *streamRepresentation,
+ PaUtilStreamInterface *streamInterface,
+ PaStreamCallback *streamCallback,
+ void *userData )
+{
+ streamRepresentation->magic = PA_STREAM_MAGIC;
+ streamRepresentation->nextOpenStream = 0;
+ streamRepresentation->streamInterface = streamInterface;
+ streamRepresentation->streamCallback = streamCallback;
+ streamRepresentation->streamFinishedCallback = 0;
+
+ streamRepresentation->userData = userData;
+
+ streamRepresentation->streamInfo.inputLatency = 0.;
+ streamRepresentation->streamInfo.outputLatency = 0.;
+ streamRepresentation->streamInfo.sampleRate = 0.;
+}
+
+
+void PaUtil_TerminateStreamRepresentation( PaUtilStreamRepresentation *streamRepresentation )
+{
+ streamRepresentation->magic = 0;
+}
+
+
+PaError PaUtil_DummyRead( PaStream* stream,
+ void *buffer,
+ unsigned long frames )
+{
+ (void)stream; /* unused parameter */
+ (void)buffer; /* unused parameter */
+ (void)frames; /* unused parameter */
+
+ return paCanNotReadFromACallbackStream;
+}
+
+
+PaError PaUtil_DummyWrite( PaStream* stream,
+ const void *buffer,
+ unsigned long frames )
+{
+ (void)stream; /* unused parameter */
+ (void)buffer; /* unused parameter */
+ (void)frames; /* unused parameter */
+
+ return paCanNotWriteToACallbackStream;
+}
+
+
+signed long PaUtil_DummyGetReadAvailable( PaStream* stream )
+{
+ (void)stream; /* unused parameter */
+
+ return paCanNotReadFromACallbackStream;
+}
+
+
+signed long PaUtil_DummyGetWriteAvailable( PaStream* stream )
+{
+ (void)stream; /* unused parameter */
+
+ return paCanNotWriteToACallbackStream;
+}
+
+
+double PaUtil_DummyGetCpuLoad( PaStream* stream )
+{
+ (void)stream; /* unused parameter */
+
+ return 0.0;
+}
diff --git a/pd/portaudio/pa_common/pa_stream.h b/pd/portaudio/pa_common/pa_stream.h
new file mode 100644
index 00000000..8b86943b
--- /dev/null
+++ b/pd/portaudio/pa_common/pa_stream.h
@@ -0,0 +1,196 @@
+#ifndef PA_STREAM_H
+#define PA_STREAM_H
+/*
+ * $Id: pa_stream.h,v 1.1.2.13 2003/11/01 06:37:28 rossbencina Exp $
+ * Portable Audio I/O Library
+ * stream interface
+ *
+ * Based on the Open Source API proposed by Ross Bencina
+ * Copyright (c) 1999-2002 Ross Bencina, Phil Burk
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/** @file
+ @brief Interface used by pa_front to virtualize functions which operate on
+ streams.
+*/
+
+
+#include "portaudio.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+
+#define PA_STREAM_MAGIC (0x18273645)
+
+
+/** A structure representing an (abstract) interface to a host API. Contains
+ pointers to functions which implement the interface.
+
+ All PaStreamInterface functions are guaranteed to be called with a non-null,
+ valid stream parameter.
+*/
+typedef struct {
+ PaError (*Close)( PaStream* stream );
+ PaError (*Start)( PaStream *stream );
+ PaError (*Stop)( PaStream *stream );
+ PaError (*Abort)( PaStream *stream );
+ PaError (*IsStopped)( PaStream *stream );
+ PaError (*IsActive)( PaStream *stream );
+ PaTime (*GetTime)( PaStream *stream );
+ double (*GetCpuLoad)( PaStream* stream );
+ PaError (*Read)( PaStream* stream, void *buffer, unsigned long frames );
+ PaError (*Write)( PaStream* stream, const void *buffer, unsigned long frames );
+ signed long (*GetReadAvailable)( PaStream* stream );
+ signed long (*GetWriteAvailable)( PaStream* stream );
+} PaUtilStreamInterface;
+
+
+/** Initialize the fields of a PaUtilStreamInterface structure.
+*/
+void PaUtil_InitializeStreamInterface( PaUtilStreamInterface *streamInterface,
+ PaError (*Close)( PaStream* ),
+ PaError (*Start)( PaStream* ),
+ PaError (*Stop)( PaStream* ),
+ PaError (*Abort)( PaStream* ),
+ PaError (*IsStopped)( PaStream* ),
+ PaError (*IsActive)( PaStream* ),
+ PaTime (*GetTime)( PaStream* ),
+ double (*GetCpuLoad)( PaStream* ),
+ PaError (*Read)( PaStream* stream, void *buffer, unsigned long frames ),
+ PaError (*Write)( PaStream* stream, const void *buffer, unsigned long frames ),
+ signed long (*GetReadAvailable)( PaStream* stream ),
+ signed long (*GetWriteAvailable)( PaStream* stream ) );
+
+
+/** Dummy Read function for use in interfaces to a callback based streams.
+ Pass to the Read parameter of PaUtil_InitializeStreamInterface.
+ @return An error code indicating that the function has no effect
+ because the stream is a callback stream.
+*/
+PaError PaUtil_DummyRead( PaStream* stream,
+ void *buffer,
+ unsigned long frames );
+
+
+/** Dummy Write function for use in an interfaces to callback based streams.
+ Pass to the Write parameter of PaUtil_InitializeStreamInterface.
+ @return An error code indicating that the function has no effect
+ because the stream is a callback stream.
+*/
+PaError PaUtil_DummyWrite( PaStream* stream,
+ const void *buffer,
+ unsigned long frames );
+
+
+/** Dummy GetReadAvailable function for use in interfaces to callback based
+ streams. Pass to the GetReadAvailable parameter of PaUtil_InitializeStreamInterface.
+ @return An error code indicating that the function has no effect
+ because the stream is a callback stream.
+*/
+signed long PaUtil_DummyGetReadAvailable( PaStream* stream );
+
+
+/** Dummy GetWriteAvailable function for use in interfaces to callback based
+ streams. Pass to the GetWriteAvailable parameter of PaUtil_InitializeStreamInterface.
+ @return An error code indicating that the function has no effect
+ because the stream is a callback stream.
+*/
+signed long PaUtil_DummyGetWriteAvailable( PaStream* stream );
+
+
+
+/** Dummy GetCpuLoad function for use in an interface to a read/write stream.
+ Pass to the GetCpuLoad parameter of PaUtil_InitializeStreamInterface.
+ @return Returns 0.
+*/
+double PaUtil_DummyGetCpuLoad( PaStream* stream );
+
+
+/** Non host specific data for a stream. This data is used by pa_front to
+ forward to the appropriate functions in the streamInterface structure.
+*/
+typedef struct PaUtilStreamRepresentation {
+ unsigned long magic; /**< set to PA_STREAM_MAGIC */
+ struct PaUtilStreamRepresentation *nextOpenStream; /**< field used by multi-api code */
+ PaUtilStreamInterface *streamInterface;
+ PaStreamCallback *streamCallback;
+ PaStreamFinishedCallback *streamFinishedCallback;
+ void *userData;
+ PaStreamInfo streamInfo;
+} PaUtilStreamRepresentation;
+
+
+/** Initialize a PaUtilStreamRepresentation structure.
+
+ @see PaUtil_InitializeStreamRepresentation
+*/
+void PaUtil_InitializeStreamRepresentation(
+ PaUtilStreamRepresentation *streamRepresentation,
+ PaUtilStreamInterface *streamInterface,
+ PaStreamCallback *streamCallback,
+ void *userData );
+
+
+/** Clean up a PaUtilStreamRepresentation structure previously initialized
+ by a call to PaUtil_InitializeStreamRepresentation.
+
+ @see PaUtil_InitializeStreamRepresentation
+*/
+void PaUtil_TerminateStreamRepresentation( PaUtilStreamRepresentation *streamRepresentation );
+
+
+/** Check that the stream pointer is valid.
+
+ @return Returns paNoError if the stream pointer appears to be OK, otherwise
+ returns an error indicating the cause of failure.
+*/
+PaError PaUtil_ValidateStreamPointer( PaStream *stream );
+
+
+/** Cast an opaque stream pointer into a pointer to a PaUtilStreamRepresentation.
+
+ @see PaUtilStreamRepresentation
+*/
+#define PA_STREAM_REP( stream )\
+ ((PaUtilStreamRepresentation*) (stream) )
+
+
+/** Cast an opaque stream pointer into a pointer to a PaUtilStreamInterface.
+
+ @see PaUtilStreamRepresentation, PaUtilStreamInterface
+*/
+#define PA_STREAM_INTERFACE( stream )\
+ PA_STREAM_REP( (stream) )->streamInterface
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* PA_STREAM_H */
diff --git a/pd/portaudio/pa_common/pa_trace.c b/pd/portaudio/pa_common/pa_trace.c
new file mode 100644
index 00000000..83514a05
--- /dev/null
+++ b/pd/portaudio/pa_common/pa_trace.c
@@ -0,0 +1,88 @@
+/*
+ * $Id: pa_trace.c,v 1.1.1.1.2.3 2003/09/20 21:09:15 rossbencina Exp $
+ * Portable Audio I/O Library Trace Facility
+ * Store trace information in real-time for later printing.
+ *
+ * Based on the Open Source API proposed by Ross Bencina
+ * Copyright (c) 1999-2000 Phil Burk
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/** @file
+ @brief Event trace mechanism for debugging.
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "pa_trace.h"
+
+#if PA_TRACE_REALTIME_EVENTS
+
+static char *traceTextArray[MAX_TRACE_RECORDS];
+static int traceIntArray[MAX_TRACE_RECORDS];
+static int traceIndex = 0;
+static int traceBlock = 0;
+
+/*********************************************************************/
+void PaUtil_ResetTraceMessages()
+{
+ traceIndex = 0;
+}
+
+/*********************************************************************/
+void PaUtil_DumpTraceMessages()
+{
+ int i;
+ int messageCount = (traceIndex < PA_MAX_TRACE_RECORDS) ? traceIndex : PA_MAX_TRACE_RECORDS;
+
+ printf("DumpTraceMessages: traceIndex = %d\n", traceIndex );
+ for( i=0; i<messageCount; i++ )
+ {
+ printf("%3d: %s = 0x%08X\n",
+ i, traceTextArray[i], traceIntArray[i] );
+ }
+ ResetTraceMessages();
+ fflush(stdout);
+}
+
+/*********************************************************************/
+void PaUtil_AddTraceMessage( const char *msg, int data )
+{
+ if( (traceIndex == PA_MAX_TRACE_RECORDS) && (traceBlock == 0) )
+ {
+ traceBlock = 1;
+ /* PaUtil_DumpTraceMessages(); */
+ }
+ else if( traceIndex < PA_MAX_TRACE_RECORDS )
+ {
+ traceTextArray[traceIndex] = msg;
+ traceIntArray[traceIndex] = data;
+ traceIndex++;
+ }
+}
+
+#endif /* TRACE_REALTIME_EVENTS */
diff --git a/pd/portaudio/pa_common/pa_trace.h b/pd/portaudio/pa_common/pa_trace.h
new file mode 100644
index 00000000..f72a78b3
--- /dev/null
+++ b/pd/portaudio/pa_common/pa_trace.h
@@ -0,0 +1,70 @@
+#ifndef PA_TRACE_H
+#define PA_TRACE_H
+/*
+ * $Id: pa_trace.h,v 1.1.1.1.2.3 2003/09/20 21:09:15 rossbencina Exp $
+ * Portable Audio I/O Library Trace Facility
+ * Store trace information in real-time for later printing.
+ *
+ * Based on the Open Source API proposed by Ross Bencina
+ * Copyright (c) 1999-2000 Phil Burk
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/** @file
+ @brief Event trace mechanism for debugging.
+
+ Allows data to be written to the buffer at interrupt time and dumped later.
+*/
+
+
+#define PA_TRACE_REALTIME_EVENTS (0) /* Keep log of various real-time events. */
+#define PA_MAX_TRACE_RECORDS (2048)
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+
+#if PA_TRACE_REALTIME_EVENTS
+
+void PaUtil_ResetTraceMessages();
+void PaUtil_AddTraceMessage( const char *msg, int data );
+void PaUtil_DumpTraceMessages();
+
+#else
+
+#define PaUtil_ResetTraceMessages() /* noop */
+#define PaUtil_AddTraceMessage(msg,data) /* noop */
+#define PaUtil_DumpTraceMessages() /* noop */
+
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* PA_TRACE_H */
diff --git a/pd/portaudio/pa_common/pa_util.h b/pd/portaudio/pa_common/pa_util.h
new file mode 100644
index 00000000..149fbca3
--- /dev/null
+++ b/pd/portaudio/pa_common/pa_util.h
@@ -0,0 +1,167 @@
+#ifndef PA_UTIL_H
+#define PA_UTIL_H
+/*
+ * $Id: pa_util.h,v 1.1.2.12 2003/09/20 21:09:55 rossbencina Exp $
+ * Portable Audio I/O Library implementation utilities header
+ * common implementation utilities and interfaces
+ *
+ * Based on the Open Source API proposed by Ross Bencina
+ * Copyright (c) 1999-2002 Ross Bencina, Phil Burk
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/** @file
+ @brief Prototypes for utility functions used by PortAudio implementations.
+
+ @todo Document and adhere to the alignment guarantees provided by
+ PaUtil_AllocateMemory().
+*/
+
+
+#include "portaudio.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+
+struct PaUtilHostApiRepresentation;
+
+
+/** Retrieve a specific host API representation. This function can be used
+ by implementations to retrieve a pointer to their representation in
+ host api specific extension functions which aren't passed a rep pointer
+ by pa_front.c.
+
+ @param hostApi A pointer to a host API represenation pointer. Apon success
+ this will receive the requested representation pointer.
+
+ @param type A valid host API type identifier.
+
+ @returns An error code. If the result is PaNoError then a pointer to the
+ requested host API representation will be stored in *hostApi. If the host API
+ specified by type is not found, this function returns paHostApiNotFound.
+*/
+PaError PaUtil_GetHostApiRepresentation( struct PaUtilHostApiRepresentation **hostApi,
+ PaHostApiTypeId type );
+
+
+/** Convert a PortAudio device index into a host API specific device index.
+ @param hostApiDevice Pointer to a device index, on success this will recieve the
+ converted device index value.
+ @param device The PortAudio device index to convert.
+ @param hostApi The host api which the index should be converted for.
+
+ @returns On success returns PaNoError and places the converted index in the
+ hostApiDevice parameter.
+*/
+PaError PaUtil_DeviceIndexToHostApiDeviceIndex(
+ PaDeviceIndex *hostApiDevice, PaDeviceIndex device,
+ struct PaUtilHostApiRepresentation *hostApi );
+
+
+/** Set the host error information returned by Pa_GetLastHostErrorInfo. This
+ function and the paUnanticipatedHostError error code should be used as a
+ last resort. Implementors should use existing PA error codes where possible,
+ or nominate new ones. Note that at it is always better to use
+ PaUtil_SetLastHostErrorInfo() and paUnanticipatedHostError than to return an
+ ambiguous or inaccurate PaError code.
+
+ @param hostApiType The host API which encountered the error (ie of the caller)
+
+ @param errorCode The error code returned by the native API function.
+
+ @param errorText A string describing the error. PaUtil_SetLastHostErrorInfo
+ makes a copy of the string, so it is not necessary for the pointer to remain
+ valid after the call to PaUtil_SetLastHostErrorInfo() returns.
+
+*/
+void PaUtil_SetLastHostErrorInfo( PaHostApiTypeId hostApiType, long errorCode,
+ const char *errorText );
+
+
+
+/** PA_DEBUG() provides a simple debug message printing facility. The macro
+ passes it's argument to a printf-like function called PaUtil_DebugPrint()
+ which prints to stderr and always flushes the stream after printing.
+ Because preprocessor macros cannot directly accept variable length argument
+ lists, calls to the macro must include an additional set of parenthesis, eg:
+ PA_DEBUG(("errorno: %d", 1001 ));
+*/
+
+void PaUtil_DebugPrint( const char *format, ... );
+
+#if (0) /* set to 1 to print debug messages */
+#define PA_DEBUG(x) PaUtil_DebugPrint x ;
+#else
+#define PA_DEBUG(x)
+#endif
+
+
+/* the following functions are implemented in a platform platform specific
+ .c file
+*/
+
+/** Allocate size bytes, guaranteed to be aligned to a FIXME byte boundary */
+void *PaUtil_AllocateMemory( long size );
+
+
+/** Realease block if non-NULL. block may be NULL */
+void PaUtil_FreeMemory( void *block );
+
+
+/** Return the number of currently allocated blocks. This function can be
+ used for detecting memory leaks.
+
+ @note Allocations will only be tracked if PA_TRACK_MEMORY is #defined. If
+ it isn't, this function will always return 0.
+*/
+int PaUtil_CountCurrentlyAllocatedBlocks( void );
+
+
+/** Initialize the clock used by PaUtil_GetTime(). Call this before calling
+ PaUtil_GetTime.
+
+ @see PaUtil_GetTime
+*/
+void PaUtil_InitializeClock( void );
+
+
+/** Return the system time in seconds. Used to implement CPU load functions
+
+ @see PaUtil_InitializeClock
+*/
+double PaUtil_GetTime( void );
+
+
+/* void Pa_Sleep( long msec ); must also be implemented in per-platform .c file */
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* PA_UTIL_H */
diff --git a/pd/portaudio/pa_common/portaudio.h b/pd/portaudio/pa_common/portaudio.h
new file mode 100644
index 00000000..e01c7aa8
--- /dev/null
+++ b/pd/portaudio/pa_common/portaudio.h
@@ -0,0 +1,1128 @@
+#ifndef PORTAUDIO_H
+#define PORTAUDIO_H
+/*
+ * $Id: portaudio.h,v 1.5.2.46 2004/02/14 10:19:01 rossbencina Exp $
+ * PortAudio Portable Real-Time Audio Library
+ * PortAudio API Header File
+ * Latest version available at: http://www.portaudio.com/
+ *
+ * Copyright (c) 1999-2002 Ross Bencina and Phil Burk
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files
+ * (the "Software"), to deal in the Software without restriction,
+ * including without limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * Any person wishing to distribute modifications to the Software is
+ * requested to send the modifications to the original developer so that
+ * they can be incorporated into the canonical version.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/** @file
+ @brief The PortAudio API.
+*/
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+
+/** Retrieve the release number of the currently running PortAudio build,
+ eg 1900.
+*/
+int Pa_GetVersion( void );
+
+
+/** Retrieve a textual description of the current PortAudio build,
+ eg "PortAudio V19-devel 13 October 2002".
+*/
+const char* Pa_GetVersionText( void );
+
+
+/** Error codes returned by PortAudio functions.
+ Note that with the exception of paNoError, all PaErrorCodes are negative.
+*/
+
+typedef int PaError;
+typedef enum PaErrorCode
+{
+ paNoError = 0,
+
+ paNotInitialized = -10000,
+ paUnanticipatedHostError,
+ paInvalidChannelCount,
+ paInvalidSampleRate,
+ paInvalidDevice,
+ paInvalidFlag,
+ paSampleFormatNotSupported,
+ paBadIODeviceCombination,
+ paInsufficientMemory,
+ paBufferTooBig,
+ paBufferTooSmall,
+ paNullCallback,
+ paBadStreamPtr,
+ paTimedOut,
+ paInternalError,
+ paDeviceUnavailable,
+ paIncompatibleHostApiSpecificStreamInfo,
+ paStreamIsStopped,
+ paStreamIsNotStopped,
+ paInputOverflowed,
+ paOutputUnderflowed,
+ paHostApiNotFound,
+ paInvalidHostApi,
+ paCanNotReadFromACallbackStream, /**< @todo review error code name */
+ paCanNotWriteToACallbackStream, /**< @todo review error code name */
+ paCanNotReadFromAnOutputOnlyStream, /**< @todo review error code name */
+ paCanNotWriteToAnInputOnlyStream, /**< @todo review error code name */
+ paIncompatibleStreamHostApi
+} PaErrorCode;
+
+
+/** Translate the supplied PortAudio error code into a human readable
+ message.
+*/
+const char *Pa_GetErrorText( PaError errorCode );
+
+
+/** Library initialization function - call this before using PortAudio.
+ This function initialises internal data structures and prepares underlying
+ host APIs for use. This function MUST be called before using any other
+ PortAudio API functions.
+
+ If Pa_Initialize() is called multiple times, each successful
+ call must be matched with a corresponding call to Pa_Terminate().
+ Pairs of calls to Pa_Initialize()/Pa_Terminate() may overlap, and are not
+ required to be fully nested.
+
+ Note that if Pa_Initialize() returns an error code, Pa_Terminate() should
+ NOT be called.
+
+ @return paNoError if successful, otherwise an error code indicating the cause
+ of failure.
+
+ @see Pa_Terminate
+*/
+PaError Pa_Initialize( void );
+
+
+/** Library termination function - call this when finished using PortAudio.
+ This function deallocates all resources allocated by PortAudio since it was
+ initializied by a call to Pa_Initialize(). In cases where Pa_Initialise() has
+ been called multiple times, each call must be matched with a corresponding call
+ to Pa_Terminate(). The final matching call to Pa_Terminate() will automatically
+ close any PortAudio streams that are still open.
+
+ Pa_Terminate() MUST be called before exiting a program which uses PortAudio.
+ Failure to do so may result in serious resource leaks, such as audio devices
+ not being available until the next reboot.
+
+ @return paNoError if successful, otherwise an error code indicating the cause
+ of failure.
+
+ @see Pa_Initialize
+*/
+PaError Pa_Terminate( void );
+
+
+
+/** The type used to refer to audio devices. Values of this type usually
+ range from 0 to (Pa_DeviceCount-1), and may also take on the PaNoDevice
+ and paUseHostApiSpecificDeviceSpecification values.
+
+ @see Pa_DeviceCount, paNoDevice, paUseHostApiSpecificDeviceSpecification
+*/
+typedef int PaDeviceIndex;
+
+
+/** A special PaDeviceIndex value indicating that no device is available,
+ or should be used.
+
+ @see PaDeviceIndex
+*/
+#define paNoDevice ((PaDeviceIndex)-1)
+
+
+/** A special PaDeviceIndex value indicating that the device(s) to be used
+ are specified in the host api specific stream info structure.
+
+ @see PaDeviceIndex
+*/
+#define paUseHostApiSpecificDeviceSpecification ((PaDeviceIndex)-2)
+
+
+/* Host API enumeration mechanism */
+
+/** The type used to enumerate to host APIs at runtime. Values of this type
+ range from 0 to (Pa_GetHostApiCount()-1).
+
+ @see Pa_GetHostApiCount
+*/
+typedef int PaHostApiIndex;
+
+
+/** Retrieve the number of available host APIs. Even if a host API is
+ available it may have no devices available.
+
+ @return A non-negative value indicating the number of available host APIs
+ or, a PaErrorCode (which are always negative) if PortAudio is not initialized
+ or an error is encountered.
+
+ @see PaHostApiIndex
+*/
+PaHostApiIndex Pa_GetHostApiCount( void );
+
+
+/** Retrieve the index of the default host API. The default host API will be
+ the lowest common denominator host API on the current platform and is
+ unlikely to provide the best performance.
+
+ @return A non-negative value ranging from 0 to (Pa_GetHostApiCount()-1)
+ indicating the default host API index or, a PaErrorCode (which are always
+ negative) if PortAudio is not initialized or an error is encountered.
+*/
+PaHostApiIndex Pa_GetDefaultHostApi( void );
+
+
+/** Unchanging unique identifiers for each supported host API. This type
+ is used in the PaHostApiInfo structure. The values are guaranteed to be
+ unique and to never change, thus allowing code to be written that
+ conditionally uses host API specific extensions.
+
+ New type ids will be allocated when support for a host API reaches
+ "public alpha" status, prior to that developers should use the
+ paInDevelopment type id.
+
+ @see PaHostApiInfo
+*/
+typedef enum PaHostApiTypeId
+{
+ paInDevelopment=0, /* use while developing support for a new host API */
+ paDirectSound=1,
+ paMME=2,
+ paASIO=3,
+ paSoundManager=4,
+ paCoreAudio=5,
+ paOSS=7,
+ paALSA=8,
+ paAL=9,
+ paBeOS=10
+} PaHostApiTypeId;
+
+
+/** A structure containing information about a particular host API. */
+
+typedef struct PaHostApiInfo
+{
+ /** this is struct version 1 */
+ int structVersion;
+ /** The well known unique identifier of this host API @see PaHostApiTypeId */
+ PaHostApiTypeId type;
+ /** A textual description of the host API for display on user interfaces. */
+ const char *name;
+
+ /** The number of devices belonging to this host API. This field may be
+ used in conjunction with Pa_HostApiDeviceIndexToDeviceIndex() to enumerate
+ all devices for this host API.
+ @see Pa_HostApiDeviceIndexToDeviceIndex
+ */
+ int deviceCount;
+
+ /** The the default input device for this host API. The value will be a
+ device index ranging from 0 to (Pa_GetDeviceCount()-1), or paNoDevice
+ if no default input device is available.
+ */
+ PaDeviceIndex defaultInputDevice;
+
+ /** The the default output device for this host API. The value will be a
+ device index ranging from 0 to (Pa_GetDeviceCount()-1), or paNoDevice
+ if no default output device is available.
+ */
+ PaDeviceIndex defaultOutputDevice;
+
+} PaHostApiInfo;
+
+
+/** Retrieve a pointer to a structure containing information about a specific
+ host Api.
+
+ @param hostApi A valid host API index ranging from 0 to (Pa_GetHostApiCount()-1)
+
+ @return A pointer to an immutable PaHostApiInfo structure describing
+ a specific host API. If the hostApi parameter is out of range or an error
+ is encountered, the function returns NULL.
+
+ The returned structure is owned by the PortAudio implementation and must not
+ be manipulated or freed. The pointer is only guaranteed to be valid between
+ calls to Pa_Initialize() and Pa_Terminate().
+*/
+const PaHostApiInfo * Pa_GetHostApiInfo( PaHostApiIndex hostApi );
+
+
+/** Convert a static host API unique identifier, into a runtime
+ host API index.
+
+ @param type A unique host API identifier belonging to the PaHostApiTypeId
+ enumeration.
+
+ @return A valid PaHostApiIndex ranging from 0 to (Pa_GetHostApiCount()-1) or,
+ a PaErrorCode (which are always negative) if PortAudio is not initialized
+ or an error is encountered.
+
+ The paHostApiNotFound error code indicates that the host API specified by the
+ type parameter is not available.
+
+ @see PaHostApiTypeId
+*/
+PaHostApiIndex Pa_HostApiTypeIdToHostApiIndex( PaHostApiTypeId type );
+
+
+/** Convert a host-API-specific device index to standard PortAudio device index.
+ This function may be used in conjunction with the deviceCount field of
+ PaHostApiInfo to enumerate all devices for the specified host API.
+
+ @param hostApi A valid host API index ranging from 0 to (Pa_GetHostApiCount()-1)
+
+ @param hostApiDeviceIndex A valid per-host device index in the range
+ 0 to (Pa_GetHostApiInfo(hostApi)->deviceCount-1)
+
+ @return A non-negative PaDeviceIndex ranging from 0 to (Pa_GetDeviceCount()-1)
+ or, a PaErrorCode (which are always negative) if PortAudio is not initialized
+ or an error is encountered.
+
+ A paInvalidHostApi error code indicates that the host API index specified by
+ the hostApi parameter is out of range.
+
+ A paInvalidDevice error code indicates that the hostApiDeviceIndex parameter
+ is out of range.
+
+ @see PaHostApiInfo
+*/
+PaDeviceIndex Pa_HostApiDeviceIndexToDeviceIndex( PaHostApiIndex hostApi,
+ int hostApiDeviceIndex );
+
+
+
+/** Structure used to return information about a host error condition.
+*/
+typedef struct PaHostErrorInfo{
+ PaHostApiTypeId hostApiType; /**< the host API which returned the error code */
+ long errorCode; /**< the error code returned */
+ const char *errorText; /**< a textual description of the error if available, otherwise a zero-length string */
+}PaHostErrorInfo;
+
+
+/** Return information about the last host error encountered. The error
+ information returned by Pa_GetLastHostErrorInfo() will never be modified
+ asyncronously by errors occurring in other PortAudio owned threads
+ (such as the thread that manages the stream callback.)
+
+ This function is provided as a last resort, primarily to enhance debugging
+ by providing clients with access to all available error information.
+
+ @return A pointer to an immutable structure constaining information about
+ the host error. The values in this structure will only be valid if a
+ PortAudio function has previously returned the paUnanticipatedHostError
+ error code.
+*/
+const PaHostErrorInfo* Pa_GetLastHostErrorInfo( void );
+
+
+
+/* Device enumeration and capabilities */
+
+/** Retrieve the number of available devices. The number of available devices
+ may be zero.
+
+ @return A non-negative value indicating the number of available devices or,
+ a PaErrorCode (which are always negative) if PortAudio is not initialized
+ or an error is encountered.
+*/
+PaDeviceIndex Pa_GetDeviceCount( void );
+
+
+/** Retrieve the index of the default input device. The result can be
+ used in the inputDevice parameter to Pa_OpenStream().
+
+ @return The default input device index for the defualt host API, or paNoDevice
+ if no default input device is available or an error was encountered.
+*/
+PaDeviceIndex Pa_GetDefaultInputDevice( void );
+
+
+/** Retrieve the index of the default output device. The result can be
+ used in the outputDevice parameter to Pa_OpenStream().
+
+ @return The default output device index for the defualt host API, or paNoDevice
+ if no default output device is available or an error was encountered.
+
+ @note
+ On the PC, the user can specify a default device by
+ setting an environment variable. For example, to use device #1.
+<pre>
+ set PA_RECOMMENDED_OUTPUT_DEVICE=1
+</pre>
+ The user should first determine the available device ids by using
+ the supplied application "pa_devs".
+*/
+PaDeviceIndex Pa_GetDefaultOutputDevice( void );
+
+
+/** The type used to represent monotonic time in seconds that can be used
+ for syncronisation. The type is used for the outTime argument to the
+ PaStreamCallback and as the result of Pa_GetStreamTime().
+
+ @see PaStreamCallback, Pa_GetStreamTime
+*/
+typedef double PaTime;
+
+
+/** A type used to specify one or more sample formats. Each value indicates
+ a possible format for sound data passed to and from the stream callback,
+ Pa_ReadStream and Pa_WriteStream.
+
+ The standard formats paFloat32, paInt16, paInt32, paInt24, paInt8
+ and aUInt8 are usually implemented by all implementations.
+
+ The floating point representation (paFloat32) uses +1.0 and -1.0 as the
+ maximum and minimum respectively.
+
+ paUInt8 is an unsigned 8 bit format where 128 is considered "ground"
+
+ The paNonInterleaved flag indicates that a multichannel buffer is passed
+ as a set of non-interleaved pointers.
+
+ @see Pa_OpenStream, Pa_OpenDefaultStream, PaDeviceInfo
+ @see paFloat32, paInt16, paInt32, paInt24, paInt8
+ @see paUInt8, paCustomFormat, paNonInterleaved
+*/
+typedef unsigned long PaSampleFormat;
+
+
+#define paFloat32 ((PaSampleFormat) 0x00000001) /**< @see PaSampleFormat */
+#define paInt32 ((PaSampleFormat) 0x00000002) /**< @see PaSampleFormat */
+#define paInt24 ((PaSampleFormat) 0x00000004) /**< Packed 24 bit format. @see PaSampleFormat */
+#define paInt16 ((PaSampleFormat) 0x00000008) /**< @see PaSampleFormat */
+#define paInt8 ((PaSampleFormat) 0x00000010) /**< @see PaSampleFormat */
+#define paUInt8 ((PaSampleFormat) 0x00000020) /**< @see PaSampleFormat */
+#define paCustomFormat ((PaSampleFormat) 0x00010000)/**< @see PaSampleFormat */
+
+#define paNonInterleaved ((PaSampleFormat) 0x80000000)
+
+/** A structure providing information and capabilities of PortAudio devices.
+ Devices may support input, output or both input and output.
+*/
+typedef struct PaDeviceInfo
+{
+ int structVersion; /* this is struct version 2 */
+ const char *name;
+ PaHostApiIndex hostApi; /* note this is a host API index, not a type id*/
+
+ int maxInputChannels;
+ int maxOutputChannels;
+
+ /* Default latency values for interactive performance. */
+ PaTime defaultLowInputLatency;
+ PaTime defaultLowOutputLatency;
+ /* Default latency values for robust non-interactive applications (eg. playing sound files). */
+ PaTime defaultHighInputLatency;
+ PaTime defaultHighOutputLatency;
+
+ double defaultSampleRate;
+} PaDeviceInfo;
+
+
+/** Retrieve a pointer to a PaDeviceInfo structure containing information
+ about the specified device.
+ @return A pointer to an immutable PaDeviceInfo structure. If the device
+ parameter is out of range the function returns NULL.
+
+ @param device A valid device index in the range 0 to (Pa_GetDeviceCount()-1)
+
+ @note PortAudio manages the memory referenced by the returned pointer,
+ the client must not manipulate or free the memory. The pointer is only
+ guaranteed to be valid between calls to Pa_Initialize() and Pa_Terminate().
+
+ @see PaDeviceInfo, PaDeviceIndex
+*/
+const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceIndex device );
+
+
+/** Parameters for one direction (input or output) of a stream.
+*/
+typedef struct PaStreamParameters
+{
+ /** A valid device index in the range 0 to (Pa_GetDeviceCount()-1)
+ specifying the device to be used or the special constant
+ paUseHostApiSpecificDeviceSpecification which indicates that the actual
+ device(s) to use are specified in hostApiSpecificStreamInfo.
+ This field must not be set to paNoDevice.
+ */
+ PaDeviceIndex device;
+
+ /** The number of channels of sound to be delivered to the
+ stream callback or accessed by Pa_ReadStream() or Pa_WriteStream().
+ It can range from 1 to the value of maxInputChannels in the
+ PaDeviceInfo record for the device specified by the device parameter.
+ */
+ int channelCount;
+
+ /** The sample format of the buffer provided to the stream callback,
+ a_ReadStream() or Pa_WriteStream(). It may be any of the formats described
+ by the PaSampleFormat enumeration.
+ FIXME: wrt below, what are we guaranteeing these days, if anything?
+ PortAudio guarantees support for
+ the device's native formats (nativeSampleFormats in the device info record)
+ and additionally 16 and 32 bit integer and 32 bit floating point formats.
+ Support for other formats is implementation defined.
+ */
+ PaSampleFormat sampleFormat;
+
+ /** The desired latency in seconds. Where practical, implementations should
+ configure their latency based on these parameters, otherwise they may
+ choose the closest viable latency instead. Unless the suggested latency
+ is greater than the absolute upper limit for the device implementations
+ shouldround the suggestedLatency up to the next practial value - ie to
+ provide an equal or higher latency than suggestedLatency whereever possibe.
+ Actual latency values for an open stream may be retrieved using the
+ inputLatency and outputLatency fields of the PaStreamInfo structure
+ returned by Pa_GetStreamInfo().
+ @see default*Latency in PaDeviceInfo, *Latency in PaStreamInfo
+ */
+ PaTime suggestedLatency;
+
+ /** An optional pointer to a host api specific data structure
+ containing additional information for device setup and/or stream processing.
+ hostApiSpecificStreamInfo is never required for correct operation,
+ if not used it should be set to NULL.
+ */
+ void *hostApiSpecificStreamInfo;
+
+} PaStreamParameters;
+
+
+/** Return code for Pa_IsFormatSupported indicating success. */
+#define paFormatIsSupported (0)
+
+/** Determine whether it would be possible to open a stream with the specified
+ parameters.
+
+ @param inputParameters A structure that describes the input parameters used to
+ open a stream. The suggestedLatency field is ignored. See PaStreamParameters
+ for a description of these parameters. inputParameters must be NULL for
+ output-only streams.
+
+ @param outputParameters A structure that describes the output parameters used
+ to open a stream. The suggestedLatency field is ignored. See PaStreamParameters
+ for a description of these parameters. outputParameters must be NULL for
+ input-only streams.
+
+ @param sampleRate The required sampleRate. For full-duplex streams it is the
+ sample rate for both input and output
+
+ @return Returns 0 if the format is supported, and an error code indicating why
+ the format is not supported otherwise. The constant paFormatIsSupported is
+ provided to compare with the return value for success.
+
+ @see paFormatIsSupported, PaStreamParameters
+*/
+PaError Pa_IsFormatSupported( const PaStreamParameters *inputParameters,
+ const PaStreamParameters *outputParameters,
+ double sampleRate );
+
+
+
+/* Streaming types and functions */
+
+
+/**
+ A single PaStream can provide multiple channels of real-time
+ streaming audio input and output to a client application. A stream
+ provides access to audio hardware represented by one or more
+ PaDevices. Depending on the underlying Host API, it may be possible
+ to open multiple streams using the same device, however this behavior
+ is implementation defined. Portable applications should assume that
+ a PaDevice may be simultaneously used by at most one PaStream.
+
+ Pointers to PaStream objects are passed between PortAudio functions that
+ operate on streams.
+
+ @see Pa_OpenStream, Pa_OpenDefaultStream, Pa_OpenDefaultStream, Pa_CloseStream,
+ Pa_StartStream, Pa_StopStream, Pa_AbortStream, Pa_IsStreamActive,
+ Pa_GetStreamTime, Pa_GetStreamCpuLoad
+
+*/
+typedef void PaStream;
+
+
+/** Can be passed as the framesPerBuffer parameter to Pa_OpenStream()
+ or Pa_OpenDefaultStream() to indicate that the stream callback will
+ accept buffers of any size.
+*/
+#define paFramesPerBufferUnspecified (0)
+
+
+/** Flags used to control the behavior of a stream. They are passed as
+ parameters to Pa_OpenStream or Pa_OpenDefaultStream. Multiple flags may be
+ ORed together.
+
+ @see Pa_OpenStream, Pa_OpenDefaultStream
+ @see paNoFlag, paClipOff, paDitherOff, paNeverDropInput,
+ paPrimeOutputBuffersUsingStreamCallback, paPlatformSpecificFlags
+*/
+typedef unsigned long PaStreamFlags;
+
+/** @see PaStreamFlags */
+#define paNoFlag ((PaStreamFlags) 0)
+
+/** Disable default clipping of out of range samples.
+ @see PaStreamFlags
+*/
+#define paClipOff ((PaStreamFlags) 0x00000001)
+
+/** Disable default dithering.
+ @see PaStreamFlags
+*/
+#define paDitherOff ((PaStreamFlags) 0x00000002)
+
+/** Flag requests that where possible a full duplex stream will not discard
+ overflowed input samples without calling the stream callback. This flag is
+ only valid for full duplex callback streams and only when used in combination
+ with the paFramesPerBufferUnspecified (0) framesPerBuffer parameter. Using
+ this flag incorrectly results in a paInvalidFlag error being returned from
+ Pa_OpenStream and Pa_OpenDefaultStream.
+
+ @see PaStreamFlags, paFramesPerBufferUnspecified
+*/
+#define paNeverDropInput ((PaStreamFlags) 0x00000004)
+
+/** Call the stream callback to fill initial output buffers, rather than the
+ default behavior of priming the buffers with zeros (silence). This flag has
+ no effect for input-only and blocking read/write streams.
+
+ @see PaStreamFlags
+*/
+#define paPrimeOutputBuffersUsingStreamCallback ((PaStreamFlags) 0x00000008)
+
+/** A mask specifying the platform specific bits.
+ @see PaStreamFlags
+*/
+#define paPlatformSpecificFlags ((PaStreamFlags)0xFFFF0000)
+
+/**
+ Timing information for the buffers passed to the stream callback.
+*/
+typedef struct PaStreamCallbackTimeInfo{
+ PaTime inputBufferAdcTime;
+ PaTime currentTime;
+ PaTime outputBufferDacTime;
+} PaStreamCallbackTimeInfo;
+
+
+/**
+ Flag bit constants for the statusFlags to PaStreamCallback.
+
+ @see paInputUnderflow, paInputOverflow, paOutputUnderflow, paOutputOverflow,
+ paPrimingOutput
+*/
+typedef unsigned long PaStreamCallbackFlags;
+
+/** In a stream opened with paFramesPerBufferUnspecified, indicates that
+ input data is all silence (zeros) because no real data is available. In a
+ stream opened without paFramesPerBufferUnspecified, it indicates that one or
+ more zero samples have been inserted into the input buffer to compensate
+ for an input underflow.
+ @see PaStreamCallbackFlags
+*/
+#define paInputUnderflow ((PaStreamCallbackFlags) 0x00000001)
+
+/** In a stream opened with paFramesPerBufferUnspecified, indicates that data
+ prior to the first sample of the input buffer was discarded due to an
+ overflow, possibly because the stream callback is using too much CPU time.
+ Otherwise indicates that data prior to one or more samples in the
+ input buffer was discarded.
+ @see PaStreamCallbackFlags
+*/
+#define paInputOverflow ((PaStreamCallbackFlags) 0x00000002)
+
+/** Indicates that output data (or a gap) was inserted, possibly because the
+ stream callback is using too much CPU time.
+ @see PaStreamCallbackFlags
+*/
+#define paOutputUnderflow ((PaStreamCallbackFlags) 0x00000004)
+
+/** Indicates that output data will be discarded because no room is available.
+ @see PaStreamCallbackFlags
+*/
+#define paOutputOverflow ((PaStreamCallbackFlags) 0x00000008)
+
+/** Some of all of the output data will be used to prime the stream, input
+ data may be zero.
+ @see PaStreamCallbackFlags
+*/
+#define paPrimingOutput ((PaStreamCallbackFlags) 0x00000010)
+
+/**
+ Allowable return values for the PaStreamCallback.
+ @see PaStreamCallback
+*/
+typedef enum PaStreamCallbackResult
+{
+ paContinue=0,
+ paComplete=1,
+ paAbort=2
+} PaStreamCallbackResult;
+
+
+/**
+ Functions of type PaStreamCallback are implemented by PortAudio clients.
+ They consume, process or generate audio in response to requests from an
+ active PortAudio stream.
+
+ @param input and @param output are arrays of interleaved samples,
+ the format, packing and number of channels used by the buffers are
+ determined by parameters to Pa_OpenStream().
+
+ @param frameCount The number of sample frames to be processed by
+ the stream callback.
+
+ @param timeInfo The time in seconds when the first sample of the input
+ buffer was received at the audio input, the time in seconds when the first
+ sample of the output buffer will begin being played at the audio output, and
+ the time in seconds when the stream callback was called.
+ See also Pa_GetStreamTime()
+
+ @param statusFlags Flags indicating whether input and/or output buffers
+ have been inserted or will be dropped to overcome underflow or overflow
+ conditions.
+
+ @param userData The value of a user supplied pointer passed to
+ Pa_OpenStream() intended for storing synthesis data etc.
+
+ @return
+ The stream callback should return one of the values in the
+ PaStreamCallbackResult enumeration. To ensure that the callback is continues
+ to be called, it should return paContinue (0). Either paComplete or paAbort
+ can be returned to finish stream processing, after either of these values is
+ returned the callback will not be called again. If paAbort is returned the
+ stream will finish as soon as possible. If paComplete is returned, the stream
+ will continue until all buffers generated by the callback have been played.
+ This may be useful in applications such as soundfile players where a specific
+ duration of output is required. However, it is not necessary to utilise this
+ mechanism as Pa_StopStream(), Pa_AbortStream() or Pa_CloseStream() can also
+ be used to stop the stream. The callback must always fill the entire output
+ buffer irrespective of its return value.
+
+ @see Pa_OpenStream, Pa_OpenDefaultStream
+
+ @note With the exception of Pa_GetStreamCpuLoad() it is not permissable to call
+ PortAudio API functions from within the stream callback.
+*/
+typedef int PaStreamCallback(
+ const void *input, void *output,
+ unsigned long frameCount,
+ const PaStreamCallbackTimeInfo* timeInfo,
+ PaStreamCallbackFlags statusFlags,
+ void *userData );
+
+
+/** Opens a stream for either input, output or both.
+
+ @param stream The address of a PaStream pointer which will receive
+ a pointer to the newly opened stream.
+
+ @param inputParameters A structure that describes the input parameters used by
+ the opened stream. See PaStreamParameters for a description of these parameters.
+ inputParameters must be NULL for output-only streams.
+
+ @param outputParameters A structure that describes the output parameters used by
+ the opened stream. See PaStreamParameters for a description of these parameters.
+ outputParameters must be NULL for input-only streams.
+
+ @param sampleRate The desired sampleRate. For full-duplex streams it is the
+ sample rate for both input and output
+
+ @param framesPerBuffer The number of frames passed to the stream callback
+ function, or the preferred block granularity for a blocking read/write stream.
+ The special value paFramesPerBufferUnspecified (0) may be used to request that
+ the stream callback will recieve an optimal (and possibly varying) number of
+ frames based on host requirements and the requested latency settings.
+ Note: With some host APIs, the use of non-zero framesPerBuffer for a callback
+ stream may introduce an additional layer of buffering which could introduce
+ additional latency. PortAudio guarantees that the additional latency
+ will be kept to the theoretical minimum however, it is strongly recommended
+ that a non-zero framesPerBuffer value only be used when your algorithm
+ requires a fixed number of frames per stream callback.
+
+ @param streamFlags Flags which modify the behaviour of the streaming process.
+ This parameter may contain a combination of flags ORed together. Some flags may
+ only be relevant to certain buffer formats.
+
+ @param streamCallback A pointer to a client supplied function that is responsible
+ for processing and filling input and output buffers. If this parameter is NULL
+ the stream will be opened in 'blocking read/write' mode. In blocking mode,
+ the client can receive sample data using Pa_ReadStream and write sample data
+ using Pa_WriteStream, the number of samples that may be read or written
+ without blocking is returned by Pa_GetStreamReadAvailable and
+ Pa_GetStreamWriteAvailable respectively.
+
+ @param userData A client supplied pointer which is passed to the stream callback
+ function. It could for example, contain a pointer to instance data necessary
+ for processing the audio buffers. This parameter is ignored if streamCallback
+ is NULL.
+
+ @return
+ Upon success Pa_OpenStream() returns paNoError and places a pointer to a
+ valid PaStream in the stream argument. The stream is inactive (stopped).
+ If a call to Pa_OpenStream() fails, a non-zero error code is returned (see
+ PaError for possible error codes) and the value of stream is invalid.
+
+ @see PaStreamParameters, PaStreamCallback, Pa_ReadStream, Pa_WriteStream,
+ Pa_GetStreamReadAvailable, Pa_GetStreamWriteAvailable
+*/
+PaError Pa_OpenStream( PaStream** stream,
+ const PaStreamParameters *inputParameters,
+ const PaStreamParameters *outputParameters,
+ double sampleRate,
+ unsigned long framesPerBuffer,
+ PaStreamFlags streamFlags,
+ PaStreamCallback *streamCallback,
+ void *userData );
+
+
+/** A simplified version of Pa_OpenStream() that opens the default input
+ and/or output devices.
+
+ @param stream The address of a PaStream pointer which will receive
+ a pointer to the newly opened stream.
+
+ @param numInputChannels The number of channels of sound that will be supplied
+ to the stream callback or returned by Pa_ReadStream. It can range from 1 to
+ the value of maxInputChannels in the PaDeviceInfo record for the default input
+ device. If 0 the stream is opened as an output-only stream.
+
+ @param numOutputChannels The number of channels of sound to be delivered to the
+ stream callback or passed to Pa_WriteStream. It can range from 1 to the value
+ of maxOutputChannels in the PaDeviceInfo record for the default output dvice.
+ If 0 the stream is opened as an output-only stream.
+
+ @param sampleFormat The sample format of both the input and output buffers
+ provided to the callback or passed to and from Pa_ReadStream and Pa_WriteStream.
+ sampleFormat may be any of the formats described by the PaSampleFormat enumeration
+ (see above).
+ FIXME: the following may need to be rewritten - PortAudio guarantees support for
+ the device's native formats (nativeSampleFormats in the device info record)
+ and additionally 16 and 32 bit integer and 32 bit float
+
+ @param sampleRate Same as Pa_OpenStream parameter of the same name.
+ @param framesPerBuffer Same as Pa_OpenStream parameter of the same name.
+ @param streamCallback Same as Pa_OpenStream parameter of the same name.
+ @param userData Same as Pa_OpenStream parameter of the same name.
+
+ @return As for Pa_OpenStream
+
+ @see Pa_OpenStream, PaStreamCallback
+*/
+PaError Pa_OpenDefaultStream( PaStream** stream,
+ int numInputChannels,
+ int numOutputChannels,
+ PaSampleFormat sampleFormat,
+ double sampleRate,
+ unsigned long framesPerBuffer,
+ PaStreamCallback *streamCallback,
+ void *userData );
+
+
+/** Closes an audio stream. If the audio stream is active it
+ discards any pending buffers as if Pa_AbortStream() had been called.
+*/
+PaError Pa_CloseStream( PaStream *stream );
+
+
+/** Functions of type PaStreamFinishedCallback are implemented by PortAudio
+ clients. They can be registered with a stream using the Pa_SetStreamFinishedCallback
+ function. Once registered they are called when the stream becomes inactive
+ (ie once a call to Pa_StopStream() will not block).
+ A stream will become inactive after the stream callback returns non-zero,
+ or when Pa_StopStream or Pa_AbortStream is called. For a stream providing audio
+ output, if the stream callback returns paComplete, or Pa_StopStream is called,
+ the stream finished callback will not be called until all generated sample data
+ has been played.
+
+ @param userData The userData parameter supplied to Pa_OpenStream()
+
+ @see Pa_SetStreamFinishedCallback
+*/
+typedef void PaStreamFinishedCallback( void *userData );
+
+
+/** Register a stream finished callback function which will be called when the
+ stream becomes inactive. See the description of PaStreamFinishedCallback for
+ further details about when the callback will be called.
+
+ @param stream a pointer to a PaStream that is in the stopped state - if the
+ stream is not stopped, the stream's finished callback will remain unchanged
+ and an error code will be returned.
+
+ @param streamFinishedCallback a pointer to a function with the same signature
+ as PaStreamFinishedCallback, that will be called when the stream becomes
+ inactive. Passing NULL for this parameter will un-register a previously
+ registered stream finished callback function.
+
+ @return on success returns paNoError, otherwise an error code indicating the cause
+ of the error.
+
+ @see PaStreamFinishedCallback
+*/
+PaError Pa_SetStreamFinishedCallback( PaStream *stream, PaStreamFinishedCallback* streamFinishedCallback );
+
+
+/** Commences audio processing.
+*/
+PaError Pa_StartStream( PaStream *stream );
+
+
+/** Terminates audio processing. It waits until all pending
+ audio buffers have been played before it returns.
+*/
+PaError Pa_StopStream( PaStream *stream );
+
+
+/** Terminates audio processing immediately without waiting for pending
+ buffers to complete.
+*/
+PaError Pa_AbortStream( PaStream *stream );
+
+
+/** Determine whether the stream is stopped.
+ A stream is considered to be stopped prior to a successful call to
+ Pa_StartStream and after a successful call to Pa_StopStream or Pa_AbortStream.
+ If a stream callback returns a value other than paContinue the stream is NOT
+ considered to be stopped.
+
+ @return Returns one (1) when the stream is stopped, zero (0) when
+ the stream is running or, a PaErrorCode (which are always negative) if
+ PortAudio is not initialized or an error is encountered.
+
+ @see Pa_StopStream, Pa_AbortStream, Pa_IsStreamActive
+*/
+PaError Pa_IsStreamStopped( PaStream *stream );
+
+
+/** Determine whether the stream is active.
+ A stream is active after a successful call to Pa_StartStream(), until it
+ becomes inactive either as a result of a call to Pa_StopStream() or
+ Pa_AbortStream(), or as a result of a return value other than paContinue from
+ the stream callback. In the latter case, the stream is considered inactive
+ after the last buffer has finished playing.
+
+ @return Returns one (1) when the stream is active (ie playing or recording
+ audio), zero (0) when not playing or, a PaErrorCode (which are always negative)
+ if PortAudio is not initialized or an error is encountered.
+
+ @see Pa_StopStream, Pa_AbortStream, Pa_IsStreamStopped
+*/
+PaError Pa_IsStreamActive( PaStream *stream );
+
+
+
+/** A structure containing unchanging information about an open stream.
+ @see Pa_GetStreamInfo
+*/
+
+typedef struct PaStreamInfo
+{
+ /** this is struct version 1 */
+ int structVersion;
+
+ /** The input latency of the stream in seconds. This value provides the most
+ accurate estimate of input latency available to the implementation. It may
+ differ significantly from the suggestedLatency value passed to Pa_OpenStream().
+ The value of this field will be zero (0.) for output-only streams.
+ @see PaTime
+ */
+ PaTime inputLatency;
+
+ /** The output latency of the stream in seconds. This value provides the most
+ accurate estimate of output latency available to the implementation. It may
+ differ significantly from the suggestedLatency value passed to Pa_OpenStream().
+ The value of this field will be zero (0.) for input-only streams.
+ @see PaTime
+ */
+ PaTime outputLatency;
+
+ /** The sample rate of the stream in Hertz (samples per second). In cases
+ where the hardware sample rate is inaccurate and PortAudio is aware of it,
+ the value of this field may be different from the sampleRate parameter
+ passed to Pa_OpenStream(). If information about the actual hardware sample
+ rate is not available, this field will have the same value as the sampleRate
+ parameter passed to Pa_OpenStream().
+ */
+ double sampleRate;
+
+} PaStreamInfo;
+
+
+/** Retrieve a pointer to a PaStreamInfo structure containing information
+ about the specified stream.
+ @return A pointer to an immutable PaStreamInfo structure. If the stream
+ parameter invalid, or an error is encountered, the function returns NULL.
+
+ @param stream A pointer to an open stream previously created with Pa_OpenStream.
+
+ @note PortAudio manages the memory referenced by the returned pointer,
+ the client must not manipulate or free the memory. The pointer is only
+ guaranteed to be valid until the specified stream is closed.
+
+ @see PaStreamInfo
+*/
+const PaStreamInfo* Pa_GetStreamInfo( PaStream *stream );
+
+
+/** Determine the current time for the stream according to the same clock used
+ to generate buffer timestamps. This time may be used for syncronising other
+ events to the audio stream, for example synchronizing audio to MIDI.
+
+ @return The stream's current time in seconds, or 0 if an error occurred.
+
+ @see PaTime, PaStreamCallback
+*/
+PaTime Pa_GetStreamTime( PaStream *stream );
+
+
+/** Retrieve CPU usage information for the specified stream.
+ The "CPU Load" is a fraction of total CPU time consumed by a callback stream's
+ audio processing routines including, but not limited to the client supplied
+ stream callback. This function does not work with blocking read/write streams.
+
+ This function may be called from the stream callback function or the
+ application.
+
+ @return
+ A floating point value, typically between 0.0 and 1.0, where 1.0 indicates
+ that the stream callback is consuming the maximum number of CPU cycles possible
+ to maintain real-time operation. A value of 0.5 would imply that PortAudio and
+ the stream callback was consuming roughly 50% of the available CPU time. The
+ return value may exceed 1.0. A value of 0.0 will always be returned for a
+ blocking read/write stream, or if an error occurrs.
+*/
+double Pa_GetStreamCpuLoad( PaStream* stream );
+
+
+/** Read samples from an input stream. The function doesn't return until
+ the entire buffer has been filled - this may involve waiting for the operating
+ system to supply the data.
+
+ @param stream A pointer to an open stream previously created with Pa_OpenStream.
+
+ @param buffer A pointer to a buffer of sample frames. The buffer contains
+ samples in the format specified by the inputParameters->sampleFormat field
+ used to open the stream, and the number of channels specified by
+ inputParameters->numChannels. If non-interleaved samples were requested,
+ buffer is a pointer to the first element of an array of non-interleaved
+ buffer pointers, one for each channel.
+
+ @param frames The number of frames to be read into buffer. This parameter
+ is not constrained to a specific range, however high performance applications
+ will want to match this parameter to the framesPerBuffer parameter used
+ when opening the stream.
+
+ @return On success PaNoError will be returned, or PaInputOverflowed if input
+ data was discarded by PortAudio after the previous call and before this call.
+*/
+PaError Pa_ReadStream( PaStream* stream,
+ void *buffer,
+ unsigned long frames );
+
+
+/** Write samples to an output stream. This function doesn't return until the
+ entire buffer has been consumed - this may involve waiting for the operating
+ system to consume the data.
+
+ @param stream A pointer to an open stream previously created with Pa_OpenStream.
+
+ @param buffer A pointer to a buffer of sample frames. The buffer contains
+ samples in the format specified by the outputParameters->sampleFormat field
+ used to open the stream, and the number of channels specified by
+ outputParameters->numChannels. If non-interleaved samples were requested,
+ buffer is a pointer to the first element of an array of non-interleaved
+ buffer pointers, one for each channel.
+
+ @param frames The number of frames to be written from buffer. This parameter
+ is not constrained to a specific range, however high performance applications
+ will want to match this parameter to the framesPerBuffer parameter used
+ when opening the stream.
+
+ @return On success PaNoError will be returned, or paOutputUnderflowed if
+ additional output data was inserted after the previous call and before this
+ call.
+*/
+PaError Pa_WriteStream( PaStream* stream,
+ const void *buffer,
+ unsigned long frames );
+
+
+/** Retrieve the number of frames that can be read from the stream without
+ waiting.
+
+ @return Returns a non-negative value representing the maximum number of frames
+ that can be read from the stream without blocking or busy waiting or, a
+ PaErrorCode (which are always negative) if PortAudio is not initialized or an
+ error is encountered.
+*/
+signed long Pa_GetStreamReadAvailable( PaStream* stream );
+
+
+/** Retrieve the number of frames that can be written to the stream without
+ waiting.
+
+ @return Returns a non-negative value representing the maximum number of frames
+ that can be written to the stream without blocking or busy waiting or, a
+ PaErrorCode (which are always negative) if PortAudio is not initialized or an
+ error is encountered.
+*/
+signed long Pa_GetStreamWriteAvailable( PaStream* stream );
+
+
+/* Miscellaneous utilities */
+
+
+/** Retrieve the size of a given sample format in bytes.
+
+ @return The size in bytes of a single sample in the specified format,
+ or paSampleFormatNotSupported if the format is not supported.
+*/
+PaError Pa_GetSampleSize( PaSampleFormat format );
+
+
+/** Put the caller to sleep for at least 'msec' milliseconds. This function is
+ provided only as a convenience for authors of portable code (such as the tests
+ and examples in the PortAudio distribution.)
+
+ The function may sleep longer than requested so don't rely on this for accurate
+ musical timing.
+*/
+void Pa_Sleep( long msec );
+
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* PORTAUDIO_H */