diff options
| author | Stephen Sinclair <sinclair@music.mcgill.ca> | 2013-10-11 01:51:47 +0200 |
|---|---|---|
| committer | Stephen Sinclair <sinclair@music.mcgill.ca> | 2013-10-11 01:51:47 +0200 |
| commit | 2572d0d544acf19943ae955059e1b64b0968a3ba (patch) | |
| tree | f908ba7889e4e05614e7425a7ff69273ec3f498e /RtAudio.cpp | |
| parent | 64f75193375cc6ec0052e33131df5939b7926ecd (diff) | |
| parent | 3dc6e2e86821303784512f86805683f1fda14ccb (diff) | |
Merge 4.0.3 into releases
Diffstat (limited to 'RtAudio.cpp')
| -rw-r--r-- | RtAudio.cpp | 114 |
1 files changed, 77 insertions, 37 deletions
diff --git a/RtAudio.cpp b/RtAudio.cpp index dd76b59..cdefda4 100644 --- a/RtAudio.cpp +++ b/RtAudio.cpp @@ -38,7 +38,7 @@ */ /************************************************************************/ -// RtAudio: Version 4.0 +// RtAudio: Version 4.0.3 #include "RtAudio.h" #include <iostream> @@ -2291,10 +2291,10 @@ bool RtApiJack :: callbackEvent( unsigned long nframes ) // on information found in // http://www.cs.wustl.edu/~schmidt/win32-cv-1.html. -#include "asio/asiosys.h" -#include "asio/asio.h" -#include "asio/iasiothiscallresolver.h" -#include "asio/asiodrivers.h" +#include "asiosys.h" +#include "asio.h" +#include "iasiothiscallresolver.h" +#include "asiodrivers.h" #include <cmath> AsioDrivers drivers; @@ -2366,11 +2366,14 @@ RtAudio::DeviceInfo RtApiAsio :: getDeviceInfo( unsigned int device ) error( RtError::INVALID_USE ); } - // Don't probe if a stream is already open. + // If a stream is already open, we cannot probe other devices. Thus, use the saved results. if ( stream_.state != STREAM_CLOSED ) { - errorText_ = "RtApiAsio::getDeviceInfo: unable to probe driver while a stream is open."; - error( RtError::WARNING ); - return info; + if ( device >= devices_.size() ) { + errorText_ = "RtApiAsio::getDeviceInfo: device ID was not present before stream was opened."; + error( RtError::WARNING ); + return info; + } + return devices_[ device ]; } char driverName[32]; @@ -2463,6 +2466,16 @@ void bufferSwitch( long index, ASIOBool processNow ) object->callbackEvent( index ); } +void RtApiAsio :: saveDeviceInfo( void ) +{ + devices_.clear(); + + unsigned int nDevices = getDeviceCount(); + devices_.resize( nDevices ); + for ( unsigned int i=0; i<nDevices; i++ ) + devices_[i] = getDeviceInfo( i ); +} + bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels, unsigned int firstChannel, unsigned int sampleRate, RtAudioFormat format, unsigned int *bufferSize, @@ -2482,6 +2495,12 @@ bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne return FAILURE; } + // The getDeviceInfo() function will not work when a stream is open + // because ASIO does not allow multiple devices to run at the same + // time. Thus, we'll probe the system before opening a stream and + // save the results for use by getDeviceInfo(). + this->saveDeviceInfo(); + // Only load the driver once for duplex stream. if ( mode != INPUT || stream_.mode != OUTPUT ) { if ( !drivers.loadDriver( driverName ) ) { @@ -2528,15 +2547,27 @@ bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne return FAILURE; } - // Set the sample rate. - result = ASIOSetSampleRate( (ASIOSampleRate) sampleRate ); + // Get the current sample rate + ASIOSampleRate currentRate; + result = ASIOGetSampleRate( ¤tRate ); if ( result != ASE_OK ) { drivers.removeCurrentDriver(); - errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error setting sample rate (" << sampleRate << ")."; + errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error getting sample rate."; errorText_ = errorStream_.str(); return FAILURE; } + // Set the sample rate only if necessary + if ( currentRate != sampleRate ) { + result = ASIOSetSampleRate( (ASIOSampleRate) sampleRate ); + if ( result != ASE_OK ) { + drivers.removeCurrentDriver(); + errorStream_ << "RtApiAsio::probeDeviceOpen: driver (" << driverName << ") error setting sample rate (" << sampleRate << ")."; + errorText_ = errorStream_.str(); + return FAILURE; + } + } + // Determine the driver data type. ASIOChannelInfo channelInfo; channelInfo.channel = 0; @@ -2696,7 +2727,8 @@ bool RtApiAsio :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne stream_.doConvertBuffer[mode] = true; // Allocate necessary internal buffers - unsigned long bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat ); + unsigned long bufferBytes; + bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat ); stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 ); if ( stream_.userBuffer[mode] == NULL ) { errorText_ = "RtApiAsio::probeDeviceOpen: error allocating user buffer memory."; @@ -2958,8 +2990,8 @@ bool RtApiAsio :: callbackEvent( long bufferIndex ) handle->internalDrain = true; } - unsigned int bufferBytes, i, j; - unsigned int nChannels = stream_.nDeviceChannels[0] + stream_.nDeviceChannels[1]; + unsigned int nChannels, bufferBytes, i, j; + nChannels = stream_.nDeviceChannels[0] + stream_.nDeviceChannels[1]; if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { bufferBytes = stream_.bufferSize * formatBytes( stream_.deviceFormat[0] ); @@ -3187,6 +3219,14 @@ static const char* getAsioErrorString( ASIOError result ) #include <dsound.h> #include <assert.h> +#if defined(__MINGW32__) +// missing from latest mingw winapi +#define WAVE_FORMAT_96M08 0x00010000 /* 96 kHz, Mono, 8-bit */ +#define WAVE_FORMAT_96S08 0x00020000 /* 96 kHz, Stereo, 8-bit */ +#define WAVE_FORMAT_96M16 0x00040000 /* 96 kHz, Mono, 16-bit */ +#define WAVE_FORMAT_96S16 0x00080000 /* 96 kHz, Stereo, 16-bit */ +#endif + #define MINIMUM_DEVICE_BUFFER_SIZE 32768 #ifdef _MSC_VER // if Microsoft Visual C++ @@ -3223,7 +3263,7 @@ struct DsHandle { HANDLE condition; DsHandle() - :drainCounter(0), internalDrain(false) { id[0] = 0, id[1] = 0; xrun[0] = false; xrun[1] = false; bufferPointer[0] = 0; bufferPointer[1] = 0; } + :drainCounter(0), internalDrain(false) { id[0] = 0; id[1] = 0; buffer[0] = 0; buffer[1] = 0; xrun[0] = false; xrun[1] = false; bufferPointer[0] = 0; bufferPointer[1] = 0; } }; /* @@ -3247,7 +3287,7 @@ RtApiDs::RtDsStatistics RtApiDs::getDsStatistics() // Declarations for utility functions, callbacks, and structures // specific to the DirectSound implementation. -static bool CALLBACK deviceCountCallback( LPGUID lpguid, +static BOOL CALLBACK deviceQueryCallback( LPGUID lpguid, LPCTSTR description, LPCTSTR module, LPVOID lpContext ); @@ -3288,7 +3328,7 @@ unsigned int RtApiDs :: getDefaultInputDevice( void ) { // Count output devices. EnumInfo info; - HRESULT result = DirectSoundEnumerate( (LPDSENUMCALLBACK) deviceCountCallback, &info ); + HRESULT result = DirectSoundEnumerate( (LPDSENUMCALLBACK) deviceQueryCallback, &info ); if ( FAILED( result ) ) { errorStream_ << "RtApiDs::getDefaultOutputDevice: error (" << getErrorString( result ) << ") counting output devices!"; errorText_ = errorStream_.str(); @@ -3299,7 +3339,7 @@ unsigned int RtApiDs :: getDefaultInputDevice( void ) // Now enumerate input devices until we find the id = NULL. info.isInput = true; info.getDefault = true; - result = DirectSoundCaptureEnumerate( (LPDSENUMCALLBACK) deviceCountCallback, &info ); + result = DirectSoundCaptureEnumerate( (LPDSENUMCALLBACK) deviceQueryCallback, &info ); if ( FAILED( result ) ) { errorStream_ << "RtApiDs::getDefaultInputDevice: error (" << getErrorString( result ) << ") enumerating input devices!"; errorText_ = errorStream_.str(); @@ -3316,7 +3356,7 @@ unsigned int RtApiDs :: getDefaultOutputDevice( void ) // Enumerate output devices until we find the id = NULL. EnumInfo info; info.getDefault = true; - HRESULT result = DirectSoundEnumerate( (LPDSENUMCALLBACK) deviceCountCallback, &info ); + HRESULT result = DirectSoundEnumerate( (LPDSENUMCALLBACK) deviceQueryCallback, &info ); if ( FAILED( result ) ) { errorStream_ << "RtApiDs::getDefaultOutputDevice: error (" << getErrorString( result ) << ") enumerating output devices!"; errorText_ = errorStream_.str(); @@ -3332,7 +3372,7 @@ unsigned int RtApiDs :: getDeviceCount( void ) { // Count DirectSound devices. EnumInfo info; - HRESULT result = DirectSoundEnumerate( (LPDSENUMCALLBACK) deviceCountCallback, &info ); + HRESULT result = DirectSoundEnumerate( (LPDSENUMCALLBACK) deviceQueryCallback, &info ); if ( FAILED( result ) ) { errorStream_ << "RtApiDs::getDeviceCount: error (" << getErrorString( result ) << ") enumerating output devices!"; errorText_ = errorStream_.str(); @@ -3341,7 +3381,7 @@ unsigned int RtApiDs :: getDeviceCount( void ) // Count DirectSoundCapture devices. info.isInput = true; - result = DirectSoundCaptureEnumerate( (LPDSENUMCALLBACK) deviceCountCallback, &info ); + result = DirectSoundCaptureEnumerate( (LPDSENUMCALLBACK) deviceQueryCallback, &info ); if ( FAILED( result ) ) { errorStream_ << "RtApiDs::getDeviceCount: error (" << getErrorString( result ) << ") enumerating input devices!"; errorText_ = errorStream_.str(); @@ -3366,7 +3406,7 @@ RtAudio::DeviceInfo RtApiDs :: getDeviceInfo( unsigned int device ) EnumInfo dsinfo; dsinfo.findIndex = true; dsinfo.index = device; - HRESULT result = DirectSoundEnumerate( (LPDSENUMCALLBACK) deviceCountCallback, &dsinfo ); + HRESULT result = DirectSoundEnumerate( (LPDSENUMCALLBACK) deviceQueryCallback, &dsinfo ); if ( FAILED( result ) ) { errorStream_ << "RtApiDs::getDeviceInfo: error (" << getErrorString( result ) << ") enumerating output devices!"; errorText_ = errorStream_.str(); @@ -3424,7 +3464,7 @@ RtAudio::DeviceInfo RtApiDs :: getDeviceInfo( unsigned int device ) probeInput: dsinfo.isInput = true; - result = DirectSoundCaptureEnumerate( (LPDSENUMCALLBACK) deviceCountCallback, &dsinfo ); + result = DirectSoundCaptureEnumerate( (LPDSENUMCALLBACK) deviceQueryCallback, &dsinfo ); if ( FAILED( result ) ) { errorStream_ << "RtApiDs::getDeviceInfo: error (" << getErrorString( result ) << ") enumerating input devices!"; errorText_ = errorStream_.str(); @@ -3534,7 +3574,7 @@ bool RtApiDs :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned EnumInfo dsinfo; dsinfo.findIndex = true; dsinfo.index = device; - HRESULT result = DirectSoundEnumerate( (LPDSENUMCALLBACK) deviceCountCallback, &dsinfo ); + HRESULT result = DirectSoundEnumerate( (LPDSENUMCALLBACK) deviceQueryCallback, &dsinfo ); if ( FAILED( result ) ) { errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") enumerating output devices!"; errorText_ = errorStream_.str(); @@ -3550,7 +3590,7 @@ bool RtApiDs :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned } else { // mode == INPUT dsinfo.isInput = true; - HRESULT result = DirectSoundCaptureEnumerate( (LPDSENUMCALLBACK) deviceCountCallback, &dsinfo ); + HRESULT result = DirectSoundCaptureEnumerate( (LPDSENUMCALLBACK) deviceQueryCallback, &dsinfo ); if ( FAILED( result ) ) { errorStream_ << "RtApiDs::probeDeviceOpen: error (" << getErrorString( result ) << ") enumerating input devices!"; errorText_ = errorStream_.str(); @@ -3858,6 +3898,7 @@ bool RtApiDs :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned } // Set various stream parameters + DsHandle *handle = 0; stream_.nDeviceChannels[mode] = channels + firstChannel; stream_.nUserChannels[mode] = channels; stream_.bufferSize = *bufferSize; @@ -3907,7 +3948,6 @@ bool RtApiDs :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigned } // Allocate our DsHandle structures for the stream. - DsHandle *handle; if ( stream_.apiHandle == 0 ) { try { handle = new DsHandle; @@ -4078,7 +4118,7 @@ void RtApiDs :: startStream() duplexPrerollBytes = (int) ( 0.5 * stream_.sampleRate * formatBytes( stream_.deviceFormat[1] ) * stream_.nDeviceChannels[1] ); } - HRESULT result; + HRESULT result = 0; if ( stream_.mode == OUTPUT || stream_.mode == DUPLEX ) { //statistics.outputFrameSize = formatBytes( stream_.deviceFormat[0] ) * stream_.nDeviceChannels[0]; @@ -4124,7 +4164,7 @@ void RtApiDs :: stopStream() MUTEX_LOCK( &stream_.mutex ); - HRESULT result; + HRESULT result = 0; LPVOID audioPtr; DWORD dataLen; DsHandle *handle = (DsHandle *) stream_.apiHandle; @@ -4665,7 +4705,7 @@ std::string convertTChar( LPCTSTR name ) return s; } -static bool CALLBACK deviceCountCallback( LPGUID lpguid, +static BOOL CALLBACK deviceQueryCallback( LPGUID lpguid, LPCTSTR description, LPCTSTR module, LPVOID lpContext ) @@ -4678,7 +4718,7 @@ static bool CALLBACK deviceCountCallback( LPGUID lpguid, LPDIRECTSOUNDCAPTURE object; hr = DirectSoundCaptureCreate( lpguid, &object, NULL ); - if ( hr != DS_OK ) return true; + if ( hr != DS_OK ) return TRUE; caps.dwSize = sizeof(caps); hr = object->GetCaps( &caps ); @@ -4692,7 +4732,7 @@ static bool CALLBACK deviceCountCallback( LPGUID lpguid, DSCAPS caps; LPDIRECTSOUND object; hr = DirectSoundCreate( lpguid, &object, NULL ); - if ( hr != DS_OK ) return true; + if ( hr != DS_OK ) return TRUE; caps.dwSize = sizeof(caps); hr = object->GetCaps( &caps ); @@ -4703,20 +4743,20 @@ static bool CALLBACK deviceCountCallback( LPGUID lpguid, object->Release(); } - if ( info->getDefault && lpguid == NULL ) return false; + if ( info->getDefault && lpguid == NULL ) return FALSE; if ( info->findIndex && info->counter > info->index ) { info->id = lpguid; info->name = convertTChar( description ); - return false; + return FALSE; } - return true; + return TRUE; } static char* getErrorString( int code ) { - switch (code) { + switch ( code ) { case DSERR_ALLOCATED: return "Already allocated"; @@ -5930,7 +5970,7 @@ extern "C" void *alsaCallbackHandler( void *ptr ) #include <sys/ioctl.h> #include <unistd.h> #include <fcntl.h> -#include "oss/soundcard.h" +#include "soundcard.h" #include <errno.h> #include <math.h> |
