Proposed Enhancements to PortAudio API

008 - Host API Specific Pa_OpenStream() Parameters

Enhancement Proposals Index, PortAudio Home Page

Updated: October 20, 2002

Status

This proposal is sufficiently well defined to be implemented. It has been implemented in v19-devel.

Dependencies

If the PaHostApiSpecificStreamInfo structure defined in this proposal includes a PaHostApiTypeId host API identifier, then this proposal depends on the 007 - Support for Multiple Host APIs in a Single PortAudio Build proposal to define the form of the identifier.

Background

Pa_OpenStream has always had inputDriverInfo and outputDriverInfo parameters, which were defined to support passing host API specific information to PortAudio implementations. Currently (V18) 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 addressing multichannel soundcards under MME.

Proposal

The inputDriverInfo and outputDriverInfo fields to Pa_OpenStream() will be moved to the PaStreamParameters structure described in 016 - Use Structs for Pa_OpenStream() Parameters. The equivalent field in this structure will be a void* field named hostApiSpecificStreamInfo.

All data structures defined by implementations to be passed to the inputStreamInfo and outputStreamInfo parameters of Pa_OpenStream must begin with the following fields:

unsigned long size;          /* size of whole structure including this header */
PaHostApiTypeId hostApiType; /* host API for which this data is intended */
unsigned long version;       /* structure version */

The common infrastructure will expect these fields to be present, and to contain valid information.

The following host API specific extensions will be placed in separate header files rather than being placed in portaudio.h

___

The following structure is proposed for passing device names to the OSS implementation:

struct{
    unsigned long size;          /* size of whole structure including this header */
    PaHostApiTypeId hostApiType; /* host API for which this data is intended */
    unsigned long version;       /* structure version */

    char *deviceName;
}PaOssSpecificStreamInfo;

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.

___

The following data types are proposed for specifying low level latency parameters, and 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.

#define PaWinMmeUseLowLevelLatencyParameters            (0x01)
#define PaWinMmeUseMultipleDevices                      (0x02)  /* use mme specific multiple device feature */

/* by default, the mme implementation boosts the process priority class to
    HIGH_PRIORITY_CLASS. This flag disables that priority boost */
#define PaWinMmeNoHighPriorityProcessClass              (0x03)

/* by default, the mme implementation drops the processing thread's priority
    to THREAD_PRIORITY_NORMAL and sleeps the thread if the CPU load exceeds 100% */
#define PaWinMmeDontThrottleOverloadedProcessingThread  (0x04)

/* by default, the mme implementation sets the processing thread's priority to
    THREAD_PRIORITY_HIGHEST. This flag sets the priority to
    THREAD_PRIORITY_TIME_CRITICAL instead. Note that this has the potential
    to freeze the machine, especially when used in combination with
    PaWinMmeDontThrottleOverloadedProcessingThread */
#define PaWinMmeUseTimeCriticalThreadPriority           (0x05)

typedef struct PaWinMmeDeviceAndNumChannels{
    PaDeviceIndex device;
    int numChannels;
}PaWinMmeDeviceAndNumChannels;


typedef struct PaWinMmeStreamInfo{
    unsigned long size;          /* size of whole structure including this header */
    PaHostApiTypeId hostApiType; /* host API for which this data is intended */
    unsigned long version;       /* structure version */

    unsigned long flags;

    /* low-level latency setting support
        These settings control the number and size of host buffers in order
        to set latency. They will be used instead of the generic parameters
        to Pa_OpenStream() if flags contains the PaWinMmeUseLowLevelLatencyParameters
        flag.
    */
    unsigned long framesPerBuffer;
    unsigned long numBuffers;  

    /* multiple devices per direction support
        If flags contains the PaWinMmeUseMultipleDevices flag,
        this functionality will be used, otherwise the device parameter to
        Pa_OpenStream() will be used instead.
        If devices are specified here, the corresponding device parameter
        to Pa_OpenStream() should be set to paUseHostApiSpecificDeviceSpecification,
        otherwise an paInvalidDevice error will result.
        The total number of channels accross all specified devices
        must agree with the corresponding numChannels parameter to
        Pa_OpenStream() otherwise a paInvalidChannelCount error will result.
    */
    PaWinMmeDeviceAndNumChannels *devices;
    unsigned long numDevices;

}PaWinMmeStreamInfo;

Discussion

Originally this proposal involved declaring a common header structure which would be embedded at the head of each host-api specific stream info structure:

struct{
    unsigned long size;          /* size of whole structure including this header */
    PaHostApiTypeId hostApiType; /* host API for which this data is intended */
    unsigned long version;       /* structure version */
}PaHostApiSpecificStreamInfo;

However, the unidiomatic type casts required to make the use of this structure transparent lead us to the current approach, where the presence of the header structure is implicit.

Originally A special constant paNullStreamInfo was to be defined, which coud be used in the inputStreamInfo and outputStreamInfo parameters. However since the introduction of the PaStreamParameters structure there is no longer any benefit to having a constant which indicates the role of the value.

#define paNullHostApiSpecificStreamInfo ((void*)0)

When PaHostApiSpecificStreamInfo was still declared, we intended to change the type of the streamInfo parameters from void* to PaHostApiSpecificStreamInfo*. Some objections were raised to this, as it may have required clients to explicitly cast to PaHostAPISpecificInfo* when passing NULL. However the added semantic and type safety advantages were considered more valuable. The current proposal leaves these parameters as void*.

The PaMMESpecificStreamInfo functionality may require the common buffer conversion functions defined in the 013 - Refactor Implementation Infrastructure proposal to support (multiple interleave <==> unified interleave) and (multiple interleave <==> non-interleaved) conversions.

Impact Analysis

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.