Version 2.1
[rtaudio-cdist.git] / RtAudio.h
1 /************************************************************************/
2 /*! \class RtAudio
3     \brief Realtime audio i/o C++ class.
4
5     RtAudio provides a common API (Application Programming Interface)
6     for realtime audio input/output across Linux (native ALSA and
7     OSS), SGI, Macintosh OS X (CoreAudio), and Windows (DirectSound
8     and ASIO) operating systems.
9
10     RtAudio WWW site: http://www-ccrma.stanford.edu/~gary/rtaudio/
11
12     RtAudio: a realtime audio i/o C++ class
13     Copyright (c) 2001-2002 Gary P. Scavone
14
15     Permission is hereby granted, free of charge, to any person
16     obtaining a copy of this software and associated documentation files
17     (the "Software"), to deal in the Software without restriction,
18     including without limitation the rights to use, copy, modify, merge,
19     publish, distribute, sublicense, and/or sell copies of the Software,
20     and to permit persons to whom the Software is furnished to do so,
21     subject to the following conditions:
22
23     The above copyright notice and this permission notice shall be
24     included in all copies or substantial portions of the Software.
25
26     Any person wishing to distribute modifications to the Software is
27     requested to send the modifications to the original developer so that
28     they can be incorporated into the canonical version.
29
30     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
31     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
32     MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
33     IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
34     ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
35     CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
36     WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 */
38 /************************************************************************/
39
40 #if !defined(__RTAUDIO_H)
41 #define __RTAUDIO_H
42
43 #include <map>
44
45 #if defined(__LINUX_ALSA__)
46   #include <alsa/asoundlib.h>
47   #include <pthread.h>
48   #include <unistd.h>
49
50   typedef snd_pcm_t *AUDIO_HANDLE;
51   typedef int DEVICE_ID;
52   typedef pthread_t THREAD_HANDLE;
53   typedef pthread_mutex_t MUTEX;
54
55 #elif defined(__LINUX_OSS__)
56   #include <pthread.h>
57   #include <unistd.h>
58
59   typedef int AUDIO_HANDLE;
60   typedef int DEVICE_ID;
61   typedef pthread_t THREAD_HANDLE;
62   typedef pthread_mutex_t MUTEX;
63
64 #elif defined(__WINDOWS_DS__)
65   #include <windows.h>
66   #include <process.h>
67
68   // The following struct is used to hold the extra variables
69   // specific to the DirectSound implementation.
70   typedef struct {
71     void * object;
72     void * buffer;
73     UINT bufferPointer;
74   } AUDIO_HANDLE;
75
76   typedef LPGUID DEVICE_ID;
77   typedef unsigned long THREAD_HANDLE;
78   typedef CRITICAL_SECTION MUTEX;
79
80 #elif defined(__WINDOWS_ASIO__)
81   #include <windows.h>
82   #include <process.h>
83
84   typedef int AUDIO_HANDLE;
85   typedef int DEVICE_ID;
86   typedef unsigned long THREAD_HANDLE;
87   typedef CRITICAL_SECTION MUTEX;
88
89 #elif defined(__IRIX_AL__)
90   #include <dmedia/audio.h>
91   #include <pthread.h>
92   #include <unistd.h>
93
94   typedef ALport AUDIO_HANDLE;
95   typedef long DEVICE_ID;
96   typedef pthread_t THREAD_HANDLE;
97   typedef pthread_mutex_t MUTEX;
98
99 #elif defined(__MACOSX_CORE__)
100
101   #include <CoreAudio/AudioHardware.h>
102   #include <pthread.h>
103
104   typedef unsigned int AUDIO_HANDLE;
105   typedef AudioDeviceID DEVICE_ID;
106   typedef pthread_t THREAD_HANDLE;
107   typedef pthread_mutex_t MUTEX;
108
109 #endif
110
111
112 /************************************************************************/
113 /*! \class RtError
114     \brief Exception handling class for RtAudio.
115
116     The RtError class is quite simple but it does allow errors to be
117     "caught" by RtError::TYPE. Almost all RtAudio methods can "throw"
118     an RtError, most typically if an invalid stream identifier is
119     supplied to a method or a driver error occurs. There are a number
120     of cases within RtAudio where warning messages may be displayed
121     but an exception is not thrown. There is a private RtAudio method,
122     error(), which can be modified to globally control how these
123     messages are handled and reported.
124 */
125 /************************************************************************/
126
127 class RtError
128 {
129 public:
130   //! Defined RtError types.
131   enum TYPE {
132     WARNING,
133     DEBUG_WARNING,
134     UNSPECIFIED,
135     NO_DEVICES_FOUND,
136     INVALID_DEVICE,
137     INVALID_STREAM,
138     MEMORY_ERROR,
139     INVALID_PARAMETER,
140     DRIVER_ERROR,
141     SYSTEM_ERROR,
142     THREAD_ERROR
143   };
144
145 protected:
146   char error_message[256];
147   TYPE type;
148
149 public:
150   //! The constructor.
151   RtError(const char *p, TYPE tipe = RtError::UNSPECIFIED);
152
153   //! The destructor.
154   virtual ~RtError(void);
155
156   //! Prints "thrown" error message to stdout.
157   virtual void printMessage(void);
158
159   //! Returns the "thrown" error message TYPE.
160   virtual const TYPE& getType(void) { return type; }
161
162   //! Returns the "thrown" error message string.
163   virtual const char *getMessage(void) { return error_message; }
164 };
165
166
167 // This public structure type is used to pass callback information
168 // between the private RtAudio stream structure and global callback
169 // handling functions.
170 typedef struct {
171   void *object;  // Used as a "this" pointer.
172   int streamId;
173   DEVICE_ID device[2];
174   THREAD_HANDLE thread;
175   void *callback;
176   void *buffers;
177   unsigned long waitTime;
178   bool blockTick;
179   bool stopStream;
180   bool usingCallback;
181   void *userData;
182 } CALLBACK_INFO;
183
184
185 // *************************************************** //
186 //
187 // RtAudio class declaration.
188 //
189 // *************************************************** //
190
191 class RtAudio
192 {
193 public:
194
195   // Support for signed integers and floats.  Audio data fed to/from
196   // the tickStream() routine is assumed to ALWAYS be in host
197   // byte order.  The internal routines will automatically take care of
198   // any necessary byte-swapping between the host format and the
199   // soundcard.  Thus, endian-ness is not a concern in the following
200   // format definitions.
201   typedef unsigned long RTAUDIO_FORMAT;
202   static const RTAUDIO_FORMAT RTAUDIO_SINT8; /*!< 8-bit signed integer. */
203   static const RTAUDIO_FORMAT RTAUDIO_SINT16; /*!< 16-bit signed integer. */
204   static const RTAUDIO_FORMAT RTAUDIO_SINT24; /*!< Upper 3 bytes of 32-bit signed integer. */
205   static const RTAUDIO_FORMAT RTAUDIO_SINT32; /*!< 32-bit signed integer. */
206   static const RTAUDIO_FORMAT RTAUDIO_FLOAT32; /*!< Normalized between plus/minus 1.0. */
207   static const RTAUDIO_FORMAT RTAUDIO_FLOAT64; /*!< Normalized between plus/minus 1.0. */
208
209   //static const int MAX_SAMPLE_RATES = 14;
210   enum { MAX_SAMPLE_RATES = 14 };
211
212   typedef int (*RTAUDIO_CALLBACK)(char *buffer, int bufferSize, void *userData);
213
214   //! The public device information structure for passing queried values.
215   typedef struct {
216     char name[128];    /*!< Character string device identifier. */
217     DEVICE_ID id[2];  /* No value reported by getDeviceInfo(). */
218     bool probed;       /*!< true if the device capabilities were successfully probed. */
219     int maxOutputChannels; /*!< Maximum output channels supported by device. */
220     int maxInputChannels;  /*!< Maximum input channels supported by device. */
221     int maxDuplexChannels; /*!< Maximum simultaneous input/output channels supported by device. */
222     int minOutputChannels; /*!< Minimum output channels supported by device. */
223     int minInputChannels;  /*!< Minimum input channels supported by device. */
224     int minDuplexChannels; /*!< Minimum simultaneous input/output channels supported by device. */
225     bool hasDuplexSupport; /*!< true if device supports duplex mode. */
226     bool isDefault;        /*!< true if this is the default output or input device. */
227     int nSampleRates;      /*!< Number of discrete rates or -1 if range supported. */
228     int sampleRates[MAX_SAMPLE_RATES]; /*!< Supported rates or (min, max) if range. */
229     RTAUDIO_FORMAT nativeFormats;     /*!< Bit mask of supported data formats. */
230   } RTAUDIO_DEVICE;
231
232   //! The default constructor.
233   /*!
234     Probes the system to make sure at least one audio input/output
235     device is available and determines the api-specific identifier for
236     each device found.  An RtError error can be thrown if no devices
237     are found or if a memory allocation error occurs.
238   */
239   RtAudio();
240
241   //! A constructor which can be used to open a stream during instantiation.
242   /*!
243     The specified output and/or input device identifiers correspond
244     to those enumerated via the getDeviceInfo() method.  If device =
245     0, the default or first available devices meeting the given
246     parameters is selected.  If an output or input channel value is
247     zero, the corresponding device value is ignored.  When a stream is
248     successfully opened, its identifier is returned via the "streamId"
249     pointer.  An RtError can be thrown if no devices are found
250     for the given parameters, if a memory allocation error occurs, or
251     if a driver error occurs. \sa openStream()
252   */
253   RtAudio(int *streamId,
254           int outputDevice, int outputChannels,
255           int inputDevice, int inputChannels,
256           RTAUDIO_FORMAT format, int sampleRate,
257           int *bufferSize, int numberOfBuffers);
258
259   //! The destructor.
260   /*!
261     Stops and closes any open streams and devices and deallocates
262     buffer and structure memory.
263   */
264   ~RtAudio();
265
266   //! A public method for opening a stream with the specified parameters.
267   /*!
268     If successful, the opened stream ID is returned.  Otherwise, an
269     RtError is thrown.
270
271     \param outputDevice: If equal to 0, the default or first device
272            found meeting the given parameters is opened.  Otherwise, the
273            device number should correspond to one of those enumerated via
274            the getDeviceInfo() method.
275     \param outputChannels: The desired number of output channels.  If
276            equal to zero, the outputDevice identifier is ignored.
277     \param inputDevice: If equal to 0, the default or first device
278            found meeting the given parameters is opened.  Otherwise, the
279            device number should correspond to one of those enumerated via
280            the getDeviceInfo() method.
281     \param inputChannels: The desired number of input channels.  If
282            equal to zero, the inputDevice identifier is ignored.
283     \param format: An RTAUDIO_FORMAT specifying the desired sample data format.
284     \param sampleRate: The desired sample rate (sample frames per second).
285     \param *bufferSize: A pointer value indicating the desired internal buffer
286            size in sample frames.  The actual value used by the device is
287            returned via the same pointer.  A value of zero can be specified,
288            in which case the lowest allowable value is determined.
289     \param numberOfBuffers: A value which can be used to help control device
290            latency.  More buffers typically result in more robust performance,
291            though at a cost of greater latency.  A value of zero can be
292            specified, in which case the lowest allowable value is used.
293   */
294   int openStream(int outputDevice, int outputChannels,
295                  int inputDevice, int inputChannels,
296                  RTAUDIO_FORMAT format, int sampleRate,
297                  int *bufferSize, int numberOfBuffers);
298
299   //! A public method which sets a user-defined callback function for a given stream.
300   /*!
301     This method assigns a callback function to a specific,
302     previously opened stream for non-blocking stream functionality.  A
303     separate process is initiated, though the user function is called
304     only when the stream is "running" (between calls to the
305     startStream() and stopStream() methods, respectively).  The
306     callback process remains active for the duration of the stream and
307     is automatically shutdown when the stream is closed (via the
308     closeStream() method or by object destruction).  The callback
309     process can also be shutdown and the user function de-referenced
310     through an explicit call to the cancelStreamCallback() method.
311     Note that a single stream can use only blocking or callback
312     functionality at the same time, though it is possible to alternate
313     modes on the same stream through the use of the
314     setStreamCallback() and cancelStreamCallback() methods (the
315     blocking tickStream() method can be used before a callback is set
316     and/or after a callback is cancelled).  An RtError will be thrown
317     for an invalid device argument.
318   */
319   void setStreamCallback(int streamId, RTAUDIO_CALLBACK callback, void *userData);
320
321   //! A public method which cancels a callback process and function for a given stream.
322   /*!
323     This method shuts down a callback process and de-references the
324     user function for a specific stream.  Callback functionality can
325     subsequently be restarted on the stream via the
326     setStreamCallback() method.  An RtError will be thrown for an
327     invalid device argument.
328    */
329   void cancelStreamCallback(int streamId);
330
331   //! A public method which returns the number of audio devices found.
332   int getDeviceCount(void);
333
334   //! Fill a user-supplied RTAUDIO_DEVICE structure for a specified device number.
335   /*!
336     Any device integer between 1 and getDeviceCount() is valid.  If
337     a device is busy or otherwise unavailable, the structure member
338     "probed" will have a value of "false" and all other members are
339     undefined.  If the specified device is the current default input
340     or output device, the "isDefault" member will have a value of
341     "true".  An RtError will be thrown for an invalid device argument.
342   */
343   void getDeviceInfo(int device, RTAUDIO_DEVICE *info);
344
345   //! A public method which returns a pointer to the buffer for an open stream.
346   /*!
347     The user should fill and/or read the buffer data in interleaved format
348     and then call the tickStream() method.  An RtError will be
349     thrown for an invalid stream identifier.
350   */
351   char * const getStreamBuffer(int streamId);
352
353   //! Public method used to trigger processing of input/output data for a stream.
354   /*!
355     This method blocks until all buffer data is read/written.  An
356     RtError will be thrown for an invalid stream identifier or if
357     a driver error occurs.
358   */
359   void tickStream(int streamId);
360
361   //! Public method which closes a stream and frees any associated buffers.
362   /*!
363     If an invalid stream identifier is specified, this method
364     issues a warning and returns (an RtError is not thrown).
365   */
366   void closeStream(int streamId);
367
368   //! Public method which starts a stream.
369   /*!
370     An RtError will be thrown for an invalid stream identifier
371     or if a driver error occurs.
372   */
373   void startStream(int streamId);
374
375   //! Stop a stream, allowing any samples remaining in the queue to be played out and/or read in.
376   /*!
377     An RtError will be thrown for an invalid stream identifier
378     or if a driver error occurs.
379   */
380   void stopStream(int streamId);
381
382   //! Stop a stream, discarding any samples remaining in the input/output queue.
383   /*!
384     An RtError will be thrown for an invalid stream identifier
385     or if a driver error occurs.
386   */
387   void abortStream(int streamId);
388
389   //! Queries a stream to determine whether a call to the tickStream() method will block.
390   /*!
391     A return value of 0 indicates that the stream will NOT block.  A positive
392     return value indicates the number of sample frames that cannot yet be
393     processed without blocking.
394   */
395   int streamWillBlock(int streamId);
396
397 #if (defined(__MACOSX_CORE__) || defined(__WINDOWS_ASIO__))
398   // This function is intended for internal use only.  It must be
399   // public because it is called by the internal callback handler,
400   // which is not a member of RtAudio.  External use of this function
401   // will most likely produce highly undesireable results!
402   void callbackEvent(int streamId, DEVICE_ID deviceId, void *inData, void *outData);
403 #endif
404
405 protected:
406
407 private:
408
409   static const unsigned int SAMPLE_RATES[MAX_SAMPLE_RATES];
410
411   enum { FAILURE, SUCCESS };
412
413   enum STREAM_MODE {
414     OUTPUT,
415     INPUT,
416     DUPLEX,
417     UNINITIALIZED = -75
418   };
419
420   enum STREAM_STATE {
421     STREAM_STOPPED,
422     STREAM_RUNNING
423   };
424
425   typedef struct {
426     int device[2];          // Playback and record, respectively.
427     STREAM_MODE mode;       // OUTPUT, INPUT, or DUPLEX.
428     AUDIO_HANDLE handle[2]; // Playback and record handles, respectively.
429     STREAM_STATE state;     // STOPPED or RUNNING
430     char *userBuffer;
431     char *deviceBuffer;
432     bool doConvertBuffer[2]; // Playback and record, respectively.
433     bool deInterleave[2];    // Playback and record, respectively.
434     bool doByteSwap[2];      // Playback and record, respectively.
435     int sampleRate;
436     int bufferSize;
437     int nBuffers;
438     int nUserChannels[2];    // Playback and record, respectively.
439     int nDeviceChannels[2];  // Playback and record channels, respectively.
440     RTAUDIO_FORMAT userFormat;
441     RTAUDIO_FORMAT deviceFormat[2]; // Playback and record, respectively.
442     MUTEX mutex;
443     CALLBACK_INFO callbackInfo;
444   } RTAUDIO_STREAM;
445
446   typedef signed short INT16;
447   typedef signed int INT32;
448   typedef float FLOAT32;
449   typedef double FLOAT64;
450
451   char message[256];
452   int nDevices;
453   RTAUDIO_DEVICE *devices;
454
455   std::map<int, void *> streams;
456
457   //! Private error method to allow global control over error handling.
458   void error(RtError::TYPE type);
459
460   /*!
461     Private method to count the system audio devices, allocate the
462     RTAUDIO_DEVICE structures, and probe the device capabilities.
463   */
464   void initialize(void);
465
466   /*!
467     Private method which returns the index in the devices array to
468     the default input device.
469   */
470   int getDefaultInputDevice(void);
471
472   /*!
473     Private method which returns the index in the devices array to
474     the default output device.
475   */
476   int getDefaultOutputDevice(void);
477
478   //! Private method to clear an RTAUDIO_DEVICE structure.
479   void clearDeviceInfo(RTAUDIO_DEVICE *info);
480
481   /*!
482     Private method which attempts to fill an RTAUDIO_DEVICE
483     structure for a given device.  If an error is encountered during
484     the probe, a "warning" message is reported and the value of
485     "probed" remains false (no exception is thrown).  A successful
486     probe is indicated by probed = true.
487   */
488   void probeDeviceInfo(RTAUDIO_DEVICE *info);
489
490   /*!
491     Private method which attempts to open a device with the given parameters.
492     If an error is encountered during the probe, a "warning" message is
493     reported and FAILURE is returned (no exception is thrown). A
494     successful probe is indicated by a return value of SUCCESS.
495   */
496   bool probeDeviceOpen(int device, RTAUDIO_STREAM *stream,
497                        STREAM_MODE mode, int channels, 
498                        int sampleRate, RTAUDIO_FORMAT format,
499                        int *bufferSize, int numberOfBuffers);
500
501   /*!
502     Private common method used to check validity of a user-passed
503     stream ID.  When the ID is valid, this method returns a pointer to
504     an RTAUDIO_STREAM structure (in the form of a void pointer).
505     Otherwise, an "invalid identifier" exception is thrown.
506   */
507   void *verifyStream(int streamId);
508
509   /*!
510     Private method used to perform format, channel number, and/or interleaving
511     conversions between the user and device buffers.
512   */
513   void convertStreamBuffer(RTAUDIO_STREAM *stream, STREAM_MODE mode);
514
515   //! Private method used to perform byte-swapping on buffers.
516   void byteSwapBuffer(char *buffer, int samples, RTAUDIO_FORMAT format);
517
518   //! Private method which returns the number of bytes for a given format.
519   int formatBytes(RTAUDIO_FORMAT format);
520 };
521
522 // Define the following flag to have extra information spewed to stderr.
523 //#define __RTAUDIO_DEBUG__
524
525 #endif