Version 4.3.1

This commit is contained in:
Gary Scavone
2009-03-24 23:02:17 -04:00
committed by Stephen Sinclair
parent 27d9b79dc7
commit d199342e86
105 changed files with 3455 additions and 12232 deletions

View File

@@ -38,7 +38,7 @@
*/
/************************************************************************/
// RtAudio: Version 4.0
// RtAudio: Version 4.0.3
#include "RtAudio.h"
#include <iostream>
@@ -539,7 +539,7 @@ RtAudio::DeviceInfo RtApiCore :: getDeviceInfo( unsigned int device )
error( RtError::WARNING );
return info;
}
info.name.append( (const char *)name, strlen(name) + 1 );
info.name.append( (const char *)name, strlen(name) );
info.name.append( ": " );
dataSize = 256;
@@ -552,7 +552,7 @@ RtAudio::DeviceInfo RtApiCore :: getDeviceInfo( unsigned int device )
error( RtError::WARNING );
return info;
}
info.name.append( (const char *)name, strlen(name) + 1 );
info.name.append( (const char *)name, strlen(name) );
// Get the output stream "configuration".
AudioBufferList *bufferList = nil;
@@ -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( &currentRate );
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";
@@ -5906,7 +5946,9 @@ extern "C" void *alsaCallbackHandler( void *ptr )
#ifdef SCHED_RR
// Set a higher scheduler priority (P.J. Leonard)
struct sched_param param;
param.sched_priority = 39; // Is this the best number?
int min = sched_get_priority_min( SCHED_RR );
int max = sched_get_priority_max( SCHED_RR );
param.sched_priority = min + ( max - min ) / 2; // Is this the best number?
sched_setscheduler( 0, SCHED_RR, &param );
#endif
@@ -5928,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>