Home   Class/Enum List   File List   Compound Members  

RtAudio.h

Go to the documentation of this file.
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.