00001 /************************************************************************/ 00038 /************************************************************************/ 00039 00040 // RtAudio: Version 3.0.3 (18 November 2005) 00041 00042 #ifndef __RTAUDIO_H 00043 #define __RTAUDIO_H 00044 00045 #include "RtError.h" 00046 #include <string> 00047 #include <vector> 00048 00049 // Operating system dependent thread functionality. 00050 #if defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__) 00051 #include <windows.h> 00052 #include <process.h> 00053 00054 typedef unsigned long ThreadHandle; 00055 typedef CRITICAL_SECTION StreamMutex; 00056 00057 #else // Various unix flavors with pthread support. 00058 #include <pthread.h> 00059 00060 typedef pthread_t ThreadHandle; 00061 typedef pthread_mutex_t StreamMutex; 00062 00063 #endif 00064 00065 // This global structure type is used to pass callback information 00066 // between the private RtAudio stream structure and global callback 00067 // handling functions. 00068 struct CallbackInfo { 00069 void *object; // Used as a "this" pointer. 00070 ThreadHandle thread; 00071 bool usingCallback; 00072 void *callback; 00073 void *userData; 00074 void *apiInfo; // void pointer for API specific callback information 00075 00076 // Default constructor. 00077 CallbackInfo() 00078 :object(0), usingCallback(false), callback(0), 00079 userData(0), apiInfo(0) {} 00080 }; 00081 00082 // Support for signed integers and floats. Audio data fed to/from 00083 // the tickStream() routine is assumed to ALWAYS be in host 00084 // byte order. The internal routines will automatically take care of 00085 // any necessary byte-swapping between the host format and the 00086 // soundcard. Thus, endian-ness is not a concern in the following 00087 // format definitions. 00088 typedef unsigned long RtAudioFormat; 00089 static const RtAudioFormat RTAUDIO_SINT8 = 0x1; 00090 static const RtAudioFormat RTAUDIO_SINT16 = 0x2; 00091 static const RtAudioFormat RTAUDIO_SINT24 = 0x4; 00092 static const RtAudioFormat RTAUDIO_SINT32 = 0x8; 00093 static const RtAudioFormat RTAUDIO_FLOAT32 = 0x10; 00094 static const RtAudioFormat RTAUDIO_FLOAT64 = 0x20; 00096 typedef int (*RtAudioCallback)(char *buffer, int bufferSize, void *userData); 00097 00099 struct RtAudioDeviceInfo { 00100 std::string name; 00101 bool probed; 00102 int outputChannels; 00103 int inputChannels; 00104 int duplexChannels; 00105 bool isDefault; 00106 std::vector<int> sampleRates; 00107 RtAudioFormat nativeFormats; 00109 // Default constructor. 00110 RtAudioDeviceInfo() 00111 :probed(false), outputChannels(0), inputChannels(0), 00112 duplexChannels(0), isDefault(false), nativeFormats(0) {} 00113 }; 00114 00115 // **************************************************************** // 00116 // 00117 // RtApi class declaration. 00118 // 00119 // Note that RtApi is an abstract base class and cannot be 00120 // explicitly instantiated. The class RtAudio will create an 00121 // instance of an RtApi subclass (RtApiOss, RtApiAlsa, 00122 // RtApiJack, RtApiCore, RtApiAl, RtApiDs, or RtApiAsio). 00123 // 00124 // **************************************************************** // 00125 00126 class RtApi 00127 { 00128 public: 00129 00130 enum StreamState { 00131 STREAM_STOPPED, 00132 STREAM_RUNNING 00133 }; 00134 00135 RtApi(); 00136 virtual ~RtApi(); 00137 void openStream( int outputDevice, int outputChannels, 00138 int inputDevice, int inputChannels, 00139 RtAudioFormat format, int sampleRate, 00140 int *bufferSize, int numberOfBuffers ); 00141 void openStream( int outputDevice, int outputChannels, 00142 int inputDevice, int inputChannels, 00143 RtAudioFormat format, int sampleRate, 00144 int *bufferSize, int *numberOfBuffers ); 00145 virtual void setStreamCallback( RtAudioCallback callback, void *userData ) = 0; 00146 virtual void cancelStreamCallback() = 0; 00147 int getDeviceCount(void); 00148 RtAudioDeviceInfo getDeviceInfo( int device ); 00149 char * const getStreamBuffer(); 00150 RtApi::StreamState getStreamState() const; 00151 virtual void tickStream() = 0; 00152 virtual void closeStream(); 00153 virtual void startStream() = 0; 00154 virtual void stopStream() = 0; 00155 virtual void abortStream() = 0; 00156 00157 protected: 00158 00159 static const unsigned int MAX_SAMPLE_RATES; 00160 static const unsigned int SAMPLE_RATES[]; 00161 00162 enum { FAILURE, SUCCESS }; 00163 00164 enum StreamMode { 00165 OUTPUT, 00166 INPUT, 00167 DUPLEX, 00168 UNINITIALIZED = -75 00169 }; 00170 00171 // A protected structure used for buffer conversion. 00172 struct ConvertInfo { 00173 int channels; 00174 int inJump, outJump; 00175 RtAudioFormat inFormat, outFormat; 00176 std::vector<int> inOffset; 00177 std::vector<int> outOffset; 00178 }; 00179 00180 // A protected structure for audio streams. 00181 struct RtApiStream { 00182 int device[2]; // Playback and record, respectively. 00183 void *apiHandle; // void pointer for API specific stream handle information 00184 StreamMode mode; // OUTPUT, INPUT, or DUPLEX. 00185 StreamState state; // STOPPED or RUNNING 00186 char *userBuffer; 00187 char *deviceBuffer; 00188 bool doConvertBuffer[2]; // Playback and record, respectively. 00189 bool deInterleave[2]; // Playback and record, respectively. 00190 bool doByteSwap[2]; // Playback and record, respectively. 00191 int sampleRate; 00192 int bufferSize; 00193 int nBuffers; 00194 int nUserChannels[2]; // Playback and record, respectively. 00195 int nDeviceChannels[2]; // Playback and record channels, respectively. 00196 RtAudioFormat userFormat; 00197 RtAudioFormat deviceFormat[2]; // Playback and record, respectively. 00198 StreamMutex mutex; 00199 CallbackInfo callbackInfo; 00200 ConvertInfo convertInfo[2]; 00201 00202 RtApiStream() 00203 :apiHandle(0), userBuffer(0), deviceBuffer(0) {} 00204 }; 00205 00206 // A protected device structure for audio devices. 00207 struct RtApiDevice { 00208 std::string name; 00209 bool probed; 00210 void *apiDeviceId; // void pointer for API specific device information 00211 int maxOutputChannels; 00212 int maxInputChannels; 00213 int maxDuplexChannels; 00214 int minOutputChannels; 00215 int minInputChannels; 00216 int minDuplexChannels; 00217 bool hasDuplexSupport; 00218 bool isDefault; 00219 std::vector<int> sampleRates; 00220 RtAudioFormat nativeFormats; 00222 // Default constructor. 00223 RtApiDevice() 00224 :probed(false), apiDeviceId(0), maxOutputChannels(0), maxInputChannels(0), 00225 maxDuplexChannels(0), minOutputChannels(0), minInputChannels(0), 00226 minDuplexChannels(0), isDefault(false), nativeFormats(0) {} 00227 }; 00228 00229 typedef signed short Int16; 00230 typedef signed int Int32; 00231 typedef float Float32; 00232 typedef double Float64; 00233 00234 char message_[1024]; 00235 int nDevices_; 00236 std::vector<RtApiDevice> devices_; 00237 RtApiStream stream_; 00238 00243 virtual void initialize(void) = 0; 00244 00253 virtual void probeDeviceInfo( RtApiDevice *info ); 00254 00263 virtual bool probeDeviceOpen( int device, StreamMode mode, int channels, 00264 int sampleRate, RtAudioFormat format, 00265 int *bufferSize, int numberOfBuffers ); 00266 00271 virtual int getDefaultInputDevice(void); 00272 00277 virtual int getDefaultOutputDevice(void); 00278 00280 void clearDeviceInfo( RtApiDevice *info ); 00281 00283 void clearStreamInfo(); 00284 00286 void error( RtError::Type type ); 00287 00292 void verifyStream(); 00293 00298 void convertBuffer( char *outBuffer, char *inBuffer, ConvertInfo &info ); 00299 00301 void byteSwapBuffer( char *buffer, int samples, RtAudioFormat format ); 00302 00304 int formatBytes( RtAudioFormat format ); 00305 }; 00306 00307 00308 // **************************************************************** // 00309 // 00310 // RtAudio class declaration. 00311 // 00312 // RtAudio is a "controller" used to select an available audio i/o 00313 // interface. It presents a common API for the user to call but all 00314 // functionality is implemented by the class RtAudioApi and its 00315 // subclasses. RtAudio creates an instance of an RtAudioApi subclass 00316 // based on the user's API choice. If no choice is made, RtAudio 00317 // attempts to make a "logical" API selection. 00318 // 00319 // **************************************************************** // 00320 00321 class RtAudio 00322 { 00323 public: 00324 00326 enum RtAudioApi { 00327 UNSPECIFIED, 00328 LINUX_ALSA, 00329 LINUX_OSS, 00330 LINUX_JACK, 00331 MACOSX_CORE, 00332 IRIX_AL, 00333 WINDOWS_ASIO, 00334 WINDOWS_DS 00335 }; 00336 00338 00348 RtAudio( RtAudioApi api=UNSPECIFIED ); 00349 00351 00362 RtAudio( int outputDevice, int outputChannels, 00363 int inputDevice, int inputChannels, 00364 RtAudioFormat format, int sampleRate, 00365 int *bufferSize, int numberOfBuffers, RtAudioApi api=UNSPECIFIED ); 00366 00368 00376 RtAudio( int outputDevice, int outputChannels, 00377 int inputDevice, int inputChannels, 00378 RtAudioFormat format, int sampleRate, 00379 int *bufferSize, int *numberOfBuffers, RtAudioApi api=UNSPECIFIED ); 00380 00382 00386 ~RtAudio(); 00387 00389 00415 void openStream( int outputDevice, int outputChannels, 00416 int inputDevice, int inputChannels, 00417 RtAudioFormat format, int sampleRate, 00418 int *bufferSize, int numberOfBuffers ); 00419 00421 00429 void openStream( int outputDevice, int outputChannels, 00430 int inputDevice, int inputChannels, 00431 RtAudioFormat format, int sampleRate, 00432 int *bufferSize, int *numberOfBuffers ); 00433 00435 00454 void setStreamCallback(RtAudioCallback callback, void *userData) { rtapi_->setStreamCallback( callback, userData ); }; 00455 00457 00464 void cancelStreamCallback() { rtapi_->cancelStreamCallback(); }; 00465 00467 int getDeviceCount(void) { return rtapi_->getDeviceCount(); }; 00468 00470 00478 RtAudioDeviceInfo getDeviceInfo(int device) { return rtapi_->getDeviceInfo( device ); }; 00479 00481 00486 char * const getStreamBuffer() { return rtapi_->getStreamBuffer(); }; 00487 00489 00494 void tickStream() { rtapi_->tickStream(); }; 00495 00497 00501 void closeStream() { rtapi_->closeStream(); }; 00502 00504 00508 void startStream() { rtapi_->startStream(); }; 00509 00511 00515 void stopStream() { rtapi_->stopStream(); }; 00516 00518 00522 void abortStream() { rtapi_->abortStream(); }; 00523 00524 00525 protected: 00526 00527 void initialize( RtAudioApi api ); 00528 00529 RtApi *rtapi_; 00530 }; 00531 00532 00533 // RtApi Subclass prototypes. 00534 00535 #if defined(__LINUX_ALSA__) 00536 00537 class RtApiAlsa: public RtApi 00538 { 00539 public: 00540 00541 RtApiAlsa(); 00542 ~RtApiAlsa(); 00543 void tickStream(); 00544 void closeStream(); 00545 void startStream(); 00546 void stopStream(); 00547 void abortStream(); 00548 int streamWillBlock(); 00549 void setStreamCallback( RtAudioCallback callback, void *userData ); 00550 void cancelStreamCallback(); 00551 00552 private: 00553 00554 void initialize(void); 00555 bool primeOutputBuffer(); 00556 void probeDeviceInfo( RtApiDevice *info ); 00557 bool probeDeviceOpen( int device, StreamMode mode, int channels, 00558 int sampleRate, RtAudioFormat format, 00559 int *bufferSize, int numberOfBuffers ); 00560 }; 00561 00562 #endif 00563 00564 #if defined(__LINUX_JACK__) 00565 00566 class RtApiJack: public RtApi 00567 { 00568 public: 00569 00570 RtApiJack(); 00571 ~RtApiJack(); 00572 void tickStream(); 00573 void closeStream(); 00574 void startStream(); 00575 void stopStream(); 00576 void abortStream(); 00577 void setStreamCallback( RtAudioCallback callback, void *userData ); 00578 void cancelStreamCallback(); 00579 // This function is intended for internal use only. It must be 00580 // public because it is called by the internal callback handler, 00581 // which is not a member of RtAudio. External use of this function 00582 // will most likely produce highly undesireable results! 00583 void callbackEvent( unsigned long nframes ); 00584 00585 private: 00586 00587 void initialize(void); 00588 void probeDeviceInfo( RtApiDevice *info ); 00589 bool probeDeviceOpen( int device, StreamMode mode, int channels, 00590 int sampleRate, RtAudioFormat format, 00591 int *bufferSize, int numberOfBuffers ); 00592 }; 00593 00594 #endif 00595 00596 #if defined(__LINUX_OSS__) 00597 00598 class RtApiOss: public RtApi 00599 { 00600 public: 00601 00602 RtApiOss(); 00603 ~RtApiOss(); 00604 void tickStream(); 00605 void closeStream(); 00606 void startStream(); 00607 void stopStream(); 00608 void abortStream(); 00609 int streamWillBlock(); 00610 void setStreamCallback( RtAudioCallback callback, void *userData ); 00611 void cancelStreamCallback(); 00612 00613 private: 00614 00615 void initialize(void); 00616 void probeDeviceInfo( RtApiDevice *info ); 00617 bool probeDeviceOpen( int device, StreamMode mode, int channels, 00618 int sampleRate, RtAudioFormat format, 00619 int *bufferSize, int numberOfBuffers ); 00620 }; 00621 00622 #endif 00623 00624 #if defined(__MACOSX_CORE__) 00625 00626 #include <CoreAudio/AudioHardware.h> 00627 00628 class RtApiCore: public RtApi 00629 { 00630 public: 00631 00632 RtApiCore(); 00633 ~RtApiCore(); 00634 int getDefaultOutputDevice(void); 00635 int getDefaultInputDevice(void); 00636 void tickStream(); 00637 void closeStream(); 00638 void startStream(); 00639 void stopStream(); 00640 void abortStream(); 00641 void setStreamCallback( RtAudioCallback callback, void *userData ); 00642 void cancelStreamCallback(); 00643 00644 // This function is intended for internal use only. It must be 00645 // public because it is called by the internal callback handler, 00646 // which is not a member of RtAudio. External use of this function 00647 // will most likely produce highly undesireable results! 00648 void callbackEvent( AudioDeviceID deviceId, void *inData, void *outData ); 00649 00650 private: 00651 00652 void initialize(void); 00653 void probeDeviceInfo( RtApiDevice *info ); 00654 bool probeDeviceOpen( int device, StreamMode mode, int channels, 00655 int sampleRate, RtAudioFormat format, 00656 int *bufferSize, int numberOfBuffers ); 00657 }; 00658 00659 #endif 00660 00661 #if defined(__WINDOWS_DS__) 00662 00663 class RtApiDs: public RtApi 00664 { 00665 public: 00666 00667 RtApiDs(); 00668 ~RtApiDs(); 00669 int getDefaultOutputDevice(void); 00670 int getDefaultInputDevice(void); 00671 void tickStream(); 00672 void closeStream(); 00673 void startStream(); 00674 void stopStream(); 00675 void abortStream(); 00676 int streamWillBlock(); 00677 void setStreamCallback( RtAudioCallback callback, void *userData ); 00678 void cancelStreamCallback(); 00679 00680 public: 00681 // \brief Internal structure that provide debug information on the state of a running DSound device. 00682 struct RtDsStatistics { 00683 // \brief Sample Rate. 00684 long sampleRate; 00685 // \brief The size of one sample * number of channels on the input device. 00686 int inputFrameSize; 00687 // \brief The size of one sample * number of channels on the output device. 00688 int outputFrameSize; 00689 /* \brief The number of times the read pointer had to be adjusted to avoid reading from an unsafe buffer position. 00690 * 00691 * This field is only used when running in DUPLEX mode. INPUT mode devices just wait until the data is 00692 * available. 00693 */ 00694 int numberOfReadOverruns; 00695 // \brief The number of times the write pointer had to be adjusted to avoid writing in an unsafe buffer position. 00696 int numberOfWriteUnderruns; 00697 // \brief Number of bytes by attribute to buffer configuration by which writing must lead the current write pointer. 00698 int writeDeviceBufferLeadBytes; 00699 // \brief Number of bytes by attributable to the device driver by which writing must lead the current write pointer on this output device. 00700 unsigned long writeDeviceSafeLeadBytes; 00701 // \brief Number of bytes by which reading must trail the current read pointer on this input device. 00702 unsigned long readDeviceSafeLeadBytes; 00703 /* \brief Estimated latency in seconds. 00704 * 00705 * For INPUT mode devices, based the latency of the device's safe read pointer, plus one buffer's 00706 * worth of additional latency. 00707 * 00708 * For OUTPUT mode devices, the latency of the device's safe write pointer, plus N buffers of 00709 * additional buffer latency. 00710 * 00711 * For DUPLEX devices, the sum of latencies for both input and output devices. DUPLEX devices 00712 * also back off the read pointers an additional amount in order to maintain synchronization 00713 * between out-of-phase read and write pointers. This time is also included. 00714 * 00715 * Note that most software packages report latency between the safe write pointer 00716 * and the software lead pointer, excluding the hardware device's safe write pointer 00717 * latency. Figures of 1 or 2ms of latency on Windows audio devices are invariably of this type. 00718 * The reality is that hardware devices often have latencies of 30ms or more (often much 00719 * higher for duplex operation). 00720 */ 00721 00722 double latency; 00723 }; 00724 // \brief Report on the current state of a running DSound device. 00725 static RtDsStatistics getDsStatistics(); 00726 00727 private: 00728 00729 void initialize(void); 00730 void probeDeviceInfo( RtApiDevice *info ); 00731 bool probeDeviceOpen( int device, StreamMode mode, int channels, 00732 int sampleRate, RtAudioFormat format, 00733 int *bufferSize, int numberOfBuffers ); 00734 00735 bool coInitialized; 00736 bool buffersRolling; 00737 long duplexPrerollBytes; 00738 static RtDsStatistics statistics; 00739 00740 }; 00741 00742 #endif 00743 00744 #if defined(__WINDOWS_ASIO__) 00745 00746 class RtApiAsio: public RtApi 00747 { 00748 public: 00749 00750 RtApiAsio(); 00751 ~RtApiAsio(); 00752 void tickStream(); 00753 void closeStream(); 00754 void startStream(); 00755 void stopStream(); 00756 void abortStream(); 00757 void setStreamCallback( RtAudioCallback callback, void *userData ); 00758 void cancelStreamCallback(); 00759 00760 // This function is intended for internal use only. It must be 00761 // public because it is called by the internal callback handler, 00762 // which is not a member of RtAudio. External use of this function 00763 // will most likely produce highly undesireable results! 00764 void callbackEvent( long bufferIndex ); 00765 00766 private: 00767 00768 void initialize(void); 00769 void probeDeviceInfo( RtApiDevice *info ); 00770 bool probeDeviceOpen( int device, StreamMode mode, int channels, 00771 int sampleRate, RtAudioFormat format, 00772 int *bufferSize, int numberOfBuffers ); 00773 00774 bool coInitialized; 00775 00776 }; 00777 00778 #endif 00779 00780 #if defined(__IRIX_AL__) 00781 00782 class RtApiAl: public RtApi 00783 { 00784 public: 00785 00786 RtApiAl(); 00787 ~RtApiAl(); 00788 int getDefaultOutputDevice(void); 00789 int getDefaultInputDevice(void); 00790 void tickStream(); 00791 void closeStream(); 00792 void startStream(); 00793 void stopStream(); 00794 void abortStream(); 00795 int streamWillBlock(); 00796 void setStreamCallback( RtAudioCallback callback, void *userData ); 00797 void cancelStreamCallback(); 00798 00799 private: 00800 00801 void initialize(void); 00802 void probeDeviceInfo( RtApiDevice *info ); 00803 bool probeDeviceOpen( int device, StreamMode mode, int channels, 00804 int sampleRate, RtAudioFormat format, 00805 int *bufferSize, int numberOfBuffers ); 00806 }; 00807 00808 #endif 00809 00810 // Define the following flag to have extra information spewed to stderr. 00811 //#define __RTAUDIO_DEBUG__ 00812 00813 #endif
©2001-2005 Gary P. Scavone, McGill University. All Rights Reserved. Maintained by Gary P. Scavone, gary@music.mcgill.ca |