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 ErrorType { 00568 WARNING, 00569 INVALID_CALL, 00570 SYSTEM 00571 }; 00572 00573 enum StreamState { 00574 STREAM_STOPPED, 00575 STREAM_RUNNING, 00576 STREAM_CLOSED = -50 00577 }; 00578 00579 enum StreamMode { 00580 OUTPUT, 00581 INPUT, 00582 DUPLEX, 00583 UNINITIALIZED = -75 00584 }; 00585 00586 // A protected structure used for buffer conversion. 00587 struct ConvertInfo { 00588 int channels; 00589 int inJump, outJump; 00590 RtAudioFormat inFormat, outFormat; 00591 std::vector<int> inOffset; 00592 std::vector<int> outOffset; 00593 }; 00594 00595 // A protected structure for audio streams. 00596 struct RtApiStream { 00597 unsigned int device[2]; // Playback and record, respectively. 00598 void *apiHandle; // void pointer for API specific stream handle information 00599 StreamMode mode; // OUTPUT, INPUT, or DUPLEX. 00600 StreamState state; // STOPPED, RUNNING, or CLOSED 00601 char *userBuffer[2]; // Playback and record, respectively. 00602 char *deviceBuffer; 00603 bool doConvertBuffer[2]; // Playback and record, respectively. 00604 bool userInterleaved; 00605 bool deviceInterleaved[2]; // Playback and record, respectively. 00606 bool doByteSwap[2]; // Playback and record, respectively. 00607 unsigned int sampleRate; 00608 unsigned int bufferSize; 00609 unsigned int nBuffers; 00610 unsigned int nUserChannels[2]; // Playback and record, respectively. 00611 unsigned int nDeviceChannels[2]; // Playback and record channels, respectively. 00612 unsigned int channelOffset[2]; // Playback and record, respectively. 00613 unsigned long latency[2]; // Playback and record, respectively. 00614 RtAudioFormat userFormat; 00615 RtAudioFormat deviceFormat[2]; // Playback and record, respectively. 00616 StreamMutex mutex; 00617 CallbackInfo callbackInfo; 00618 ConvertInfo convertInfo[2]; 00619 double streamTime; // Number of elapsed seconds since the stream started. 00620 00621 #if defined(HAVE_GETTIMEOFDAY) 00622 struct timeval lastTickTimestamp; 00623 #endif 00624 00625 RtApiStream() 00626 :apiHandle(0), deviceBuffer(0) {} 00627 }; 00628 00629 typedef signed short Int16; 00630 typedef signed int Int32; 00631 typedef float Float32; 00632 typedef double Float64; 00633 00634 std::ostringstream errorStream_; 00635 std::string errorText_; 00636 bool showWarnings_; 00637 RtApiStream stream_; 00638 00646 virtual bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, 00647 unsigned int firstChannel, unsigned int sampleRate, 00648 RtAudioFormat format, unsigned int *bufferSize, 00649 RtAudio::StreamOptions *options ); 00650 00652 void tickStreamTime( void ); 00653 00655 void clearStreamInfo(); 00656 00661 void verifyStream( void ); 00662 00664 void error( ErrorType type ); 00665 00670 void convertBuffer( char *outBuffer, char *inBuffer, ConvertInfo &info ); 00671 00673 void byteSwapBuffer( char *buffer, unsigned int samples, RtAudioFormat format ); 00674 00676 unsigned int formatBytes( RtAudioFormat format ); 00677 00679 void setConvertInfo( StreamMode mode, unsigned int firstChannel ); 00680 }; 00681 00682 // **************************************************************** // 00683 // 00684 // Inline RtAudio definitions. 00685 // 00686 // **************************************************************** // 00687 00688 inline RtAudio::Api RtAudio :: getCurrentApi( void ) throw() { return rtapi_->getCurrentApi(); }; 00689 inline unsigned int RtAudio :: getDeviceCount( void ) throw() { return rtapi_->getDeviceCount(); }; 00690 inline RtAudio::DeviceInfo RtAudio :: getDeviceInfo( unsigned int device ) { return rtapi_->getDeviceInfo( device ); }; 00691 inline unsigned int RtAudio :: getDefaultInputDevice( void ) throw() { return rtapi_->getDefaultInputDevice(); }; 00692 inline unsigned int RtAudio :: getDefaultOutputDevice( void ) throw() { return rtapi_->getDefaultOutputDevice(); }; 00693 inline void RtAudio :: closeStream( void ) throw() { return rtapi_->closeStream(); }; 00694 inline void RtAudio :: startStream( void ) { return rtapi_->startStream(); }; 00695 inline void RtAudio :: stopStream( void ) { return rtapi_->stopStream(); }; 00696 inline void RtAudio :: abortStream( void ) { return rtapi_->abortStream(); }; 00697 inline bool RtAudio :: isStreamOpen( void ) throw() { return rtapi_->isStreamOpen(); }; 00698 inline bool RtAudio :: isStreamRunning( void ) throw() { return rtapi_->isStreamRunning(); }; 00699 inline long RtAudio :: getStreamLatency( void ) { return rtapi_->getStreamLatency(); }; 00700 inline double RtAudio :: getStreamTime( void ) { return rtapi_->getStreamTime(); }; 00701 inline void RtAudio :: showWarnings( bool value ) throw() { rtapi_->showWarnings( value ); }; 00702 00703 // RtApi Subclass prototypes. 00704 00705 #if defined(__MACOSX_CORE__) 00706 00707 #include <CoreAudio/AudioHardware.h> 00708 00709 class RtApiCore: public RtApi 00710 { 00711 public: 00712 00713 RtApiCore(); 00714 ~RtApiCore(); 00715 RtAudio::Api getCurrentApi( void ) { return RtAudio::MACOSX_CORE; }; 00716 unsigned int getDeviceCount( void ); 00717 RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); 00718 unsigned int getDefaultOutputDevice( void ); 00719 unsigned int getDefaultInputDevice( void ); 00720 void closeStream( void ); 00721 void startStream( void ); 00722 void stopStream( void ); 00723 void abortStream( void ); 00724 long getStreamLatency( void ); 00725 00726 // This function is intended for internal use only. It must be 00727 // public because it is called by the internal callback handler, 00728 // which is not a member of RtAudio. External use of this function 00729 // will most likely produce highly undesireable results! 00730 bool callbackEvent( AudioDeviceID deviceId, 00731 const AudioBufferList *inBufferList, 00732 const AudioBufferList *outBufferList ); 00733 00734 private: 00735 00736 bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, 00737 unsigned int firstChannel, unsigned int sampleRate, 00738 RtAudioFormat format, unsigned int *bufferSize, 00739 RtAudio::StreamOptions *options ); 00740 static const char* getErrorCode( OSStatus code ); 00741 }; 00742 00743 #endif 00744 00745 #if defined(__UNIX_JACK__) 00746 00747 class RtApiJack: public RtApi 00748 { 00749 public: 00750 00751 RtApiJack(); 00752 ~RtApiJack(); 00753 RtAudio::Api getCurrentApi( void ) { return RtAudio::UNIX_JACK; }; 00754 unsigned int getDeviceCount( void ); 00755 RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); 00756 void closeStream( void ); 00757 void startStream( void ); 00758 void stopStream( void ); 00759 void abortStream( void ); 00760 long getStreamLatency( void ); 00761 00762 // This function is intended for internal use only. It must be 00763 // public because it is called by the internal callback handler, 00764 // which is not a member of RtAudio. External use of this function 00765 // will most likely produce highly undesireable results! 00766 bool callbackEvent( unsigned long nframes ); 00767 00768 private: 00769 00770 bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, 00771 unsigned int firstChannel, unsigned int sampleRate, 00772 RtAudioFormat format, unsigned int *bufferSize, 00773 RtAudio::StreamOptions *options ); 00774 }; 00775 00776 #endif 00777 00778 #if defined(__WINDOWS_ASIO__) 00779 00780 class RtApiAsio: public RtApi 00781 { 00782 public: 00783 00784 RtApiAsio(); 00785 ~RtApiAsio(); 00786 RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_ASIO; }; 00787 unsigned int getDeviceCount( void ); 00788 RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); 00789 void closeStream( void ); 00790 void startStream( void ); 00791 void stopStream( void ); 00792 void abortStream( void ); 00793 long getStreamLatency( void ); 00794 00795 // This function is intended for internal use only. It must be 00796 // public because it is called by the internal callback handler, 00797 // which is not a member of RtAudio. External use of this function 00798 // will most likely produce highly undesireable results! 00799 bool callbackEvent( long bufferIndex ); 00800 00801 private: 00802 00803 bool coInitialized_; 00804 bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, 00805 unsigned int firstChannel, unsigned int sampleRate, 00806 RtAudioFormat format, unsigned int *bufferSize, 00807 RtAudio::StreamOptions *options ); 00808 }; 00809 00810 #endif 00811 00812 #if defined(__WINDOWS_DS__) 00813 00814 class RtApiDs: public RtApi 00815 { 00816 public: 00817 00818 RtApiDs(); 00819 ~RtApiDs(); 00820 RtAudio::Api getCurrentApi( void ) { return RtAudio::WINDOWS_DS; }; 00821 unsigned int getDeviceCount( void ); 00822 unsigned int getDefaultOutputDevice( void ); 00823 unsigned int getDefaultInputDevice( void ); 00824 RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); 00825 void closeStream( void ); 00826 void startStream( void ); 00827 void stopStream( void ); 00828 void abortStream( void ); 00829 long getStreamLatency( void ); 00830 00831 // This function is intended for internal use only. It must be 00832 // public because it is called by the internal callback handler, 00833 // which is not a member of RtAudio. External use of this function 00834 // will most likely produce highly undesireable results! 00835 void callbackEvent( void ); 00836 00837 private: 00838 00839 bool coInitialized_; 00840 bool buffersRolling; 00841 long duplexPrerollBytes; 00842 bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, 00843 unsigned int firstChannel, unsigned int sampleRate, 00844 RtAudioFormat format, unsigned int *bufferSize, 00845 RtAudio::StreamOptions *options ); 00846 }; 00847 00848 #endif 00849 00850 #if defined(__LINUX_ALSA__) 00851 00852 class RtApiAlsa: public RtApi 00853 { 00854 public: 00855 00856 RtApiAlsa(); 00857 ~RtApiAlsa(); 00858 RtAudio::Api getCurrentApi() { return RtAudio::LINUX_ALSA; }; 00859 unsigned int getDeviceCount( void ); 00860 RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); 00861 void closeStream( void ); 00862 void startStream( void ); 00863 void stopStream( void ); 00864 void abortStream( void ); 00865 00866 // This function is intended for internal use only. It must be 00867 // public because it is called by the internal callback handler, 00868 // which is not a member of RtAudio. External use of this function 00869 // will most likely produce highly undesireable results! 00870 void callbackEvent( void ); 00871 00872 private: 00873 00874 bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, 00875 unsigned int firstChannel, unsigned int sampleRate, 00876 RtAudioFormat format, unsigned int *bufferSize, 00877 RtAudio::StreamOptions *options ); 00878 }; 00879 00880 #endif 00881 00882 #if defined(__LINUX_OSS__) 00883 00884 class RtApiOss: public RtApi 00885 { 00886 public: 00887 00888 RtApiOss(); 00889 ~RtApiOss(); 00890 RtAudio::Api getCurrentApi() { return RtAudio::LINUX_OSS; }; 00891 unsigned int getDeviceCount( void ); 00892 RtAudio::DeviceInfo getDeviceInfo( unsigned int device ); 00893 void closeStream( void ); 00894 void startStream( void ); 00895 void stopStream( void ); 00896 void abortStream( void ); 00897 00898 // This function is intended for internal use only. It must be 00899 // public because it is called by the internal callback handler, 00900 // which is not a member of RtAudio. External use of this function 00901 // will most likely produce highly undesireable results! 00902 void callbackEvent( void ); 00903 00904 private: 00905 00906 bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, 00907 unsigned int firstChannel, unsigned int sampleRate, 00908 RtAudioFormat format, unsigned int *bufferSize, 00909 RtAudio::StreamOptions *options ); 00910 }; 00911 00912 #endif 00913 00914 #if defined(__RTAUDIO_DUMMY__) 00915 00916 class RtApiDummy: public RtApi 00917 { 00918 public: 00919 00920 RtApiDummy() { errorText_ = "RtApiDummy: This class provides no functionality."; error( WARNING ); }; 00921 RtAudio::Api getCurrentApi( void ) { return RtAudio::RTAUDIO_DUMMY; }; 00922 unsigned int getDeviceCount( void ) { return 0; }; 00923 RtAudio::DeviceInfo getDeviceInfo( unsigned int device ) { RtAudio::DeviceInfo info; return info; }; 00924 void closeStream( void ) {}; 00925 void startStream( void ) {}; 00926 void stopStream( void ) {}; 00927 void abortStream( void ) {}; 00928 00929 private: 00930 00931 bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, 00932 unsigned int firstChannel, unsigned int sampleRate, 00933 RtAudioFormat format, unsigned int *bufferSize, 00934 RtAudio::StreamOptions *options ) { return false; }; 00935 }; 00936 00937 #endif 00938 00939 #endif 00940 00941 // Indentation settings for Vim and Emacs 00942 // 00943 // Local Variables: 00944 // c-basic-offset: 2 00945 // indent-tabs-mode: nil 00946 // End: 00947 // 00948 // vim: et sts=2 sw=2
![]() |
©2001-2007 Gary P. Scavone, McGill University. All Rights Reserved. Maintained by Gary P. Scavone. |