Version 2.0
[rtaudio.git] / RtAudio.h
1 /******************************************/
2 /*
3   RtAudio - realtime sound I/O C++ class
4   Version 2.0 by Gary P. Scavone, 2001-2002.
5 */
6 /******************************************/
7
8 #if !defined(__RtAudio_h)
9 #define __RtAudio_h
10
11 #include <map>
12
13 #if defined(__LINUX_ALSA_)
14   #include <alsa/asoundlib.h>
15   #include <pthread.h>
16   #include <unistd.h>
17
18   typedef snd_pcm_t *AUDIO_HANDLE;
19   typedef int DEVICE_ID;
20   typedef pthread_t THREAD_HANDLE;
21   typedef pthread_mutex_t MUTEX;
22
23 #elif defined(__LINUX_OSS_)
24   #include <pthread.h>
25   #include <unistd.h>
26
27   typedef int AUDIO_HANDLE;
28   typedef int DEVICE_ID;
29   typedef pthread_t THREAD_HANDLE;
30   typedef pthread_mutex_t MUTEX;
31
32 #elif defined(__WINDOWS_DS_)
33   #include <windows.h>
34   #include <process.h>
35
36   // The following struct is used to hold the extra variables
37   // specific to the DirectSound implementation.
38   typedef struct {
39     void * object;
40     void * buffer;
41     UINT bufferPointer;
42   } AUDIO_HANDLE;
43
44   typedef LPGUID DEVICE_ID;
45   typedef unsigned long THREAD_HANDLE;
46   typedef CRITICAL_SECTION MUTEX;
47
48 #elif defined(__IRIX_AL_)
49   #include <dmedia/audio.h>
50   #include <pthread.h>
51   #include <unistd.h>
52
53   typedef ALport AUDIO_HANDLE;
54   typedef int DEVICE_ID;
55   typedef pthread_t THREAD_HANDLE;
56   typedef pthread_mutex_t MUTEX;
57
58 #endif
59
60
61 // *************************************************** //
62 //
63 // RtAudioError class declaration.
64 //
65 // *************************************************** //
66
67 class RtAudioError
68 {
69 public:
70   enum TYPE {
71     WARNING,
72     DEBUG_WARNING,
73     UNSPECIFIED,
74     NO_DEVICES_FOUND,
75     INVALID_DEVICE,
76     INVALID_STREAM,
77     MEMORY_ERROR,
78     INVALID_PARAMETER,
79     DRIVER_ERROR,
80     SYSTEM_ERROR,
81     THREAD_ERROR
82   };
83
84 protected:
85   char error_message[256];
86   TYPE type;
87
88 public:
89   //! The constructor.
90   RtAudioError(const char *p, TYPE tipe = RtAudioError::UNSPECIFIED);
91
92   //! The destructor.
93   virtual ~RtAudioError(void);
94
95   //! Prints "thrown" error message to stdout.
96   virtual void printMessage(void);
97
98   //! Returns the "thrown" error message TYPE.
99   virtual const TYPE& getType(void) { return type; }
100
101   //! Returns the "thrown" error message string.
102   virtual const char *getMessage(void) { return error_message; }
103 };
104
105
106 // *************************************************** //
107 //
108 // RtAudio class declaration.
109 //
110 // *************************************************** //
111
112 class RtAudio
113 {
114 public:
115
116   // Support for signed integers and floats.  Audio data fed to/from
117   // the tickStream() routine is assumed to ALWAYS be in host
118   // byte order.  The internal routines will automatically take care of
119   // any necessary byte-swapping between the host format and the
120   // soundcard.  Thus, endian-ness is not a concern in the following
121   // format definitions.
122   typedef unsigned long RTAUDIO_FORMAT;
123   static const RTAUDIO_FORMAT RTAUDIO_SINT8;
124   static const RTAUDIO_FORMAT RTAUDIO_SINT16;
125   static const RTAUDIO_FORMAT RTAUDIO_SINT24; /*!< Upper 3 bytes of 32-bit integer. */
126   static const RTAUDIO_FORMAT RTAUDIO_SINT32;
127   static const RTAUDIO_FORMAT RTAUDIO_FLOAT32; /*!< Normalized between plus/minus 1.0. */
128   static const RTAUDIO_FORMAT RTAUDIO_FLOAT64; /*!< Normalized between plus/minus 1.0. */
129
130   //static const int MAX_SAMPLE_RATES = 14;
131   enum { MAX_SAMPLE_RATES = 14 };
132
133   typedef int (*RTAUDIO_CALLBACK)(char *buffer, int bufferSize, void *userData);
134
135   typedef struct {
136     char name[128];
137     DEVICE_ID id[2];  /*!< No value reported by getDeviceInfo(). */
138     bool probed;       /*!< true if the device capabilities were successfully probed. */
139     int maxOutputChannels;
140     int maxInputChannels;
141     int maxDuplexChannels;
142     int minOutputChannels;
143     int minInputChannels;
144     int minDuplexChannels;
145     bool hasDuplexSupport; /*!< true if device supports duplex mode. */
146     int nSampleRates;      /*!< Number of discrete rates or -1 if range supported. */
147     int sampleRates[MAX_SAMPLE_RATES]; /*!< Supported rates or (min, max) if range. */
148     RTAUDIO_FORMAT nativeFormats;     /*!< Bit mask of supported data formats. */
149   } RTAUDIO_DEVICE;
150
151   //! The default constructor.
152   /*!
153     Probes the system to make sure at least one audio
154     input/output device is available and determines
155     the api-specific identifier for each device found.
156     An RtAudioError error can be thrown if no devices are
157     found or if a memory allocation error occurs.
158   */
159   RtAudio();
160
161   //! A constructor which can be used to open a stream during instantiation.
162   /*!
163     The specified output and/or input device identifiers correspond
164     to those enumerated via the getDeviceInfo() method.  If device =
165     0, the default or first available devices meeting the given
166     parameters is selected.  If an output or input channel value is
167     zero, the corresponding device value is ignored.  When a stream is
168     successfully opened, its identifier is returned via the "streamID"
169     pointer.  An RtAudioError can be thrown if no devices are found
170     for the given parameters, if a memory allocation error occurs, or
171     if a driver error occurs. \sa openStream()
172   */
173   RtAudio(int *streamID,
174           int outputDevice, int outputChannels,
175           int inputDevice, int inputChannels,
176           RTAUDIO_FORMAT format, int sampleRate,
177           int *bufferSize, int numberOfBuffers);
178
179   //! The destructor.
180   /*!
181     Stops and closes any open streams and devices and deallocates
182     buffer and structure memory.
183   */
184   ~RtAudio();
185
186   //! A public method for opening a stream with the specified parameters.
187   /*!
188     If successful, the opened stream ID is returned.  Otherwise, an
189     RtAudioError is thrown.
190
191     \param outputDevice: If equal to 0, the default or first device
192            found meeting the given parameters is opened.  Otherwise, the
193            device number should correspond to one of those enumerated via
194            the getDeviceInfo() method.
195     \param outputChannels: The desired number of output channels.  If
196            equal to zero, the outputDevice identifier is ignored.
197     \param inputDevice: If equal to 0, the default or first device
198            found meeting the given parameters is opened.  Otherwise, the
199            device number should correspond to one of those enumerated via
200            the getDeviceInfo() method.
201     \param inputChannels: The desired number of input channels.  If
202            equal to zero, the inputDevice identifier is ignored.
203     \param format: An RTAUDIO_FORMAT specifying the desired sample data format.
204     \param sampleRate: The desired sample rate (sample frames per second).
205     \param *bufferSize: A pointer value indicating the desired internal buffer
206            size in sample frames.  The actual value used by the device is
207            returned via the same pointer.  A value of zero can be specified,
208            in which case the lowest allowable value is determined.
209     \param numberOfBuffers: A value which can be used to help control device
210            latency.  More buffers typically result in more robust performance,
211            though at a cost of greater latency.  A value of zero can be
212            specified, in which case the lowest allowable value is used.
213   */
214   int openStream(int outputDevice, int outputChannels,
215                  int inputDevice, int inputChannels,
216                  RTAUDIO_FORMAT format, int sampleRate,
217                  int *bufferSize, int numberOfBuffers);
218
219   //! A public method which sets a user-defined callback function for a given stream.
220   /*!
221     This method assigns a callback function to a specific,
222     previously opened stream for non-blocking stream functionality.  A
223     separate process is initiated, though the user function is called
224     only when the stream is "running" (between calls to the
225     startStream() and stopStream() methods, respectively).  The
226     callback process remains active for the duration of the stream and
227     is automatically shutdown when the stream is closed (via the
228     closeStream() method or by object destruction).  The callback
229     process can also be shutdown and the user function de-referenced
230     through an explicit call to the cancelStreamCallback() method.
231     Note that a single stream can use only blocking or callback
232     functionality at the same time, though it is possible to alternate
233     modes on the same stream through the use of the
234     setStreamCallback() and cancelStreamCallback() methods (the
235     blocking tickStream() method can be used before a callback is set
236     and/or after a callback is cancelled).  An RtAudioError will be
237     thrown for an invalid device argument.
238   */
239   void setStreamCallback(int streamID, RTAUDIO_CALLBACK callback, void *userData);
240
241   //! A public method which cancels a callback process and function for a given stream.
242   /*!
243     This method shuts down a callback process and de-references the
244     user function for a specific stream.  Callback functionality can
245     subsequently be restarted on the stream via the
246     setStreamCallback() method.  An RtAudioError will be thrown for an
247     invalid device argument.
248    */
249   void cancelStreamCallback(int streamID);
250
251   //! A public method which returns the number of audio devices found.
252   int getDeviceCount(void);
253
254   //! Fill a user-supplied RTAUDIO_DEVICE structure for a specified device.
255   /*!
256     Any device between 0 and getDeviceCount()-1 is valid.  If a
257     device is busy or otherwise unavailable, the structure member
258     "probed" has a value of "false".  The system default input and
259     output devices are referenced by device identifier = 0.  On
260     systems which allow dynamic default device settings, the default
261     devices are not identified by name (specific device enumerations
262     are assigned device identifiers > 0).  An RtAudioError will be
263     thrown for an invalid device argument.
264   */
265   void getDeviceInfo(int device, RTAUDIO_DEVICE *info);
266
267   //! A public method which returns a pointer to the buffer for an open stream.
268   /*!
269     The user should fill and/or read the buffer data in interleaved format
270     and then call the tickStream() method.  An RtAudioError will be
271     thrown for an invalid stream identifier.
272   */
273   char * const getStreamBuffer(int streamID);
274
275   //! Public method used to trigger processing of input/output data for a stream.
276   /*!
277     This method blocks until all buffer data is read/written.  An
278     RtAudioError will be thrown for an invalid stream identifier or if
279     a driver error occurs.
280   */
281   void tickStream(int streamID);
282
283   //! Public method which closes a stream and frees any associated buffers.
284   /*!
285     If an invalid stream identifier is specified, this method
286     issues a warning and returns (an RtAudioError is not thrown).
287   */
288   void closeStream(int streamID);
289
290   //! Public method which starts a stream.
291   /*!
292     An RtAudioError will be thrown for an invalid stream identifier
293     or if a driver error occurs.
294   */
295   void startStream(int streamID);
296
297   //! Stop a stream, allowing any samples remaining in the queue to be played out and/or read in.
298   /*!
299     An RtAudioError will be thrown for an invalid stream identifier
300     or if a driver error occurs.
301   */
302   void stopStream(int streamID);
303
304   //! Stop a stream, discarding any samples remaining in the input/output queue.
305   /*!
306     An RtAudioError will be thrown for an invalid stream identifier
307     or if a driver error occurs.
308   */
309   void abortStream(int streamID);
310
311   //! Queries a stream to determine whether a call to the tickStream() method will block.
312   /*!
313     A return value of 0 indicates that the stream will NOT block.  A positive
314     return value indicates the number of sample frames that cannot yet be
315     processed without blocking.
316   */
317   int streamWillBlock(int streamID);
318
319 protected:
320
321 private:
322
323   static const unsigned int SAMPLE_RATES[MAX_SAMPLE_RATES];
324
325   enum { FAILURE, SUCCESS };
326
327   enum STREAM_MODE {
328     PLAYBACK,
329     RECORD,
330     DUPLEX,
331     UNINITIALIZED = -75
332   };
333
334   enum STREAM_STATE {
335     STREAM_STOPPED,
336     STREAM_RUNNING
337   };
338
339   typedef struct {
340     int device[2];           // Playback and record, respectively.
341     STREAM_MODE mode;       // PLAYBACK, RECORD, or DUPLEX.
342     AUDIO_HANDLE handle[2]; // Playback and record handles, respectively.
343     STREAM_STATE state;     // STOPPED or RUNNING
344     char *userBuffer;
345     char *deviceBuffer;
346     bool doConvertBuffer[2]; // Playback and record, respectively.
347     bool deInterleave[2];    // Playback and record, respectively.
348     bool doByteSwap[2];      // Playback and record, respectively.
349     int sampleRate;
350     int bufferSize;
351     int nBuffers;
352     int nUserChannels[2];    // Playback and record, respectively.
353     int nDeviceChannels[2];  // Playback and record channels, respectively.
354     RTAUDIO_FORMAT userFormat;
355     RTAUDIO_FORMAT deviceFormat[2]; // Playback and record, respectively.
356     bool usingCallback;
357     THREAD_HANDLE thread;
358     MUTEX mutex;
359     RTAUDIO_CALLBACK callback;
360     void *userData;
361   } RTAUDIO_STREAM;
362
363   typedef signed short INT16;
364   typedef signed int INT32;
365   typedef float FLOAT32;
366   typedef double FLOAT64;
367
368   char message[256];
369   int nDevices;
370   RTAUDIO_DEVICE *devices;
371
372   std::map<int, void *> streams;
373
374   //! Private error method to allow global control over error handling.
375   void error(RtAudioError::TYPE type);
376
377   /*!
378     Private method to count the system audio devices, allocate the
379     RTAUDIO_DEVICE structures, and probe the device capabilities.
380   */
381   void initialize(void);
382
383   //! Private method to clear an RTAUDIO_DEVICE structure.
384   void clearDeviceInfo(RTAUDIO_DEVICE *info);
385
386   /*!
387     Private method which attempts to fill an RTAUDIO_DEVICE
388     structure for a given device.  If an error is encountered during
389     the probe, a "warning" message is reported and the value of
390     "probed" remains false (no exception is thrown).  A successful
391     probe is indicated by probed = true.
392   */
393   void probeDeviceInfo(RTAUDIO_DEVICE *info);
394
395   /*!
396     Private method which attempts to open a device with the given parameters.
397     If an error is encountered during the probe, a "warning" message is
398     reported and FAILURE is returned (no exception is thrown). A
399     successful probe is indicated by a return value of SUCCESS.
400   */
401   bool probeDeviceOpen(int device, RTAUDIO_STREAM *stream,
402                        STREAM_MODE mode, int channels, 
403                        int sampleRate, RTAUDIO_FORMAT format,
404                        int *bufferSize, int numberOfBuffers);
405
406   /*!
407     Private common method used to check validity of a user-passed
408     stream ID.  When the ID is valid, this method returns a pointer to
409     an RTAUDIO_STREAM structure (in the form of a void pointer).
410     Otherwise, an "invalid identifier" exception is thrown.
411   */
412   void *verifyStream(int streamID);
413
414   /*!
415     Private method used to perform format, channel number, and/or interleaving
416     conversions between the user and device buffers.
417   */
418   void convertStreamBuffer(RTAUDIO_STREAM *stream, STREAM_MODE mode);
419
420   //! Private method used to perform byte-swapping on buffers.
421   void byteSwapBuffer(char *buffer, int samples, RTAUDIO_FORMAT format);
422
423   //! Private method which returns the number of bytes for a given format.
424   int formatBytes(RTAUDIO_FORMAT format);
425 };
426
427 // Uncomment the following definition to have extra information spewed to stderr.
428 //#define RTAUDIO_DEBUG
429
430 #endif