--- /dev/null
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="GENERATOR" content="Mozilla/4.79 [en] (Windows NT 5.0; U) [Netscape]">
+ <meta name="Author" content="Phil Burk">
+ <meta name="Description" content="PortAudio Docs, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
+ <meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
+ <title>PortAudio Docs</title>
+</head>
+<body>
+
+<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
+<tr>
+<td>
+<center>
+<h1>
+PortAudio Documentation</h1></center>
+</td>
+</tr>
+</table></center>
+
+<p>Copyright 2000 Phil Burk and Ross Bencina
+<br>
+<h3>
+<a href="portaudio_h.txt">API Reference</a></h3>
+
+<blockquote>The Application Programmer Interface is documented in "portaudio.h".</blockquote>
+
+<h3>
+<a href="pa_tutorial.html">Tutorial</a></h3>
+
+<blockquote>Describes how to write audio programs using the PortAudio API.</blockquote>
+
+<h3>
+<a href="pa_impl_guide.html">Implementation Guide</a></h3>
+
+<blockquote>Describes how to write an implementation of PortAudio for a
+new computer platform.</blockquote>
+
+<h3>
+<a href="portaudio_icmc2001.pdf">Paper Presented at ICMC2001</a> (PDF)</h3>
+
+<blockquote>Describes the PortAudio API and discusses implementation issues.
+Written July 2001.</blockquote>
+
+<h3>
+<a href="latency.html">Improving Latency</a></h3>
+
+<blockquote>How to tune your computer to achieve the lowest possible audio
+delay.</blockquote>
+
+<h3>
+<a href="proposals.html">Proposed Changes</a></h3>
+
+<blockquote>Describes API changes being considered by the developer community.
+Feedback welcome.</blockquote>
+<a href="http://www.portaudio.com/">Return to PortAudio Home Page</a>
+</body>
+</html>
--- /dev/null
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="GENERATOR" content="Mozilla/4.79 [en] (Windows NT 5.0; U) [Netscape]">
+ <meta name="Author" content="Phil Burk">
+ <meta name="Description" content="Internal docs. How a stream is started or stopped.">
+ <meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
+ <title>PortAudio Implementation - Start/Stop</title>
+</head>
+<body>
+
+<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
+<tr>
+<td>
+<center>
+<h1>
+<a href="http://www.portaudio.com">PortAudio</a> Latency</h1></center>
+</td>
+</tr>
+</table></center>
+
+<p>This page discusses the issues of audio latency for <a href="http://www.portaudio.com">PortAudio</a>
+. It offers suggestions on how to lower latency to improve the responsiveness
+of applications.
+<blockquote><b><a href="#what">What is Latency?</a></b>
+<br><b><a href="#portaudio">PortAudio and Latency</a></b>
+<br><b><a href="#macintosh">Macintosh</a></b>
+<br><b><a href="#unix">Unix</a></b>
+<br><b><a href="#windows">WIndows</a></b></blockquote>
+By Phil Burk, Copyright 2002 Phil Burk and Ross Bencina
+<h2>
+<a NAME="what"></a>What is Latency?</h2>
+Latency is basically longest time that you have to wait before you obtain
+a desired result. For digital audio output it is the time between making
+a sound in software and finally hearing it.
+<p>Consider the example of pressing a key on the ASCII keyboard to play
+a note. There are several stages in this process which each contribute
+their own latency. First the operating system must respond to the keypress.
+Then the audio signal generated must work its way through the PortAudio
+buffers. Then it must work its way through the audio card hardware. Then
+it must go through the audio amplifier which is very quick and then travel
+through the air. Sound travels at abous one foot per millisecond through
+air so placing speakers across the room can add 5-20 msec of delay.
+<p>The reverse process occurs when recording or responding to audio input.
+If you are processing audio, for example if you implement a software guitar
+fuzz box, then you have both the audio input and audio output latencies
+added together.
+<p>The audio buffers are used to prevent glitches in the audio stream.
+The user software writes audio into the output buffers. That audio is read
+by the low level audio driver or by DMA and sent to the DAC. If the computer
+gets busy doing something like reading the disk or redrawing the screen,
+then it may not have time to fill the audio buffer. The audio hardware
+then runs out of audio data, which causes a glitch. By using a large enough
+buffer we can ensure that there is always enough audio data for the audio
+hardware to play. But if the buffer is too large then the latency is high
+and the system feels sluggish. If you play notes on the keyboard then the
+"instrument" will feel unresponsive. So you want the buffers to be as small
+as possible without glitching.
+<h2>
+<a NAME="portaudio"></a>PortAudio and Latency</h2>
+The only delay that PortAudio can control is the total length of its buffers.
+The Pa_OpenStream() call takes two parameters: numBuffers and framesPerBuffer.
+The latency is also affected by the sample rate which we will call framesPerSecond.
+A frame is a set of samples that occur simultaneously. For a stereo stream,
+a frame is two samples.
+<p>The latency in milliseconds due to this buffering is:
+<blockquote><tt>latency_msec = 1000 * numBuffers * framesPerBuffer / framesPerSecond</tt></blockquote>
+This is not the total latency, as we have seen, but it is the part we can
+control.
+<p>If you call Pa_OpenStream() with numBuffers equal to zero, then PortAudio
+will select a conservative number that will prevent audio glitches. If
+you still get glitches, then you can pass a larger value for numBuffers
+until the glitching stops. if you try to pass a numBuffers value that is
+too small, then PortAudio will use its own idea of the minimum value.
+<p>PortAudio decides on the minimum number of buffers in a conservative
+way based on the frameRate, operating system and other variables. You can
+query the value that PortAudio will use by calling:
+<blockquote><tt>int Pa_GetMinNumBuffers( int framesPerBuffer, double sampleRate
+);</tt></blockquote>
+On some systems you can override the PortAudio minimum if you know your
+system can handle a lower value. You do this by setting an environment
+variable called PA_MIN_LATENCY_MSEC which is read by PortAudio when it
+starts up. This is supported on the PortAudio implementations for Windows
+MME, Windows DirectSound, and Unix OSS.
+<h2>
+<a NAME="macintosh"></a>Macintosh</h2>
+The best thing you can do to improve latency on Mac OS 8 and 9 is to turn
+off Virtual Memory. PortAudio V18 will detect that Virtual Memory is turned
+off and use a very low latency.
+<p>For Mac OS X the latency is very low because Apple Core Audio is so
+well written. You can set the PA_MIN_LATENCY_MSEC variable using:
+<blockquote><tt>setenv PA_MIN_LATENCY_MSEC 4</tt></blockquote>
+
+<h2>
+<a NAME="unix"></a>Unix</h2>
+PortAudio under Unix currently uses a backgroud thread that reads and writes
+to OSS. This gives you decent but not great latency. But if you raise the
+priority of the background thread to a very priority then you can get under
+10 milliseconds latency. In order to raise your priority you must run the
+PortAudio program as root! You must also set PA_MIN_LATENCY_MSEC using
+the appropriate command for your shell.
+<h2>
+<a NAME="windows"></a>Windows</h2>
+Latency under Windows is a complex issue because of all the alternative
+operating system versions and device drivers. I have seen latency range
+from 8 milliseconds to 400 milliseconds. The worst case is when using Windows
+NT. Windows 98 is a little better, and Windows XP can be quite good if
+properly tuned.
+<p>The underlying audio API also makes a lot of difference. If the audio
+device has its own DirectSound driver then DirectSound can often provide
+better latency than WMME. But if a real DirectSound driver is not available
+for your device then it is emulated using WMME and the latency can be very
+high. That's where I saw the 400 millisecond latency. The ASIO implementation
+is generally very good and will give the lowest latency if available.
+<p>You can set the PA_MIN_LATENCY_MSEC variable to 50, for example, by
+entering in MS-DOS:
+<blockquote><tt>set PA_MIN_LATENCY_MSEC=50</tt></blockquote>
+If you enter this in a DOS window then you must run the PortAudio program
+from that same window for the variable to have an effect. You can add that
+line to your C:\AUTOEXEC.BAT file and reboot if you want it to affect any
+PortAudio based program.
+<p>For Windows XP, you can set environment variables as follows:
+<ol>
+<li>
+Select "Control Panel" from the "Start Menu".</li>
+
+<li>
+Launch the "System" Control Panel</li>
+
+<li>
+Click on the "Advanced" tab.</li>
+
+<li>
+Click on the "Environment Variables" button.</li>
+
+<li>
+Click "New" button under User Variables.</li>
+
+<li>
+Enter PA_MIN_LATENCY_MSEC for the name and some optimistic number for the
+value.</li>
+
+<li>
+Click OK, OK, OK.</li>
+</ol>
+
+<h3>
+Improving Latency on Windows</h3>
+There are several steps you can take to improve latency under windows.
+<ol>
+<li>
+Avoid reading or writng to disk when doing audio.</li>
+
+<li>
+Turn off all automated background tasks such as email clients, virus scanners,
+backup programs, FTP servers, web servers, etc. when doing audio.</li>
+
+<li>
+Disconnect from the network to prevent network traffic from interrupting
+your CPU.</li>
+</ol>
+<b>Important: </b>Windows XP users can also tune the OS to favor background
+tasks, such as audio, over foreground tasks, such as word processing. I
+lowered my latency from 40 to 10 milliseconds using this simple technique.
+<ol>
+<li>
+Select "Control Panel" from the "Start Menu".</li>
+
+<li>
+Launch the "System" Control Panel</li>
+
+<li>
+Click on the "Advanced" tab.</li>
+
+<li>
+Click on the "Settings" button in the Performance area.</li>
+
+<li>
+Click on the "Advanced" tab.</li>
+
+<li>
+Select "Background services" in the Processor Scheduling area.</li>
+
+<li>
+Click OK, OK.</li>
+</ol>
+Please let us know if you have others sugestions for lowering latency.
+<br>
+<br>
+</body>
+</html>
--- /dev/null
+/*
+ This file contains the host-neutral code for implementing multiple driver model
+ support in PortAudio.
+
+ It has not been compiled, but it is supplied only for example purposes at this stage.
+
+ TODO: use of CHECK_DRIVER_MODEL is bogus in some instances since some
+ of those functions don't return a PaError
+
+
+*/
+
+#include "pa_drivermodel.h.txt"
+
+
+#ifndef PA_MULTIDRIVER
+/* single driver support, most functions will stay in the implementation files */
+
+PaDriverModelID Pa_CountDriverModels()
+{
+ return 1;
+}
+
+/*
+Perhaps all drivers should define this with this signature
+const PaDriverModelInfo* Pa_GetDriverModelInfo( PaDriverModelID driverModelID )
+{
+}
+*/
+
+PaDeviceID Pa_DriverModelDefaultInputDeviceID( PaDriverModelID driverModelID )
+{
+ return Pa_GetDefaultInputDeviceID();
+}
+
+
+PaDeviceID Pa_DriverModelDefaultOutputDeviceID( PaDriverModelID driverModelID )
+{
+ return Pa_GetDefaultInputDeviceID();
+}
+
+/*
+Perhaps all drivers should define with this signature
+int Pa_DriverModelMinNumBuffers( PaDriverModelID driverModelID, int framesPerBuffer, double sampleRate )
+{
+
+}
+*/
+
+int Pa_DriverModelCountDevices( PaDriverModelID driverModelID )
+{
+ return Pa_CountDevices();
+}
+
+PaDeviceID Pa_DriverModelGetDeviceID(PaDriverModelID driverModelID, int perDriverModelIndex )
+{
+ return perDriverModelIndex;
+}
+
+
+#else
+/* multidriver support */
+
+
+typedef PaError (*PaInitializeFunPtr)( PaDriverModelImplementation** );
+
+/*
+ the initializers array is a static table of function pointers
+ to all the available driverModels on the current platform.
+
+ the order of pointers in the array is important. the first
+ pointer is always considered to be the "default" driver model.
+*/
+
+static PaInitializeFunPtr driverModelInitializers[] = {
+#ifdef WINDOWS
+ PaWin32WMME_MultiDriverInitialize,
+ PaWin32DS_MultiDriverInitialize,
+ PaASIO_MultiDriverInitialize
+#endif
+#ifdef MAC
+ PaMacSM_MultiDriverInitialize,
+ PaMacCA_MultiDriverInitialize,
+ PaASIO_MultiDriverInitialize
+#endif
+/* other platforms here */
+ (PaInitializeFunPtr*)0 /* NULL terminate the list */
+};
+
+
+/*
+ the driverModels array is a dynamically created table of
+ currently available driverModels.
+*/
+static PaDriverModelImplementation* driverModels = 0;
+static int numDriverModels = 0;
+
+
+#define PA_CHECK_INITIALIZED\
+ if( driverModels == 0 )
+ return paLibraryNotInitialised
+
+#define PA_CHECK_DRIVER_MODEL_ID( id )
+ if( id < 0 || id >= numDriverModels )
+ return paBadDriverModelID;
+
+
+/*
+ ConvertPublicDeviceIdToImplementationDeviceId converts deviceId
+ from a public device id, to a device id for a particular
+ PortAudio implementation. On return impl will either point
+ to a valid implementation or will be NULL.
+*/
+static void ConvertPublicDeviceIDToImplementationDeviceID(
+ PaDriverModelImplementation *impl, PaDeviceID deviceID )
+{
+ int i, count;
+
+ impl = NULL;
+
+ for( i=0; i < numDriverModels; ++i ){
+ count = driverModels[i]->countDevices();
+ if( deviceID < count ){
+ impl = driverModels[i];
+ return NULL;
+ }else{
+ deviceID -= count;
+ }
+ }
+}
+
+static PaDeviceID ConvertImplementationDeviceIDToPublicDeviceID(
+ PaDriverModelID driverModelID, PaDeviceID deviceID )
+{
+ int i;
+
+ for( i=0; i < driverModelID; ++i )
+ deviceID += driverModels[i]->countDevices();
+}
+
+
+PaError Pa_Initialize( void )
+{
+ PaError result = paNoError;
+ int i, initializerCount;
+ PaDriverModelImplementation *impl;
+
+ if( driverModels != 0 )
+ return paAlreadyInitialized;
+
+ /* count the number of driverModels */
+ initializerCount=0;
+ while( driverModelInitializers[initializerCount] != 0 ){
+ ++initializerCount;
+ }
+
+ driverModels = malloc( sizeof(PaDriverModelImplementation*) * initializerCount );
+ if( driverModels == NULL )
+ return paInsufficientMemory;
+
+ numDriverModels = 0;
+ for( i=0; i<initializerCount; ++i ){
+ result = (*driverModelInitializers[i])( &impl );
+ if( result == paNoError ){
+ driverModels[numDriverModels] = impl;
+ ++numDriverModels;
+ }else{
+ // TODO: terminate the drivers which have already been initialized.
+ }
+ }
+
+ return result;
+}
+
+
+
+PaError Pa_Terminate( void )
+{
+ int i;
+
+ PA_CHECK_INITIALIZED;
+
+ /*
+ rather than require each implementation to do it separately we could
+ keep track of all open streams and close them here
+ */
+
+ for( i=0; i<numDriverModels; ++i )
+ driverModels[i]->terminate( driverModels[i] );
+}
+
+
+long Pa_GetHostError( void )
+{
+ PA_CHECK_INITIALIZED;
+
+ under construction. depends on error text proposal.
+}
+
+
+const char *Pa_GetErrorText( PaError errnum )
+{
+ PA_CHECK_INITIALIZED;
+
+ under construction. may need to call driver model specific code
+ depending on how the error text proposal pans out.
+}
+
+
+
+int Pa_CountDevices()
+{
+ int i, result;
+
+ PA_CHECK_INITIALIZED;
+
+ result = 0;
+ for( i=0; i < numDriverModels; ++i )
+ result += driverModels[i]->countDevices();
+
+ return result;
+}
+
+
+PaDeviceID Pa_GetDefaultInputDeviceID( void )
+{
+ PA_CHECK_INITIALIZED;
+
+ return driverModels[0]->getDefaultInputDeviceID();
+}
+
+PaDeviceID Pa_GetDefaultOutputDeviceID( void )
+{
+ PA_CHECK_INITIALIZED;
+
+ return driverModels[0]->getDefaultInputDeviceID();
+}
+
+
+const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceID deviceID )
+{
+ PaDriverModelImplementation *impl;
+
+ PA_CHECK_INITIALIZED;
+
+ ConvertPublicDeviceIDToImplementationDeviceID( impl, deviceID );
+ if( impl == NULL )
+ return paInvalidDeviceID;
+
+ return impl->getDeviceInfo( deviceID );
+}
+
+/* NEW MULTIPLE DRIVER MODEL FUNCTIONS ---------------------------------- */
+
+PaDriverModelID Pa_CountDriverModels()
+{
+ PA_CHECK_INITIALIZED;
+
+ return numDriverModels;
+}
+
+
+const PaDriverModelInfo* Pa_GetDriverModelInfo( PaDriverModelID driverModelID )
+{
+ PA_CHECK_INITIALIZED;
+ PA_CHECK_DRIVER_MODEL_ID( driverModelID );
+
+ return driverModels[ driverModelID ]->getDriverModelInfo();
+}
+
+
+PaDeviceID Pa_DriverModelDefaultInputDeviceID( PaDriverModelID driverModelID )
+{
+ PA_CHECK_INITIALIZED;
+ PA_CHECK_DRIVER_MODEL_ID( driverModelID );
+
+ return ConvertImplementationDeviceIDToPublicDeviceID( driverModelID,
+ driverModels[ driverModelID ]->getDefaultInputDeviceID();
+}
+
+
+PaDeviceID Pa_DriverModelDefaultOutputDeviceID( PaDriverModelID driverModelID )
+{
+ PA_CHECK_INITIALIZED;
+ PA_CHECK_DRIVER_MODEL_ID( driverModelID );
+
+ return ConvertImplementationDeviceIDToPublicDeviceID( driverModelID,
+ driverModels[ driverModelID ]->getDefaultOutputDeviceID();
+}
+
+
+int Pa_DriverModelMinNumBuffers( PaDriverModelID driverModelID, int framesPerBuffer, double sampleRate )
+{
+ PA_CHECK_INITIALIZED;
+ PA_CHECK_DRIVER_MODEL_ID( driverModelID );
+
+ return driverModels[ driverModelID ]->getMinNumBuffers( int framesPerBuffer, double sampleRate );
+}
+
+
+int Pa_DriverModelCountDevices( PaDriverModelID driverModelID )
+{
+ PA_CHECK_INITIALIZED;
+ PA_CHECK_DRIVER_MODEL_ID( driverModelID );
+
+ return driverModels[ driverModelID ]->coundDevices();
+}
+
+PaDeviceID Pa_DriverModelGetDeviceID(PaDriverModelID driverModelID, int perDriverModelIndex )
+{
+ PA_CHECK_INITIALIZED;
+ PA_CHECK_DRIVER_MODEL_ID( driverModelID );
+
+ return ConvertImplementationDeviceIDToPublicDeviceID( driverModelID, perDriverModelIndex );
+}
+
+/* END NEW MULTIPLE DRIVER MODEL FUNCTIONS ------------------------------ */
+
+
+PaError Pa_OpenStream( PortAudioStream** stream,
+ PaDeviceID inputDevice,
+ int numInputChannels,
+ PaSampleFormat inputSampleFormat,
+ void *inputDriverInfo,
+ PaDeviceID outputDevice,
+ int numOutputChannels,
+ PaSampleFormat outputSampleFormat,
+ void *outputDriverInfo,
+ double sampleRate,
+ unsigned long framesPerBuffer,
+ unsigned long numberOfBuffers,
+ PaStreamFlags streamFlags,
+ PortAudioCallback *callback,
+ void *userData )
+{
+ PaError result;
+ PaDriverModelImplementation *inputImpl, *outputImpl, impl;
+
+ PA_CHECK_INITIALIZED;
+
+ if( inputDevice != paNoDevice ){
+ ConvertPublicDeviceIDToImplementationDeviceID( inputImpl, inputDevice );
+ if( inputImpl == NULL )
+ return paInvalidDeviceID;
+ else
+ impl = inputImpl;
+ }
+
+ if( outputDevice != paNoDevice ){
+ ConvertPublicDeviceIDToImplementationDeviceID( outputImpl, outputDevice );
+ if( outputImpl == NULL )
+ return paInvalidDeviceID;
+ else
+ impl = outputImpl;
+ }
+
+ if( inputDevice != paNoDevice && outputDevice != paNoDevice ){
+ if( inputImpl != outputImpl )
+ return paDevicesMustBelongToTheSameDriverModel;
+ }
+
+
+ result = impl->openStream( stream, inputDevice, numInputChannels, inputSampleFormat, inputDriverInfo,
+ outputDevice, numOutputChannels, outputSampleFormat, outputDriverInfo,
+ sampleRate, framesPerBuffer, numberOfBuffers, streamFlags, callback, userData );
+
+
+ if( result == paNoError )
+ ((PaStreamImplementation*)stream)->magic = PA_STREAM_MAGIC;
+
+ return result;
+}
+
+
+PaError Pa_OpenDefaultStream( PortAudioStream** stream,
+ int numInputChannels,
+ int numOutputChannels,
+ PaSampleFormat sampleFormat,
+ double sampleRate,
+ unsigned long framesPerBuffer,
+ unsigned long numberOfBuffers,
+ PortAudioCallback *callback,
+ void *userData )
+{
+ PaError result;
+ int inputDevice = driverModels[0]->getDefaultInputDeviceID;
+ int outputDevice = driverModels[0]->getDefaultOutputDeviceID;
+
+ result = driverModels[0]->openStream( stream, inputDevice, numInputChannels, sampleFormat, 0,
+ outputDevice, numOutputChannels, sampleFormat, 0,
+ sampleRate, framesPerBuffer, numberOfBuffers,
+ streamFlags, callback, userData );
+
+ if( result == paNoError )
+ ((PaStreamImplementation*)stream)->magic = PA_STREAM_MAGIC;
+
+ return result;
+}
+
+
+PaError Pa_CloseStream( PortAudioStream* stream )
+{
+ PA_CHECK_INITIALIZED;
+
+ PaError result = ((PaStreamImplementation*)stream)->close();
+
+ if( result == PaNoError )
+ ((PaStreamImplementation*)stream)->magic = 0; /* clear magic number */
+
+ return result;
+}
+
+
+PaError Pa_StartStream( PortAudioStream *stream );
+{
+ PA_CHECK_INITIALIZED;
+
+ return ((PaStreamImplementation*)stream)->start();
+}
+
+
+PaError Pa_StopStream( PortAudioStream *stream );
+{
+ PA_CHECK_INITIALIZED;
+
+ return ((PaStreamImplementation*)stream)->stop();
+}
+
+
+PaError Pa_AbortStream( PortAudioStream *stream );
+{
+ PA_CHECK_INITIALIZED;
+
+ return ((PaStreamImplementation*)stream)->abort();
+}
+
+
+PaError Pa_StreamActive( PortAudioStream *stream )
+{
+ PA_CHECK_INITIALIZED;
+
+ return ((PaStreamImplementation*)stream)->active();
+}
+
+PaTimestamp Pa_StreamTime( PortAudioStream *stream )
+{
+ PA_CHECK_INITIALIZED;
+
+ return ((PaStreamImplementation*)stream)->time();
+}
+
+
+double Pa_StreamCPULoad( PortAudioStream* stream )
+{
+ PA_CHECK_INITIALIZED;
+
+ return ((PaStreamImplementation*)stream)->cpuLoad();
+}
+
+
+
+int Pa_GetMinNumBuffers( PaDeviceID deviceID, int framesPerBuffer, double sampleRate )
+{
+ PaDriverModelImplementation *impl;
+ PA_CHECK_INITIALIZED;
+
+ ConvertPublicDeviceIDToImplementationDeviceID( impl, deviceID );
+ if( impl == NULL )
+ return paInvalidDeviceID;
+
+ return impl->getMinNumBuffers( framesPerBuffer, sampleRate );
+}
+
+
+void Pa_Sleep( long msec )
+{
+ same as existing implementaion
+}
+
+
+PaError Pa_GetSampleSize( PaSampleFormat format )
+{
+ same as existing implementation
+}
+
+#endif /* PA_MULTIDRIVER */
+
+
--- /dev/null
+#ifndef PA_MULTIDRIVERMODEL_H
+#define PA_MULTIDRIVERMODEL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/*
+ This file contains the host-neutral code for implementing multiple driver model
+ support in PortAudio.
+
+ It has not been compiled, but it is supplied only for example purposes at this stage.
+*/
+
+
+#include "portaudio.h"
+
+
+#define PA_MULTIDRIVER // for multidriver support
+
+
+
+TODO: declare function pointer types for the following function pointers
+
+/*
+ Each driver model implementation needs to implement an initialize function
+ which is added to the driverModelInitializers array in pa_multidrivermodel.c
+
+ the initializer function needs to return a pointer to a
+ PaDriverModelImplementation structure, or NULL if initiliazation failed. TODO: need error code instead
+
+ the function pointer members of this structure point to funtions
+ which operate in exactly the same way as the corresponding functions
+ in the PortAudio API.
+*/
+
+struct{
+ fptr terminate; /* takes the PaDriverModelImplementation* returned by initialize */
+ fptr getDriverModelInfo;
+ fptr getHostError;
+ fptr getHostErrorText;
+ fptr countDevices;
+ fptr getDefaultInputDeviceID;
+ fptr getDefaultOutputDeviceID;
+ fptr getDeviceInfo;
+ fptr openStream;
+ fptr getMinNumBuffers;
+} PaDriverModelImplementation;
+
+/*
+ whenever an implementaion's openstream method is called it should return a
+ PortAudioStream* whose first segment is actually the following structure.
+
+ the functions pointer members of this structure point to funcitons
+ which operate in exactly the same way as the corresponding functions
+ in the PortAudio API.
+*/
+struct{
+ unsigned long magic;
+ fptr close;
+ fptr start;
+ fptr stop;
+ fptr abort;
+ fptr active;
+ fptr time;
+ fptr cpuLoad;
+} PaStreamImplementation;
+
+/*
+ Implementations should set magic to PA_STREAM_MAGIC when opening
+ a stream _and_ clear it to zero when closing a stream.
+ All functions which operate on streams should check the validity
+ of magic.
+*/
+
+#define PA_STREAM_MAGIC 0x12345678
+
+#define PA_CHECK_STREAM( stream )\
+ if( ((PaStreamImplementation*)stream)->magic != PA_STREAM_MAGIC )\
+ return paBadStreamPtr;
+
+
+/*
+ PA_API allows the same implementation to be used for single
+ driver model and multi-driver model operation. If
+ PA_MULTIDRIVER not defined, PA_API will declare api
+ functions as global, otherwise they will be static, and include
+ the drivermodel code.
+
+ Usage would be something like:
+
+ int PA_API(CountDevices)();
+
+ The PA_MULTIDRIVER_SUPPORT macro declares the initialization and
+ termination functions required by the multidriver support. it also
+ allocates and deallocates the PaDriverModelImplementation structure.
+
+ TODO: add macros for initializing PaStreamImplementation PortAudioStream
+ these would be PA_INITIALIZE_STREAM and PA_TERMINATE_STREAM
+ they would assign and clear the magic number and assign the
+ interface functions if neceassary.
+*/
+
+#ifdef PA_MULTIDRIVER
+
+#define PA_API( model, name ) static Pa ## model ## _ ## name
+
+#define PA_MULTIDRIVER_SUPPORT( model )\
+PaError Pa_ ## model ## _MultiDriverTerminate( PaStreamImplementation *impl )\
+{\
+ free( impl );\
+ return Pa ## model ## _Terminate();\
+}\
+PaError Pa ## model ## _MultiDriverInitialize( PaStreamImplementation** impl )\
+{\
+ PaError result = Pa ## model ## _Initialize();\
+\
+ if( result == paNoError ){\
+ *impl = malloc( sizeof( PaDriverModelImplementation ) );\
+ if( impl == NULL ){\
+ // TODO: call terminate, return an error
+ }else{\
+ (*impl)->terminate = Pa ## model ## _MultiDriverTerminate();\
+ (*impl)->getDriverModelInfo = Pa ## model ## _GetDriverModelInfo();\
+ (*impl)->getHostError = Pa ## model ## _GetHostError();\
+ // TODO: assign the rest of the interface functions
+ }\
+ }\
+ return result;\
+}
+
+#else /* !PA_MULTIDRIVER */
+
+#define PA_API( model, name ) Pa_ ## name
+
+#define PA_MULTIDRIVER_SUPPORT
+
+#endif /* PA_MULTIDRIVER */
+
+
+
+#endif /* PA_MULTIDRIVERMODEL_H */
--- /dev/null
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="GENERATOR" content="Mozilla/4.79 [en] (Windows NT 5.0; U) [Netscape]">
+ <meta name="Author" content="Phil Burk">
+ <meta name="Description" content="Internal docs. How a stream is started or stopped.">
+ <meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
+ <title>PortAudio Implementation - Start/Stop</title>
+</head>
+<body>
+
+<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
+<tr>
+<td>
+<center>
+<h1>
+<a href="http://www.portaudio.com">PortAudio</a> Implementation Guide</h1></center>
+</td>
+</tr>
+</table></center>
+
+<p>This document describes how to implement the PortAudio API on a new
+computer platform. Implementing PortAudio on a new platform, makes it possible
+to port many existing audio applications to that platform.
+<p>By Phil Burk
+<br>Copyright 2000 Phil Burk and Ross Bencina
+<p>Note that the license says: <b>"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."</b>.
+So when you have finished a new implementation, please send it back to
+us at "<a href="http://www.portaudio.com">http://www.portaudio.com</a>"
+so that we can make it available for other users. Thank you!
+<h2>
+Download the Latest PortAudio Implementation</h2>
+Always start with the latest implementation available at "<a href="http://www.portaudio.com">http://www.portaudio.com</a>".
+Look for the nightly snapshot under the CVS section.
+<h2>
+Select an Existing Implementation as a Basis</h2>
+The fastest way to get started is to take an existing implementation and
+translate it for your new platform. Choose an implementation whose architecture
+is as close as possible to your target.
+<ul>
+<li>
+DirectSound Implementation - pa_win_ds - Uses a timer callback for the
+background "thread". Polls a circular buffer and writes blocks of data
+to keep it full.</li>
+
+<li>
+Windows MME - pa_win_wmme - Spawns an actual Win32 thread. Writes blocks
+of data to the HW device and waits for events that signal buffer completion.</li>
+
+<li>
+Linux OSS - pa_linux - Spawns a real thread that writes to the "/dev/dsp"
+stream using blocking I/O calls.</li>
+</ul>
+When you write a new implementation, you will be using some code that is
+in common with all implementations. This code is in the folder "pa_common".
+It provides various functions such as parameter checking, error code to
+text conversion, sample format conversion, clipping and dithering, etc.
+<p>The code that you write will go into a separate folder called "pa_{os}_{api}".
+For example, code specific to the DirectSound interface for Windows goes
+in "pa_win_ds".
+<h2>
+Read Docs and Code</h2>
+Famialiarize yourself with the system by reading the documentation provided.
+here is a suggested order:
+<ol>
+<li>
+User Programming <a href="pa_tutorial.html">Tutorial</a></li>
+
+<li>
+Header file "pa_common/portaudio.h" which defines API.</li>
+
+<li>
+Header file "pa_common/pa_host.h" for host dependant code. This definces
+the routine you will need to provide.</li>
+
+<li>
+Shared code in "pa_common/pa_lib.c".</li>
+
+<li>
+Docs on Implementation of <a href="pa_impl_startstop.html">Start/Stop</a>
+code.</li>
+</ol>
+
+<h2>
+Implement Output to Default Device</h2>
+Now we are ready to crank some code. For instant gratification, let's try
+to play a sine wave.
+<ol>
+<li>
+Link the test program "pa_tests/patest_sine.c" with the file "pa_lib.c"
+and the implementation specific file you are creating.</li>
+
+<li>
+For now, just stub out the device query code and the audio input code.</li>
+
+<li>
+Modify PaHost_OpenStream() to open your default target device and get everything
+setup.</li>
+
+<li>
+Modify PaHost_StartOutput() to start playing audio.</li>
+
+<li>
+Modify PaHost_StopOutput() to stop audio.</li>
+
+<li>
+Modify PaHost_CloseStream() to clean up. Free all memory that you allocated
+in PaHost_OpenStream().</li>
+
+<li>
+Keep cranking until you can play a sine wave using "patest_sine.c".</li>
+
+<li>
+Once that works, try "patest_pink.c", "patest_clip.c", "patest_sine8.c".</li>
+
+<li>
+To test your Open and Close code, try "patest_many.c".</li>
+
+<li>
+Now test to make sure that the three modes of stopping are properly supported
+by running "patest_stop.c".</li>
+
+<li>
+Test your implementation of time stamping with "patest_sync.c".</li>
+</ol>
+
+<h2>
+Implement Device Queries</h2>
+Now that output is working, lets implement the code for querying what devices
+are available to the user. Run "pa_tests/pa_devs.c". It should print all
+of the devices available and their characteristics.
+<h2>
+Implement Input</h2>
+Implement audio input and test it with:
+<ol>
+<li>
+patest_record.c - record in half duplex, play back as recorded.</li>
+
+<li>
+patest_wire.c - full duplex, copies input to output. Note that some HW
+may not support full duplex.</li>
+
+<li>
+patest_fuzz.c - plug in your guitar and get a feel for why latency is an
+important issue in computer music.</li>
+
+<li>
+paqa_devs.c - try to open every device and use it with every possible format</li>
+</ol>
+
+<h2>
+Debugging Tools</h2>
+You generally cannot use printf() calls to debug real-time processes because
+they disturb the timing. Also calling printf() from your background thread
+or interrupt could crash the machine. So PA includes a tool for capturing
+events and storing the information while it is running. It then prints
+the events when Pa_Terminate() is called.
+<ol>
+<li>
+To enable trace mode, change TRACE_REALTIME_EVENTS in "pa_common/pa_trace.h"
+from a (0) to a (1).</li>
+
+<li>
+Link with "pa_common/pa_trace.c".</li>
+
+<li>
+Add trace messages to your code by calling:</li>
+
+<br><tt> void AddTraceMessage( char *msg, int data );</tt>
+<br><tt>for example</tt>
+<br><tt> AddTraceMessage("Pa_TimeSlice: past_NumCallbacks ",
+past->past_NumCallbacks );</tt>
+<li>
+Run your program. You will get a dump of events at the end.</li>
+
+<li>
+You can leave the trace messages in your code. They will turn to NOOPs
+when you change TRACE_REALTIME_EVENTS back to (0).</li>
+</ol>
+
+<h2>
+Delivery</h2>
+Please send your new code along with notes on the implementation back to
+us at "<a href="http://www.portaudio.com">http://www.portaudio.com</a>".
+We will review the implementation and post it with your name. If you had
+to make any modifications to the code in "pa_common" or "pa_tests" <b>please</b>
+send us those modifications and your notes. We will try to merge your changes
+so that the "pa_common" code works with <b>all</b> implementations.
+<p>If you have suggestions for how to make future implementations easier,
+please let us know.
+<br>THANKS!
+<br>
+</body>
+</html>
--- /dev/null
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="GENERATOR" content="Mozilla/4.75 [en]C-gatewaynet (Win98; U) [Netscape]">
+ <meta name="Author" content="Phil Burk">
+ <meta name="Description" content="Internal docs. How a stream is started or stopped.">
+ <meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
+ <title>PortAudio Implementation - Start/Stop</title>
+</head>
+<body>
+
+<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
+<tr>
+<td>
+<center>
+<h1>
+PortAudio Implementation</h1></center>
+</td>
+</tr>
+</table></center>
+
+<h2>
+Starting and Stopping Streams</h2>
+PortAudio is generally executed in two "threads". The foreground thread
+is the application thread. The background "thread" may be implemented as
+an actual thread, an interrupt handler, or a callback from a timer thread.
+<p>There are three ways that PortAudio can stop a stream. In each case
+we look at the sequence of events and the messages sent between the two
+threads. The following variables are contained in the internalPortAudioStream.
+<blockquote><tt>int past_IsActive;
+/* Background is still playing. */</tt>
+<br><tt>int past_StopSoon; /* Stop
+when last buffer done. */</tt>
+<br><tt>int past_StopNow; /*
+Stop IMMEDIATELY. */</tt></blockquote>
+
+<h3>
+Pa_AbortStream()</h3>
+This function causes the background thread to terminate as soon as possible
+and audio I/O to stop abruptly.
+<br>
+<table BORDER COLS=2 WIDTH="60%" >
+<tr>
+<td><b>Foreground Thread</b></td>
+
+<td><b>Background Thread</b></td>
+</tr>
+
+<tr>
+<td>sets <tt>StopNow</tt></td>
+
+<td></td>
+</tr>
+
+<tr>
+<td></td>
+
+<td>sees <tt>StopNow</tt>, </td>
+</tr>
+
+<tr>
+<td></td>
+
+<td>clears IsActive, stops thread</td>
+</tr>
+
+<tr>
+<td>waits for thread to exit</td>
+
+<td></td>
+</tr>
+
+<tr>
+<td>turns off audio I/O</td>
+
+<td></td>
+</tr>
+</table>
+
+<h3>
+Pa_StopStream()</h3>
+This function stops the user callback function from being called and then
+waits for all audio data written to the output buffer to be played. In
+a system with very low latency, you may not hear any difference between
+<br>
+<table BORDER COLS=2 WIDTH="60%" >
+<tr>
+<td><b>Foreground Thread</b></td>
+
+<td><b>Background Thread</b></td>
+</tr>
+
+<tr>
+<td>sets StopSoon</td>
+
+<td></td>
+</tr>
+
+<tr>
+<td></td>
+
+<td>stops calling user callback</td>
+</tr>
+
+<tr>
+<td></td>
+
+<td>continues until output buffer empty</td>
+</tr>
+
+<tr>
+<td></td>
+
+<td>clears IsActive, stops thread</td>
+</tr>
+
+<tr>
+<td>waits for thread to exit</td>
+
+<td></td>
+</tr>
+
+<tr>
+<td>turns off audio I/O</td>
+
+<td></td>
+</tr>
+</table>
+
+<h3>
+User callback returns one.</h3>
+If the user callback returns one then the user callback function will no
+longer be called. Audio output will continue until all audio data written
+to the output buffer has been played. Then the audio I/O is stopped, the
+background thread terminates, and the stream becomes inactive.
+<br>
+<table BORDER COLS=2 WIDTH="60%" >
+<tr>
+<td><b>Foreground Thread</b></td>
+
+<td><b>Background Thread</b></td>
+</tr>
+
+<tr>
+<td></td>
+
+<td>callback returns 1</td>
+</tr>
+
+<tr>
+<td></td>
+
+<td>sets StopSoon</td>
+</tr>
+
+<tr>
+<td></td>
+
+<td>stops calling user callback</td>
+</tr>
+
+<tr>
+<td></td>
+
+<td>continues until output buffer empty</td>
+</tr>
+
+<tr>
+<td></td>
+
+<td>clears IsActive, stops thread</td>
+</tr>
+
+<tr>
+<td>waits for thread to exit</td>
+
+<td></td>
+</tr>
+
+<tr>
+<td>turns off audio I/O</td>
+
+<td></td>
+</tr>
+</table>
+
+<br>
+</body>
+</html>
--- /dev/null
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="GENERATOR" content="Mozilla/4.77 [en]C-gatewaynet (Win98; U) [Netscape]">
+ <meta name="Author" content="Phil Burk">
+ <meta name="Description" content="Tutorial for PortAudio, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
+ <meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
+ <title>PortAudio Tutorial</title>
+</head>
+<body>
+
+<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
+<tr>
+<td>
+<center>
+<h1>
+PortAudio Tutorial</h1></center>
+</td>
+</tr>
+</table></center>
+
+<h2>
+Compiling for ASIO (Windows or Macintosh)</h2>
+
+<blockquote>ASIO is a low latency audio API from Steinberg. To compile
+an ASIO application, you must first <a href="http://www.steinberg.net/developers/ASIO2SDKAbout.phtml">download
+the ASIO SDK</a> from Steinberg. You also need to obtain ASIO drivers for
+your audio device.
+<p>Note: I am using '/' as a file separator below. On Macintosh replace
+'/' with ':'. On Windows, replace '/' with '\'.
+<p> To use ASIO with the PortAudio library add the following source
+files to your project:
+<blockquote>
+<pre>pa_asio/pa_asio.cpp</pre>
+</blockquote>
+and also these files from the ASIO SDK:
+<blockquote>
+<pre>common/asio.cpp
+host/asiodrivers.cpp
+host/asiolist.cpp</pre>
+</blockquote>
+and add these directories to the path for include files
+<blockquote>
+<pre>asiosdk2/host/pc (for Windows)
+asiosdk2/common
+asiosdk2/host</pre>
+</blockquote>
+You may try compiling the "pa_tests/patest_saw.c" file first because it
+is the simplest.</blockquote>
+<font size=+2><a href="http://www.portaudio.com/">home</a> |
+<a href="pa_tutorial.html">contents</a>
+| <a href="pa_tut_over.html">previous</a> | <a href="pa_tut_callback.html">next</a></font>
+</body>
+</html>
--- /dev/null
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="GENERATOR" content="Mozilla/4.77 [en]C-gatewaynet (Win98; U) [Netscape]">
+ <meta name="Author" content="Phil Burk">
+ <meta name="Description" content="Tutorial for PortAudio, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
+ <meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
+ <title>PortAudio Tutorial</title>
+</head>
+<body>
+
+<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
+<tr>
+<td>
+<center>
+<h1>
+PortAudio Tutorial</h1></center>
+</td>
+</tr>
+</table></center>
+
+<h2>
+Writing a Callback Function</h2>
+
+<blockquote>To write a program using PortAudio, you must include the "portaudio.h"
+include file. You may wish to read "<a href="portaudio_h.txt">portaudio.h</a>"
+because it contains a complete description of the PortAudio functions and
+constants.
+<blockquote>
+<pre>#include "portaudio.h"</pre>
+</blockquote>
+The next task is to write your custom callback function. It is a function
+that is called by the PortAudio engine whenever it has captured audio data,
+or when it needs more audio data for output.
+<p>Your callback function is often called by an interrupt, or low level
+process so you should not do any complex system activities like allocating
+memory, or reading or writing files, or printf(). Just crunch numbers and
+generate audio signals. What is safe or not safe will vary from platform
+to platform. On the Macintosh, for example, you can only call "interrupt
+safe" routines. Also do not call any PortAudio functions in the callback
+except for Pa_StreamTime() and Pa_GetCPULoad().
+<p>Your callback function must return an int and accept the exact parameters
+specified in this typedef:
+<blockquote>
+<pre>typedef int (PortAudioCallback)(
+ void *inputBuffer, void *outputBuffer,
+ unsigned long framesPerBuffer,
+ PaTimestamp outTime, void *userData );</pre>
+</blockquote>
+Here is an example callback function from the test file "patests/patest_saw.c".
+It calculates a simple left and right sawtooth signal and writes it to
+the output buffer. Notice that in this example, the signals are of <tt>float</tt>
+data type. The signals must be between -1.0 and +1.0. You can also use
+16 bit integers or other formats which are specified during setup. You
+can pass a pointer to your data structure through PortAudio which will
+appear as <tt>userData</tt>.
+<blockquote>
+<pre>int patestCallback( void *inputBuffer, void *outputBuffer,
+ unsigned long framesPerBuffer,
+ PaTimestamp outTime, void *userData )
+{
+ unsigned int i;
+/* Cast data passed through stream to our structure type. */
+ paTestData *data = (paTestData*)userData;
+ float *out = (float*)outputBuffer;
+
+ for( i=0; i<framesPerBuffer; i++ )
+ {
+ /* Stereo channels are interleaved. */
+ *out++ = data->left_phase; /* left */
+ *out++ = data->right_phase; /* right */
+
+ /* Generate simple sawtooth phaser that ranges between -1.0 and 1.0. */
+ data->left_phase += 0.01f;
+ /* When signal reaches top, drop back down. */
+ if( data->left_phase >= 1.0f ) data->left_phase -= 2.0f;
+
+ /* higher pitch so we can distinguish left and right. */
+ data->right_phase += 0.03f;
+ if( data->right_phase >= 1.0f ) data->right_phase -= 2.0f;
+ }
+ return 0;
+}</pre>
+</blockquote>
+</blockquote>
+<font size=+2><a href="http://www.portaudio.com/">home</a> |
+<a href="pa_tutorial.html">contents</a>
+| <a href="pa_tut_over.html">previous</a> | <a href="pa_tut_init.html">next</a></font>
+</body>
+</html>
--- /dev/null
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="GENERATOR" content="Mozilla/4.75 [en]C-gatewaynet (Win98; U) [Netscape]">
+ <meta name="Author" content="Phil Burk">
+ <meta name="Description" content="Tutorial for PortAudio, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
+ <meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
+ <title>PortAudio Tutorial</title>
+</head>
+<body>
+
+<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
+<tr>
+<td>
+<center>
+<h1>
+PortAudio Tutorial</h1></center>
+</td>
+</tr>
+</table></center>
+
+<h2>
+Querying for Available Devices</h2>
+
+<blockquote>There are often several different audio devices available in
+a computer with different capabilities. They can differ in the sample rates
+supported, bit widths, etc. PortAudio provides a simple way to query for
+the available devices, and then pass the selected device to Pa_OpenStream().
+For an example, see the file "pa_tests/pa_devs.c".
+<p>To determine the number of devices:
+<blockquote>
+<pre>numDevices = Pa_CountDevices();</pre>
+</blockquote>
+You can then query each device in turn by calling Pa_GetDeviceInfo() with
+an index.
+<blockquote>
+<pre>for( i=0; i<numDevices; i++ ) {
+ pdi = Pa_GetDeviceInfo( i );</pre>
+</blockquote>
+It will return a pointer to a <tt>PaDeviceInfo</tt> structure which is
+defined as:
+<blockquote>
+<pre>typedef struct{
+ int structVersion;
+ const char *name;
+ int maxInputChannels;
+ int maxOutputChannels;
+/* Number of discrete rates, or -1 if range supported. */
+ int numSampleRates;
+/* Array of supported sample rates, or {min,max} if range supported. */
+ const double *sampleRates;
+ PaSampleFormat nativeSampleFormat;
+}PaDeviceInfo;</pre>
+</blockquote>
+If the device supports a continuous range of sample rates, then numSampleRates
+will equal -1, and the sampleRates array will have two values, the minimum
+and maximum rate.
+<p>The device information is allocated by Pa_Initialize() and freed by
+Pa_Terminate() so you do not have to free() the structure returned by Pa_GetDeviceInfo().</blockquote>
+<font size=+2><a href="http://www.portaudio.com/">home</a> |
+<a href="pa_tutorial.html">contents</a>
+| <a href="pa_tut_util.html">previous</a> | <a href="pa_tut_rw.html">next</a></font>
+</body>
+</html>
--- /dev/null
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="GENERATOR" content="Mozilla/4.73 [en]C-gatewaynet (Win98; U) [Netscape]">
+ <meta name="Author" content="Phil Burk">
+ <meta name="Description" content="Tutorial for PortAudio, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
+ <meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
+ <title>PortAudio Tutorial</title>
+</head>
+<body>
+
+<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
+<tr>
+<td>
+<center>
+<h1>
+PortAudio Tutorial</h1></center>
+</td>
+</tr>
+</table></center>
+
+<h2>
+Exploring PortAudio</h2>
+
+<blockquote>Now that you have a good idea of how PortAudio works, you can
+try out the test programs.
+<ul>
+<li>
+For an example of playing a sine wave, see "pa_tests/patest_sine.c".</li>
+
+<li>
+For an example of recording and playing back a sound, see "pa_tests/patest_record.c".</li>
+</ul>
+I also encourage you to examine the source for the PortAudio libraries.
+If you have suggestions on ways to improve them, please let us know. if
+you want to implement PortAudio on a new platform, please let us know as
+well so we can coordinate people's efforts.</blockquote>
+<font size=+2><a href="http://www.portaudio.com/">home</a> | <a href="pa_tutorial.html">contents</a>
+| <a href="pa_tut_rw.html">previous</a> | next</font>
+</body>
+</html>
--- /dev/null
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="GENERATOR" content="Mozilla/4.73 [en]C-gatewaynet (Win98; U) [Netscape]">
+ <meta name="Author" content="Phil Burk">
+ <meta name="Description" content="Tutorial for PortAudio, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
+ <meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
+ <title>PortAudio Tutorial</title>
+</head>
+<body>
+
+<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
+<tr>
+<td>
+<center>
+<h1>
+PortAudio Tutorial</h1></center>
+</td>
+</tr>
+</table></center>
+
+<h2>
+Initializing PortAudio</h2>
+
+<blockquote>Before making any other calls to PortAudio, you must call <tt>Pa_Initialize</tt>().
+This will trigger a scan of available devices which can be queried later.
+Like most PA functions, it will return a result of type <tt>paError</tt>.
+If the result is not <tt>paNoError</tt>, then an error has occurred.
+<blockquote>
+<pre>err = Pa_Initialize();
+if( err != paNoError ) goto error;</pre>
+</blockquote>
+You can get a text message that explains the error message by passing it
+to
+<blockquote>
+<pre>printf( "PortAudio error: %s\n", Pa_GetErrorText( err ) );</pre>
+</blockquote>
+</blockquote>
+<font size=+2><a href="http://www.portaudio.com/">home</a> | <a href="pa_tutorial.html">contents</a>
+| <a href="pa_tut_callback.html">previous</a> | <a href="pa_tut_open.html">next</a></font>
+</body>
+</html>
--- /dev/null
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="GENERATOR" content="Mozilla/4.77 [en]C-gatewaynet (Win98; U) [Netscape]">
+ <meta name="Author" content="Phil Burk">
+ <meta name="Description" content="Tutorial for PortAudio, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
+ <meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
+ <title>PortAudio Tutorial</title>
+</head>
+<body>
+
+<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
+<tr>
+<td>
+<center>
+<h1>
+PortAudio Tutorial</h1></center>
+</td>
+</tr>
+</table></center>
+
+<h2>
+Compiling for Macintosh</h2>
+
+<blockquote>To compile a Macintosh application with the PortAudio library,
+add the following source files to your project:
+<blockquote>
+<pre>pa_mac:pa_mac.c
+pa_common:pa_lib.c
+pa_common:portaudio.h
+pa_common:pa_host.h</pre>
+</blockquote>
+Also add the Apple <b>SoundLib</b> to your project.
+<p>You may try compiling the "pa_tests:patest_saw.c" file first because
+it is the simplest.</blockquote>
+<font size=+2><a href="http://www.portaudio.com/">home</a> |
+<a href="pa_tutorial.html">contents</a>
+| <a href="pa_tut_over.html">previous</a> | <a href="pa_tut_callback.html">next</a></font>
+</body>
+</html>
--- /dev/null
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="GENERATOR" content="Mozilla/4.79 [en] (Windows NT 5.0; U) [Netscape]">
+ <meta name="Author" content="Phil Burk">
+ <meta name="Description" content="Tutorial for PortAudio, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
+ <meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
+ <title>PortAudio Tutorial</title>
+</head>
+<body>
+
+<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
+<tr>
+<td>
+<center>
+<h1>
+PortAudio Tutorial</h1></center>
+</td>
+</tr>
+</table></center>
+
+<h2>
+Compiling for Macintosh OS X</h2>
+
+<blockquote>To compile a Macintosh OS X CoreAudio application with the
+PortAudio library:
+<p>Create a new ProjectBuilder project. You can use a "Tool" project to
+run the PortAudio examples.
+<p>Add the following source files to your Project:
+<blockquote>
+<pre>pa_mac_core/pa_mac_core.c
+pa_common/pa_lib.c
+pa_common/portaudio.h
+pa_common/pa_host.h
+pa_common/pa_convert.c</pre>
+</blockquote>
+Add the Apple CoreAudio.framework to your project by selecting "Add FrameWorks..."
+from the Project menu.
+<p>Compile and run the "pa_tests:patest_saw.c" file first because it is
+the simplest.</blockquote>
+<font size=+2><a href="http://www.portaudio.com/">home</a> |
+<a href="pa_tutorial.html">contents</a>
+| <a href="pa_tut_over.html">previous</a> | <a href="pa_tut_callback.html">next</a></font>
+</body>
+</html>
--- /dev/null
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="GENERATOR" content="Mozilla/4.73 [en]C-gatewaynet (Win98; U) [Netscape]">
+ <meta name="Author" content="Phil Burk">
+ <meta name="Description" content="Tutorial for PortAudio, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
+ <meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
+ <title>PortAudio Tutorial</title>
+</head>
+<body>
+
+<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
+<tr>
+<td>
+<center>
+<h1>
+PortAudio Tutorial</h1></center>
+</td>
+</tr>
+</table></center>
+
+<h2>
+Opening a Stream using Defaults</h2>
+
+<blockquote>The next step is to open a stream which is similar to opening
+a file. You can specify whether you want audio input and/or output, how
+many channels, the data format, sample rate, etc. There are two calls for
+opening streams, <tt>Pa_OpenStream</tt>() and <tt>Pa_OpenDefaultStream</tt>().
+<p><tt>Pa_OpenStream()</tt> takes extra parameters which give you
+more control. You can normally just use <tt>Pa_OpenDefaultStream</tt>()
+which just calls <tt>Pa_OpenStream()</tt> <tt>with</tt> some reasonable
+default values. Let's open a stream for stereo output, using floating
+point data, at 44100 Hz.
+<blockquote>
+<pre>err = Pa_OpenDefaultStream(
+ &stream, /* passes back stream pointer */
+ 0, /* no input channels */
+ 2, /* stereo output */
+ paFloat32, /* 32 bit floating point output */
+ 44100, /* sample rate */
+ 256, /* frames per buffer */
+ 0, /* number of buffers, if zero then use default minimum */
+ patestCallback, /* specify our custom callback */
+ &data ); /* pass our data through to callback */</pre>
+</blockquote>
+If you want to use 16 bit integer data, pass <tt>paInt16</tt> instead of
+<tt>paFloat32</tt>.</blockquote>
+<font size=+2><a href="http://www.portaudio.com/">home</a> | <a href="pa_tutorial.html">contents</a>
+| <a href="pa_tut_init.html">previous</a> | <a href="pa_tut_run.html">next</a></font>
+</body>
+</html>
--- /dev/null
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="GENERATOR" content="Mozilla/4.77 [en]C-gatewaynet (Win98; U) [Netscape]">
+ <meta name="Author" content="Phil Burk">
+ <meta name="Description" content="Tutorial for PortAudio, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
+ <meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
+ <title>PortAudio Tutorial</title>
+</head>
+<body>
+
+<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
+<tr>
+<td>
+<center>
+<h1>
+PortAudio Tutorial</h1></center>
+</td>
+</tr>
+</table></center>
+
+<h2>
+Compiling for Unix OSS</h2>
+
+<blockquote>[Skip this page if you are not using Unix and OSS]
+<p>We currently support the <a href="http://www.opensound.com/">OSS</a>
+audio drivers for Linux, Solaris, and FreeBSD. We hope to someday support
+the newer ALSA drivers.
+<ol>
+<li>
+cd to pa_unix_oss directory</li>
+
+<li>
+Edit the Makefile and uncomment one of the tests. You may try compiling
+the "patest_sine.c" file first because it is very simple.</li>
+
+<li>
+gmake run</li>
+</ol>
+</blockquote>
+<font size=+2><a href="http://www.portaudio.com/">home</a> |
+<a href="pa_tutorial.html">contents</a>
+| <a href="pa_tut_pc.html">previous</a> | <a href="pa_tut_callback.html">next</a></font>
+</body>
+</html>
--- /dev/null
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="GENERATOR" content="Mozilla/4.79 [en] (Windows NT 5.0; U) [Netscape]">
+ <meta name="Author" content="Phil Burk">
+ <meta name="Description" content="Tutorial for PortAudio, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
+ <meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
+ <title>PortAudio Tutorial</title>
+</head>
+<body>
+
+<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
+<tr>
+<td>
+<center>
+<h1>
+PortAudio Tutorial</h1></center>
+</td>
+</tr>
+</table></center>
+
+<h2>
+Overview of PortAudio</h2>
+
+<blockquote>PortAudio is a library that provides streaming audio input
+and output. It is a cross-platform API (Application Programming Interface)
+that works on Windows, Macintosh, Unix running OSS, SGI, BeOS, and perhaps
+other platforms by the time you read this. This means that you can write
+a simple 'C' program to process or generate an audio signal, and that program
+can run on several different types of computer just by recompiling the
+source code.
+<p>Here are the steps to writing a PortAudio application:
+<ol>
+<li>
+Write a callback function that will be called by PortAudio when audio processing
+is needed.</li>
+
+<li>
+Initialize the PA library and open a stream for audio I/O.</li>
+
+<li>
+Start the stream. Your callback function will be now be called repeatedly
+by PA in the background.</li>
+
+<li>
+In your callback you can read audio data from the inputBuffer and/or write
+data to the outputBuffer.</li>
+
+<li>
+Stop the stream by returning 1 from your callback, or by calling a stop
+function.</li>
+
+<li>
+Close the stream and terminate the library.</li>
+</ol>
+</blockquote>
+
+<blockquote>There is also <a href="pa_tut_rw.html">another interface</a>
+provided that allows you to generate audio in the foreground. You then
+simply write data to the stream and the tool will not return until it is
+ready to accept more data. This interface is simpler to use but is usually
+not preferred for large applications because it requires that you launch
+a thread to perform the synthesis. Launching a thread may be difficult
+on non-multi-tasking systems such as the Macintosh prior to MacOS X.
+<p>Let's continue by building a simple application that will play a sawtooth
+wave.
+<p>Please select the page for the specific implementation you would like
+to use:
+<ul>
+<li>
+<a href="pa_tut_pc.html">Windows (WMME or DirectSound)</a></li>
+
+<li>
+<a href="pa_tut_mac.html">Macintosh SoundManager for OS 7,8,9</a></li>
+
+<li>
+<a href="pa_tut_mac_osx.html">Macintosh CoreAudio for OS X</a></li>
+
+<li>
+<a href="pa_tut_asio.html">ASIO on Windows or Macintosh</a></li>
+
+<li>
+<a href="pa_tut_oss.html">Unix OSS</a></li>
+</ul>
+or continue with the <a href="pa_tut_callback.html">next page of the programming
+tutorial</a>.</blockquote>
+<font size=+2><a href="http://www.portaudio.com/">home</a> |
+<a href="pa_tutorial.html">contents</a>
+| <a href="pa_tutorial.html">previous</a></font>
+</body>
+</html>
--- /dev/null
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="GENERATOR" content="Mozilla/4.77 [en]C-gatewaynet (Win98; U) [Netscape]">
+ <meta name="Author" content="Phil Burk">
+ <meta name="Description" content="Tutorial for PortAudio, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
+ <meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
+ <title>PortAudio Tutorial</title>
+</head>
+<body>
+
+<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
+<tr>
+<td>
+<center>
+<h1>
+PortAudio Tutorial</h1></center>
+</td>
+</tr>
+</table></center>
+
+<h2>
+Compiling for Windows (WMME or DirectSound)</h2>
+
+<blockquote>To compile PortAudio for Windows, you can choose between two
+options. One implementation uses the DirectSound API. The other uses the
+Windows MultiMedia Extensions API (aka WMME or WAVE).
+<p>Some advantages of using DirectSound are that DirectSound may have lower
+latency than WMME, and supports effects processing plugins. But one disadvantage
+is that DirectSound is not installed on all PCs, and is not well supported
+under Windows NT. So WMME is the best choice for most projects.
+<p>For either implementation add the following source files to your project:
+<blockquote>
+<pre><b>pa_common\pa_lib.c
+pa_common\portaudio.h
+pa_common\pa_host.h</b></pre>
+</blockquote>
+Link with the system library "<b>winmm.lib</b>". For Visual C++:
+<ol>
+<li>
+select "Settings..." from the "Project" menu,</li>
+
+<li>
+select the project name in the tree on the left,</li>
+
+<li>
+choose "All Configurations" in the popup menu above the tree,</li>
+
+<li>
+select the "Link" tab,</li>
+
+<li>
+enter "winmm.lib", without quotes, as the first item in the "Object/library
+modules:" field.</li>
+</ol>
+<b>WMME</b> - To use the WMME implementation, add the following source
+files to your project:
+<blockquote><b><tt>pa_win_wmme/pa_win_wmme.c</tt></b></blockquote>
+<b>DirectSound</b> - If you want to use the DirectSound implementation
+of PortAudio then you must have a recent copy of the free
+<a href="http://www.microsoft.com/directx/download.asp">DirectX</a>
+SDK for Developers from Microsoft installed on your computer. To compile
+an application add the following source files to your project:
+<blockquote>
+<pre><b>pa_win_ds\dsound_wrapper.c
+pa_win_ds\pa_dsound.c</b></pre>
+</blockquote>
+Link with the system library "<b>dsound.lib</b>" using the procedure described
+above for "winmm.lib".</blockquote>
+
+<blockquote>You might try compiling the "pa_tests\patest_saw.c" file first
+because it is the simplest.</blockquote>
+<font size=+2><a href="http://www.portaudio.com/">home</a> |
+<a href="pa_tutorial.html">contents</a>
+| <a href="pa_tut_over.html">previous</a> | <a href="pa_tut_callback.html">next</a></font>
+</body>
+</html>
--- /dev/null
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="GENERATOR" content="Mozilla/4.73 [en]C-gatewaynet (Win98; U) [Netscape]">
+ <meta name="Author" content="Phil Burk">
+ <meta name="Description" content="Tutorial for PortAudio, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
+ <meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
+ <title>PortAudio Tutorial</title>
+</head>
+<body>
+
+<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
+<tr>
+<td>
+<center>
+<h1>
+PortAudio Tutorial</h1></center>
+</td>
+</tr>
+</table></center>
+
+<h2>
+Starting and Stopping a Stream</h2>
+
+<blockquote>The stream will not start running until you call Pa_StartStream().
+Then it will start calling your callback function to perform the audio
+processing.
+<blockquote>
+<pre>err = Pa_StartStream( stream );
+if( err != paNoError ) goto error;</pre>
+</blockquote>
+At this point, audio is being generated. You can communicate to your callback
+routine through the data structure you passed in on the open call, or through
+global variables, or using other interprocess communication techniques.
+Please be aware that your callback function may be called at interrupt
+time when your foreground process is least expecting it. So avoid sharing
+complex data structures that are easily corrupted like double linked lists.
+<p>In many of the tests we simply sleep for a few seconds so we can hear
+the sound. This is easy to do with Pa_Sleep() which will sleep for some
+number of milliseconds. Do not rely on this function for accurate scheduling.
+it is mostly for writing examples.
+<blockquote>
+<pre>/* Sleep for several seconds. */
+Pa_Sleep(NUM_SECONDS*1000);</pre>
+</blockquote>
+When you are through, you can stop the stream from the foreground.
+<blockquote>
+<pre>err = Pa_StopStream( stream );
+if( err != paNoError ) goto error;</pre>
+</blockquote>
+You can also stop the stream by returning 1 from your custom callback function.</blockquote>
+<font size=+2><a href="http://www.portaudio.com/">home</a> | <a href="pa_tutorial.html">contents</a>
+| <a href="pa_tut_open.html">previous</a> | <a href="pa_tut_term.html">next</a></font>
+</body>
+</html>
--- /dev/null
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="GENERATOR" content="Mozilla/4.77 [en]C-gatewaynet (Win98; U) [Netscape]">
+ <meta name="Author" content="Phil Burk">
+ <meta name="Description" content="Tutorial for PortAudio, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
+ <meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
+ <title>PortAudio Tutorial</title>
+</head>
+<body>
+
+<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
+<tr>
+<td>
+<center>
+<h1>
+PortAudio Tutorial</h1></center>
+</td>
+</tr>
+</table></center>
+
+<h2>
+Blocking Read/Write Functions</h2>
+
+<blockquote>[Note: These functions are not part of the official PortAudio
+API. They are simply built on top of PortAudio as an extra utility. Also
+note that they are under evaluation and their definition may change.]
+<p>There are two fundamentally different ways to design an audio API. One
+is to use callback functions the way we have already shown. The callback
+function operates under an interrupt or background thread This leaves the
+foreground application free to do other things while the audio just runs
+in the background. But this can sometimes be awkward.
+<p>So we have provided an alternative technique that lets a program generate
+audio in the foreground and then just write it to the audio stream as if
+it was a file. If there is not enough room in the audio buffer for more
+data, then the write function will just block until more room is available.
+This can make it very easy to write an audio example. To use this tool,
+you must add the files "pablio/pablio.c" and "pablio/ringbuffer.c" to your
+project. You must also:
+<blockquote>
+<pre>#include "pablio.h"</pre>
+</blockquote>
+Here is a short excerpt of a program that opens a stream for input and
+output. It then reads a block of samples from input, and writes them to
+output, in a loop. The complete example can be found in "pablio/test_rw.c".
+<blockquote>
+<pre> #define SAMPLES_PER_FRAME (2)
+ #define FRAMES_PER_BLOCK (1024)
+ SAMPLE samples[SAMPLES_PER_FRAME * FRAMES_PER_BLOCK];
+ PaError err;
+ PABLIO_Stream *aStream;
+
+/* Open simplified blocking I/O layer on top of PortAudio. */
+ err = OpenAudioStream( &rwbl, SAMPLE_RATE, paFloat32,
+ (PABLIO_READ_WRITE | PABLIO_STEREO) );
+ if( err != paNoError ) goto error;
+
+/* Process samples in the foreground. */
+ for( i=0; i<(NUM_SECONDS * SAMPLE_RATE); i++ )
+ {
+ /* Read one block of data into sample array from audio input. */
+ ReadAudioStream( aStream, samples, FRAMES_PER_BLOCK );
+ /*
+ ** At this point you could process the data in samples array,
+ ** and write the result back to the same samples array.
+ */
+ /* Write that same frame of data to output. */
+ WriteAudioStream( aStream, samples, FRAMES_PER_BLOCK );
+ }
+
+ CloseAudioStream( aStream );</pre>
+</blockquote>
+</blockquote>
+<font size=+2><a href="http://www.portaudio.com/">home</a> |
+<a href="pa_tutorial.html">contents</a>
+| <a href="pa_tut_devs.html">previous</a> | <a href="pa_tut_explore.html">next</a></font>
+</body>
+</html>
--- /dev/null
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="GENERATOR" content="Mozilla/4.73 [en]C-gatewaynet (Win98; U) [Netscape]">
+ <meta name="Author" content="Phil Burk">
+ <meta name="Description" content="Tutorial for PortAudio, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
+ <meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
+ <title>PortAudio Tutorial</title>
+</head>
+<body>
+
+<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
+<tr>
+<td>
+<center>
+<h1>
+PortAudio Tutorial</h1></center>
+</td>
+</tr>
+</table></center>
+
+<h2>
+Terminating PortAudio</h2>
+
+<blockquote>You can start and stop a stream as many times as you like.
+But when you are done using it, you should close it by calling:</blockquote>
+
+<blockquote>
+<blockquote>
+<pre>err = Pa_CloseStream( stream );
+if( err != paNoError ) goto error;</pre>
+</blockquote>
+Then when you are done using PortAudio, you should terminate the whole
+system by calling:
+<blockquote>
+<pre>Pa_Terminate();</pre>
+</blockquote>
+That's basically it. You can now write an audio program in 'C' that will
+run on multiple platforms, for example PCs and Macintosh.
+<p>In the rest of the tutorial we will look at some additional utility
+functions, and a different way of using PortAudio that does not require
+the use of a callback function.</blockquote>
+<font size=+2><a href="http://www.portaudio.com/">home</a> | <a href="pa_tutorial.html">contents</a>
+| <a href="pa_tut_run.html">previous</a> | <a href="pa_tut_util.html">next</a></font>
+</body>
+</html>
--- /dev/null
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="GENERATOR" content="Mozilla/4.75 [en]C-gatewaynet (Win98; U) [Netscape]">
+ <meta name="Author" content="Phil Burk">
+ <meta name="Description" content="Tutorial for PortAudio, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
+ <meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
+ <title>PortAudio Tutorial</title>
+</head>
+<body>
+
+<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
+<tr>
+<td>
+<center>
+<h1>
+PortAudio Tutorial</h1></center>
+</td>
+</tr>
+</table></center>
+
+<h2>
+Utility Functions</h2>
+
+<blockquote>Here are several more functions that are not critical, but
+may be handy when using PortAudio.
+<p>Pa_StreamActive() returns one when the stream in playing audio, zero
+when not playing, or a negative error number if the stream is invalid.
+The stream is active between calls to Pa_StartStream() and Pa_StopStream(),
+but may also become inactive if the callback returns a non-zero value.
+In the latter case, the stream is considered inactive after the last buffer
+has finished playing.
+<blockquote>
+<pre>PaError Pa_StreamActive( PortAudioStream *stream );</pre>
+</blockquote>
+Pa_StreamTime() returns the number of samples that have been generated.
+PaTimeStamp is a double precision number which is a convenient way to pass
+big numbers around even though we only need integers.
+<blockquote>
+<pre>PaTimestamp Pa_StreamTime( PortAudioStream *stream );</pre>
+</blockquote>
+The "CPU Load" is a fraction of total CPU time consumed by the stream's
+audio processing. A value of 0.5 would imply that PortAudio and the sound
+generating callback was consuming roughly 50% of the available CPU time.
+This function may be called from the callback function or the application.
+<blockquote>
+<pre>double Pa_GetCPULoad( PortAudioStream* stream );</pre>
+</blockquote>
+</blockquote>
+<font size=+2><a href="http://www.portaudio.com/">home</a> |
+<a href="pa_tutorial.html">contents</a> | <a href="pa_tut_term.html">previous</a>
+| <a href="pa_tut_devs.html">next</a></font>
+</body>
+</html>
--- /dev/null
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="GENERATOR" content="Mozilla/4.79 [en] (Windows NT 5.0; U) [Netscape]">
+ <meta name="Author" content="Phil Burk">
+ <meta name="Description" content="Tutorial for PortAudio, a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
+ <meta name="KeyWords" content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
+ <title>PortAudio Tutorial</title>
+</head>
+<body>
+
+<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
+<tr>
+<td>
+<center>
+<h1>
+PortAudio Tutorial</h1></center>
+</td>
+</tr>
+</table></center>
+
+<p>Copyright 2000 Phil Burk and Ross Bencina
+<h2>
+Table of Contents</h2>
+
+<blockquote><a href="pa_tut_over.html">Overview of PortAudio</a>
+<br><a href="pa_tut_mac.html">Compiling for Macintosh OS 7,8,9</a>
+<br><a href="pa_tut_mac_osx.html">Compiling for Macintosh OS X</a>
+<br><a href="pa_tut_pc.html">Compiling for Windows (DirectSound and WMME)</a>
+<br><a href="pa_tut_asio.html">Compiling for ASIO on Windows or Mac OS
+8,9</a>
+<br><a href="pa_tut_oss.html">Compiling for Unix OSS</a>
+<br><a href="pa_tut_callback.html">Writing a Callback Function</a>
+<br><a href="pa_tut_init.html">Initializing PortAudio</a>
+<br><a href="pa_tut_open.html">Opening a Stream using Defaults</a>
+<br><a href="pa_tut_run.html">Starting and Stopping a Stream</a>
+<br><a href="pa_tut_term.html">Cleaning Up</a>
+<br><a href="pa_tut_util.html">Utilities</a>
+<br><a href="pa_tut_devs.html">Querying for Devices</a>
+<br><a href="pa_tut_rw.html">Blocking Read/Write Functions</a>
+<br><a href="pa_tut_explore.html">Exploring the PortAudio Package</a></blockquote>
+<font size=+2><a href="http://www.portaudio.com/">home</a> | contents |
+previous | <a href="pa_tut_over.html">next</a></font>
+</body>
+</html>
--- /dev/null
+#ifndef PORT_AUDIO_H
+#define PORT_AUDIO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * PortAudio Portable Real-Time Audio Library
+ * PortAudio API Header File
+ * Latest version available at: http://www.audiomulch.com/portaudio/
+ *
+ * Copyright (c) 1999-2000 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.
+ *
+ */
+
+typedef int PaError;
+typedef enum {
+ paNoError = 0,
+
+ paHostError = -10000,
+ paInvalidChannelCount,
+ paInvalidSampleRate,
+ paInvalidDeviceId,
+ paInvalidFlag,
+ paSampleFormatNotSupported,
+ paBadIODeviceCombination,
+ paInsufficientMemory,
+ paBufferTooBig,
+ paBufferTooSmall,
+ paNullCallback,
+ paBadStreamPtr,
+ paTimedOut,
+ paInternalError
+} PaErrorNum;
+
+/*
+ Pa_Initialize() is the library initialisation function - call this before
+ using the library.
+*/
+
+PaError Pa_Initialize( void );
+
+/*
+ Pa_Terminate() is the library termination function - call this after
+ using the library.
+*/
+
+PaError Pa_Terminate( void );
+
+/*
+ Return host specific error.
+ This can be called after receiving a paHostError.
+*/
+long Pa_GetHostError( void );
+
+/*
+ Translate the error number into a human readable message.
+*/
+const char *Pa_GetErrorText( PaError errnum );
+
+/*
+ Sample formats
+
+ These are formats used to pass sound data between the callback and the
+ stream. Each device has a "native" format which may be used when optimum
+ efficiency or control over conversion is required.
+
+ Formats marked "always available" are supported (emulated) by all devices.
+
+ The floating point representation uses +1.0 and -1.0 as the respective
+ maximum and minimum.
+
+*/
+
+typedef unsigned long PaSampleFormat;
+#define paFloat32 ((PaSampleFormat) (1<<0)) /*always available*/
+#define paInt16 ((PaSampleFormat) (1<<1)) /*always available*/
+#define paInt32 ((PaSampleFormat) (1<<2)) /*always available*/
+#define paInt24 ((PaSampleFormat) (1<<3))
+#define paPackedInt24 ((PaSampleFormat) (1<<4))
+#define paInt8 ((PaSampleFormat) (1<<5))
+#define paUInt8 ((PaSampleFormat) (1<<6)) /* unsigned 8 bit, 128 is "ground" */
+#define paCustomFormat ((PaSampleFormat) (1<<16))
+
+/*
+ Device enumeration mechanism.
+
+ Device ids range from 0 to Pa_CountDevices()-1.
+
+ Devices may support input, output or both. Device 0 is always the "default"
+ device and should support at least stereo in and out if that is available
+ on the taget platform _even_ if this involves kludging an input/output
+ device on platforms that usually separate input from output. Other platform
+ specific devices are specified by positive device ids.
+*/
+
+typedef int PaDeviceID;
+#define paNoDevice -1
+
+typedef struct{
+ int structVersion;
+ const char *name;
+ int maxInputChannels;
+ int maxOutputChannels;
+/* Number of discrete rates, or -1 if range supported. */
+ int numSampleRates;
+/* Array of supported sample rates, or {min,max} if range supported. */
+ const double *sampleRates;
+ PaSampleFormat nativeSampleFormats;
+} PaDeviceInfo;
+
+
+int Pa_CountDevices();
+/*
+ Pa_GetDefaultInputDeviceID(), Pa_GetDefaultOutputDeviceID()
+
+ Return the default device ID or paNoDevice if there is no devices.
+ The result can be passed to Pa_OpenStream().
+
+ On the PC, the user can specify a default device by
+ setting an environment variable. For example, to use device #1.
+
+ set PA_RECOMMENDED_OUTPUT_DEVICE=1
+
+ The user should first determine the available device ID by using
+ the supplied application "pa_devs".
+*/
+PaDeviceID Pa_GetDefaultInputDeviceID( void );
+PaDeviceID Pa_GetDefaultOutputDeviceID( void );
+
+/*
+ PaTimestamp is used to represent a continuous sample clock with arbitrary
+ start time useful for syncronisation. The type is used in the outTime
+ argument to the callback function and the result of Pa_StreamTime()
+*/
+
+typedef double PaTimestamp;
+
+/*
+ Pa_GetDeviceInfo() returns a pointer to an immutable PaDeviceInfo structure
+ referring to the device specified by id.
+ If id is out of range the function returns NULL.
+
+ The returned structure is owned by the PortAudio implementation and must
+ not be manipulated or freed. The pointer is guaranteed to be valid until
+ between calls to Pa_Initialize() and Pa_Terminate().
+*/
+
+const PaDeviceInfo* Pa_GetDeviceInfo( PaDeviceID devID );
+
+/*
+ PortAudioCallback is implemented by clients of the portable audio api.
+
+ inputBuffer and outputBuffer are arrays of interleaved samples,
+ the format, packing and number of channels used by the buffers are
+ determined by parameters to Pa_OpenStream() (see below).
+
+ framesPerBuffer is the number of sample frames to be processed by the callback.
+
+ outTime is the time in samples when the buffer(s) processed by
+ this callback will begin being played at the audio output.
+ See also Pa_StreamTime()
+
+ userData is the value of a user supplied pointer passed to Pa_OpenStream()
+ intended for storing synthesis data etc.
+
+ return value:
+ The callback can return a nonzero value to stop the stream. 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 StopStream() will also terminate the stream. A callback returning a
+ nonzero value must fill the entire outputBuffer.
+
+ NOTE: None of the other stream functions may be called from within the
+ callback function except for Pa_GetCPULoad().
+
+*/
+
+typedef int (PortAudioCallback)(
+ void *inputBuffer, void *outputBuffer,
+ unsigned long framesPerBuffer,
+ PaTimestamp outTime, void *userData );
+
+
+/*
+ Stream flags
+
+ These flags may be supplied (ored together) in the streamFlags argument to
+ the Pa_OpenStream() function.
+
+ [ suggestions? ]
+*/
+
+#define paNoFlag (0)
+#define paClipOff (1<<0) /* disable defult clipping of out of range samples */
+#define paDitherOff (1<<1) /* disable default dithering */
+#define paPlatformSpecificFlags (0x00010000)
+typedef unsigned long PaStreamFlags;
+
+/*
+ A single PortAudioStream provides multiple channels of real-time
+ input and output audio streaming to a client application.
+ Pointers to PortAudioStream objects are passed between PortAudio functions.
+*/
+
+typedef void PortAudioStream;
+#define PaStream PortAudioStream
+
+/*
+ Pa_OpenStream() opens a stream for either input, output or both.
+
+ stream is the address of a PortAudioStream pointer which will receive
+ a pointer to the newly opened stream.
+
+ inputDevice is the id of the device used for input (see PaDeviceID above.)
+ inputDevice may be paNoDevice to indicate that an input device is not required.
+
+ numInputChannels is the number of channels of sound to be delivered to the
+ callback. It can range from 1 to the value of maxInputChannels in the
+ device input record for the device specified in the inputDevice parameter.
+ If inputDevice is paNoDevice numInputChannels is ignored.
+
+ inputSampleFormat is the format of inputBuffer provided to the callback
+ function. inputSampleFormat may be any of the formats described by the
+ PaSampleFormat enumeration (see above). PortAudio guarantees support for
+ the sound devices 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.
+
+ inputDriverInfo is a pointer to an optional driver specific data structure
+ containing additional information for device setup or stream processing.
+ inputDriverInfo is never required for correct operation. If not used
+ inputDriverInfo should be NULL.
+
+ outputDevice is the id of the device used for output (see PaDeviceID above.)
+ outputDevice may be paNoDevice to indicate that an output device is not required.
+
+ numOutputChannels is the number of channels of sound to be supplied by the
+ callback. See the definition of numInputChannels above for more details.
+
+ outputSampleFormat is the sample format of the outputBuffer filled by the
+ callback function. See the definition of inputSampleFormat above for more
+ details.
+
+ outputDriverInfo is a pointer to an optional driver specific data structure
+ containing additional information for device setup or stream processing.
+ outputDriverInfo is never required for correct operation. If not used
+ outputDriverInfo should be NULL.
+
+ sampleRate is the desired sampleRate for input and output
+
+ framesPerBuffer is the length in sample frames of all internal sample buffers
+ used for communication with platform specific audio routines. Wherever
+ possible this corresponds to the framesPerBuffer parameter passed to the
+ callback function.
+
+ numberOfBuffers is the number of buffers used for multibuffered
+ communication with the platform specific audio routines. This parameter is
+ provided only as a guide - and does not imply that an implementation must
+ use multibuffered i/o when reliable double buffering is available (such as
+ SndPlayDoubleBuffer() on the Macintosh.)
+
+ streamFlags may contain a combination of flags ORed together.
+ These flags modify the behavior of the
+ streaming process. Some flags may only be relevant to certain buffer formats.
+
+ callback is a pointer to a client supplied function that is responsible
+ for processing and filling input and output buffers (see above for details.)
+
+ userData is a client supplied pointer which is passed to the callback
+ function. It could for example, contain a pointer to instance data necessary
+ for processing the audio buffers.
+
+ return value:
+ Apon success Pa_OpenStream() returns PaNoError and places a pointer to a
+ valid PortAudioStream in the stream argument. The stream is inactive (stopped).
+ If a call to Pa_OpenStream() fails a nonzero error code is returned (see
+ PAError above) and the value of stream is invalid.
+
+*/
+
+PaError Pa_OpenStream( PortAudioStream** stream,
+ PaDeviceID inputDevice,
+ int numInputChannels,
+ PaSampleFormat inputSampleFormat,
+ void *inputDriverInfo,
+ PaDeviceID outputDevice,
+ int numOutputChannels,
+ PaSampleFormat outputSampleFormat,
+ void *outputDriverInfo,
+ double sampleRate,
+ unsigned long framesPerBuffer,
+ unsigned long numberOfBuffers,
+ PaStreamFlags streamFlags,
+ PortAudioCallback *callback,
+ void *userData );
+
+
+/*
+ Pa_OpenDefaultStream() is a simplified version of Pa_OpenStream() that
+ opens the default input and/or ouput devices. Most parameters have
+ identical meaning to their Pa_OpenStream() counterparts, with the following
+ exceptions:
+
+ If either numInputChannels or numOutputChannels is 0 the respective device
+ is not opened (same as passing paNoDevice in the device arguments to Pa_OpenStream() )
+
+ sampleFormat applies to both the input and output buffers.
+*/
+
+PaError Pa_OpenDefaultStream( PortAudioStream** stream,
+ int numInputChannels,
+ int numOutputChannels,
+ PaSampleFormat sampleFormat,
+ double sampleRate,
+ unsigned long framesPerBuffer,
+ unsigned long numberOfBuffers,
+ PortAudioCallback *callback,
+ void *userData );
+
+/*
+ Pa_CloseStream() closes an audio stream, flushing any pending buffers.
+*/
+
+PaError Pa_CloseStream( PortAudioStream* );
+
+/*
+ Pa_StartStream() and Pa_StopStream() begin and terminate audio processing.
+ Pa_StopStream() waits until all pending audio buffers have been played.
+ Pa_AbortStream() stops playing immediately without waiting for pending
+ buffers to complete.
+*/
+
+PaError Pa_StartStream( PortAudioStream *stream );
+
+PaError Pa_StopStream( PortAudioStream *stream );
+
+PaError Pa_AbortStream( PortAudioStream *stream );
+
+/*
+ Pa_StreamActive() returns one when the stream is playing audio,
+ zero when not playing, or a negative error number if the
+ stream is invalid.
+ The stream is active between calls to Pa_StartStream() and Pa_StopStream(),
+ but may also become inactive if the callback returns a non-zero value.
+ In the latter case, the stream is considered inactive after the last
+ buffer has finished playing.
+*/
+
+PaError Pa_StreamActive( PortAudioStream *stream );
+
+/*
+ Pa_StreamTime() returns the current output time for the stream in samples.
+ This time may be used as a time reference (for example syncronising audio to
+ MIDI).
+*/
+
+PaTimestamp Pa_StreamTime( PortAudioStream *stream );
+
+/*
+ The "CPU Load" is a fraction of total CPU time consumed by the
+ stream's audio processing.
+ A value of 0.5 would imply that PortAudio and the sound generating
+ callback was consuming roughly 50% of the available CPU time.
+ This function may be called from the callback function or the application.
+*/
+double Pa_GetCPULoad( PortAudioStream* stream );
+
+/*
+ Use Pa_GetMinNumBuffers() to determine minimum number of buffers required for
+ the current host based on minimum latency.
+ On the PC, for the DirectSound implementation, latency can be optionally set
+ by user by setting an environment variable.
+ For example, to set latency to 200 msec, put:
+
+ set PA_MIN_LATENCY_MSEC=200
+
+ in the AUTOEXEC.BAT file and reboot.
+ If the environment variable is not set, then the latency will be determined
+ based on the OS. Windows NT has higher latency than Win95.
+*/
+
+int Pa_GetMinNumBuffers( int framesPerBuffer, double sampleRate );
+
+/*
+ Sleep for at least 'msec' milliseconds.
+ You may sleep longer than the requested time so don't rely
+ on this for accurate musical timing.
+*/
+void Pa_Sleep( long msec );
+
+/*
+ Return size in bytes of a single sample in a given PaSampleFormat
+ or paSampleFormatNotSupported.
+*/
+PaError Pa_GetSampleSize( PaSampleFormat format );
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+#endif /* PORT_AUDIO_H */
--- /dev/null
+<HTML>
+<HEAD>
+<TITLE>Proposed Changes to PortAudio API</TITLE>
+<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252">
+<META content="Phil Burk, Ross Bencina" name=Author>
+<META content="Changes being discussed by the community of PortAudio deveopers."
+name=Description>
+<META
+content="audio, tutorial, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,"
+name=KeyWords>
+</HEAD>
+<BODY LINK="#0000ff" VLINK="#800080">
+<CENTER>
+<TABLE bgColor=#fada7a cols=1 width="100%">
+ <TBODY>
+ <TR>
+ <TD>
+ <CENTER>
+ <H1>Proposed Changes to PortAudio API</H1>
+ </CENTER>
+</TD></TR></TBODY></TABLE></CENTER>
+<P><A href="http://www.portaudio.com/">PortAudio Home Page</A></P>
+
+<P>Updated: January 7, 2002 </P>
+<P>This document describes modifications to the PortAudio API currently being considered by the developer community. It is intended to capture the current state of discussions. The authors are the various members of the PortAudio community and are too numerous to mention. Please refer to the mailing list archives to see who said what. </P>
+<P>We are still at the design stage with all of these proposals - if you think something is missing, could be improved, or would just like to comment please do so on the PortAudio mailing list.</P>
+<P> <A HREF="http://techweb.rfa.org/mailman/listinfo/portaudio">http://techweb.rfa.org/mailman/listinfo/portaudio</A> </P>
+<H2>Contents</H2>
+
+<UL>
+<LI><A HREF="#Underflow">PortAudioCallback Underflow/Overflow Handling</A> </LI>
+<LI><A HREF="#ImproveDeviceFormatQuerySystem">Improve Device Format Query System</A> * </LI>
+<LI><A HREF="#Latency">Improve Latency Mechanism</A>s * </LI>
+<LI><A HREF="#Blocking">Blocking Read/Write API</A> * </LI>
+<LI><A HREF="#Interleaved">Non-Interleaved Buffers</A> </LI>
+<LI><A HREF="#MultipleDriverModels">Support for Multiple Driver Models in a Single PortAudio Build</A> * </LI>
+<LI><A HREF="#DriverModelSpecificPa_OpenStream">Driver Model Specific Pa_OpenStream() Parameters</A> |C| </LI>
+<LI><A HREF="#Error">Handling of Host-Specific Error Codes</A> * </LI>
+<LI><A HREF="#RenamePa_GetCPULoad">Rename Pa_GetCPULoad() to Pa_StreamCPULoad()</A> </LI>
+<LI><A HREF="#CodingStyleGuidelines">Coding Style Guidelines</A> * </LI>
+<LI><A HREF="#AdditionalPa_TerminateBehaviour">Additional Pa_Terminate() Behaviour</A> </LI>
+<LI><A HREF="#ReviseInternalHostAPI">Revise Internal Host API</A> *</LI></UL>
+
+<I><P>The proposals above which are marked with a * are under construction, those marked with |</I>C<I>| are essentially complete but require approval or comment before they are considered complete. The remaining proposals are essentially complete and will be implemented as-is unless significant objections are raised.</P>
+</I><P>____________</P>
+<H2>PortAudioCallback <A NAME="Underflow"></A>Underflow/Overflow Handling</H2>
+<H4>Status</H4>
+<P>This proposal is sufficiently well defined to be implemented</P>
+<H4>Background</H4>
+<P>There are conditions where a full-duplex stream needs to generate output but doesn't have any input available, or where it has too much input so some input needs to be discarded (not passed to the output.) There is also the case where output is needed, but the callback has (transiently) consumed so much CPU time that output has to be generated without the callback being called.</P>
+<P>Currently (V17) the PortAudioCallback Function handles these underflow/overflow conditions by passing NULL buffer pointers to the callback. This can happen if the output is pre-rolled and there is not yet any input data. It can also happen if the input underflows. </P>
+<P>A number of concerns have been raised about the current system: For PortAudio to discard input just because it is not needed for output is considered unacceptable for some recording applications. Passing of NULL buffer pointers has been deemed to be too error prone and requires too much housekeeping for simple programs. </P>
+<P>See <A HREF="http://techweb.rfa.org/pipermail/portaudio/2001-October/000222.html">http://techweb.rfa.org/pipermail/portaudio/2001-October/000222.html</A> and subsequent messages in various threads.</P>
+<P>This proposal seeks to keep the PortAudioCallback as simple as possible for ease-of-use while providing full access to overflow/underflow information, and all input and output sample data when clients require it.</P>
+<H4>Proposal</H4>
+<P>For streams providing input, the inputBuffer parameter will always point to a valid memory location containing framesPerBuffer frames of sample data in the requested format. The inputBuffer parameter will be NULL for output only streams. Similarly, the outputBuffer parameter will be NULL for input only streams, otherwise it will point to a valid memory location containing framesPerBuffer frames of sample data.</P>
+<P>A new parameter will be added to the PortAudioCallback Function that gives the status of the data as bit flags. </P>
+<TT><PRE>typedef int (PortAudioCallback)(</TT>
+<TT> void *inputBuffer, void *outputBuffer,</TT>
+<TT> unsigned long framesPerBuffer,</TT>
+<TT> PaTimestamp outTime,
+ unsigned long statusFlags,
+ void *userData );</TT>
+
+These bits may be set in the statusFlags parameter.
+<TT>#define paInputUnderflow (1<<0) /* Input data is all zeros because no real data is available. */</TT>
+#define paInputOverflow (1<<1) /* Input data was discarded by PortAudio */
+<TT>#define </TT>paOutputUnderflow <TT>(1<<2) </TT>/* Output data was inserted by PortAudio because the callback is using too much CPU */
+#define paOutputOverflow (1<<3) <TT>/* Output data will be ignored because no room is available. */</PRE>
+</TT><P> </P>
+<P>New rules will govern when the <TT>PortAudioCallback</TT> is called:</P>
+
+<UL>
+<LI>For input-only streams, the callback will be called for every available input buffer. If the callback takes too long to complete and input samples have to be discarded the paInputOverflow flag will be set the next time the callback is called. In input-only stream will never be called with the paInputUnderflow flag set. </LI>
+<LI>For output-only streams, the callback will be called whenever an output buffer needs to be filled, except when doing so would cause the stream to fall further behind real-time due to CPULoad being too high. In such cases PortAudio will insert silence or repeat the previous buffer to the output and the paOutputUnderflow bit will be set next time the callback is called. An output-only stream will never be called with the paOutputOverflow flag set. </LI>
+<LI>By default, a full duplex stream will behave according to the same rules as an output-only stream. If input is not available, the paInputUnderflow bit will be set and the input buffers will contain zeros. In the case of an input buffer overflow, PortAudio will discard input - in such cases the input samples will <B>not</B> be passed to a callback, and paInputOverflow will be set next time the callback is called to generate more output. A default full-duplex stream will never be called with the paOutputOverflow flag set. </LI>
+<LI>A new mode flag <I>paNeverDropInput</I> to Pa_OpenStream() specifies that a full duplex stream will not discard overflowed input samples without calling the callback. When an input buffer overflow occurs, the callback will be called with the paOutputOverflow flag set, when the callback completes the output buffers will be discarded.</LI></UL>
+
+<P>Note that the default full-duplex mode is intended to cover most common uses of PortAudio, where the client wants a simple audio streaming interface, and is happy to let PortAudio handle buffer underflow/overflow conditions when they occurs.</P>
+<H4>Impact Analysis</H4>
+<P>This proposal involves adding a new statusFlags parameter to PortAudioCallback. This will require all clients to update their callback implementations accordingly. Clients who previously checked for NULL buffers will be able to remove such checks.</P>
+<P>____________</P>
+<H2><A NAME="ImproveDeviceFormatQuerySystem">Improve Device Format Query System</A></H2>
+<H4>Status</H4>
+<P>This proposal is open for discussion.</P>
+<H4>Background</H4>
+<P>It has been noted that the current method (Pa_GetDeviceInfo()) of querying devices for supported sample formats, channels and sample rates is weak. It does not cleanly differentiate between 'PortAudio supported' formats and 'native' formats, and it is incapable of representing formats where the parameters are interdependent (eg where full duplex is only supported for certain sample rates.) We have also found that a static structure is not a good match for many driver models where format discovery is performed by polling the driver. Even if a sound card supports arbitrary sample rates, the driver model may only allow a client to poll to see whether a rate is available rather than providing the available rate ranges.</P>
+<P>It has been noted that most (platform specific) audio APIs do a pretty bad job of allowing for device capability querying. Even the better APIs (ALSA is perhaps one) don't necessarily provide accurate information. This proposal should seek to maximise the amount of information that can be extracted from existing APIs while remaining expressive enough to take full advantage of APIs with more advanced capability querying systems should they become available in the future.</P>
+<H4>Proposal</H4>
+<P>Use PaDeviceInfo only for representing information that can be expressed without polling the driver multiple times, or only check for "standard" formats, or leave it unchanged, or do away with it completely.</P>
+<P>And/Or</P>
+<P>We could do things the way MME does: if Pa_OpenStream() is called with a NULL stream parameter then the stream isn't opened, but it is checked to see if the device supports the specified format - if the format is supported then paNoError would be returned, otherwise an error would be returned.</P>
+<P>And/Or</P>
+<P>Add an IsFormatSupported() function:</P>
+<PRE>Pa_IsFormatSupported( deviceId, inputDevice, numInputChannels, inputSampleFormat, inputDriverInfo, outputDevice, numOutputChannels, outputSampleFormat, outputDriverInfo, sampleRate );</PRE>
+<H4>Impact Analysis</H4>
+<P>This proposal will provide clients with more expressive methods for querying device capabilities, which should improve the utility of PortAudio. It is not yet clear what the full impact of this proposal will be.</P>
+<P>____________</P>
+<H2><A NAME="Latency"></A>Improve Latency Mechanisms</H2>
+<H4>Status</H4>
+<P>This proposal is open for discussion.</P>
+<H4>Background</H4>
+<P>The current mechanism for setting latency is not considered optimal by all clients of the API. There seems to be some tension between using the framesPerBuffer parameter of Pa_OpenStream as a latency control parameter and as a specifier for the number of frames supplied to the callback. Specifying latency as a single millisecond value would be more user friendly for some users, however some driver models need latency to be tuned by specifying buffer sizes and number of buffers. Additionally, it not clear whether separate input and output buffer counts would allow tuning of lower latencies in some circumstances.</P>
+<P>A related issue is the need to improve the interface available to determine default latency parameters. The most recent proposal is documented below, however there is still some debate as to whether this is satisfactory. </P>
+<P>See this thread: <A HREF="http://techweb.rfa.org/pipermail/portaudio/2001-October/000196.html">http://techweb.rfa.org/pipermail/portaudio/2001-October/000196.html</A> </P>
+<H4>Proposal</H4>
+<P>The numBuffers parameter for Pa_OpenStream() could accept the following values in addition to the normal N>0 values. Use PA_LATENCY_LOW for interactive performance, when response time is critical. Use PA_LATENCY_HIGH when playing sound files or other non-interactive uses, when glitch free operation is more critical. </P>
+<TT><P>#define PA_LATENCY_WHATEVER (0) /* or _NO_OPINION or? */</TT> <BR>
+<TT>#define PA_LATENCY_LOW (-1) /* For interactive performance. */</TT> <BR>
+<TT>#define PA_LATENCY_HIGH (-2) /* For playing sound files. */</TT> </P>
+<P>Currently, when numBuffers>0, Pa_OpenStream will constrain the actual numBuffers so that the latency is within a valid range determined by the driver, or an environment variables such as PA_MIN_LATENCY_MSEC. Propose changing the behaviour so that the requested value is honoured as much as possible. This will allow the user to override the minimum if they know their system can handle it. This might be used, for example on patched Linux kernels. By doing this we simplify the implementations and eliminate the need for adding a Pa_SetMinimumLatency() function. </P>
+<TT><P>/* Negative return values are (double) paError */</TT> <BR>
+<TT>double Pa_GetMinimumLatency( int deviceId, double frameRate );</TT> <BR>
+<TT>double Pa_GetPreferredLatency( int deviceId, double frameRate );</TT> <BR>
+<TT>double Pa_GetMaximumLatency( int deviceId, double frameRate );</TT> </P>
+<TT><P>/* This would only be valid after Pa_OpenStream() */</TT> <BR>
+<TT>double Pa_GetActualLatency( int deviceId, double frameRate );</TT> </P>
+<H4>Discussion</H4>
+<P>This proposal does not yet address the question of whether there needs to be separate numInputBuffers and numOutputBuffers parameters for optimal latency specification.</P>
+<P>____________</P>
+<H2><A NAME="Blocking"></A>Blocking Read/Write API</H2>
+<H4>Status</H4>
+<P>This proposal is waiting to be written up (assigned to Roger Dannenberg.)</P>
+<H4>Background</H4>
+<P>Many PortAudio users have requested a blocking read/write API which will be supported in addition to the current callback based API. A blocking Read/Write API would allow a more natural style of multi-threaded programming, and facilitate single-threaded reactive applications, while insulating clients from platform-specific thread synchronisation facilities. A blocking read/write API would also be useful when binding PortAudio to languages that don't easily support callbacks such as Python, Java, Lisp and Smalltalk. However in this case it has been noted that a blocking API is not sufficient - the host language also needs to support native threads to interact efficiently with blocking.</P>
+<P>Adding a blocking Read/Write interface to PortAudio has been discussed on a number of occasions, including the following threads:</P>
+<P><A HREF="http://techweb.rfa.org/pipermail/portaudio/2001-August/000063.html">http://techweb.rfa.org/pipermail/portaudio/2001-August/000063.html</A> a long thread about blocking calls.</P>
+<P><A HREF="http://techweb.rfa.org/pipermail/portaudio/2001-August/000137.html">http://techweb.rfa.org/pipermail/portaudio/2001-August/000137.html</A> this is Roger Dannenberg's proposal and a subsequent discussion</P>
+<P><A HREF="http://techweb.rfa.org/pipermail/portaudio/2001-August/000144.html">http://techweb.rfa.org/pipermail/portaudio/2001-August/000144.html</A> is a thread discussing using blocking APIs with other languages</P>
+<H4>Proposal</H4>
+<P>This proposal needs further documentation, but some details are provided below.</P>
+<P>If a NULL callback parameter is passed to Pa_OpenStream() then the stream is opened in blocking mode. This enables users to call Pa_WriteStream() and Pa_ReadStream() to read and write sample data.</P>
+<P>For a while there was a talk about only requiring implementations to implement blocking calls and that callbacks would always be implemented on top of blocking. The current direction is that this decision will be made independently for each driver-model.</P>
+<P>There needs to be a way to call the read and write functions without them blocking or to determine in advance how many samples can be read or written without blocking. One proposal to avoid blocking in environments without native threads is to ask PortAudio how many frames are available, and then to sleep() (using non-native thread management) until the next buffer boundary.</P>
+<P>Roger Dannenberg wrote the following email that is included here because it didn't seem to make it into the mailing list archive:</P>
+<BLOCKQUOTE>> It would be nice if the buffer could be returned to PortAudio as soon<BR>
+> as the client had finished with it. For example, in the MME<BR>
+> implementation this would allow the buffer to be requeued with<BR>
+> the driver sooner.<BR>
+<BR>
+My model is that, in general, you should target the worst case where audio processing takes most of the CPU time. In that case, the app finishes reading and writing buffers just before it's time to start the next buffer. In that case, there's little to gain by trying to return buffers early. Alternatively, if CPU time is negligible, wouldn't returning the buffer immediately (to MME) effectively increase the buffer count by one? In other words, you could just allocate one extra buffer and not return read buffers until later.<BR>
+<BR>
+I agree that ideally you should return the buffer when you can, but this adds complexity to the application and is not typical of a blocking read interface. If the call to release the buffer was *optional*, I'd have no objection, but that puts some additional bookkeeping back on the library side.<BR>
+<BR>
+> Is GetAvailable() the best way to implement non-blocking i/o?<BR>
+It works in practice. Some systems including Windows do not implement this function very well, i.e. the reported available space comes in fits and starts. But at least you can find out if an IO call would block or fail. I'd like to avoid the extra system call when possible though.</BLOCKQUOTE>
+<H4>Implementation Notes</H4>
+<P>Implementing blocking i/o will be quite simple for driver models where the underlying API is blocking-based, and quite difficult to do well under Windows where much fun will be had with Win32 synchronisation primitives.</P>
+<H4>Impact Analysis</H4>
+<P>This proposal would extend the functionality of PortAudio without requiring any changes to client code. </P>
+<P>____________</P>
+<H2>Non-<A NAME="Interleaved"></A>Interleaved Buffers</H2>
+<H4>Status</H4>
+<P>This proposal is sufficiently well defined to be implemented. No objections have been raised.</P>
+<H4>Background</H4>
+<P><A HREF="http://techweb.rfa.org/pipermail/portaudio/2001-October/000210.html">http://techweb.rfa.org/pipermail/portaudio/2001-October/000210.html</A> </P>
+<P>Some native APIs use non-interleaved buffers, particularly those that support N>2 channels. Additionally, many client applications use non-interleaved buffers internally. In order to avoid adding unnecessary overhead, PortAudio should support both interleaved and non-interleaved buffers on all platforms. </P>
+<P>The current PortAudio/ASIO implementation works as follows : ASIO native buffers are non-interleaved and the de-interleaving, format conversion and copying the data into PortAudio interleaved buffers is done in one loop. But if PortAudio supported non-interleaved buffers then we could use efficient vector operations even for native buffer <==> port audio buffers transfers. </P>
+<H4>Proposal</H4>
+<P>A new sample format could be defined: </P>
+<PRE>#define paNonInterleaved ((PaSampleFormat) (1<<32)) </PRE>
+<P> </P>
+<P>This could be used as a modifier flag to the buffer format fields of Pa_OpenStream(). When present, this flag would indicate that non-interleaved buffers would be passed to the callback. When not present, interleaved buffers would be used as is currently always the case. For example, the following code would open an interleaved stream:</P>
+<PRE>
+Pa_OpenStream(&stream,
+ paNoDevice,
+ 0,
+ paFloat32
+ NULL,
+ Pa_GetDefaultOutputDeviceID(),
+ 2,
+ paFloat32,
+ NULL,
+ SAMPLE_RATE,
+ FRAMES_PER_BUFFER,
+ 0,
+ paClipOff,
+ patestCallback,
+ &data );</PRE>
+<P>And the following code would open a non-interleaved stream:</P>
+<PRE>
+Pa_OpenStream(&stream,
+ paNoDevice,
+ 0,
+ paFloat32|paNonInterleaved,
+ NULL,
+ Pa_GetDefaultOutputDeviceID(),
+ 2,
+ paFloat32|paNonInterleaved,
+ NULL,
+ SAMPLE_RATE,
+ FRAMES_PER_BUFFER,
+ 0,
+ paClipOff,
+ patestCallback,
+ &data );</PRE>
+<P>In the user callback, the application would be passed a pointer to an array of buffers. The left and right buffers of a non-interleaved stream could be accessed as follows: </P>
+<PRE>
+ float *left = ((float **) inputBuffer)[0];
+ float *right = ((float **) inputBuffer)[1];</PRE>
+<P>This new sample format could also be used to interrogate the native driver to see if it supports interleaved or non-interleaved buffers. This would be achieved by reading the nativeSampleFormats field of the PaDeviceInfo structure. </P>
+<H4>Impact Analysis</H4>
+<P>This proposal extends the functionality of PortAudio without any impact on existing client code. It will require new conversion functions and all existing PortAudio implementations will have to be modified to reference these new conversion functions.</P>
+<P>____________</P>
+<H2><A NAME="MultipleDriverModels">Support For Multiple Driver Models</A> in a Single Build</H2>
+<H4>Status</H4>
+<P>This proposal is currently being discussed. Its final form depends on a number of other unfinished proposals.</P>
+<H4>Dependencies </H4>
+<P>The API changes described in this proposal are independent of all other proposals. However, changes to the host error mechanism defined in <A HREF="#Error">Handling of Host-Specific Error Codes</A>, and the addition of new API functions due to the <A HREF="#Blocking">Blocking Read/Write API</A> proposal may effect the implementation of this proposal. Changes to the API defined by the <A HREF="#ImproveDeviceFormatQuerySystem">Improve Device Format Query System</A> and the <A HREF="#Latency">Improve the Latency Setting Mechanism</A> proposals will need to be multi-driver-model capable. </P>
+<H4>Background</H4>
+<P>As the number of supported driver models available on each platform grows (WMME, ASIO, and DirectSound under Windows for example) client applications need to be able to select between different driver models at run-time. At least four platforms supported by PortAudio have multiple native driver models. At present PortAudio allows clients to link in support for at most one driver model.</P>
+<P>This proposal is based this email: <A HREF="http://techweb.rfa.org/pipermail/portaudio/2001-December/000308.html">http://techweb.rfa.org/pipermail/portaudio/2001-December/000308.html</A></P>
+<H4>Requirements</H4>
+<P>It will be necessary to supply clients with a method of displaying a textual description of the driver model for each PortAudio device.</P>
+<P>Some PortAudio functions do not operate on PortAudioStreams, but rather they operate on or return the global state of the PortAudio library as a whole. If multiple driver-models were present, some of these functions would have different implementations, or would return different values depending on which the driver model they applied to. These functions include:</P>
+<PRE> int Pa_GetMinNumBuffers( int framesPerBuffer, double sampleRate );
+ PaDeviceID Pa_GetDefaultInputDeviceID( void );
+ PaDeviceID Pa_GetDefaultOutputDeviceID( void );
+ </PRE>
+<P>Note that Pa_CountDevices() could also be interpreted as applying to a specific driver model.</P>
+<P>PortAudio currently implements a per-driver-model extension mechanism via the inputDriverInfo and outputDriverInfo parameters to Pa_OpenStream(). For code to take advantage of driver-model-specific extensions when multiple driver models are present there needs to be a way to establish which (statically named) driver model is associated with each device. This is because driver-model-specific extensions should only be used in combination with devices supplied by that driver model.</P>
+<P>PortAudio should present clients with all of the devices made available by each driver model. This means that some physical devices may be accessible though multiple driver models. Since it will not be possible to open a full duplex stream with input and output devices from different driver models, some clients may want to enumerate the available driver models and only display devices from one driver model at a time.</P>
+<P>Introducing a new PortAudioDriverModel abstraction could fulfil the above requirements. At a minimum, this abstraction would need to have the following attributes:</P>
+
+<UL>
+<LI>A textual description for display on user interfaces </LI>
+<LI>Functions for querying default device ids and latency parameters for each driver model </LI>
+<LI>A unique identifier published in portaudio.h for use in code which takes advantage of driver model specific extensions</LI></UL>
+
+<P>Additionally, the following features could be present:</P>
+
+<UL>
+<LI>A method for querying the default PortAudioDriverModel (perhaps the "best" driver model which has more than 0 devices available) </LI>
+<LI>A method for enumerating 'currently available' PortAudioDriverModels. 'Currently available' could be interpreted as meaning the driver models linked into the current PortAudio implementation, or it could mean the driver models which currently have more than zero devices available. </LI>
+<LI>A method of enumerating PortAudioDevices independently for each available PortAudioDriverModel</LI></UL>
+
+<H4>Proposal</H4>
+<P>This proposal consists of the 7 modifications to the PortAudio API listed below.</P>
+<P>1. Define a new PaDriverModelTypeID enumeration, with fixed values for each driver model:</P>
+<PRE>
+/*
+ The PaDriverModelTypeID enumeration contains constants for uniquely
+ Identifying each driver model supported by PortAudio. This type
+ is used in the PaDriverModelInfo structure below. Driver model type ids
+ are guaranteed to never change, thus allowing code to be written that
+ conditionally uses driver model specific extensions.
+ New type ids will only be allocated when support for a new driver
+ model reaches "public alpha" status, prior to that developers should
+ use the paInDevelopment type id.
+*/
+
+typedef enum {
+ paInDevelopment=0, /* use while developing support for a new driver model */
+ paWin32DirectSound=1,
+ paWin32MME=2,
+ paWin32ASIO=3,
+ paMacOSSoundManager=4,
+ paMacOSCoreAudio=5,
+ paMacOSASIO=6,
+ paOSS=7,
+ paALSA=8,
+ paIRIXAL=9,
+ paBeOS=10
+}PaDriverModelTypeID;</PRE>
+<P>2. Define a method for enumerating driver models:</P>
+<PRE>
+/*
+ Driver model enumeration mechanism.
+
+ Driver model ids range from 0 to Pa_CountDriverModels()-1.
+
+ The default driver model is the lowest common denominator
+ driver model on the current platform and is unlikely to provide
+ the best performance.
+*/
+
+typedef int PaDriverModelID;
+#define paDefaultDriverModel 0;
+
+struct{
+ int structVersion;
+ PaDriverModelTypeID typeID; /* the well known unique identifier of this driver model */
+ const char *name; /* a textual description of the driver model for display on user interfaces */
+}PaDriverModelInfo;
+
+
+PaDriverModelID Pa_CountDriverModels();</PRE>
+<P>3. Provide a method for retrieving information about a given driver model:</P>
+<PRE>
+/*
+ Pa_ GetDriverModelInfo () returns a pointer to an immutable
+ PaDriverModelInfo structure referring to the device specified by driverModelID.
+ If driverModelID is out of range 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 PaDriverModelInfo* Pa_GetDriverModelInfo( PaDriverModelID driverModelID );</PRE>
+<P>4. Add a new field to PaDeviceInfo to identify the driver model type:</P>
+<PRE>
+struct{
+ ...
+ PaDriverModelID driverModel; /* note this is the run-time id */
+ ...
+}PaDeviceInfo;</PRE>
+<P>This would enable the following two code fragments to be written.</P>
+<PRE>
+/* obtain the user-readable name of a device's driver model */
+Pa_GetDriverModelInfo( deviceInfo->driverModel )->name;
+
+/* implement special behavior for a specific driver model */
+if( Pa_GetDriverModelInfo( deviceInfo->driverModel )->typeID == paWin32MME ){
+ InitialiseMMESpecificDeviceInfo();
+}</PRE>
+<P>5. Provide methods for finding per-driver model default devices and latency settings:</P>
+<PRE>
+PaDeviceID Pa_DriverModelDefaultInputDeviceID( PaDriverModelID driverModelID );
+PaDeviceID Pa_DriverModelDefaultOutputDeviceID( PaDriverModelID driverModelID );
+int Pa_DriverModelMinNumBuffers( PaDriverModelID driverModelID, int framesPerBuffer, double sampleRate );</PRE>
+<P>6. Provide functions for enumerating devices on a per-driver-model basis. Note that this functionality is provided in addition to the current Pa_CountDevices() and Pa_GetDeviceInfo() functions:</P>
+<PRE>
+int Pa_DriverModelCountDevices( PaDriverModelID driverModelID );
+PaDeviceID Pa_DriverModelGetDeviceID( PaDriverModelID driverModelID, int perDriverModelIndex );</PRE>
+<P>7. Re-implement the following existing functions to use the default driver model. This would be a backwards compatible change except for Pa_GetMinNumBuffers() which gains an extra parameter.</P>
+<PRE>
+PaDeviceID Pa_GetDefaultInputDeviceID( void ); /* returns the default device id for the default driver model */
+PaDeviceID Pa_GetDefaultOutputDeviceID( void );
+
+int Pa_GetMinNumBuffers( PaDeviceID id, int framesPerBuffer, double sampleRate );</PRE>
+<P>Note that Pa_GetMinNumBuffers() takes a device id, not a driver model id. This minimises the need for clients to be aware of the multiple driver model extensions. </P>
+<H4>Discussion</H4>
+<P>The main disadvantage of this proposal it that it may make the API seem more complex for new users.</P>
+<P>There is concern that this proposal is too complex, and that the simpler solution of simply adding a driverModel string to the device info structure of each device would be sufficient. It is true that the simple solution would allow clients to duplicate the functionality of this proposal, provided driverModel strings were published and guaranteed not to change in the future. However, the bulk of the functionality included in this proposal will need to be implemented internally to facilitate multiple driver model support anyway. This proposal is based on the assumption that it is better to expose such functionality in the PortAudio API rather than require clients to reimplement what is already present internally. </P>
+<P>There has been discussion about supporting "pluggable" driver models - the general idea is that a client application could link against PortAudio and PortAudio would load the available Driver Models at run-time using "PortAudio Driver Model Plugins." Some people consider this to be an overly complex solution, and no significant advantages over a monolithic PortAudio dll have been submitted yet. Some people would like PortAudio to always be able to be statically linked with multiple driver model support.</P>
+<P>The overhead (both processor and memory) of the Multiple Driver Model support should be minimised on platforms which don't have multiple driver models (such as BeOS and some handheld devices.) Essentially this means that the functionality provided in the multiple driver model façade should be easy to duplicate.</P>
+<H4>Implementation Notes</H4>
+<P>The implementation will follow the methodology currently employed in PortMIDI described here: <A HREF="http://techweb.rfa.org/pipermail/portaudio/2001-December/000295.html">http://techweb.rfa.org/pipermail/portaudio/2001-December/000295.html</A></P>
+<P>An implementation of the driver model neutral "Façade" of this proposal exists here: </P>
+<P><A HREF="pa_drivermodel.c.txt">pa_drivermodel.c.txt</A></P>
+<P><A HREF="pa_drivermodel.h.txt">pa_drivermodel.h.txt</A></P>
+<P>This proposal will involve the changes described below. Note that the string <DM> will be replaced with a driver model tag for each implementation.</P>
+<P>Each driver model will have it's own Initialize function which PortAudio will call in response to client calls to Pa_Initialize and Pa_Terminate respectively. This will be the only identifier each driver model implementation will be required to expose.</P>
+<PRE>PaError Pa<DM>_MultiDriverInitialize( PaDriverModelImplementation **impl );</PRE>
+<P>PaDriverModelImplementation is an internal data structure containing a set of function pointers for globally relevant functions: (function pointer type declarations omitted for simplicity:)</P>
+<PRE>struct{
+ fptr terminate; /* takes the PaDriverModelImplementation* returned by initialize */
+ fptr getDriverModelInfo;
+ fptr getHostError;
+ fptr getHostErrorText;
+ fptr countDevices;
+ fptr getDefaultInputDeviceID;
+ fptr getDefaultOutputDeviceID;
+ fptr getDeviceInfo;
+ fptr openStream;
+ fptr getMinNumBuffers;
+} PaDriverModelImplementation;</PRE>
+<P>The function pointers in PaDriverModelImplementation will point to the corresponding functions in current PortAudio implementations. The new multiple driver model support code will take care of mapping per-driver model device ids onto a single homogenous driver id range. A significant advantage of this scheme is that it will require very little change to existing PortAudio implementations.</P>
+<P>A new PaStreamImplementation internal data structure will be defined to contain function pointers to implementations of the stream functions for each driver model. This structure will be placed at the head of implementation-specific data structures returned as PortAudioStream* in current implementations.</P>
+<PRE>struct{
+ unsigned long magic;
+ fptr close;
+ fptr start;
+ fptr stop;
+ fptr abort;
+ fptr active;
+ fptr time;
+ fptr cpuLoad;
+} PaStreamImplementation;</PRE>
+<P>Magic contains a unique bit pattern which should be set by implementations when a stream is opened, and cleared when it is closed. This technique will allow implementations to perform some degree of validation on PortAudioStream* passed to PortAudio.</P>
+<H4>Impact Analysis</H4>
+<P>This proposal will significantly improve the utility of PortAudio by allowing clients to support multiple driver models in a single executable. </P>
+<P>The only required change for existing clients will to insert an extra deviceID parameter into calls to Pa_GetMinNumBuffers().</P>
+<P>Since multiple driver models may return devices with the same names, a minimum requirement for clients who want to be "multiple driver model aware" will be to ensure that the appropriate driver model name is displayed alongside device names in the user interface.</P>
+<P>____________</P>
+<H2><A NAME="DriverModelSpecificPa_OpenStream">Driver Model Specific Pa_OpenStream() Parameters</A></H2>
+<H4>Status</H4>
+<P>This proposal is essentially complete, but is pending the final definition of PaDriverModelTypeID (see below.) </P>
+<H4>Dependencies</H4>
+<P>If the PaDriverModelSpecificStreamInfo structure defined in this proposal includes a PaDriverModelTypeID driver model identifier, then this proposal depends on the <A HREF="#MultipleDriverModels">Support for Multiple Driver Models in a Single PortAudio Build</A> proposal to define the form of the identifier.</P>
+<H4>Background</H4>
+<P>Pa_OpenStream has always had the inputDriverInfo and outputDriverInfo parameters, which were defined to support passing driver-model specific information to PortAudio implementations. Currently these parameters are defined as void* and are not used by any implementation. Two uses of inputDriverInfo and outputDriverInfo are planned for the near future: passing device names to OSS drivers, and passing additional device ids for opening multichannel soundcards under MME.</P>
+<H4>Proposal</H4>
+<P>The following structure could be defined and be placed at the head of all data structures passed to the inputDriverInfo and outputDriverInfo parameters of Pa_OpenStream:</P>
+<PRE>struct{
+ unsigned long size; /* size of whole structure including this header */
+ PaDriverModelTypeID driverModel; /* driver model for which this data is intended */
+ unsigned long version; /* structure version */
+}PaDriverModelSpecificStreamInfo;</PRE>
+<P>The following driver model specific extensions should be placed in separate header files rather than being placed in portaudio.h</P>
+<P>___</P>
+<P>The following structure is proposed for passing device names to the OSS implementation:</P>
+<PRE>struct{
+ PaDriverModelSpecificStreamInfo header;
+ char *deviceName;
+}PaOSSSpecificStreamInfo;</PRE>
+<P>A pointer to this structure could be passed to Pa_OpenStream() to request that a device other than the default dsp device be opened. This structure could be used for opening input and/or output devices.</P>
+<P>___</P>
+<P>The following structure is proposed for passing multiple interleaved device ids to the MME implementation in order to open a multichannel stream with some soundcards that support multichannel operation via multiple stereo (or other number of channels) interleaved devices. When this structure is passed, the MME implementation would ignore the deviceId parameters passed directly to Pa_OpenStream(), however it would not ignore the channelCount parameters.</P>
+<P>#define paWMMEPassMultipleInterleavedBuffers 0x01 /* a flag */</P>
+<PRE>struct{
+ PaDriverModelSpecificStreamInfo header;
+ int *deviceIdsAndChannelCounts; /* interleaved deviceIds and channelCounts */
+ int deviceCount;
+ int flags;
+}PaMMESpecificStreamInfo;</PRE>
+<P>The deviceIdsAndChannelCounts field points to an array of ints containing multiple {deviceId, channelCount} pairs. The number of integer elements in the array must be two times the value of the deviceCount field. Specified deviceIds must have a driver model type of Windows MME. Currently only one flag is defined: paWMMEPassMultipleInterleavedBuffers, this can be used to request that the raw, multiple interleaved buffers be passed to the callback.</P>
+<H4>Discussion</H4>
+<P>The type of the inputDriverInfo and outputDriverInfo parameters could be changed to PaDriverModelSpecificStreamInfo* however this may cause more trouble that it's worth.</P>
+<P>The PaMMESpecificStreamInfo functionality may require the common buffer conversion functions defined in the <A HREF="#ReviseInternalHostAPI">Revise Internal Host API</A> proposal to support (multiple interleave <==> unified interleave) and (multiple interleave <==> non-interleaved) conversions.</P>
+<H4>Impact Analysis</H4>
+<P>This proposal provides access to new platform-specific extensions. No existing client code will be modified. Only implementations that implement the extensions will be effected.</P>
+<P>____________</P>
+<H2><A NAME="Error"></A>Handling of Host-Specific Error Codes</H2>
+<H4>Status</H4>
+<P>This proposal is sufficiently well defined to be implemented immediately. However, the possibility of extending the scope of this proposal is being discussed in this thread: <A HREF="http://techweb.rfa.org/pipermail/portaudio/2002-January/000358.html">http://techweb.rfa.org/pipermail/portaudio/2002-January/000358.html</A></P>
+<H4>Background</H4>
+<P>Currently the PaHostError error code is used to notify clients that a platform-specific error condition occurred. This is considered ambiguous and difficult to work with. </P>
+<H4>Proposal</H4>
+<P>PortAudio should seek to avoid returning ambiguous paHostError error codes, and instead translate to portable PortAudio error codes instead. In the case of the pa_win_mme implementation this means translating the following MME error codes:</P>
+<P>MMSYSERR_ALLOCATED to paDeviceBusy (new) <BR>
+MMSYSERR_BADDEVICEID to paInvalidDeviceId (already defined) <BR>
+MMSYSERR_NODRIVER to paDriverMissing (new) <BR>
+MMSYSERR_NOMEM to paInsufficientMemory (already defined) <BR>
+WAVERR_BADFORMAT to paSampleFormatNotSupported (already defined) </P>
+<H4>Discussion</H4>
+<P>It is suggested that all implementations should be audited for their use of PaHostError.</P>
+<P>There was some concern about polluting the PortAudio error code namespace with platform-specific error codes, and of the potential overhead of including platform specific error strings on other platforms. Another suggestion has been to add a Pa_GetHostErrorText() function.</P>
+<P>If all error codes are mapped to PortAudio error codes do we need a PaHostError code and the Pa_GetHostErrorCode() function?</P>
+<P>A suggestion has been made to extend Pa_GetErrorText() so that it retrieved driver model specific error strings when a host error occurs.</P>
+<H4>Impact Analysis</H4>
+<P>This proposal improves the quality of PortAudio diagnostics. Client code that depends on paHostError code to flag certain conditions may be effected.</P>
+<P>____________</P>
+<H2><A NAME="RenamePa_GetCPULoad">Rename Pa_GetCPULoad() to Pa_StreamCPULoad()</A></H2>
+<H4>Status</H4>
+<P>Proposal is sufficiently well defined to be implemented. No objections have been raised.</P>
+<H4>Background</H4>
+<P>PortAudio functions that return global information typically have names of the form Pa_Get*() (eg. Pa_GetDeviceInfo). Almost all functions operating on PortAudio streams conform to the following implicit naming convention: Pa_*Stream( stream ) performs an action on a stream (eg Pa_StartStream() ) and Pa_Stream*( stream ) returns a stream attribute (eg. Pa_StreamTime() ). The only exception to this convention is the confusingly named Pa_GetCPULoad() which actually returns the CPU consumption of a particular stream's callback. </P>
+<H4>Proposal</H4>
+<P>Rename PaGetCPULoad() to Pa_StreamCPULoad() in order to conform to established naming conventions.</P>
+<H4>Impact Analysis</H4>
+<P>This proposal improves the consistency of the naming scheme making the API easier to learn and remember. All clients which call Pa_GetCPULoad() will need to alter their code by renaming the function call.</P>
+<P>____________</P>
+<H2><A NAME="CodingStyleGuidelines">Coding Style Guidelines</A></H2>
+<H4>Status</H4>
+<P>This proposal is under construction. Further suggestions and comments would be extremely welcome.</P>
+<H4>Background</H4>
+<P>Since the PortAudio code is commonly edited on many different platforms using different editors it has been suggested that some conventions be adopted to improve readability and consistency. The general opinion is that the definition of such conventions, and their enforcement shouldn't be too extreme. There are also a number of unspoken implementation standards that could be usefully written down. This proposal consists of a list of mechanical formatting conventions, and a list of "quality of implementation" conventions. When completed this proposal will packaged with the distribution and placed on the web site as "Coding Style Guidelines for PortAudio Implementors."</P>
+<H4>Proposal</H4>
+<P>The following formatting conventions should be adhered to in all PortAudio code:</P>
+
+<UL>
+<LI>TABs should not be used in .c and .h files; instead 4 spaces should be used. Makefiles should continue to use TABs since this is required by Make </LI>
+<LI>Adopt a consistent set of rules for placement of braces (see note regarding Astyle below) </LI>
+<LI>Adopt a consistent policy for line-end characters. This could be 'use CR on Mac, CRLF on Windows and LF on Unix' or it could be 'use Unix style new-lines in all source files.</LI></UL>
+
+<P>AStyle ( <A HREF="http://astyle.sourceforge.net/">http://astyle.sourceforge.net/</A> ) has been proposed as helpful tool for cleaning code, however we haven't yet decided whether to use it on an ongoing basis. Once our style guidelines have been established it is expected that contributors of each implementation will take responsibility for keeping their code clean, as an automated tool applied by someone unfamiliar with the code will probably just mess things up.</P>
+<P>In addition to the formatting conventions noted above, the following "quality of implementation" coding guidelines are being proposed to establish a quality baseline for our implementations:</P>
+
+<UL>
+<LI>All code should be written in C++-compatible plain ANSI-C (i.e. no // comments). The following guideline has been proposed: should compile silently with both "gcc -ansi -pedantic -Wall" and "g++ -ansi -pedantic -Wall" </LI>
+<LI>Think of PortAudio as a heavyweight library rather than a lightweight wrapper. Always code defensively. Efficiency is important where it matters (eg in real-time callbacks) but safety is important everywhere. </LI>
+<LI>All parameters passed to PortAudio by the user should be validated, and error codes returned where necessary. All reasonable efforts should be made to minimise the risk of a crash resulting from passing incorrect parameters to PortAudio. </LI>
+<LI>Error handling should be complete. Every host function that can return an error condition should have its status checked. PortAudio may attempt to recover from errors, but generally error codes should be returned to the client. </LI>
+<LI>In almost all cases, a PortAudio error code should be preferred to returning PaHostError. If a new PortAudio error code is needed it should be discussed with the maintainer to coordinate updating port_audio.h </LI>
+<LI>PortAudio code should not cause resource leaks. After Pa_Terminate() is called, implementations should guarantee that all dynamically allocated resources have been freed. </LI>
+<LI>The definition of the PortAudio API should minimise "implementation defined behaviour". For example, calling functions such as Pa_Initialize() after PortAudio is initialised, or Pa_Terminate() after PortAudio has been terminated should have well defined behaviour. (In this example, both calls should be safe and simply return an error code.) </LI>
+<LI>Minimise dependence on ANSI C runtime on platforms where it would have to be loaded separately (eg on Win32 prefer Win32 API functions such as GlobalAlloc() to ANSI C functions such as malloc().)</LI></UL>
+
+<P>It has been suggested that we make an effort to minimise the use of global and static data in PortAudio implementations. Another related goal is to reduce name pollution in the global scope. Some possible guidelines in this regard are:</P>
+
+<UL>
+<LI>Implementations should avoid exporting any symbols except where absolutely necessary. Specifically, global data must be declared statically. We will need a naming convention for non-public global symbols, such as internal functions defined in one module and used in another. </LI>
+<LI>Implementations should minimise their use of static data. </LI></UL>
+
+<H4>Discussion</H4>
+<P>There will always be time to improve these guidelines, however we are making a concerted effort to document some standards before the next round of changes are implemented.</P>
+<H4>Impact Analysis</H4>
+<P>This proposal will require all existing code to be reviewed and possibly revised. This is not expected to be a "big-bang" operation. Rather it is envisaged that this will be a long term, ongoing process aimed at improving the quality of the PortAudio codebase. </P>
+<P>____________</P>
+<H2><A NAME="AdditionalPa_TerminateBehaviour">Additional Pa_Terminate() Behaviour</A></H2>
+<H4>Status</H4>
+<P>This proposal is sufficiently well defined to be implemented. </P>
+<H4>Background</H4>
+<P>Some driver models (eg ASIO, MME and DirectSound under Windows NT) can require a reboot to free devices when they are not closed properly (due to a program not calling Pa_Close() either in error, or due to a crash.) As a quality of implementation issue PortAudio should seek to avoid such circumstances.</P>
+<H4>Proposal</H4>
+<P>The definition of Pa_Terminate() should be extended as follows:</P>
+<PRE>/*
+ Pa_Terminate() is the library termination function - call this after
+ using the library. This function deallocates all resources allocated
+ by PortAudio since it was initializied using Pa_Initialize(). Any open
+ PortAudioStreams are closed.
+
+ 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.
+*/
+PaError Pa_Terminate( void );</PRE>
+<H4>Implementation Notes</H4>
+<P>One possible implementation strategy would be to add a "next" member to the internal stream data structure thus making it a linked list node, which could be linked into a list of all open streams.</P>
+<H4>Discussion</H4>
+<P>Some concerns have been raised about the overhead involved in PortAudio having to keep track of which streams are currently open. </P>
+<P>There has been some discussion about the behaviour of nesting multiple calls to Pa_Initialize() and Pa_Terminate() - there is no intention of changing the current behaviour, which is that PortAudio has two states: "Initialized" and "Uninitialized" - in the Initialized state, Pa_Initialize() does nothing and returns an error, in the Uninitialized state Pa_Terminate() does nothing and returns an error.</P>
+<H4>Impact Analysis</H4>
+<P>This proposal changes the termination behaviour of PortAudio to reduce the likelihood of resource leaks.</P>
+<P>On Windows, the new Pa_Terminate() behaviour would allow users who want full protection against device leakage to install a global Win32 exception handler that calls Pa_Terminate() before exiting when a crash occurs. Similar techniques (using SIGNAL handlers perhaps?) may be possible on other platforms where necessary.</P>
+<P>____________</P>
+<H2><A NAME="ReviseInternalHostAPI">Revise Internal Host API</A></H2>
+<H4>Status</H4>
+<P>This proposal is under construction. Ideally, someone should go through all of the existing implementations and identify code that could be factored into a common library (parameter validation code for example.)</P>
+<H4>Dependencies</H4>
+<P>This proposal is dependent on the <A HREF="#MultipleDriverModels">Support for Multiple Driver Models in a Single PortAudio Build</A> proposal, and the <A HREF="#Interleaved">Non-Interleaved Buffers</A> proposal. The proposed conversion functions may be dependent on the MME multichannel via stereo pairs extension which is part of the <A HREF="#DriverModelSpecificPa_OpenStream">Driver Model Specific Pa_OpenStream() Parameters</A> proposal.</P>
+<H4>Background</H4>
+<P>PortAudio defines a set of helper functions that all implementations share. It is envisaged that these internal functions will need to be revised in response to the changes proposed in this document. It would also be beneficial to take this opportunity to refactor any other common code fragments that could be shared by multiple implementations.</P>
+<P>A refactoring of the buffer data conversion functions was proposed here: <A HREF="http://techweb.rfa.org/pipermail/portaudio/2001-November/000244.html">http://techweb.rfa.org/pipermail/portaudio/2001-November/000244.html</A> However the proposal below is not quite the same. A significant benefit of formally specifying the interface to the buffer conversion functions is that it would facilitate the creation of optimised assembly language versions for different platforms.</P>
+<H4>Proposal</H4>
+<P>A common set of buffer conversion functions should be defined and shared by all implementations. The buffer conversion functions should handle all permutations of:</P>
+
+<UL>
+<LI>Sample format </LI>
+<LI>Channels </LI>
+<LI>Interleave / Non-interleave </LI>
+<LI>Endianness </LI>
+<LI>Channel compensation</LI></UL>
+
+<P>"Channel-compensation" is necessary when certain devices require a higher number of channels than the user requests. With the Midiman Delta1010, for example, the device always needs to be fed 10 channels of output and you must read 12 channels of input (at least under ALSA without the "plug" interface).</P>
+<P>The conversion functions could look something like:</P>
+<PRE>void ConversionFunction_DestType_DestInterleave_SrcType_SrcInterleave_ ( void *dest, int destChannels, void *src, int srcChannels, int frames );</PRE>
+<P>The dest and src parameters have the same format as those supplied to the PortAudio client callback.</P>
+<P>Rather than have each implementation call these conversion functions directly, a 'factory function' could be implemented that returnes a pointer to a conversion function based on parameters specifying the format of the source and destination buffers. This factory function could be called as needed when a stream is opened. The conversion functions could then be made static and hidden from the rest of PortAudio. The 'factory function' could have the following form:</P>
+<PRE>enum PaEndiannes { paBigEndian, paSmallEndian, paHostEndian };
+
+PaBufferConversionFunction* Pa_GetBufferConversionFunction(
+ PaSampleFormat destFormat, int destChannels, PaEndianness destEndianness,
+ PaSampleFormat srcFormat, int srcChannels, PaEndianness srcEndianness );</PRE>
+<P>Note that the interleave/deinterleave status is encoded in the destFormat and srcFormat parameters. paHostEndian is used to represent the endianness of the current platform since some driver models (eg ASIO) allow the driver to use samples in a different endianness from the host endianness. Another alternative is to encode sample endianness in PaSampleFormat - this would allow clients to write sample data of either endianness to PortAudio (e.g. soundfile playback direct from file) and benefit from PortAudio's byte swapping code.</P>
+<P>The redundant use of channel parameters in both the conversion functions and the factory function is intentional and would allow channel-optimised conversion functions to be supplied for common cases such as 16-bit stereo.</P>
+<H4>Discussion</H4>
+<P>This proposal currently only addresses buffer conversion functions, but we would like to identify other common code fragments which could be placed in the shared PortAudio library.</P>
+<P>This proposal has not yet addressed the fact that the conversion functions also need to handle clipping and dithering.</P>
+<P>It is not clear whether additional conversion functions will be needed to accommodate the MME interleaved stereo pairs for multichannel devices proposal.</P>
+<P>It hasn't been established whether PortAudio will be extended to support all PaSampleFormats on all devices.</P>
+<P>It isn't clear whether paCustomFormat is viable under this proposal, or how it would be accommodated.</P>
+<P>When the client requested format and the host format are different a temporary buffer may be required to hold the converted data. However, in general PortAudio should aim to convert data in-place. Functions may be needed to establish when temporary buffers are needed, and to allocate them.</P>
+<P>Due to a mismatch between the API buffer size and the PortAudio callback buffer size some driver models require PortAudio to shuffle data among multiple buffers in order to fulfil client requests - this has not yet been considered within the current proposal.</P>
+<P>Memory allocation should probably be handled with platform specific functions such as Win32 GlobalAlloc() rather than using malloc()</P>
+<H4>Impact Analysis</H4>
+<P>This proposal only effects PortAudio implementors. Increasing the utility of shared code will improve the quality of all PortAudio implementations in terms of speed, size, and robustness. It should also reduce the effort involved in porting PortAudio to a new driver model.</P>
+<P>____________</P></BODY>
+</HTML>
--- /dev/null
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="GENERATOR" content="Mozilla/4.77 [en]C-gatewaynet (Win98; U) [Netscape]">
+ <meta name="Author" content="Phil Burk">
+ <meta name="Description" content="PortAudio is a cross platform, open-source, audio I/O library.It provides a very simple API for recording and/or playing sound using a simple callback function.">
+ <meta name="KeyWords" content="audio, library, portable, open-source, DirectSound,sound, music, JSyn, synthesis,">
+ <title>PortAudio Implementations for DirectSound</title>
+</head>
+<body>
+
+<center><table COLS=1 WIDTH="100%" BGCOLOR="#FADA7A" >
+<tr>
+<td>
+<center>
+<h1>
+PortAudio - Release Notes</h1></center>
+</td>
+</tr>
+</table></center>
+
+<p>Link to <a href="http://www.portaudio.com">PortAudio Home Page</a>
+<h2>
+<b>V18 - unreleased</b></h2>
+
+<blockquote>Ran most of the code through <a href="http://astyle.sourceforge.net/">AStyle</a>
+to cleanup ragged indentation caused by using different editors. Used this
+command:
+<br><tt>astyle --style=ansi -c -o --convert-tabs --indent-preprocessor
+*.c</tt></blockquote>
+
+<blockquote><b>WMME</b>
+<ul>
+<li>
+Fixed bug that caused TIMEOUT in Pa_StopStream(). Added check for past_StopSoon()
+in Pa_TimeSlice(). Thanks Julien Maillard.</li>
+</ul>
+<b>Unix OSS</b>
+<ul>
+<li>
+Use high real-time priority if app is running with root priveledges. Lowers
+latency.</li>
+</ul>
+</blockquote>
+
+<h2>
+<b>V17 - 10/15/01</b></h2>
+
+<blockquote><b>Unix OSS</b>
+<ul>
+<li>
+Set num channels back to two after device query for ALSA. This fixed a
+bug in V16 that sometimes caused a failure when querying for the sample
+rates. Thanks Stweart Greenhill.</li>
+</ul>
+</blockquote>
+
+<blockquote>
+<h4>
+<b>Macintosh Sound Manager</b></h4>
+
+<ul>
+<li>
+Use NewSndCallBackUPP() for CARBON compatibility.</li>
+</ul>
+</blockquote>
+
+<h2>
+<b>V16 - 9/27/01</b></h2>
+
+<blockquote><b>Added Alpha implementations for ASIO, SGI, and BeOS!</b>
+<br>
+<li>
+CPULoad is now calculated based on the time spent to generate a known number
+of frames. This is more accurate than a simple percentage of real-time.
+Implemented in pa_unix_oss, pa_win_wmme and pa_win_ds.</li>
+
+<li>
+Fix dither and shift for recording PaUInt8 format data.</li>
+
+<li>
+Added "patest_maxsines.c" which tests <tt>Pa_GetCPULoad().</tt></li>
+</blockquote>
+
+<blockquote>
+<h4>
+Windows WMME</h4>
+
+<ul>
+<li>
+sDevicePtrs now allocated using <tt>GlobalAlloc()</tt>. This prevents a
+crash in Pa_Terminate() on Win2000. Thanks Mike Berry for finding this.
+Thanks Mike Berry.</li>
+
+<li>
+Pass process instead of thread to <tt>SetPriorityClass</tt>(). This fixes
+a bug that caused the priority to not be increased. Thanks to Alberto di
+Bene for spotting this.</li>
+</ul>
+
+<h4>
+Windows DirectSound</h4>
+
+<ul>
+<li>
+Casts for compiling with __MWERKS__ CodeWarrior.</li>
+</ul>
+
+<h4>
+UNIX OSS</h4>
+
+<ul>
+<li>
+Derived from Linux OSS implementation.</li>
+
+<li>
+Numerous patches from Heiko Purnhagen, Stephen Brandon, etc.</li>
+
+<li>
+Improved query mechanism which often bailed out unnecessarily.</li>
+
+<li>
+Removed sNumDevices and potential related bugs,</li>
+
+<li>
+Use <tt>getenv("PA_MIN_LATENCY_MSEC")</tt> in code to set desired latency.
+User can set by entering:</li>
+
+<br> <tt>export PA_MIN_LATENCY_MSEC=40</tt></ul>
+
+<h4>
+Macintosh Sound Manager</h4>
+
+<ul>
+<li>
+Pass unused event to WaitNextEvent instead of NULL to prevent Mac OSX crash.
+Thanks Dominic Mazzoni.</li>
+
+<li>
+Use requested number of input channels.</li>
+
+<br> </ul>
+</blockquote>
+
+<h2>
+<b>V15 - 5/29/01</b></h2>
+
+<blockquote>
+<ul>
+<li>
+<b>New Linux OSS Beta</b></li>
+</ul>
+
+<h4>
+Windows WMME</h4>
+
+<ul>
+<li>
+ sDevicePtrs now allocated based on sizeof(pointer). Was allocating
+too much space.</li>
+
+<li>
+ Check for excessive numbers of channels. Some drivers reported bogus
+numbers.</li>
+
+<li>
+Apply Mike Berry's changes for CodeWarrior on PC including condition including
+of memory.h, and explicit typecasting on memory allocation.</li>
+</ul>
+
+<h4>
+Macintosh Sound Manager</h4>
+
+<ul>
+<li>
+ScanInputDevices was setting sDefaultOutputDeviceID instead of sDefaultInputDeviceID.</li>
+
+<li>
+Device Scan was crashing for anything other than siBadSoundInDevice, but
+some Macs may return other errors! Caused failure to init on some G4s under
+OS9.</li>
+
+<li>
+Fix TIMEOUT in record mode.</li>
+
+<li>
+Change CARBON_COMPATIBLE to TARGET_API_MAC_CARBON</li>
+</ul>
+</blockquote>
+
+<h2>
+<b>V14 - 2/6/01</b></h2>
+
+<blockquote>
+<ul>
+<li>
+Added implementation for Windows MultiMedia Extensions (WMME) by Ross and
+Phil</li>
+
+<li>
+Changed Pa_StopStream() so that it waits for the buffers to drain.</li>
+
+<li>
+Added Pa_AbortStream() that stops immediately without waiting.</li>
+
+<li>
+Added new test: patest_stop.c to test above two mods.</li>
+
+<li>
+Fixed Pa_StreamTime() so that it returns current play position instead
+of the write position. Added "patest_sync.c" to demo audio/video sync.</li>
+
+<li>
+Improved stability of Macintosh implementation. Added timeouts to prevent
+hangs.</li>
+
+<li>
+Added Pa_GetSampleSize( PaSampleFormat format );</li>
+
+<li>
+Changes some "int"s to "long"s so that PA works properly on Macintosh which
+often compiles using 16 bit ints.</li>
+
+<li>
+Added Implementation Guide</li>
+</ul>
+</blockquote>
+
+<h2>
+<b>V12 - 1/9/01</b></h2>
+
+<blockquote>
+<ul>
+<li>
+Mac now scans for and queries all devices. But it does not yet support
+selecting any other than the default device.</li>
+
+<li>
+Blocking I/O calls renamed to separate them from the PortAudio API.</li>
+
+<li>
+Cleaned up indentation problems with tabs versus spaces.</li>
+
+<li>
+Now attempts to correct bogus sample rate info returned from DirectSound
+device queries.</li>
+</ul>
+</blockquote>
+
+</body>
+</html>