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