1 /************************************************************************/
3 \brief Realtime audio i/o C++ class.
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.
10 RtAudio WWW site: http://www-ccrma.stanford.edu/~gary/rtaudio/
12 RtAudio: a realtime audio i/o C++ class
13 Copyright (c) 2001-2002 Gary P. Scavone
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:
23 The above copyright notice and this permission notice shall be
24 included in all copies or substantial portions of the Software.
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.
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.
38 /************************************************************************/
40 #if !defined(__RTAUDIO_H)
45 #if defined(__LINUX_ALSA__)
46 #include <alsa/asoundlib.h>
50 typedef snd_pcm_t *AUDIO_HANDLE;
51 typedef int DEVICE_ID;
52 typedef pthread_t THREAD_HANDLE;
53 typedef pthread_mutex_t MUTEX;
55 #elif defined(__LINUX_OSS__)
59 typedef int AUDIO_HANDLE;
60 typedef int DEVICE_ID;
61 typedef pthread_t THREAD_HANDLE;
62 typedef pthread_mutex_t MUTEX;
64 #elif defined(__WINDOWS_DS__)
68 // The following struct is used to hold the extra variables
69 // specific to the DirectSound implementation.
76 typedef LPGUID DEVICE_ID;
77 typedef unsigned long THREAD_HANDLE;
78 typedef CRITICAL_SECTION MUTEX;
80 #elif defined(__WINDOWS_ASIO__)
84 typedef int AUDIO_HANDLE;
85 typedef int DEVICE_ID;
86 typedef unsigned long THREAD_HANDLE;
87 typedef CRITICAL_SECTION MUTEX;
89 #elif defined(__IRIX_AL__)
90 #include <dmedia/audio.h>
94 typedef ALport AUDIO_HANDLE;
95 typedef long DEVICE_ID;
96 typedef pthread_t THREAD_HANDLE;
97 typedef pthread_mutex_t MUTEX;
99 #elif defined(__MACOSX_CORE__)
101 #include <CoreAudio/AudioHardware.h>
104 typedef unsigned int AUDIO_HANDLE;
105 typedef AudioDeviceID DEVICE_ID;
106 typedef pthread_t THREAD_HANDLE;
107 typedef pthread_mutex_t MUTEX;
112 /************************************************************************/
114 \brief Exception handling class for RtAudio.
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.
125 /************************************************************************/
130 //! Defined RtError types.
146 char error_message[256];
151 RtError(const char *p, TYPE tipe = RtError::UNSPECIFIED);
154 virtual ~RtError(void);
156 //! Prints "thrown" error message to stdout.
157 virtual void printMessage(void);
159 //! Returns the "thrown" error message TYPE.
160 virtual const TYPE& getType(void) { return type; }
162 //! Returns the "thrown" error message string.
163 virtual const char *getMessage(void) { return error_message; }
167 // This public structure type is used to pass callback information
168 // between the private RtAudio stream structure and global callback
169 // handling functions.
171 void *object; // Used as a "this" pointer.
174 THREAD_HANDLE thread;
177 unsigned long waitTime;
185 // *************************************************** //
187 // RtAudio class declaration.
189 // *************************************************** //
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. */
209 //static const int MAX_SAMPLE_RATES = 14;
210 enum { MAX_SAMPLE_RATES = 14 };
212 typedef int (*RTAUDIO_CALLBACK)(char *buffer, int bufferSize, void *userData);
214 //! The public device information structure for passing queried values.
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. */
232 //! The default constructor.
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.
241 //! A constructor which can be used to open a stream during instantiation.
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()
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);
261 Stops and closes any open streams and devices and deallocates
262 buffer and structure memory.
266 //! A public method for opening a stream with the specified parameters.
268 If successful, the opened stream ID is returned. Otherwise, an
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.
294 int openStream(int outputDevice, int outputChannels,
295 int inputDevice, int inputChannels,
296 RTAUDIO_FORMAT format, int sampleRate,
297 int *bufferSize, int numberOfBuffers);
299 //! A public method which sets a user-defined callback function for a given stream.
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.
319 void setStreamCallback(int streamId, RTAUDIO_CALLBACK callback, void *userData);
321 //! A public method which cancels a callback process and function for a given stream.
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.
329 void cancelStreamCallback(int streamId);
331 //! A public method which returns the number of audio devices found.
332 int getDeviceCount(void);
334 //! Fill a user-supplied RTAUDIO_DEVICE structure for a specified device number.
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.
343 void getDeviceInfo(int device, RTAUDIO_DEVICE *info);
345 //! A public method which returns a pointer to the buffer for an open stream.
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.
351 char * const getStreamBuffer(int streamId);
353 //! Public method used to trigger processing of input/output data for a stream.
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.
359 void tickStream(int streamId);
361 //! Public method which closes a stream and frees any associated buffers.
363 If an invalid stream identifier is specified, this method
364 issues a warning and returns (an RtError is not thrown).
366 void closeStream(int streamId);
368 //! Public method which starts a stream.
370 An RtError will be thrown for an invalid stream identifier
371 or if a driver error occurs.
373 void startStream(int streamId);
375 //! Stop a stream, allowing any samples remaining in the queue to be played out and/or read in.
377 An RtError will be thrown for an invalid stream identifier
378 or if a driver error occurs.
380 void stopStream(int streamId);
382 //! Stop a stream, discarding any samples remaining in the input/output queue.
384 An RtError will be thrown for an invalid stream identifier
385 or if a driver error occurs.
387 void abortStream(int streamId);
389 //! Queries a stream to determine whether a call to the tickStream() method will block.
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.
395 int streamWillBlock(int streamId);
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);
409 static const unsigned int SAMPLE_RATES[MAX_SAMPLE_RATES];
411 enum { FAILURE, SUCCESS };
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
432 bool doConvertBuffer[2]; // Playback and record, respectively.
433 bool deInterleave[2]; // Playback and record, respectively.
434 bool doByteSwap[2]; // Playback and record, respectively.
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.
443 CALLBACK_INFO callbackInfo;
446 typedef signed short INT16;
447 typedef signed int INT32;
448 typedef float FLOAT32;
449 typedef double FLOAT64;
453 RTAUDIO_DEVICE *devices;
455 std::map<int, void *> streams;
457 //! Private error method to allow global control over error handling.
458 void error(RtError::TYPE type);
461 Private method to count the system audio devices, allocate the
462 RTAUDIO_DEVICE structures, and probe the device capabilities.
464 void initialize(void);
467 Private method which returns the index in the devices array to
468 the default input device.
470 int getDefaultInputDevice(void);
473 Private method which returns the index in the devices array to
474 the default output device.
476 int getDefaultOutputDevice(void);
478 //! Private method to clear an RTAUDIO_DEVICE structure.
479 void clearDeviceInfo(RTAUDIO_DEVICE *info);
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.
488 void probeDeviceInfo(RTAUDIO_DEVICE *info);
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.
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);
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.
507 void *verifyStream(int streamId);
510 Private method used to perform format, channel number, and/or interleaving
511 conversions between the user and device buffers.
513 void convertStreamBuffer(RTAUDIO_STREAM *stream, STREAM_MODE mode);
515 //! Private method used to perform byte-swapping on buffers.
516 void byteSwapBuffer(char *buffer, int samples, RTAUDIO_FORMAT format);
518 //! Private method which returns the number of bytes for a given format.
519 int formatBytes(RTAUDIO_FORMAT format);
522 // Define the following flag to have extra information spewed to stderr.
523 //#define __RTAUDIO_DEBUG__