API. Developers interested in making use of the API are advised to consult the portaudio.h header file, which contains full documentation for the API. There is also a tutorial on the PortAudio website. A minimal PortAudio program that performs ring modulation and mixing of a stereo input signal can be found at the end of this paper. It does not do any error checking in order to save space. It, hopefully, demonstrates the simplicity of using PortAudio to obtain audio I/O on multiple platforms. 3.1. Initialisation and Device Enumeration Before making use of the PortAudio library Pa_Initialize () must be called to initialise the library. When the library is no longer required Pa_Terminate () should be called. Pa_CountDevices () returns the number of available audio devices. Pa_GetDeviceInfo (id) returns a pointer to a PaDeviceInfo structure which contains information about the requested device. It includes the device name, maximum number of input and output channels, available sample rates, and the supported data formats. The Pa_GetDefaultInputDeviceID() and Pa_GetDefaultOutputDevicelD () functions may be used to retrieve the ids of the host's preferred input and output devices. 3.2. Stream Management PortAudio streams may be opened with either the Pa_OpenStream() or PaOpenDefaultStream() functions, both of which return an opaque handle to a PortAudioStream object. Pa_OpenStream () allows specification of: input and output devices; sample format; number of channels and a device specific information block for input and output; sample rate; number and size of i/o buffers; a set of implementation defined stream flags; the user callback function and a user specified data pointer which is passed to the callback function. Pa_OpenDefaultStream () provides a simplified interface for opening a stream using the default device(s) The Pa_StartStream () and Pa_StopStream () functions are used to begin and end processing on a stream. Pa_AbortStream() may be used to immediately abort playback on a stream rather than waiting for queued samples to finish playing. When the stream is started, audio I/O begins and the user callback function is repeatedly called with a pointer to a full input buffer that is to be read, and a pointer to an empty output buffer that is to be filled. It is also passed a time-stamp that is the number of sample frames generated so far. The time-stamp of the currently playing sample can also be queried which allows the audio output to be synchronized with MIDI or video events. The user defined callback function supplied to Pa_OpenStream() and Pa_OpenDefaultStream() has the following prototype: typedef int (PortAudioCallback)( void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, PaTimestamp outTime, void *userData ); The callback function may return a non-zero value to indicate that use of the stream has completed. The main program can determine whether a stream has completed using the Pa_StreamActive () function. Pa_StreamTime () returns the current playback time of a stream. It is intended for use as a time reference when synchronising audio to MIDI. Pa_GetCPULoad() returns a floating point value ranging from zero to one which indicates the fraction of total CPU time being consumed by the stream's audio processing. This gives the programmer an opportunity to modify their synthesis techniques, or to reduce the number of voices, in order to prevent excessive loading of the CPU. The Pa_CloseStream() function should be used to close a stream when it is no longer needed. 3.3. Error Handling Most PortAudio functions return an error code of type PaError. The Pa_GetErrorText (err) function may be used to retrieve textual error information. PortAudio also provides the Pa_GetHostError () function for retrieving host specific error codes. 4. Existing Implementations At the time of writing, stable PortAudio implementations exist for Windows (WMME and DirectX), the Apple Macintosh Sound Manager, and for Unix using the OSS driver model. The functions common to all platforms are implemented in a shared module. These include error code interpretation, parameter checking, clipping, dithering, and conversion between different data formats. Implementation for a new platform, therefore, only involves the implementation of host specific functions. An implementation guide is provided as well as a programming tutorial. There is also a suite of test programs and example programs that can be used to validate a new implementation. The Windows Multimedia API implementation utilises a high priority worker thread to process sample buffers. A Win32 Event synchronization object is used to allow the soundcard driver to efficiently wake the worker thread when an input buffer is full or an output buffer is empty. When the worker thread wakes, it gathers the available buffers and passess them to the user defined callback function. It calls waveOutWrite () to output the data generated by the callback function, and requeues used input buffers by calling
Top of page Top of page