X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=RtAudio.h;h=4bb75545a29dcd7a72602f3f634ff03618c97654;hb=482eceb06ac1c19260e120a2c9e6dc1d04d28fcb;hp=e26f81d186d54e2b7299f0e0290a214577af9a68;hpb=fdc3f15bec57b30fae67f65270392ba7a86680b8;p=rtaudio-cdist.git diff --git a/RtAudio.h b/RtAudio.h index e26f81d..4bb7554 100644 --- a/RtAudio.h +++ b/RtAudio.h @@ -4,13 +4,13 @@ RtAudio provides a common API (Application Programming Interface) for realtime audio input/output across Linux (native ALSA, Jack, - and OSS), SGI, Macintosh OS X (CoreAudio), and Windows - (DirectSound and ASIO) operating systems. + and OSS), Macintosh OS X (CoreAudio and Jack), and Windows + (DirectSound, ASIO and WASAPI) operating systems. - RtAudio WWW site: http://music.mcgill.ca/~gary/rtaudio/ + RtAudio WWW site: http://www.music.mcgill.ca/~gary/rtaudio/ RtAudio: realtime audio i/o C++ classes - Copyright (c) 2001-2005 Gary P. Scavone + Copyright (c) 2001-2017 Gary P. Scavone Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files @@ -24,8 +24,9 @@ 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. + asked to send the modifications to the original developer so that + they can be incorporated into the canonical version. This is, + however, not a binding provision of this license. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF @@ -37,29 +38,607 @@ */ /************************************************************************/ -// RtAudio: Version 3.0.2 (14 October 2005) +/*! + \file RtAudio.h + */ #ifndef __RTAUDIO_H #define __RTAUDIO_H -#include "RtError.h" +#define RTAUDIO_VERSION "5.0.0" + +#if defined _WIN32 || defined __CYGWIN__ + #if defined(RTAUDIO_EXPORT) + #define RTAUDIO_DLL_PUBLIC __declspec(dllexport) + #else + #define RTAUDIO_DLL_PUBLIC + #endif +#else + #if __GNUC__ >= 4 + #define RTAUDIO_DLL_PUBLIC __attribute__( (visibility( "default" )) ) + #else + #define RTAUDIO_DLL_PUBLIC + #endif +#endif + #include #include +#include +#include + +/*! \typedef typedef unsigned long RtAudioFormat; + \brief RtAudio data format type. + + Support for signed integers and floats. Audio data fed to/from an + RtAudio stream is assumed to ALWAYS be in host byte order. The + internal routines will automatically take care of any necessary + byte-swapping between the host format and the soundcard. Thus, + endian-ness is not a concern in the following format definitions. + + - \e RTAUDIO_SINT8: 8-bit signed integer. + - \e RTAUDIO_SINT16: 16-bit signed integer. + - \e RTAUDIO_SINT24: 24-bit signed integer. + - \e RTAUDIO_SINT32: 32-bit signed integer. + - \e RTAUDIO_FLOAT32: Normalized between plus/minus 1.0. + - \e RTAUDIO_FLOAT64: Normalized between plus/minus 1.0. +*/ +typedef unsigned long RtAudioFormat; +static const RtAudioFormat RTAUDIO_SINT8 = 0x1; // 8-bit signed integer. +static const RtAudioFormat RTAUDIO_SINT16 = 0x2; // 16-bit signed integer. +static const RtAudioFormat RTAUDIO_SINT24 = 0x4; // 24-bit signed integer. +static const RtAudioFormat RTAUDIO_SINT32 = 0x8; // 32-bit signed integer. +static const RtAudioFormat RTAUDIO_FLOAT32 = 0x10; // Normalized between plus/minus 1.0. +static const RtAudioFormat RTAUDIO_FLOAT64 = 0x20; // Normalized between plus/minus 1.0. + +/*! \typedef typedef unsigned long RtAudioStreamFlags; + \brief RtAudio stream option flags. + + The following flags can be OR'ed together to allow a client to + make changes to the default stream behavior: + + - \e RTAUDIO_NONINTERLEAVED: Use non-interleaved buffers (default = interleaved). + - \e RTAUDIO_MINIMIZE_LATENCY: Attempt to set stream parameters for lowest possible latency. + - \e RTAUDIO_HOG_DEVICE: Attempt grab device for exclusive use. + - \e RTAUDIO_ALSA_USE_DEFAULT: Use the "default" PCM device (ALSA only). + - \e RTAUDIO_JACK_DONT_CONNECT: Do not automatically connect ports (JACK only). + + By default, RtAudio streams pass and receive audio data from the + client in an interleaved format. By passing the + RTAUDIO_NONINTERLEAVED flag to the openStream() function, audio + data will instead be presented in non-interleaved buffers. In + this case, each buffer argument in the RtAudioCallback function + will point to a single array of data, with \c nFrames samples for + each channel concatenated back-to-back. For example, the first + sample of data for the second channel would be located at index \c + nFrames (assuming the \c buffer pointer was recast to the correct + data type for the stream). + + Certain audio APIs offer a number of parameters that influence the + I/O latency of a stream. By default, RtAudio will attempt to set + these parameters internally for robust (glitch-free) performance + (though some APIs, like Windows DirectSound, make this difficult). + By passing the RTAUDIO_MINIMIZE_LATENCY flag to the openStream() + function, internal stream settings will be influenced in an attempt + to minimize stream latency, though possibly at the expense of stream + performance. + + If the RTAUDIO_HOG_DEVICE flag is set, RtAudio will attempt to + open the input and/or output stream device(s) for exclusive use. + Note that this is not possible with all supported audio APIs. + + If the RTAUDIO_SCHEDULE_REALTIME flag is set, RtAudio will attempt + to select realtime scheduling (round-robin) for the callback thread. + + If the RTAUDIO_ALSA_USE_DEFAULT flag is set, RtAudio will attempt to + open the "default" PCM device when using the ALSA API. Note that this + will override any specified input or output device id. + + If the RTAUDIO_JACK_DONT_CONNECT flag is set, RtAudio will not attempt + to automatically connect the ports of the client to the audio device. +*/ +typedef unsigned int RtAudioStreamFlags; +static const RtAudioStreamFlags RTAUDIO_NONINTERLEAVED = 0x1; // Use non-interleaved buffers (default = interleaved). +static const RtAudioStreamFlags RTAUDIO_MINIMIZE_LATENCY = 0x2; // Attempt to set stream parameters for lowest possible latency. +static const RtAudioStreamFlags RTAUDIO_HOG_DEVICE = 0x4; // Attempt grab device and prevent use by others. +static const RtAudioStreamFlags RTAUDIO_SCHEDULE_REALTIME = 0x8; // Try to select realtime scheduling for callback thread. +static const RtAudioStreamFlags RTAUDIO_ALSA_USE_DEFAULT = 0x10; // Use the "default" PCM device (ALSA only). +static const RtAudioStreamFlags RTAUDIO_JACK_DONT_CONNECT = 0x20; // Do not automatically connect ports (JACK only). + +/*! \typedef typedef unsigned long RtAudioStreamStatus; + \brief RtAudio stream status (over- or underflow) flags. + + Notification of a stream over- or underflow is indicated by a + non-zero stream \c status argument in the RtAudioCallback function. + The stream status can be one of the following two options, + depending on whether the stream is open for output and/or input: + + - \e RTAUDIO_INPUT_OVERFLOW: Input data was discarded because of an overflow condition at the driver. + - \e RTAUDIO_OUTPUT_UNDERFLOW: The output buffer ran low, likely producing a break in the output sound. +*/ +typedef unsigned int RtAudioStreamStatus; +static const RtAudioStreamStatus RTAUDIO_INPUT_OVERFLOW = 0x1; // Input data was discarded because of an overflow condition at the driver. +static const RtAudioStreamStatus RTAUDIO_OUTPUT_UNDERFLOW = 0x2; // The output buffer ran low, likely causing a gap in the output sound. + +//! RtAudio callback function prototype. +/*! + All RtAudio clients must create a function of type RtAudioCallback + to read and/or write data from/to the audio stream. When the + underlying audio system is ready for new input or output data, this + function will be invoked. + + \param outputBuffer For output (or duplex) streams, the client + should write \c nFrames of audio sample frames into this + buffer. This argument should be recast to the datatype + specified when the stream was opened. For input-only + streams, this argument will be NULL. + + \param inputBuffer For input (or duplex) streams, this buffer will + hold \c nFrames of input audio sample frames. This + argument should be recast to the datatype specified when the + stream was opened. For output-only streams, this argument + will be NULL. + + \param nFrames The number of sample frames of input or output + data in the buffers. The actual buffer size in bytes is + dependent on the data type and number of channels in use. + + \param streamTime The number of seconds that have elapsed since the + stream was started. + + \param status If non-zero, this argument indicates a data overflow + or underflow condition for the stream. The particular + condition can be determined by comparison with the + RtAudioStreamStatus flags. + + \param userData A pointer to optional data provided by the client + when opening the stream (default = NULL). + + To continue normal stream operation, the RtAudioCallback function + should return a value of zero. To stop the stream and drain the + output buffer, the function should return a value of one. To abort + the stream immediately, the client should return a value of two. + */ +typedef int (*RtAudioCallback)( void *outputBuffer, void *inputBuffer, + unsigned int nFrames, + double streamTime, + RtAudioStreamStatus status, + void *userData ); + +/************************************************************************/ +/*! \class RtAudioError + \brief Exception handling class for RtAudio. + + The RtAudioError class is quite simple but it does allow errors to be + "caught" by RtAudioError::Type. See the RtAudio documentation to know + which methods can throw an RtAudioError. +*/ +/************************************************************************/ + +class RTAUDIO_DLL_PUBLIC RtAudioError : public std::runtime_error +{ + public: + //! Defined RtAudioError types. + enum Type { + WARNING, /*!< A non-critical error. */ + DEBUG_WARNING, /*!< A non-critical error which might be useful for debugging. */ + UNSPECIFIED, /*!< The default, unspecified error type. */ + NO_DEVICES_FOUND, /*!< No devices found on system. */ + INVALID_DEVICE, /*!< An invalid device ID was specified. */ + MEMORY_ERROR, /*!< An error occured during memory allocation. */ + INVALID_PARAMETER, /*!< An invalid parameter was specified to a function. */ + INVALID_USE, /*!< The function was called incorrectly. */ + DRIVER_ERROR, /*!< A system driver error occured. */ + SYSTEM_ERROR, /*!< A system error occured. */ + THREAD_ERROR /*!< A thread error occured. */ + }; + + //! The constructor. + RtAudioError( const std::string& message, + Type type = RtAudioError::UNSPECIFIED ) + : std::runtime_error(message), type_(type) {} + + //! Prints thrown error message to stderr. + virtual void printMessage( void ) const + { std::cerr << '\n' << what() << "\n\n"; } + + //! Returns the thrown error message type. + virtual const Type& getType(void) const { return type_; } + + //! Returns the thrown error message string. + virtual const std::string getMessage(void) const + { return std::string(what()); } + + protected: + Type type_; +}; + +//! RtAudio error callback function prototype. +/*! + \param type Type of error. + \param errorText Error description. + */ +typedef void (*RtAudioErrorCallback)( RtAudioError::Type type, const std::string &errorText ); + +// **************************************************************** // +// +// RtAudio class declaration. +// +// RtAudio is a "controller" used to select an available audio i/o +// interface. It presents a common API for the user to call but all +// functionality is implemented by the class RtApi and its +// subclasses. RtAudio creates an instance of an RtApi subclass +// based on the user's API choice. If no choice is made, RtAudio +// attempts to make a "logical" API selection. +// +// **************************************************************** // + +class RtApi; + +class RTAUDIO_DLL_PUBLIC RtAudio +{ + public: + + //! Audio API specifier arguments. + enum Api { + UNSPECIFIED, /*!< Search for a working compiled API. */ + LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */ + LINUX_PULSE, /*!< The Linux PulseAudio API. */ + LINUX_OSS, /*!< The Linux Open Sound System API. */ + UNIX_JACK, /*!< The Jack Low-Latency Audio Server API. */ + MACOSX_CORE, /*!< Macintosh OS-X Core Audio API. */ + WINDOWS_WASAPI, /*!< The Microsoft WASAPI API. */ + WINDOWS_ASIO, /*!< The Steinberg Audio Stream I/O API. */ + WINDOWS_DS, /*!< The Microsoft DirectSound API. */ + RTAUDIO_DUMMY, /*!< A compilable but non-functional API. */ + NUM_APIS /*!< Number of values in this enum. */ + }; + + //! The public device information structure for returning queried values. + struct DeviceInfo { + bool probed; /*!< true if the device capabilities were successfully probed. */ + std::string name; /*!< Character string device identifier. */ + unsigned int outputChannels; /*!< Maximum output channels supported by device. */ + unsigned int inputChannels; /*!< Maximum input channels supported by device. */ + unsigned int duplexChannels; /*!< Maximum simultaneous input/output channels supported by device. */ + bool isDefaultOutput; /*!< true if this is the default output device. */ + bool isDefaultInput; /*!< true if this is the default input device. */ + std::vector sampleRates; /*!< Supported sample rates (queried from list of standard rates). */ + unsigned int preferredSampleRate; /*!< Preferred sample rate, e.g. for WASAPI the system sample rate. */ + RtAudioFormat nativeFormats; /*!< Bit mask of supported data formats. */ + + // Default constructor. + DeviceInfo() + :probed(false), outputChannels(0), inputChannels(0), duplexChannels(0), + isDefaultOutput(false), isDefaultInput(false), preferredSampleRate(0), nativeFormats(0) {} + }; + + //! The structure for specifying input or ouput stream parameters. + struct StreamParameters { + unsigned int deviceId; /*!< Device index (0 to getDeviceCount() - 1). */ + unsigned int nChannels; /*!< Number of channels. */ + unsigned int firstChannel; /*!< First channel index on device (default = 0). */ + + // Default constructor. + StreamParameters() + : deviceId(0), nChannels(0), firstChannel(0) {} + }; + + //! The structure for specifying stream options. + /*! + The following flags can be OR'ed together to allow a client to + make changes to the default stream behavior: + + - \e RTAUDIO_NONINTERLEAVED: Use non-interleaved buffers (default = interleaved). + - \e RTAUDIO_MINIMIZE_LATENCY: Attempt to set stream parameters for lowest possible latency. + - \e RTAUDIO_HOG_DEVICE: Attempt grab device for exclusive use. + - \e RTAUDIO_SCHEDULE_REALTIME: Attempt to select realtime scheduling for callback thread. + - \e RTAUDIO_ALSA_USE_DEFAULT: Use the "default" PCM device (ALSA only). + + By default, RtAudio streams pass and receive audio data from the + client in an interleaved format. By passing the + RTAUDIO_NONINTERLEAVED flag to the openStream() function, audio + data will instead be presented in non-interleaved buffers. In + this case, each buffer argument in the RtAudioCallback function + will point to a single array of data, with \c nFrames samples for + each channel concatenated back-to-back. For example, the first + sample of data for the second channel would be located at index \c + nFrames (assuming the \c buffer pointer was recast to the correct + data type for the stream). + + Certain audio APIs offer a number of parameters that influence the + I/O latency of a stream. By default, RtAudio will attempt to set + these parameters internally for robust (glitch-free) performance + (though some APIs, like Windows DirectSound, make this difficult). + By passing the RTAUDIO_MINIMIZE_LATENCY flag to the openStream() + function, internal stream settings will be influenced in an attempt + to minimize stream latency, though possibly at the expense of stream + performance. + + If the RTAUDIO_HOG_DEVICE flag is set, RtAudio will attempt to + open the input and/or output stream device(s) for exclusive use. + Note that this is not possible with all supported audio APIs. + + If the RTAUDIO_SCHEDULE_REALTIME flag is set, RtAudio will attempt + to select realtime scheduling (round-robin) for the callback thread. + The \c priority parameter will only be used if the RTAUDIO_SCHEDULE_REALTIME + flag is set. It defines the thread's realtime priority. + + If the RTAUDIO_ALSA_USE_DEFAULT flag is set, RtAudio will attempt to + open the "default" PCM device when using the ALSA API. Note that this + will override any specified input or output device id. + + The \c numberOfBuffers parameter can be used to control stream + latency in the Windows DirectSound, Linux OSS, and Linux Alsa APIs + only. A value of two is usually the smallest allowed. Larger + numbers can potentially result in more robust stream performance, + though likely at the cost of stream latency. The value set by the + user is replaced during execution of the RtAudio::openStream() + function by the value actually used by the system. + + The \c streamName parameter can be used to set the client name + when using the Jack API. By default, the client name is set to + RtApiJack. However, if you wish to create multiple instances of + RtAudio with Jack, each instance must have a unique client name. + */ + struct StreamOptions { + RtAudioStreamFlags flags; /*!< A bit-mask of stream flags (RTAUDIO_NONINTERLEAVED, RTAUDIO_MINIMIZE_LATENCY, RTAUDIO_HOG_DEVICE, RTAUDIO_ALSA_USE_DEFAULT). */ + unsigned int numberOfBuffers; /*!< Number of stream buffers. */ + std::string streamName; /*!< A stream name (currently used only in Jack). */ + int priority; /*!< Scheduling priority of callback thread (only used with flag RTAUDIO_SCHEDULE_REALTIME). */ + + // Default constructor. + StreamOptions() + : flags(0), numberOfBuffers(0), priority(0) {} + }; + + //! A static function to determine the current RtAudio version. + static std::string getVersion( void ); + + //! A static function to determine the available compiled audio APIs. + /*! + The values returned in the std::vector can be compared against + the enumerated list values. Note that there can be more than one + API compiled for certain operating systems. + */ + static void getCompiledApi( std::vector &apis ); + + //! Return the name of a specified compiled audio API. + /*! + This obtains a short lower-case name used for identification purposes. + This value is guaranteed to remain identical across library versions. + If the API is unknown, this function will return the empty string. + */ + static std::string getApiName( RtAudio::Api api ); + + //! Return the display name of a specified compiled audio API. + /*! + This obtains a long name used for display purposes. + If the API is unknown, this function will return the empty string. + */ + static std::string getApiDisplayName( RtAudio::Api api ); + + //! Return the compiled audio API having the given name. + /*! + A case insensitive comparison will check the specified name + against the list of compiled APIs, and return the one which + matches. On failure, the function returns UNSPECIFIED. + */ + static RtAudio::Api getCompiledApiByName( const std::string &name ); + + //! The class constructor. + /*! + The constructor performs minor initialization tasks. An exception + can be thrown if no API support is compiled. + + If no API argument is specified and multiple API support has been + compiled, the default order of use is JACK, ALSA, OSS (Linux + systems) and ASIO, DS (Windows systems). + */ + RtAudio( RtAudio::Api api=UNSPECIFIED ); + + //! The destructor. + /*! + If a stream is running or open, it will be stopped and closed + automatically. + */ + ~RtAudio(); + + //! Returns the audio API specifier for the current instance of RtAudio. + RtAudio::Api getCurrentApi( void ); + + //! A public function that queries for the number of audio devices available. + /*! + This function performs a system query of available devices each time it + is called, thus supporting devices connected \e after instantiation. If + a system error occurs during processing, a warning will be issued. + */ + unsigned int getDeviceCount( void ); + + //! Return an RtAudio::DeviceInfo structure for a specified device number. + /*! + + Any device integer between 0 and getDeviceCount() - 1 is valid. + If an invalid argument is provided, an RtAudioError (type = INVALID_USE) + will be thrown. If a device is busy or otherwise unavailable, the + structure member "probed" will have a value of "false" and all + other members are undefined. If the specified device is the + current default input or output device, the corresponding + "isDefault" member will have a value of "true". + */ + RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); + + //! A function that returns the index of the default output device. + /*! + If the underlying audio API does not provide a "default + device", or if no devices are available, the return value will be + 0. Note that this is a valid device identifier and it is the + client's responsibility to verify that a device is available + before attempting to open a stream. + */ + unsigned int getDefaultOutputDevice( void ); + + //! A function that returns the index of the default input device. + /*! + If the underlying audio API does not provide a "default + device", or if no devices are available, the return value will be + 0. Note that this is a valid device identifier and it is the + client's responsibility to verify that a device is available + before attempting to open a stream. + */ + unsigned int getDefaultInputDevice( void ); + + //! A public function for opening a stream with the specified parameters. + /*! + An RtAudioError (type = SYSTEM_ERROR) is thrown if a stream cannot be + opened with the specified parameters or an error occurs during + processing. An RtAudioError (type = INVALID_USE) is thrown if any + invalid device ID or channel number parameters are specified. + + \param outputParameters Specifies output stream parameters to use + when opening a stream, including a device ID, number of channels, + and starting channel number. For input-only streams, this + argument should be NULL. The device ID is an index value between + 0 and getDeviceCount() - 1. + \param inputParameters Specifies input stream parameters to use + when opening a stream, including a device ID, number of channels, + and starting channel number. For output-only streams, this + argument should be NULL. The device ID is an index value between + 0 and getDeviceCount() - 1. + \param format An RtAudioFormat specifying the desired sample data format. + \param sampleRate The desired sample rate (sample frames per second). + \param *bufferFrames A pointer to a value indicating the desired + internal buffer size in sample frames. The actual value + used by the device is returned via the same pointer. A + value of zero can be specified, in which case the lowest + allowable value is determined. + \param callback A client-defined function that will be invoked + when input data is available and/or output data is needed. + \param userData An optional pointer to data that can be accessed + from within the callback function. + \param options An optional pointer to a structure containing various + global stream options, including a list of OR'ed RtAudioStreamFlags + and a suggested number of stream buffers that can be used to + control stream latency. More buffers typically result in more + robust performance, though at a cost of greater latency. If a + value of zero is specified, a system-specific median value is + chosen. If the RTAUDIO_MINIMIZE_LATENCY flag bit is set, the + lowest allowable value is used. The actual value used is + returned via the structure argument. The parameter is API dependent. + \param errorCallback A client-defined function that will be invoked + when an error has occured. + */ + void openStream( RtAudio::StreamParameters *outputParameters, + RtAudio::StreamParameters *inputParameters, + RtAudioFormat format, unsigned int sampleRate, + unsigned int *bufferFrames, RtAudioCallback callback, + void *userData = NULL, RtAudio::StreamOptions *options = NULL, RtAudioErrorCallback errorCallback = NULL ); + + //! A function that closes a stream and frees any associated stream memory. + /*! + If a stream is not open, this function issues a warning and + returns (no exception is thrown). + */ + void closeStream( void ); + + //! A function that starts a stream. + /*! + An RtAudioError (type = SYSTEM_ERROR) is thrown if an error occurs + during processing. An RtAudioError (type = INVALID_USE) is thrown if a + stream is not open. A warning is issued if the stream is already + running. + */ + void startStream( void ); + + //! Stop a stream, allowing any samples remaining in the output queue to be played. + /*! + An RtAudioError (type = SYSTEM_ERROR) is thrown if an error occurs + during processing. An RtAudioError (type = INVALID_USE) is thrown if a + stream is not open. A warning is issued if the stream is already + stopped. + */ + void stopStream( void ); + + //! Stop a stream, discarding any samples remaining in the input/output queue. + /*! + An RtAudioError (type = SYSTEM_ERROR) is thrown if an error occurs + during processing. An RtAudioError (type = INVALID_USE) is thrown if a + stream is not open. A warning is issued if the stream is already + stopped. + */ + void abortStream( void ); + + //! Returns true if a stream is open and false if not. + bool isStreamOpen( void ) const; + + //! Returns true if the stream is running and false if it is stopped or not open. + bool isStreamRunning( void ) const; + + //! Returns the number of elapsed seconds since the stream was started. + /*! + If a stream is not open, an RtAudioError (type = INVALID_USE) will be thrown. + */ + double getStreamTime( void ); + + //! Set the stream time to a time in seconds greater than or equal to 0.0. + /*! + If a stream is not open, an RtAudioError (type = INVALID_USE) will be thrown. + */ + void setStreamTime( double time ); + + //! Returns the internal stream latency in sample frames. + /*! + The stream latency refers to delay in audio input and/or output + caused by internal buffering by the audio system and/or hardware. + For duplex streams, the returned value will represent the sum of + the input and output latencies. If a stream is not open, an + RtAudioError (type = INVALID_USE) will be thrown. If the API does not + report latency, the return value will be zero. + */ + long getStreamLatency( void ); + + //! Returns actual sample rate in use by the stream. + /*! + On some systems, the sample rate used may be slightly different + than that specified in the stream parameters. If a stream is not + open, an RtAudioError (type = INVALID_USE) will be thrown. + */ + unsigned int getStreamSampleRate( void ); + + //! Specify whether warning messages should be printed to stderr. + void showWarnings( bool value = true ); + + protected: + + void openRtApi( RtAudio::Api api ); + RtApi *rtapi_; +}; // Operating system dependent thread functionality. -#if defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__) +#if defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__) || defined(__WINDOWS_WASAPI__) + + #ifndef NOMINMAX + #define NOMINMAX + #endif #include #include + #include - typedef unsigned long ThreadHandle; + typedef uintptr_t ThreadHandle; typedef CRITICAL_SECTION StreamMutex; -#else // Various unix flavors with pthread support. +#elif defined(__LINUX_ALSA__) || defined(__LINUX_PULSE__) || defined(__UNIX_JACK__) || defined(__LINUX_OSS__) || defined(__MACOSX_CORE__) + // Using pthread library for various flavors of unix. #include typedef pthread_t ThreadHandle; typedef pthread_mutex_t StreamMutex; +#else // Setup for "dummy" behavior + + #define __RTAUDIO_DUMMY__ + typedef int ThreadHandle; + typedef int StreamMutex; + #endif // This global structure type is used to pass callback information @@ -68,91 +647,97 @@ struct CallbackInfo { void *object; // Used as a "this" pointer. ThreadHandle thread; - bool usingCallback; void *callback; void *userData; + void *errorCallback; void *apiInfo; // void pointer for API specific callback information + bool isRunning; + bool doRealtime; + int priority; // Default constructor. CallbackInfo() - :object(0), usingCallback(false), callback(0), - userData(0), apiInfo(0) {} -}; - -// Support for signed integers and floats. Audio data fed to/from -// the tickStream() routine is assumed to ALWAYS be in host -// byte order. The internal routines will automatically take care of -// any necessary byte-swapping between the host format and the -// soundcard. Thus, endian-ness is not a concern in the following -// format definitions. -typedef unsigned long RtAudioFormat; -static const RtAudioFormat RTAUDIO_SINT8 = 0x1; /*!< 8-bit signed integer. */ -static const RtAudioFormat RTAUDIO_SINT16 = 0x2; /*!< 16-bit signed integer. */ -static const RtAudioFormat RTAUDIO_SINT24 = 0x4; /*!< Upper 3 bytes of 32-bit signed integer. */ -static const RtAudioFormat RTAUDIO_SINT32 = 0x8; /*!< 32-bit signed integer. */ -static const RtAudioFormat RTAUDIO_FLOAT32 = 0x10; /*!< Normalized between plus/minus 1.0. */ -static const RtAudioFormat RTAUDIO_FLOAT64 = 0x20; /*!< Normalized between plus/minus 1.0. */ - -typedef int (*RtAudioCallback)(char *buffer, int bufferSize, void *userData); - -//! The public device information structure for returning queried values. -struct RtAudioDeviceInfo { - std::string name; /*!< Character string device identifier. */ - bool probed; /*!< true if the device capabilities were successfully probed. */ - int outputChannels; /*!< Maximum output channels supported by device. */ - int inputChannels; /*!< Maximum input channels supported by device. */ - int duplexChannels; /*!< Maximum simultaneous input/output channels supported by device. */ - bool isDefault; /*!< true if this is the default output or input device. */ - std::vector sampleRates; /*!< Supported sample rates (queried from list of standard rates). */ - RtAudioFormat nativeFormats; /*!< Bit mask of supported data formats. */ - - // Default constructor. - RtAudioDeviceInfo() - :probed(false), outputChannels(0), inputChannels(0), - duplexChannels(0), isDefault(false), nativeFormats(0) {} + :object(0), callback(0), userData(0), errorCallback(0), apiInfo(0), isRunning(false), doRealtime(false), priority(0) {} }; // **************************************************************** // // // RtApi class declaration. // +// Subclasses of RtApi contain all API- and OS-specific code necessary +// to fully implement the RtAudio API. +// // Note that RtApi is an abstract base class and cannot be // explicitly instantiated. The class RtAudio will create an // instance of an RtApi subclass (RtApiOss, RtApiAlsa, -// RtApiJack, RtApiCore, RtApiAl, RtApiDs, or RtApiAsio). +// RtApiJack, RtApiCore, RtApiDs, or RtApiAsio). // // **************************************************************** // -class RtApi +#pragma pack(push, 1) +class S24 { + + protected: + unsigned char c3[3]; + + public: + S24() {} + + S24& operator = ( const int& i ) { + c3[0] = (i & 0x000000ff); + c3[1] = (i & 0x0000ff00) >> 8; + c3[2] = (i & 0x00ff0000) >> 16; + return *this; + } + + S24( const double& d ) { *this = (int) d; } + S24( const float& f ) { *this = (int) f; } + S24( const signed short& s ) { *this = (int) s; } + S24( const char& c ) { *this = (int) c; } + + int asInt() { + int i = c3[0] | (c3[1] << 8) | (c3[2] << 16); + if (i & 0x800000) i |= ~0xffffff; + return i; + } +}; +#pragma pack(pop) + +#if defined( HAVE_GETTIMEOFDAY ) + #include +#endif + +#include + +class RTAUDIO_DLL_PUBLIC RtApi { public: - enum StreamState { - STREAM_STOPPED, - STREAM_RUNNING - }; - RtApi(); virtual ~RtApi(); - void openStream( int outputDevice, int outputChannels, - int inputDevice, int inputChannels, - RtAudioFormat format, int sampleRate, - int *bufferSize, int numberOfBuffers ); - void openStream( int outputDevice, int outputChannels, - int inputDevice, int inputChannels, - RtAudioFormat format, int sampleRate, - int *bufferSize, int *numberOfBuffers ); - virtual void setStreamCallback( RtAudioCallback callback, void *userData ) = 0; - virtual void cancelStreamCallback() = 0; - int getDeviceCount(void); - RtAudioDeviceInfo getDeviceInfo( int device ); - char * const getStreamBuffer(); - RtApi::StreamState getStreamState() const; - virtual void tickStream() = 0; - virtual void closeStream(); - virtual void startStream() = 0; - virtual void stopStream() = 0; - virtual void abortStream() = 0; + virtual RtAudio::Api getCurrentApi( void ) = 0; + virtual unsigned int getDeviceCount( void ) = 0; + virtual RtAudio::DeviceInfo getDeviceInfo( unsigned int device ) = 0; + virtual unsigned int getDefaultInputDevice( void ); + virtual unsigned int getDefaultOutputDevice( void ); + void openStream( RtAudio::StreamParameters *outputParameters, + RtAudio::StreamParameters *inputParameters, + RtAudioFormat format, unsigned int sampleRate, + unsigned int *bufferFrames, RtAudioCallback callback, + void *userData, RtAudio::StreamOptions *options, + RtAudioErrorCallback errorCallback ); + virtual void closeStream( void ); + virtual void startStream( void ) = 0; + virtual void stopStream( void ) = 0; + virtual void abortStream( void ) = 0; + long getStreamLatency( void ); + unsigned int getStreamSampleRate( void ); + virtual double getStreamTime( void ); + virtual void setStreamTime( double time ); + bool isStreamOpen( void ) const { return stream_.state != STREAM_CLOSED; } + bool isStreamRunning( void ) const { return stream_.state == STREAM_RUNNING; } + void showWarnings( bool value ) { showWarnings_ = value; } + protected: @@ -161,6 +746,13 @@ protected: enum { FAILURE, SUCCESS }; + enum StreamState { + STREAM_STOPPED, + STREAM_STOPPING, + STREAM_RUNNING, + STREAM_CLOSED = -50 + }; + enum StreamMode { OUTPUT, INPUT, @@ -179,117 +771,76 @@ protected: // A protected structure for audio streams. struct RtApiStream { - int device[2]; // Playback and record, respectively. - void *apiHandle; // void pointer for API specific stream handle information - StreamMode mode; // OUTPUT, INPUT, or DUPLEX. - StreamState state; // STOPPED or RUNNING - char *userBuffer; + unsigned int device[2]; // Playback and record, respectively. + void *apiHandle; // void pointer for API specific stream handle information + StreamMode mode; // OUTPUT, INPUT, or DUPLEX. + StreamState state; // STOPPED, RUNNING, or CLOSED + char *userBuffer[2]; // Playback and record, respectively. char *deviceBuffer; - bool doConvertBuffer[2]; // Playback and record, respectively. - bool deInterleave[2]; // Playback and record, respectively. - bool doByteSwap[2]; // Playback and record, respectively. - int sampleRate; - int bufferSize; - int nBuffers; - int nUserChannels[2]; // Playback and record, respectively. - int nDeviceChannels[2]; // Playback and record channels, respectively. + bool doConvertBuffer[2]; // Playback and record, respectively. + bool userInterleaved; + bool deviceInterleaved[2]; // Playback and record, respectively. + bool doByteSwap[2]; // Playback and record, respectively. + unsigned int sampleRate; + unsigned int bufferSize; + unsigned int nBuffers; + unsigned int nUserChannels[2]; // Playback and record, respectively. + unsigned int nDeviceChannels[2]; // Playback and record channels, respectively. + unsigned int channelOffset[2]; // Playback and record, respectively. + unsigned long latency[2]; // Playback and record, respectively. RtAudioFormat userFormat; - RtAudioFormat deviceFormat[2]; // Playback and record, respectively. + RtAudioFormat deviceFormat[2]; // Playback and record, respectively. StreamMutex mutex; CallbackInfo callbackInfo; ConvertInfo convertInfo[2]; + double streamTime; // Number of elapsed seconds since the stream started. - RtApiStream() - :apiHandle(0), userBuffer(0), deviceBuffer(0) {} - }; - - // A protected device structure for audio devices. - struct RtApiDevice { - std::string name; /*!< Character string device identifier. */ - bool probed; /*!< true if the device capabilities were successfully probed. */ - void *apiDeviceId; // void pointer for API specific device information - int maxOutputChannels; /*!< Maximum output channels supported by device. */ - int maxInputChannels; /*!< Maximum input channels supported by device. */ - int maxDuplexChannels; /*!< Maximum simultaneous input/output channels supported by device. */ - int minOutputChannels; /*!< Minimum output channels supported by device. */ - int minInputChannels; /*!< Minimum input channels supported by device. */ - int minDuplexChannels; /*!< Minimum simultaneous input/output channels supported by device. */ - bool hasDuplexSupport; /*!< true if device supports duplex mode. */ - bool isDefault; /*!< true if this is the default output or input device. */ - std::vector sampleRates; /*!< Supported sample rates. */ - RtAudioFormat nativeFormats; /*!< Bit mask of supported data formats. */ +#if defined(HAVE_GETTIMEOFDAY) + struct timeval lastTickTimestamp; +#endif - // Default constructor. - RtApiDevice() - :probed(false), apiDeviceId(0), maxOutputChannels(0), maxInputChannels(0), - maxDuplexChannels(0), minOutputChannels(0), minInputChannels(0), - minDuplexChannels(0), isDefault(false), nativeFormats(0) {} + RtApiStream() + :apiHandle(0), deviceBuffer(0) { device[0] = 11111; device[1] = 11111; } }; + typedef S24 Int24; typedef signed short Int16; typedef signed int Int32; typedef float Float32; typedef double Float64; - char message_[1024]; - int nDevices_; - std::vector devices_; + std::ostringstream errorStream_; + std::string errorText_; + bool showWarnings_; RtApiStream stream_; + bool firstErrorOccurred_; /*! - Protected, api-specific method to count and identify the system - audio devices. This function MUST be implemented by all subclasses. - */ - virtual void initialize(void) = 0; - - /*! - Protected, api-specific method which attempts to fill an - RtAudioDevice structure for a given device. This function MUST be - implemented by all subclasses. If an error is encountered during - the probe, a "warning" message is reported and the value of - "probed" remains false (no exception is thrown). A successful - probe is indicated by probed = true. - */ - virtual void probeDeviceInfo( RtApiDevice *info ); - - /*! - Protected, api-specific method which attempts to open a device + Protected, api-specific method that attempts to open a device with the given parameters. This function MUST be implemented by all subclasses. If an error is encountered during the probe, a - "warning" message is reported and FAILURE is returned (no - exception is thrown). A successful probe is indicated by a return - value of SUCCESS. + "warning" message is reported and FAILURE is returned. A + successful probe is indicated by a return value of SUCCESS. */ - virtual bool probeDeviceOpen( int device, StreamMode mode, int channels, - int sampleRate, RtAudioFormat format, - int *bufferSize, int numberOfBuffers ); + virtual bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, + unsigned int firstChannel, unsigned int sampleRate, + RtAudioFormat format, unsigned int *bufferSize, + RtAudio::StreamOptions *options ); - /*! - Protected method which returns the index in the devices array to - the default input device. - */ - virtual int getDefaultInputDevice(void); - - /*! - Protected method which returns the index in the devices array to - the default output device. - */ - virtual int getDefaultOutputDevice(void); - - //! Protected common method to clear an RtApiDevice structure. - void clearDeviceInfo( RtApiDevice *info ); + //! A protected function used to increment the stream time. + void tickStreamTime( void ); //! Protected common method to clear an RtApiStream structure. void clearStreamInfo(); - //! Protected common error method to allow global control over error handling. - void error( RtError::Type type ); - /*! - Protected common method used to check whether a stream is open. - If not, an "invalid identifier" exception is thrown. + Protected common method that throws an RtAudioError (type = + INVALID_USE) if a stream is not open. */ - void verifyStream(); + void verifyStream( void ); + + //! Protected common error method to allow global control over error handling. + void error( RtAudioError::Type type ); /*! Protected method used to perform format, channel number, and/or interleaving @@ -298,515 +849,353 @@ protected: void convertBuffer( char *outBuffer, char *inBuffer, ConvertInfo &info ); //! Protected common method used to perform byte-swapping on buffers. - void byteSwapBuffer( char *buffer, int samples, RtAudioFormat format ); + void byteSwapBuffer( char *buffer, unsigned int samples, RtAudioFormat format ); - //! Protected common method which returns the number of bytes for a given format. - int formatBytes( RtAudioFormat format ); -}; + //! Protected common method that returns the number of bytes for a given format. + unsigned int formatBytes( RtAudioFormat format ); + //! Protected common method that sets up the parameters for buffer conversion. + void setConvertInfo( StreamMode mode, unsigned int firstChannel ); +}; // **************************************************************** // // -// RtAudio class declaration. -// -// RtAudio is a "controller" used to select an available audio i/o -// interface. It presents a common API for the user to call but all -// functionality is implemented by the class RtAudioApi and its -// subclasses. RtAudio creates an instance of an RtAudioApi subclass -// based on the user's API choice. If no choice is made, RtAudio -// attempts to make a "logical" API selection. +// Inline RtAudio definitions. // // **************************************************************** // -class RtAudio -{ -public: - - //! Audio API specifier arguments. - enum RtAudioApi { - UNSPECIFIED, /*!< Search for a working compiled API. */ - LINUX_ALSA, /*!< The Advanced Linux Sound Architecture API. */ - LINUX_OSS, /*!< The Linux Open Sound System API. */ - LINUX_JACK, /*!< The Linux Jack Low-Latency Audio Server API. */ - MACOSX_CORE, /*!< Macintosh OS-X Core Audio API. */ - IRIX_AL, /*!< The Irix Audio Library API. */ - WINDOWS_ASIO, /*!< The Steinberg Audio Stream I/O API. */ - WINDOWS_DS /*!< The Microsoft Direct Sound API. */ - }; - - //! The default class constructor. - /*! - Probes the system to make sure at least one audio input/output - device is available and determines the api-specific identifier for - each device found. An RtError error can be thrown if no devices - are found or if a memory allocation error occurs. +inline RtAudio::Api RtAudio :: getCurrentApi( void ) { return rtapi_->getCurrentApi(); } +inline unsigned int RtAudio :: getDeviceCount( void ) { return rtapi_->getDeviceCount(); } +inline RtAudio::DeviceInfo RtAudio :: getDeviceInfo( unsigned int device ) { return rtapi_->getDeviceInfo( device ); } +inline unsigned int RtAudio :: getDefaultInputDevice( void ) { return rtapi_->getDefaultInputDevice(); } +inline unsigned int RtAudio :: getDefaultOutputDevice( void ) { return rtapi_->getDefaultOutputDevice(); } +inline void RtAudio :: closeStream( void ) { return rtapi_->closeStream(); } +inline void RtAudio :: startStream( void ) { return rtapi_->startStream(); } +inline void RtAudio :: stopStream( void ) { return rtapi_->stopStream(); } +inline void RtAudio :: abortStream( void ) { return rtapi_->abortStream(); } +inline bool RtAudio :: isStreamOpen( void ) const { return rtapi_->isStreamOpen(); } +inline bool RtAudio :: isStreamRunning( void ) const { return rtapi_->isStreamRunning(); } +inline long RtAudio :: getStreamLatency( void ) { return rtapi_->getStreamLatency(); } +inline unsigned int RtAudio :: getStreamSampleRate( void ) { return rtapi_->getStreamSampleRate(); } +inline double RtAudio :: getStreamTime( void ) { return rtapi_->getStreamTime(); } +inline void RtAudio :: setStreamTime( double time ) { return rtapi_->setStreamTime( time ); } +inline void RtAudio :: showWarnings( bool value ) { rtapi_->showWarnings( value ); } - If no API argument is specified and multiple API support has been - compiled, the default order of use is JACK, ALSA, OSS (Linux - systems) and ASIO, DS (Windows systems). - */ - RtAudio( RtAudioApi api=UNSPECIFIED ); - - //! A constructor which can be used to open a stream during instantiation. - /*! - The specified output and/or input device identifiers correspond - to those enumerated via the getDeviceInfo() method. If device = - 0, the default or first available devices meeting the given - parameters is selected. If an output or input channel value is - zero, the corresponding device value is ignored. When a stream is - successfully opened, its identifier is returned via the "streamId" - pointer. An RtError can be thrown if no devices are found - for the given parameters, if a memory allocation error occurs, or - if a driver error occurs. \sa openStream() - */ - RtAudio( int outputDevice, int outputChannels, - int inputDevice, int inputChannels, - RtAudioFormat format, int sampleRate, - int *bufferSize, int numberOfBuffers, RtAudioApi api=UNSPECIFIED ); - - //! An overloaded constructor which opens a stream and also returns \c numberOfBuffers parameter via pointer argument. - /*! - See the previous constructor call for details. This overloaded - version differs only in that it takes a pointer argument for the - \c numberOfBuffers parameter and returns the value used by the - audio device (which may be different from that requested). Note - that the \c numberofBuffers parameter is not used with the Linux - Jack, Macintosh CoreAudio, and Windows ASIO APIs. - */ - RtAudio( int outputDevice, int outputChannels, - int inputDevice, int inputChannels, - RtAudioFormat format, int sampleRate, - int *bufferSize, int *numberOfBuffers, RtAudioApi api=UNSPECIFIED ); +// RtApi Subclass prototypes. - //! The destructor. - /*! - Stops and closes an open stream and devices and deallocates - buffer and structure memory. - */ - ~RtAudio(); +#if defined(__MACOSX_CORE__) - //! A public method for opening a stream with the specified parameters. - /*! - An RtError is thrown if a stream cannot be opened. - - \param outputDevice: If equal to 0, the default or first device - found meeting the given parameters is opened. Otherwise, the - device number should correspond to one of those enumerated via - the getDeviceInfo() method. - \param outputChannels: The desired number of output channels. If - equal to zero, the outputDevice identifier is ignored. - \param inputDevice: If equal to 0, the default or first device - found meeting the given parameters is opened. Otherwise, the - device number should correspond to one of those enumerated via - the getDeviceInfo() method. - \param inputChannels: The desired number of input channels. If - equal to zero, the inputDevice identifier is ignored. - \param format: An RtAudioFormat specifying the desired sample data format. - \param sampleRate: The desired sample rate (sample frames per second). - \param *bufferSize: A pointer value indicating the desired internal buffer - size in sample frames. The actual value used by the device is - returned via the same pointer. A value of zero can be specified, - in which case the lowest allowable value is determined. - \param numberOfBuffers: A value which can be used to help control device - latency. More buffers typically result in more robust performance, - though at a cost of greater latency. A value of zero can be - specified, in which case the lowest allowable value is used. - */ - void openStream( int outputDevice, int outputChannels, - int inputDevice, int inputChannels, - RtAudioFormat format, int sampleRate, - int *bufferSize, int numberOfBuffers ); +#include - //! A public method for opening a stream and also returning \c numberOfBuffers parameter via pointer argument. - /*! - See the previous function call for details. This overloaded - version differs only in that it takes a pointer argument for the - \c numberOfBuffers parameter and returns the value used by the - audio device (which may be different from that requested). Note - that the \c numberofBuffers parameter is not used with the Linux - Jack, Macintosh CoreAudio, and Windows ASIO APIs. - */ - void openStream( int outputDevice, int outputChannels, - int inputDevice, int inputChannels, - RtAudioFormat format, int sampleRate, - int *bufferSize, int *numberOfBuffers ); +class RtApiCore: public RtApi +{ +public: - //! A public method which sets a user-defined callback function for a given stream. - /*! - This method assigns a callback function to a previously opened - stream for non-blocking stream functionality. A separate process - is initiated, though the user function is called only when the - stream is "running" (between calls to the startStream() and - stopStream() methods, respectively). The callback process remains - active for the duration of the stream and is automatically - shutdown when the stream is closed (via the closeStream() method - or by object destruction). The callback process can also be - shutdown and the user function de-referenced through an explicit - call to the cancelStreamCallback() method. Note that the stream - can use only blocking or callback functionality at a particular - time, though it is possible to alternate modes on the same stream - through the use of the setStreamCallback() and - cancelStreamCallback() methods (the blocking tickStream() method - can be used before a callback is set and/or after a callback is - cancelled). An RtError will be thrown if called when no stream is - open or a thread errors occurs. - */ - void setStreamCallback(RtAudioCallback callback, void *userData) { rtapi_->setStreamCallback( callback, userData ); }; + RtApiCore(); + ~RtApiCore(); + RtAudio::Api getCurrentApi( void ) { return RtAudio::MACOSX_CORE; } + unsigned int getDeviceCount( void ); + RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); + unsigned int getDefaultOutputDevice( void ); + unsigned int getDefaultInputDevice( void ); + void closeStream( void ); + void startStream( void ); + void stopStream( void ); + void abortStream( void ); - //! A public method which cancels a callback process and function for the stream. - /*! - This method shuts down a callback process and de-references the - user function for the stream. Callback functionality can - subsequently be restarted on the stream via the - setStreamCallback() method. An RtError will be thrown if called - when no stream is open. - */ - void cancelStreamCallback() { rtapi_->cancelStreamCallback(); }; - - //! A public method which returns the number of audio devices found. - int getDeviceCount(void) { return rtapi_->getDeviceCount(); }; - - //! Return an RtAudioDeviceInfo structure for a specified device number. - /*! - Any device integer between 1 and getDeviceCount() is valid. If - a device is busy or otherwise unavailable, the structure member - "probed" will have a value of "false" and all other members are - undefined. If the specified device is the current default input - or output device, the "isDefault" member will have a value of - "true". An RtError will be thrown for an invalid device argument. - */ - RtAudioDeviceInfo getDeviceInfo(int device) { return rtapi_->getDeviceInfo( device ); }; + // This function is intended for internal use only. It must be + // public because it is called by the internal callback handler, + // which is not a member of RtAudio. External use of this function + // will most likely produce highly undesireable results! + bool callbackEvent( AudioDeviceID deviceId, + const AudioBufferList *inBufferList, + const AudioBufferList *outBufferList ); - //! A public method which returns a pointer to the buffer for an open stream. - /*! - The user should fill and/or read the buffer data in interleaved format - and then call the tickStream() method. An RtError will be - thrown if called when no stream is open. - */ - char * const getStreamBuffer() { return rtapi_->getStreamBuffer(); }; + private: - //! Public method used to trigger processing of input/output data for a stream. - /*! - This method blocks until all buffer data is read/written. An - RtError will be thrown if a driver error occurs or if called when - no stream is open. - */ - void tickStream() { rtapi_->tickStream(); }; + bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, + unsigned int firstChannel, unsigned int sampleRate, + RtAudioFormat format, unsigned int *bufferSize, + RtAudio::StreamOptions *options ); + static const char* getErrorCode( OSStatus code ); +}; - //! Public method which closes a stream and frees any associated buffers. - /*! - If a stream is not open, this method issues a warning and - returns (an RtError is not thrown). - */ - void closeStream() { rtapi_->closeStream(); }; +#endif - //! Public method which starts a stream. - /*! - An RtError will be thrown if a driver error occurs or if called - when no stream is open. - */ - void startStream() { rtapi_->startStream(); }; +#if defined(__UNIX_JACK__) - //! Stop a stream, allowing any samples remaining in the queue to be played out and/or read in. - /*! - An RtError will be thrown if a driver error occurs or if called - when no stream is open. - */ - void stopStream() { rtapi_->stopStream(); }; +class RtApiJack: public RtApi +{ +public: - //! Stop a stream, discarding any samples remaining in the input/output queue. - /*! - An RtError will be thrown if a driver error occurs or if called - when no stream is open. - */ - void abortStream() { rtapi_->abortStream(); }; + RtApiJack(); + ~RtApiJack(); + RtAudio::Api getCurrentApi( void ) { return RtAudio::UNIX_JACK; } + unsigned int getDeviceCount( void ); + RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); + void closeStream( void ); + void startStream( void ); + void stopStream( void ); + void abortStream( void ); + // This function is intended for internal use only. It must be + // public because it is called by the internal callback handler, + // which is not a member of RtAudio. External use of this function + // will most likely produce highly undesireable results! + bool callbackEvent( unsigned long nframes ); - protected: + private: - void initialize( RtAudioApi api ); + bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, + unsigned int firstChannel, unsigned int sampleRate, + RtAudioFormat format, unsigned int *bufferSize, + RtAudio::StreamOptions *options ); - RtApi *rtapi_; + bool shouldAutoconnect_; }; +#endif -// RtApi Subclass prototypes. - -#if defined(__LINUX_ALSA__) +#if defined(__WINDOWS_ASIO__) -class RtApiAlsa: public RtApi +class RtApiAsio: public RtApi { public: - RtApiAlsa(); - ~RtApiAlsa(); - void tickStream(); - void closeStream(); - void startStream(); - void stopStream(); - void abortStream(); - int streamWillBlock(); - void setStreamCallback( RtAudioCallback callback, void *userData ); - void cancelStreamCallback(); + RtApiAsio(); + ~RtApiAsio(); + RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_ASIO; } + unsigned int getDeviceCount( void ); + RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); + void closeStream( void ); + void startStream( void ); + void stopStream( void ); + void abortStream( void ); + + // This function is intended for internal use only. It must be + // public because it is called by the internal callback handler, + // which is not a member of RtAudio. External use of this function + // will most likely produce highly undesireable results! + bool callbackEvent( long bufferIndex ); private: - void initialize(void); - void probeDeviceInfo( RtApiDevice *info ); - bool probeDeviceOpen( int device, StreamMode mode, int channels, - int sampleRate, RtAudioFormat format, - int *bufferSize, int numberOfBuffers ); + std::vector devices_; + void saveDeviceInfo( void ); + bool coInitialized_; + bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, + unsigned int firstChannel, unsigned int sampleRate, + RtAudioFormat format, unsigned int *bufferSize, + RtAudio::StreamOptions *options ); }; #endif -#if defined(__LINUX_JACK__) +#if defined(__WINDOWS_DS__) -class RtApiJack: public RtApi +class RtApiDs: public RtApi { public: - RtApiJack(); - ~RtApiJack(); - void tickStream(); - void closeStream(); - void startStream(); - void stopStream(); - void abortStream(); - void setStreamCallback( RtAudioCallback callback, void *userData ); - void cancelStreamCallback(); + RtApiDs(); + ~RtApiDs(); + RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_DS; } + unsigned int getDeviceCount( void ); + unsigned int getDefaultOutputDevice( void ); + unsigned int getDefaultInputDevice( void ); + RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); + void closeStream( void ); + void startStream( void ); + void stopStream( void ); + void abortStream( void ); + // This function is intended for internal use only. It must be // public because it is called by the internal callback handler, // which is not a member of RtAudio. External use of this function // will most likely produce highly undesireable results! - void callbackEvent( unsigned long nframes ); + void callbackEvent( void ); private: - void initialize(void); - void probeDeviceInfo( RtApiDevice *info ); - bool probeDeviceOpen( int device, StreamMode mode, int channels, - int sampleRate, RtAudioFormat format, - int *bufferSize, int numberOfBuffers ); + bool coInitialized_; + bool buffersRolling; + long duplexPrerollBytes; + std::vector dsDevices; + bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, + unsigned int firstChannel, unsigned int sampleRate, + RtAudioFormat format, unsigned int *bufferSize, + RtAudio::StreamOptions *options ); }; #endif -#if defined(__LINUX_OSS__) +#if defined(__WINDOWS_WASAPI__) -class RtApiOss: public RtApi +struct IMMDeviceEnumerator; + +class RtApiWasapi : public RtApi { public: - - RtApiOss(); - ~RtApiOss(); - void tickStream(); - void closeStream(); - void startStream(); - void stopStream(); - void abortStream(); - int streamWillBlock(); - void setStreamCallback( RtAudioCallback callback, void *userData ); - void cancelStreamCallback(); - - private: - - void initialize(void); - void probeDeviceInfo( RtApiDevice *info ); - bool probeDeviceOpen( int device, StreamMode mode, int channels, - int sampleRate, RtAudioFormat format, - int *bufferSize, int numberOfBuffers ); + RtApiWasapi(); + virtual ~RtApiWasapi(); + + RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_WASAPI; } + unsigned int getDeviceCount( void ); + RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); + unsigned int getDefaultOutputDevice( void ); + unsigned int getDefaultInputDevice( void ); + void closeStream( void ); + void startStream( void ); + void stopStream( void ); + void abortStream( void ); + +private: + bool coInitialized_; + IMMDeviceEnumerator* deviceEnumerator_; + + bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, + unsigned int firstChannel, unsigned int sampleRate, + RtAudioFormat format, unsigned int* bufferSize, + RtAudio::StreamOptions* options ); + + static DWORD WINAPI runWasapiThread( void* wasapiPtr ); + static DWORD WINAPI stopWasapiThread( void* wasapiPtr ); + static DWORD WINAPI abortWasapiThread( void* wasapiPtr ); + void wasapiThread(); }; #endif -#if defined(__MACOSX_CORE__) - -#include +#if defined(__LINUX_ALSA__) -class RtApiCore: public RtApi +class RtApiAlsa: public RtApi { public: - RtApiCore(); - ~RtApiCore(); - int getDefaultOutputDevice(void); - int getDefaultInputDevice(void); - void tickStream(); - void closeStream(); - void startStream(); - void stopStream(); - void abortStream(); - void setStreamCallback( RtAudioCallback callback, void *userData ); - void cancelStreamCallback(); + RtApiAlsa(); + ~RtApiAlsa(); + RtAudio::Api getCurrentApi() { return RtAudio::LINUX_ALSA; } + unsigned int getDeviceCount( void ); + RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); + void closeStream( void ); + void startStream( void ); + void stopStream( void ); + void abortStream( void ); // This function is intended for internal use only. It must be // public because it is called by the internal callback handler, // which is not a member of RtAudio. External use of this function // will most likely produce highly undesireable results! - void callbackEvent( AudioDeviceID deviceId, void *inData, void *outData ); + void callbackEvent( void ); private: - void initialize(void); - void probeDeviceInfo( RtApiDevice *info ); - bool probeDeviceOpen( int device, StreamMode mode, int channels, - int sampleRate, RtAudioFormat format, - int *bufferSize, int numberOfBuffers ); + std::vector devices_; + void saveDeviceInfo( void ); + bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, + unsigned int firstChannel, unsigned int sampleRate, + RtAudioFormat format, unsigned int *bufferSize, + RtAudio::StreamOptions *options ); }; #endif -#if defined(__WINDOWS_DS__) +#if defined(__LINUX_PULSE__) -class RtApiDs: public RtApi +class RtApiPulse: public RtApi { public: + ~RtApiPulse(); + RtAudio::Api getCurrentApi() { return RtAudio::LINUX_PULSE; } + unsigned int getDeviceCount( void ); + RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); + void closeStream( void ); + void startStream( void ); + void stopStream( void ); + void abortStream( void ); - RtApiDs(); - ~RtApiDs(); - int getDefaultOutputDevice(void); - int getDefaultInputDevice(void); - void tickStream(); - void closeStream(); - void startStream(); - void stopStream(); - void abortStream(); - int streamWillBlock(); - void setStreamCallback( RtAudioCallback callback, void *userData ); - void cancelStreamCallback(); - - public: - // \brief Internal structure that provide debug information on the state of a running DSound device. - struct RtDsStatistics { - // \brief Sample Rate. - long sampleRate; - // \brief The size of one sample * number of channels on the input device. - int inputFrameSize; - // \brief The size of one sample * number of channels on the output device. - int outputFrameSize; - /* \brief The number of times the read pointer had to be adjusted to avoid reading from an unsafe buffer position. - * - * This field is only used when running in DUPLEX mode. INPUT mode devices just wait until the data is - * available. - */ - int numberOfReadOverruns; - // \brief The number of times the write pointer had to be adjusted to avoid writing in an unsafe buffer position. - int numberOfWriteUnderruns; - // \brief Number of bytes by attribute to buffer configuration by which writing must lead the current write pointer. - int writeDeviceBufferLeadBytes; - // \brief Number of bytes by attributable to the device driver by which writing must lead the current write pointer on this output device. - unsigned long writeDeviceSafeLeadBytes; - // \brief Number of bytes by which reading must trail the current read pointer on this input device. - unsigned long readDeviceSafeLeadBytes; - /* \brief Estimated latency in seconds. - * - * For INPUT mode devices, based the latency of the device's safe read pointer, plus one buffer's - * worth of additional latency. - * - * For OUTPUT mode devices, the latency of the device's safe write pointer, plus N buffers of - * additional buffer latency. - * - * For DUPLEX devices, the sum of latencies for both input and output devices. DUPLEX devices - * also back off the read pointers an additional amount in order to maintain synchronization - * between out-of-phase read and write pointers. This time is also included. - * - * Note that most software packages report latency between the safe write pointer - * and the software lead pointer, excluding the hardware device's safe write pointer - * latency. Figures of 1 or 2ms of latency on Windows audio devices are invariably of this type. - * The reality is that hardware devices often have latencies of 30ms or more (often much - * higher for duplex operation). - */ - - double latency; - }; - // \brief Report on the current state of a running DSound device. - static RtDsStatistics getDsStatistics(); + // This function is intended for internal use only. It must be + // public because it is called by the internal callback handler, + // which is not a member of RtAudio. External use of this function + // will most likely produce highly undesireable results! + void callbackEvent( void ); private: - void initialize(void); - void probeDeviceInfo( RtApiDevice *info ); - bool probeDeviceOpen( int device, StreamMode mode, int channels, - int sampleRate, RtAudioFormat format, - int *bufferSize, int numberOfBuffers ); - - bool coInitialized; - bool buffersRolling; - long duplexPrerollBytes; - static RtDsStatistics statistics; - + std::vector devices_; + void saveDeviceInfo( void ); + bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, + unsigned int firstChannel, unsigned int sampleRate, + RtAudioFormat format, unsigned int *bufferSize, + RtAudio::StreamOptions *options ); }; #endif -#if defined(__WINDOWS_ASIO__) +#if defined(__LINUX_OSS__) -class RtApiAsio: public RtApi +class RtApiOss: public RtApi { public: - RtApiAsio(); - ~RtApiAsio(); - void tickStream(); - void closeStream(); - void startStream(); - void stopStream(); - void abortStream(); - void setStreamCallback( RtAudioCallback callback, void *userData ); - void cancelStreamCallback(); + RtApiOss(); + ~RtApiOss(); + RtAudio::Api getCurrentApi() { return RtAudio::LINUX_OSS; } + unsigned int getDeviceCount( void ); + RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); + void closeStream( void ); + void startStream( void ); + void stopStream( void ); + void abortStream( void ); // This function is intended for internal use only. It must be // public because it is called by the internal callback handler, // which is not a member of RtAudio. External use of this function // will most likely produce highly undesireable results! - void callbackEvent( long bufferIndex ); + void callbackEvent( void ); private: - void initialize(void); - void probeDeviceInfo( RtApiDevice *info ); - bool probeDeviceOpen( int device, StreamMode mode, int channels, - int sampleRate, RtAudioFormat format, - int *bufferSize, int numberOfBuffers ); - - bool coInitialized; - + bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, + unsigned int firstChannel, unsigned int sampleRate, + RtAudioFormat format, unsigned int *bufferSize, + RtAudio::StreamOptions *options ); }; #endif -#if defined(__IRIX_AL__) +#if defined(__RTAUDIO_DUMMY__) -class RtApiAl: public RtApi +class RtApiDummy: public RtApi { public: - RtApiAl(); - ~RtApiAl(); - int getDefaultOutputDevice(void); - int getDefaultInputDevice(void); - void tickStream(); - void closeStream(); - void startStream(); - void stopStream(); - void abortStream(); - int streamWillBlock(); - void setStreamCallback( RtAudioCallback callback, void *userData ); - void cancelStreamCallback(); + RtApiDummy() { errorText_ = "RtApiDummy: This class provides no functionality."; error( RtAudioError::WARNING ); } + RtAudio::Api getCurrentApi( void ) { return RtAudio::RTAUDIO_DUMMY; } + unsigned int getDeviceCount( void ) { return 0; } + RtAudio::DeviceInfo getDeviceInfo( unsigned int /*device*/ ) { RtAudio::DeviceInfo info; return info; } + void closeStream( void ) {} + void startStream( void ) {} + void stopStream( void ) {} + void abortStream( void ) {} private: - void initialize(void); - void probeDeviceInfo( RtApiDevice *info ); - bool probeDeviceOpen( int device, StreamMode mode, int channels, - int sampleRate, RtAudioFormat format, - int *bufferSize, int numberOfBuffers ); + bool probeDeviceOpen( unsigned int /*device*/, StreamMode /*mode*/, unsigned int /*channels*/, + unsigned int /*firstChannel*/, unsigned int /*sampleRate*/, + RtAudioFormat /*format*/, unsigned int * /*bufferSize*/, + RtAudio::StreamOptions * /*options*/ ) { return false; } }; #endif -// Define the following flag to have extra information spewed to stderr. -//#define __RTAUDIO_DEBUG__ - #endif + +// Indentation settings for Vim and Emacs +// +// Local Variables: +// c-basic-offset: 2 +// indent-tabs-mode: nil +// End: +// +// vim: et sts=2 sw=2