00001 /************************************************************************/ 00039 /************************************************************************/ 00040 00045 // RtAudio: Version 4.0 00046 00047 #ifndef __RTAUDIO_H 00048 #define __RTAUDIO_H 00049 00050 #include <string> 00051 #include <vector> 00052 #include "RtError.h" 00053 00070 typedef unsigned long RtAudioFormat; 00071 static const RtAudioFormat RTAUDIO_SINT8 = 0x1; // 8-bit signed integer. 00072 static const RtAudioFormat RTAUDIO_SINT16 = 0x2; // 16-bit signed integer. 00073 static const RtAudioFormat RTAUDIO_SINT24 = 0x4; // Lower 3 bytes of 32-bit signed integer. 00074 static const RtAudioFormat RTAUDIO_SINT32 = 0x8; // 32-bit signed integer. 00075 static const RtAudioFormat RTAUDIO_FLOAT32 = 0x10; // Normalized between plus/minus 1.0. 00076 static const RtAudioFormat RTAUDIO_FLOAT64 = 0x20; // Normalized between plus/minus 1.0. 00077 00112 typedef unsigned int RtAudioStreamFlags; 00113 static const RtAudioStreamFlags RTAUDIO_NONINTERLEAVED = 0x1; // Use non-interleaved buffers (default = interleaved). 00114 static const RtAudioStreamFlags RTAUDIO_MINIMIZE_LATENCY = 0x2; // Attempt to set stream parameters for lowest possible latency. 00115 static const RtAudioStreamFlags RTAUDIO_HOG_DEVICE = 0x4; // Attempt grab device and prevent use by others. 00116 00128 typedef unsigned int RtAudioStreamStatus; 00129 static const RtAudioStreamStatus RTAUDIO_INPUT_OVERFLOW = 0x1; // Input data was discarded because of an overflow condition at the driver. 00130 static const RtAudioStreamStatus RTAUDIO_OUTPUT_UNDERFLOW = 0x2; // The output buffer ran low, likely causing a gap in the output sound. 00131 00133 00171 typedef int (*RtAudioCallback)( void *outputBuffer, void *inputBuffer, 00172 unsigned int nFrames, 00173 double streamTime, 00174 RtAudioStreamStatus status, 00175 void *userData ); 00176 00177 00178 // **************************************************************** // 00179 // 00180 // RtAudio class declaration. 00181 // 00182 // RtAudio is a "controller" used to select an available audio i/o 00183 // interface. It presents a common API for the user to call but all 00184 // functionality is implemented by the class RtApi and its 00185 // subclasses. RtAudio creates an instance of an RtApi subclass 00186 // based on the user's API choice. If no choice is made, RtAudio 00187 // attempts to make a "logical" API selection. 00188 // 00189 // **************************************************************** // 00190 00191 class RtApi; 00192 00193 class RtAudio 00194 { 00195 public: 00196 00198 enum Api { 00199 UNSPECIFIED, 00200 LINUX_ALSA, 00201 LINUX_OSS, 00202 UNIX_JACK, 00203 MACOSX_CORE, 00204 WINDOWS_ASIO, 00205 WINDOWS_DS, 00206 RTAUDIO_DUMMY 00207 }; 00208 00210 struct DeviceInfo { 00211 bool probed; 00212 std::string name; 00213 unsigned int outputChannels; 00214 unsigned int inputChannels; 00215 unsigned int duplexChannels; 00216 bool isDefaultOutput; 00217 bool isDefaultInput; 00218 std::vector<unsigned int> sampleRates; 00219 RtAudioFormat nativeFormats; 00221 // Default constructor. 00222 DeviceInfo() 00223 :probed(false), outputChannels(0), inputChannels(0), duplexChannels(0), 00224 isDefaultOutput(false), isDefaultInput(false), nativeFormats(0) {} 00225 }; 00226 00228 struct StreamParameters { 00229 unsigned int deviceId; 00230 unsigned int nChannels; 00231 unsigned int firstChannel; 00233 // Default constructor. 00234 StreamParameters() 00235 : deviceId(0), nChannels(0), firstChannel(0) {} 00236 }; 00237 00239 00284 struct StreamOptions { 00285 RtAudioStreamFlags flags; 00286 unsigned int numberOfBuffers; 00287 std::string streamName; 00289 // Default constructor. 00290 StreamOptions() 00291 : flags(0), numberOfBuffers(0) {} 00292 }; 00293 00295 00300 static void getCompiledApi( std::vector<RtAudio::Api> &apis ) throw(); 00301 00303 00311 RtAudio( RtAudio::Api api=UNSPECIFIED ) throw(); 00312 00314 00318 ~RtAudio() throw(); 00319 00321 RtAudio::Api getCurrentApi( void ) throw(); 00322 00324 00329 unsigned int getDeviceCount( void ) throw(); 00330 00332 00342 RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); 00343 00345 00352 unsigned int getDefaultOutputDevice( void ) throw(); 00353 00355 00362 unsigned int getDefaultInputDevice( void ) throw(); 00363 00365 00402 void openStream( RtAudio::StreamParameters *outputParameters, 00403 RtAudio::StreamParameters *inputParameters, 00404 RtAudioFormat format, unsigned int sampleRate, 00405 unsigned int *bufferFrames, RtAudioCallback callback, 00406 void *userData = NULL, RtAudio::StreamOptions *options = NULL ); 00407 00409 00413 void closeStream( void ) throw(); 00414 00416 00422 void startStream( void ); 00423 00425 00431 void stopStream( void ); 00432 00434 00440 void abortStream( void ); 00441 00443 bool isStreamOpen( void ) throw(); 00444 00446 bool isStreamRunning( void ) throw(); 00447 00449 00452 double getStreamTime( void ); 00453 00455 00463 long getStreamLatency( void ); 00464 00466 void showWarnings( bool value = true ) throw(); 00467 00468 protected: 00469 00470 void openRtApi( RtAudio::Api api ); 00471 RtApi *rtapi_; 00472 }; 00473 00474 // Operating system dependent thread functionality. 00475 #if defined(__WINDOWS_DS__) || defined(__WINDOWS_ASIO__) 00476 #include <windows.h> 00477 #include <process.h> 00478 00479 typedef unsigned long ThreadHandle; 00480 typedef CRITICAL_SECTION StreamMutex; 00481 00482 #elif defined(__LINUX_ALSA__) || defined(__UNIX_JACK__) || defined(__LINUX_OSS__) || defined(__MACOSX_CORE__) 00483 // Using pthread library for various flavors of unix. 00484 #include <pthread.h> 00485 00486 typedef pthread_t ThreadHandle; 00487 typedef pthread_mutex_t StreamMutex; 00488 00489 #else // Setup for "dummy" behavior 00490 00491 #define __RTAUDIO_DUMMY__ 00492 typedef int ThreadHandle; 00493 typedef int StreamMutex; 00494 00495 #endif 00496 00497 // This global structure type is used to pass callback information 00498 // between the private RtAudio stream structure and global callback 00499 // handling functions. 00500 struct CallbackInfo { 00501 void *object; // Used as a "this" pointer. 00502 ThreadHandle thread; 00503 void *callback; 00504 void *userData; 00505 void *apiInfo; // void pointer for API specific callback information 00506 bool isRunning; 00507 00508 // Default constructor. 00509 CallbackInfo() 00510 :object(0), callback(0), userData(0), apiInfo(0), isRunning(false) {} 00511 }; 00512 00513 // **************************************************************** // 00514 // 00515 // RtApi class declaration. 00516 // 00517 // Subclasses of RtApi contain all API- and OS-specific code necessary 00518 // to fully implement the RtAudio API. 00519 // 00520 // Note that RtApi is an abstract base class and cannot be 00521 // explicitly instantiated. The class RtAudio will create an 00522 // instance of an RtApi subclass (RtApiOss, RtApiAlsa, 00523 // RtApiJack, RtApiCore, RtApiAl, RtApiDs, or RtApiAsio). 00524 // 00525 // **************************************************************** // 00526 00527 #if defined( HAVE_GETTIMEOFDAY ) 00528 #include <sys/time.h> 00529 #endif 00530 00531 #include <sstream> 00532 00533 class RtApi 00534 { 00535 public: 00536 00537 RtApi(); 00538 virtual ~RtApi(); 00539 virtual RtAudio::Api getCurrentApi( void ) = 0; 00540 virtual unsigned int getDeviceCount( void ) = 0; 00541 virtual RtAudio::DeviceInfo getDeviceInfo( unsigned int device ) = 0; 00542 virtual unsigned int getDefaultInputDevice( void ); 00543 virtual unsigned int getDefaultOutputDevice( void ); 00544 void openStream( RtAudio::StreamParameters *outputParameters, 00545 RtAudio::StreamParameters *inputParameters, 00546 RtAudioFormat format, unsigned int sampleRate, 00547 unsigned int *bufferFrames, RtAudioCallback callback, 00548 void *userData, RtAudio::StreamOptions *options ); 00549 virtual void closeStream( void ); 00550 virtual void startStream( void ) = 0; 00551 virtual void stopStream( void ) = 0; 00552 virtual void abortStream( void ) = 0; 00553 long getStreamLatency( void ); 00554 virtual double getStreamTime( void ); 00555 bool isStreamOpen( void ) { return stream_.state != STREAM_CLOSED; }; 00556 bool isStreamRunning( void ) { return stream_.state == STREAM_RUNNING; }; 00557 void showWarnings( bool value ) { showWarnings_ = value; }; 00558 00559 00560 protected: 00561 00562 static const unsigned int MAX_SAMPLE_RATES; 00563 static const unsigned int SAMPLE_RATES[]; 00564 00565 enum { FAILURE, SUCCESS }; 00566 00567 enum StreamState { 00568 STREAM_STOPPED, 00569 STREAM_RUNNING, 00570 STREAM_CLOSED = -50 00571 }; 00572 00573 enum StreamMode { 00574 OUTPUT, 00575 INPUT, 00576 DUPLEX, 00577 UNINITIALIZED = -75 00578 }; 00579 00580 // A protected structure used for buffer conversion. 00581 struct ConvertInfo { 00582 int channels; 00583 int inJump, outJump; 00584 RtAudioFormat inFormat, outFormat; 00585 std::vector<int> inOffset; 00586 std::vector<int> outOffset; 00587 }; 00588 00589 // A protected structure for audio streams. 00590 struct RtApiStream { 00591 unsigned int device[2]; // Playback and record, respectively. 00592 void *apiHandle; // void pointer for API specific stream handle information 00593 StreamMode mode; // OUTPUT, INPUT, or DUPLEX. 00594 StreamState state; // STOPPED, RUNNING, or CLOSED 00595 char *userBuffer[2]; // Playback and record, respectively. 00596 char *deviceBuffer; 00597 bool doConvertBuffer[2]; // Playback and record, respectively. 00598 bool userInterleaved; 00599 bool deviceInterleaved[2]; // Playback and record, respectively. 00600 bool doByteSwap[2]; // Playback and record, respectively. 00601 unsigned int sampleRate; 00602 unsigned int bufferSize; 00603 unsigned int nBuffers; 00604 unsigned int nUserChannels[2]; // Playback and record, respectively. 00605 unsigned int nDeviceChannels[2]; // Playback and record channels, respectively. 00606 unsigned int channelOffset[2]; // Playback and record, respectively. 00607 unsigned long latency[2]; // Playback and record, respectively. 00608 RtAudioFormat userFormat; 00609 RtAudioFormat deviceFormat[2]; // Playback and record, respectively. 00610 StreamMutex mutex; 00611 CallbackInfo callbackInfo; 00612 ConvertInfo convertInfo[2]; 00613 double streamTime; // Number of elapsed seconds since the stream started. 00614 00615 #if defined(HAVE_GETTIMEOFDAY) 00616 struct timeval lastTickTimestamp; 00617 #endif 00618 00619 RtApiStream() 00620 :apiHandle(0), deviceBuffer(0) {} 00621 }; 00622 00623 typedef signed short Int16; 00624 typedef signed int Int32; 00625 typedef float Float32; 00626 typedef double Float64; 00627 00628 std::ostringstream errorStream_; 00629 std::string errorText_; 00630 bool showWarnings_; 00631 RtApiStream stream_; 00632 00640 virtual bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, 00641 unsigned int firstChannel, unsigned int sampleRate, 00642 RtAudioFormat format, unsigned int *bufferSize, 00643 RtAudio::StreamOptions *options ); 00644 00646 void tickStreamTime( void ); 00647 00649 void clearStreamInfo(); 00650 00655 void verifyStream( void ); 00656 00658 void error( RtError::Type type ); 00659 00664 void convertBuffer( char *outBuffer, char *inBuffer, ConvertInfo &info ); 00665 00667 void byteSwapBuffer( char *buffer, unsigned int samples, RtAudioFormat format ); 00668 00670 unsigned int formatBytes( RtAudioFormat format ); 00671 00673 void setConvertInfo( StreamMode mode, unsigned int firstChannel ); 00674 }; 00675 00676 // **************************************************************** // 00677 // 00678 // Inline RtAudio definitions. 00679 // 00680 // **************************************************************** // 00681 00682 inline RtAudio::Api RtAudio :: getCurrentApi( void ) throw() { return rtapi_->getCurrentApi(); }; 00683 inline unsigned int RtAudio :: getDeviceCount( void ) throw() { return rtapi_->getDeviceCount(); }; 00684 inline RtAudio::DeviceInfo RtAudio :: getDeviceInfo( unsigned int device ) { return rtapi_->getDeviceInfo( device ); }; 00685 inline unsigned int RtAudio :: getDefaultInputDevice( void ) throw() { return rtapi_->getDefaultInputDevice(); }; 00686 inline unsigned int RtAudio :: getDefaultOutputDevice( void ) throw() { return rtapi_->getDefaultOutputDevice(); }; 00687 inline void RtAudio :: closeStream( void ) throw() { return rtapi_->closeStream(); }; 00688 inline void RtAudio :: startStream( void ) { return rtapi_->startStream(); }; 00689 inline void RtAudio :: stopStream( void ) { return rtapi_->stopStream(); }; 00690 inline void RtAudio :: abortStream( void ) { return rtapi_->abortStream(); }; 00691 inline bool RtAudio :: isStreamOpen( void ) throw() { return rtapi_->isStreamOpen(); }; 00692 inline bool RtAudio :: isStreamRunning( void ) throw() { return rtapi_->isStreamRunning(); }; 00693 inline long RtAudio :: getStreamLatency( void ) { return rtapi_->getStreamLatency(); }; 00694 inline double RtAudio :: getStreamTime( void ) { return rtapi_->getStreamTime(); }; 00695 inline void RtAudio :: showWarnings( bool value ) throw() { rtapi_->showWarnings( value ); }; 00696 00697 // RtApi Subclass prototypes. 00698 00699 #if defined(__MACOSX_CORE__) 00700 00701 #include <CoreAudio/AudioHardware.h> 00702 00703 class RtApiCore: public RtApi 00704 { 00705 public: 00706 00707 RtApiCore(); 00708 ~RtApiCore(); 00709 RtAudio::Api getCurrentApi( void ) { return RtAudio::MACOSX_CORE; }; 00710 unsigned int getDeviceCount( void ); 00711 RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); 00712 unsigned int getDefaultOutputDevice( void ); 00713 unsigned int getDefaultInputDevice( void ); 00714 void closeStream( void ); 00715 void startStream( void ); 00716 void stopStream( void ); 00717 void abortStream( void ); 00718 long getStreamLatency( void ); 00719 00720 // This function is intended for internal use only. It must be 00721 // public because it is called by the internal callback handler, 00722 // which is not a member of RtAudio. External use of this function 00723 // will most likely produce highly undesireable results! 00724 bool callbackEvent( AudioDeviceID deviceId, 00725 const AudioBufferList *inBufferList, 00726 const AudioBufferList *outBufferList ); 00727 00728 private: 00729 00730 bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, 00731 unsigned int firstChannel, unsigned int sampleRate, 00732 RtAudioFormat format, unsigned int *bufferSize, 00733 RtAudio::StreamOptions *options ); 00734 static const char* getErrorCode( OSStatus code ); 00735 }; 00736 00737 #endif 00738 00739 #if defined(__UNIX_JACK__) 00740 00741 class RtApiJack: public RtApi 00742 { 00743 public: 00744 00745 RtApiJack(); 00746 ~RtApiJack(); 00747 RtAudio::Api getCurrentApi( void ) { return RtAudio::UNIX_JACK; }; 00748 unsigned int getDeviceCount( void ); 00749 RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); 00750 void closeStream( void ); 00751 void startStream( void ); 00752 void stopStream( void ); 00753 void abortStream( void ); 00754 long getStreamLatency( void ); 00755 00756 // This function is intended for internal use only. It must be 00757 // public because it is called by the internal callback handler, 00758 // which is not a member of RtAudio. External use of this function 00759 // will most likely produce highly undesireable results! 00760 bool callbackEvent( unsigned long nframes ); 00761 00762 private: 00763 00764 bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, 00765 unsigned int firstChannel, unsigned int sampleRate, 00766 RtAudioFormat format, unsigned int *bufferSize, 00767 RtAudio::StreamOptions *options ); 00768 }; 00769 00770 #endif 00771 00772 #if defined(__WINDOWS_ASIO__) 00773 00774 class RtApiAsio: public RtApi 00775 { 00776 public: 00777 00778 RtApiAsio(); 00779 ~RtApiAsio(); 00780 RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_ASIO; }; 00781 unsigned int getDeviceCount( void ); 00782 RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); 00783 void closeStream( void ); 00784 void startStream( void ); 00785 void stopStream( void ); 00786 void abortStream( void ); 00787 long getStreamLatency( void ); 00788 00789 // This function is intended for internal use only. It must be 00790 // public because it is called by the internal callback handler, 00791 // which is not a member of RtAudio. External use of this function 00792 // will most likely produce highly undesireable results! 00793 bool callbackEvent( long bufferIndex ); 00794 00795 private: 00796 00797 bool coInitialized_; 00798 bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, 00799 unsigned int firstChannel, unsigned int sampleRate, 00800 RtAudioFormat format, unsigned int *bufferSize, 00801 RtAudio::StreamOptions *options ); 00802 }; 00803 00804 #endif 00805 00806 #if defined(__WINDOWS_DS__) 00807 00808 class RtApiDs: public RtApi 00809 { 00810 public: 00811 00812 RtApiDs(); 00813 ~RtApiDs(); 00814 RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_DS; }; 00815 unsigned int getDeviceCount( void ); 00816 unsigned int getDefaultOutputDevice( void ); 00817 unsigned int getDefaultInputDevice( void ); 00818 RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); 00819 void closeStream( void ); 00820 void startStream( void ); 00821 void stopStream( void ); 00822 void abortStream( void ); 00823 long getStreamLatency( void ); 00824 00825 // This function is intended for internal use only. It must be 00826 // public because it is called by the internal callback handler, 00827 // which is not a member of RtAudio. External use of this function 00828 // will most likely produce highly undesireable results! 00829 void callbackEvent( void ); 00830 00831 private: 00832 00833 bool coInitialized_; 00834 bool buffersRolling; 00835 long duplexPrerollBytes; 00836 bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, 00837 unsigned int firstChannel, unsigned int sampleRate, 00838 RtAudioFormat format, unsigned int *bufferSize, 00839 RtAudio::StreamOptions *options ); 00840 }; 00841 00842 #endif 00843 00844 #if defined(__LINUX_ALSA__) 00845 00846 class RtApiAlsa: public RtApi 00847 { 00848 public: 00849 00850 RtApiAlsa(); 00851 ~RtApiAlsa(); 00852 RtAudio::Api getCurrentApi() { return RtAudio::LINUX_ALSA; }; 00853 unsigned int getDeviceCount( void ); 00854 RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); 00855 void closeStream( void ); 00856 void startStream( void ); 00857 void stopStream( void ); 00858 void abortStream( void ); 00859 00860 // This function is intended for internal use only. It must be 00861 // public because it is called by the internal callback handler, 00862 // which is not a member of RtAudio. External use of this function 00863 // will most likely produce highly undesireable results! 00864 void callbackEvent( void ); 00865 00866 private: 00867 00868 bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, 00869 unsigned int firstChannel, unsigned int sampleRate, 00870 RtAudioFormat format, unsigned int *bufferSize, 00871 RtAudio::StreamOptions *options ); 00872 }; 00873 00874 #endif 00875 00876 #if defined(__LINUX_OSS__) 00877 00878 class RtApiOss: public RtApi 00879 { 00880 public: 00881 00882 RtApiOss(); 00883 ~RtApiOss(); 00884 RtAudio::Api getCurrentApi() { return RtAudio::LINUX_OSS; }; 00885 unsigned int getDeviceCount( void ); 00886 RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); 00887 void closeStream( void ); 00888 void startStream( void ); 00889 void stopStream( void ); 00890 void abortStream( void ); 00891 00892 // This function is intended for internal use only. It must be 00893 // public because it is called by the internal callback handler, 00894 // which is not a member of RtAudio. External use of this function 00895 // will most likely produce highly undesireable results! 00896 void callbackEvent( void ); 00897 00898 private: 00899 00900 bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, 00901 unsigned int firstChannel, unsigned int sampleRate, 00902 RtAudioFormat format, unsigned int *bufferSize, 00903 RtAudio::StreamOptions *options ); 00904 }; 00905 00906 #endif 00907 00908 #if defined(__RTAUDIO_DUMMY__) 00909 00910 class RtApiDummy: public RtApi 00911 { 00912 public: 00913 00914 RtApiDummy() { errorText_ = "RtApiDummy: This class provides no functionality."; error( RtError::WARNING ); }; 00915 RtAudio::Api getCurrentApi( void ) { return RtAudio::RTAUDIO_DUMMY; }; 00916 unsigned int getDeviceCount( void ) { return 0; }; 00917 RtAudio::DeviceInfo getDeviceInfo( unsigned int device ) { RtAudio::DeviceInfo info; return info; }; 00918 void closeStream( void ) {}; 00919 void startStream( void ) {}; 00920 void stopStream( void ) {}; 00921 void abortStream( void ) {}; 00922 00923 private: 00924 00925 bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, 00926 unsigned int firstChannel, unsigned int sampleRate, 00927 RtAudioFormat format, unsigned int *bufferSize, 00928 RtAudio::StreamOptions *options ) { return false; }; 00929 }; 00930 00931 #endif 00932 00933 #endif 00934 00935 // Indentation settings for Vim and Emacs 00936 // 00937 // Local Variables: 00938 // c-basic-offset: 2 00939 // indent-tabs-mode: nil 00940 // End: 00941 // 00942 // vim: et sts=2 sw=2
![]() |
©2001-2007 Gary P. Scavone, McGill University. All Rights Reserved. Maintained by Gary P. Scavone. |