1 /******************************************/
\r
3 RtAudio - realtime sound I/O C++ class
\r
4 by Gary P. Scavone, 2001-2002.
\r
6 /******************************************/
\r
8 #if !defined(__RTAUDIO_H)
\r
13 #if defined(__LINUX_ALSA__)
\r
14 #include <alsa/asoundlib.h>
\r
15 #include <pthread.h>
\r
19 typedef snd_pcm_t *AUDIO_HANDLE;
\r
20 typedef int DEVICE_ID;
\r
21 typedef pthread_t THREAD_HANDLE;
\r
22 typedef pthread_mutex_t MUTEX;
\r
24 #elif defined(__LINUX_OSS__)
\r
25 #include <pthread.h>
\r
29 typedef int AUDIO_HANDLE;
\r
30 typedef int DEVICE_ID;
\r
31 typedef pthread_t THREAD_HANDLE;
\r
32 typedef pthread_mutex_t MUTEX;
\r
34 #elif defined(__WINDOWS_DS__)
\r
35 #include <windows.h>
\r
36 #include <process.h>
\r
38 // The following struct is used to hold the extra variables
\r
39 // specific to the DirectSound implementation.
\r
46 #define THREAD_TYPE __stdcall
\r
47 typedef LPGUID DEVICE_ID;
\r
48 typedef unsigned long THREAD_HANDLE;
\r
49 typedef CRITICAL_SECTION MUTEX;
\r
51 #elif defined(__IRIX_AL__)
\r
52 #include <dmedia/audio.h>
\r
53 #include <pthread.h>
\r
57 typedef ALport AUDIO_HANDLE;
\r
58 typedef int DEVICE_ID;
\r
59 typedef pthread_t THREAD_HANDLE;
\r
60 typedef pthread_mutex_t MUTEX;
\r
65 // *************************************************** //
\r
67 // RtError class declaration.
\r
69 // *************************************************** //
\r
89 char error_message[256];
\r
93 //! The constructor.
\r
94 RtError(const char *p, TYPE tipe = RtError::UNSPECIFIED);
\r
97 virtual ~RtError(void);
\r
99 //! Prints "thrown" error message to stdout.
\r
100 virtual void printMessage(void);
\r
102 //! Returns the "thrown" error message TYPE.
\r
103 virtual const TYPE& getType(void) { return type; }
\r
105 //! Returns the "thrown" error message string.
\r
106 virtual const char *getMessage(void) { return error_message; }
\r
110 // *************************************************** //
\r
112 // RtAudio class declaration.
\r
114 // *************************************************** //
\r
120 // Support for signed integers and floats. Audio data fed to/from
\r
121 // the tickStream() routine is assumed to ALWAYS be in host
\r
122 // byte order. The internal routines will automatically take care of
\r
123 // any necessary byte-swapping between the host format and the
\r
124 // soundcard. Thus, endian-ness is not a concern in the following
\r
125 // format definitions.
\r
126 typedef unsigned long RTAUDIO_FORMAT;
\r
127 static const RTAUDIO_FORMAT RTAUDIO_SINT8;
\r
128 static const RTAUDIO_FORMAT RTAUDIO_SINT16;
\r
129 static const RTAUDIO_FORMAT RTAUDIO_SINT24; /*!< Upper 3 bytes of 32-bit integer. */
\r
130 static const RTAUDIO_FORMAT RTAUDIO_SINT32;
\r
131 static const RTAUDIO_FORMAT RTAUDIO_FLOAT32; /*!< Normalized between plus/minus 1.0. */
\r
132 static const RTAUDIO_FORMAT RTAUDIO_FLOAT64; /*!< Normalized between plus/minus 1.0. */
\r
134 //static const int MAX_SAMPLE_RATES = 14;
\r
135 enum { MAX_SAMPLE_RATES = 14 };
\r
137 typedef int (*RTAUDIO_CALLBACK)(char *buffer, int bufferSize, void *userData);
\r
141 DEVICE_ID id[2]; /*!< No value reported by getDeviceInfo(). */
\r
142 bool probed; /*!< true if the device capabilities were successfully probed. */
\r
143 int maxOutputChannels;
\r
144 int maxInputChannels;
\r
145 int maxDuplexChannels;
\r
146 int minOutputChannels;
\r
147 int minInputChannels;
\r
148 int minDuplexChannels;
\r
149 bool hasDuplexSupport; /*!< true if device supports duplex mode. */
\r
150 int nSampleRates; /*!< Number of discrete rates or -1 if range supported. */
\r
151 int sampleRates[MAX_SAMPLE_RATES]; /*!< Supported rates or (min, max) if range. */
\r
152 RTAUDIO_FORMAT nativeFormats; /*!< Bit mask of supported data formats. */
\r
155 //! The default constructor.
\r
157 Probes the system to make sure at least one audio
\r
158 input/output device is available and determines
\r
159 the api-specific identifier for each device found.
\r
160 An RtError error can be thrown if no devices are
\r
161 found or if a memory allocation error occurs.
\r
165 //! A constructor which can be used to open a stream during instantiation.
\r
167 The specified output and/or input device identifiers correspond
\r
168 to those enumerated via the getDeviceInfo() method. If device =
\r
169 0, the default or first available devices meeting the given
\r
170 parameters is selected. If an output or input channel value is
\r
171 zero, the corresponding device value is ignored. When a stream is
\r
172 successfully opened, its identifier is returned via the "streamId"
\r
173 pointer. An RtError can be thrown if no devices are found
\r
174 for the given parameters, if a memory allocation error occurs, or
\r
175 if a driver error occurs. \sa openStream()
\r
177 RtAudio(int *streamId,
\r
178 int outputDevice, int outputChannels,
\r
179 int inputDevice, int inputChannels,
\r
180 RTAUDIO_FORMAT format, int sampleRate,
\r
181 int *bufferSize, int numberOfBuffers);
\r
183 //! The destructor.
\r
185 Stops and closes any open streams and devices and deallocates
\r
186 buffer and structure memory.
\r
190 //! A public method for opening a stream with the specified parameters.
\r
192 If successful, the opened stream ID is returned. Otherwise, an
\r
195 \param outputDevice: If equal to 0, the default or first device
\r
196 found meeting the given parameters is opened. Otherwise, the
\r
197 device number should correspond to one of those enumerated via
\r
198 the getDeviceInfo() method.
\r
199 \param outputChannels: The desired number of output channels. If
\r
200 equal to zero, the outputDevice identifier is ignored.
\r
201 \param inputDevice: If equal to 0, the default or first device
\r
202 found meeting the given parameters is opened. Otherwise, the
\r
203 device number should correspond to one of those enumerated via
\r
204 the getDeviceInfo() method.
\r
205 \param inputChannels: The desired number of input channels. If
\r
206 equal to zero, the inputDevice identifier is ignored.
\r
207 \param format: An RTAUDIO_FORMAT specifying the desired sample data format.
\r
208 \param sampleRate: The desired sample rate (sample frames per second).
\r
209 \param *bufferSize: A pointer value indicating the desired internal buffer
\r
210 size in sample frames. The actual value used by the device is
\r
211 returned via the same pointer. A value of zero can be specified,
\r
212 in which case the lowest allowable value is determined.
\r
213 \param numberOfBuffers: A value which can be used to help control device
\r
214 latency. More buffers typically result in more robust performance,
\r
215 though at a cost of greater latency. A value of zero can be
\r
216 specified, in which case the lowest allowable value is used.
\r
218 int openStream(int outputDevice, int outputChannels,
\r
219 int inputDevice, int inputChannels,
\r
220 RTAUDIO_FORMAT format, int sampleRate,
\r
221 int *bufferSize, int numberOfBuffers);
\r
223 //! A public method which sets a user-defined callback function for a given stream.
\r
225 This method assigns a callback function to a specific,
\r
226 previously opened stream for non-blocking stream functionality. A
\r
227 separate process is initiated, though the user function is called
\r
228 only when the stream is "running" (between calls to the
\r
229 startStream() and stopStream() methods, respectively). The
\r
230 callback process remains active for the duration of the stream and
\r
231 is automatically shutdown when the stream is closed (via the
\r
232 closeStream() method or by object destruction). The callback
\r
233 process can also be shutdown and the user function de-referenced
\r
234 through an explicit call to the cancelStreamCallback() method.
\r
235 Note that a single stream can use only blocking or callback
\r
236 functionality at the same time, though it is possible to alternate
\r
237 modes on the same stream through the use of the
\r
238 setStreamCallback() and cancelStreamCallback() methods (the
\r
239 blocking tickStream() method can be used before a callback is set
\r
240 and/or after a callback is cancelled). An RtError will be
\r
241 thrown for an invalid device argument.
\r
243 void setStreamCallback(int streamId, RTAUDIO_CALLBACK callback, void *userData);
\r
245 //! A public method which cancels a callback process and function for a given stream.
\r
247 This method shuts down a callback process and de-references the
\r
248 user function for a specific stream. Callback functionality can
\r
249 subsequently be restarted on the stream via the
\r
250 setStreamCallback() method. An RtError will be thrown for an
\r
251 invalid device argument.
\r
253 void cancelStreamCallback(int streamId);
\r
255 //! A public method which returns the number of audio devices found.
\r
256 int getDeviceCount(void);
\r
258 //! Fill a user-supplied RTAUDIO_DEVICE structure for a specified device.
\r
260 Any device between 0 and getDeviceCount()-1 is valid. If a
\r
261 device is busy or otherwise unavailable, the structure member
\r
262 "probed" has a value of "false". The system default input and
\r
263 output devices are referenced by device identifier = 0. On
\r
264 systems which allow dynamic default device settings, the default
\r
265 devices are not identified by name (specific device enumerations
\r
266 are assigned device identifiers > 0). An RtError will be
\r
267 thrown for an invalid device argument.
\r
269 void getDeviceInfo(int device, RTAUDIO_DEVICE *info);
\r
271 //! A public method which returns a pointer to the buffer for an open stream.
\r
273 The user should fill and/or read the buffer data in interleaved format
\r
274 and then call the tickStream() method. An RtError will be
\r
275 thrown for an invalid stream identifier.
\r
277 char * const getStreamBuffer(int streamId);
\r
279 //! Public method used to trigger processing of input/output data for a stream.
\r
281 This method blocks until all buffer data is read/written. An
\r
282 RtError will be thrown for an invalid stream identifier or if
\r
283 a driver error occurs.
\r
285 void tickStream(int streamId);
\r
287 //! Public method which closes a stream and frees any associated buffers.
\r
289 If an invalid stream identifier is specified, this method
\r
290 issues a warning and returns (an RtError is not thrown).
\r
292 void closeStream(int streamId);
\r
294 //! Public method which starts a stream.
\r
296 An RtError will be thrown for an invalid stream identifier
\r
297 or if a driver error occurs.
\r
299 void startStream(int streamId);
\r
301 //! Stop a stream, allowing any samples remaining in the queue to be played out and/or read in.
\r
303 An RtError will be thrown for an invalid stream identifier
\r
304 or if a driver error occurs.
\r
306 void stopStream(int streamId);
\r
308 //! Stop a stream, discarding any samples remaining in the input/output queue.
\r
310 An RtError will be thrown for an invalid stream identifier
\r
311 or if a driver error occurs.
\r
313 void abortStream(int streamId);
\r
315 //! Queries a stream to determine whether a call to the tickStream() method will block.
\r
317 A return value of 0 indicates that the stream will NOT block. A positive
\r
318 return value indicates the number of sample frames that cannot yet be
\r
319 processed without blocking.
\r
321 int streamWillBlock(int streamId);
\r
327 static const unsigned int SAMPLE_RATES[MAX_SAMPLE_RATES];
\r
329 enum { FAILURE, SUCCESS };
\r
335 UNINITIALIZED = -75
\r
338 enum STREAM_STATE {
\r
344 int device[2]; // Playback and record, respectively.
\r
345 STREAM_MODE mode; // PLAYBACK, RECORD, or DUPLEX.
\r
346 AUDIO_HANDLE handle[2]; // Playback and record handles, respectively.
\r
347 STREAM_STATE state; // STOPPED or RUNNING
\r
349 char *deviceBuffer;
\r
350 bool doConvertBuffer[2]; // Playback and record, respectively.
\r
351 bool deInterleave[2]; // Playback and record, respectively.
\r
352 bool doByteSwap[2]; // Playback and record, respectively.
\r
356 int nUserChannels[2]; // Playback and record, respectively.
\r
357 int nDeviceChannels[2]; // Playback and record channels, respectively.
\r
358 RTAUDIO_FORMAT userFormat;
\r
359 RTAUDIO_FORMAT deviceFormat[2]; // Playback and record, respectively.
\r
360 bool usingCallback;
\r
361 THREAD_HANDLE thread;
\r
363 RTAUDIO_CALLBACK callback;
\r
367 typedef signed short INT16;
\r
368 typedef signed int INT32;
\r
369 typedef float FLOAT32;
\r
370 typedef double FLOAT64;
\r
374 RTAUDIO_DEVICE *devices;
\r
376 std::map<int, void *> streams;
\r
378 //! Private error method to allow global control over error handling.
\r
379 void error(RtError::TYPE type);
\r
382 Private method to count the system audio devices, allocate the
\r
383 RTAUDIO_DEVICE structures, and probe the device capabilities.
\r
385 void initialize(void);
\r
387 //! Private method to clear an RTAUDIO_DEVICE structure.
\r
388 void clearDeviceInfo(RTAUDIO_DEVICE *info);
\r
391 Private method which attempts to fill an RTAUDIO_DEVICE
\r
392 structure for a given device. If an error is encountered during
\r
393 the probe, a "warning" message is reported and the value of
\r
394 "probed" remains false (no exception is thrown). A successful
\r
395 probe is indicated by probed = true.
\r
397 void probeDeviceInfo(RTAUDIO_DEVICE *info);
\r
400 Private method which attempts to open a device with the given parameters.
\r
401 If an error is encountered during the probe, a "warning" message is
\r
402 reported and FAILURE is returned (no exception is thrown). A
\r
403 successful probe is indicated by a return value of SUCCESS.
\r
405 bool probeDeviceOpen(int device, RTAUDIO_STREAM *stream,
\r
406 STREAM_MODE mode, int channels,
\r
407 int sampleRate, RTAUDIO_FORMAT format,
\r
408 int *bufferSize, int numberOfBuffers);
\r
411 Private common method used to check validity of a user-passed
\r
412 stream ID. When the ID is valid, this method returns a pointer to
\r
413 an RTAUDIO_STREAM structure (in the form of a void pointer).
\r
414 Otherwise, an "invalid identifier" exception is thrown.
\r
416 void *verifyStream(int streamId);
\r
419 Private method used to perform format, channel number, and/or interleaving
\r
420 conversions between the user and device buffers.
\r
422 void convertStreamBuffer(RTAUDIO_STREAM *stream, STREAM_MODE mode);
\r
424 //! Private method used to perform byte-swapping on buffers.
\r
425 void byteSwapBuffer(char *buffer, int samples, RTAUDIO_FORMAT format);
\r
427 //! Private method which returns the number of bytes for a given format.
\r
428 int formatBytes(RTAUDIO_FORMAT format);
\r
431 // Uncomment the following definition to have extra information spewed to stderr.
\r
432 //#define RTAUDIO_DEBUG
\r