reorganize ASIO sound interface, not yet ready!

This commit is contained in:
Volker Fischer 2009-03-05 15:22:54 +00:00
parent bc43ed3605
commit 56c91ce201
3 changed files with 112 additions and 100 deletions

View file

@ -413,6 +413,9 @@
</item> </item>
<item> <item>
<layout class="QHBoxLayout" > <layout class="QHBoxLayout" >
<property name="spacing" >
<number>1</number>
</property>
<item> <item>
<widget class="QLabel" name="TextLabelOverallDelay" > <widget class="QLabel" name="TextLabelOverallDelay" >
<property name="sizePolicy" > <property name="sizePolicy" >

View file

@ -60,6 +60,12 @@ CSound* pSound;
\******************************************************************************/ \******************************************************************************/
void CSound::SetDev ( const int iNewDev ) void CSound::SetDev ( const int iNewDev )
{ {
// TODO do check if sound interface is running here, take action
// check if an ASIO driver was already initialized // check if an ASIO driver was already initialized
if ( lCurDev >= 0 ) if ( lCurDev >= 0 )
{ {
@ -86,6 +92,7 @@ void CSound::SetDev ( const int iNewDev )
throw CGenErr ( strErrorMessage.c_str() ); throw CGenErr ( strErrorMessage.c_str() );
} }
Init ( iBufferSizeStereo ); Init ( iBufferSizeStereo );
} }
else else
@ -120,6 +127,31 @@ void CSound::SetDev ( const int iNewDev )
} }
} }
bool CSound::LoadAndInitializeFirstValidDriver()
{
// load and initialize first valid ASIO driver
bool bValidDriverDetected = false;
int iCurDriverIdx = 0;
// try all available drivers in the system ("lNumDevs" devices)
while ( !bValidDriverDetected && ( iCurDriverIdx < lNumDevs ) )
{
if ( LoadAndInitializeDriver ( iCurDriverIdx ).empty() )
{
// initialization was successful
bValidDriverDetected = true;
// store ID of selected driver
lCurDev = iCurDriverIdx;
}
// try next driver
iCurDriverIdx++;
}
return bValidDriverDetected;
}
std::string CSound::LoadAndInitializeDriver ( int iDriverIdx ) std::string CSound::LoadAndInitializeDriver ( int iDriverIdx )
{ {
// first check and correct input parameter // first check and correct input parameter
@ -138,61 +170,39 @@ std::string CSound::LoadAndInitializeDriver ( int iDriverIdx )
return "The audio driver could not be initialized."; return "The audio driver could not be initialized.";
} }
const std::string strStat = PrepareDriver(); // check device capabilities if it fullfills our requirements
const std::string strStat = CheckDeviceCapabilities();
// store ID of selected driver if initialization was successful // store ID of selected driver if initialization was successful
if ( strStat.empty() ) if ( strStat.empty() )
{ {
lCurDev = iDriverIdx; lCurDev = iDriverIdx;
} }
else
{
// driver cannot be used, clean up
asioDrivers->removeCurrentDriver();
}
return strStat; return strStat;
} }
bool CSound::LoadAndInitializeFirstValidDriver() std::string CSound::CheckDeviceCapabilities()
{ {
// load and initialize first valid ASIO driver // This function checks if our required input/output channel
bool bValidDriverDetected = false; // properties are supported by the selected device. If the return
int iCurDriverIdx = 0; // string is empty, the device can be used, otherwise the error
// message is returned.
// try all available drivers in the system ("lNumDevs" devices) // check the sample rate
while ( !bValidDriverDetected && iCurDriverIdx < lNumDevs ) const ASIOError CanSaRateReturn = ASIOCanSampleRate ( SND_CRD_SAMPLE_RATE );
if ( ( CanSaRateReturn == ASE_NoClock ) ||
( CanSaRateReturn == ASE_NotPresent ) )
{ {
if ( loadAsioDriver ( cDriverNames[iCurDriverIdx] ) ) // return error string
{ return "The audio device does not support the "
if ( ASIOInit ( &driverInfo ) == ASE_OK ) "required sample rate.";
{
if ( PrepareDriver().empty() )
{
// initialization was successful
bValidDriverDetected = true;
// store ID of selected driver
lCurDev = iCurDriverIdx;
} }
else
{
// driver could not be loaded, free memory
asioDrivers->removeCurrentDriver();
}
}
else
{
// driver could not be loaded, free memory
asioDrivers->removeCurrentDriver();
}
}
// try next driver
iCurDriverIdx++;
}
return bValidDriverDetected;
}
std::string CSound::PrepareDriver()
{
int i;
// check the number of available channels // check the number of available channels
long lNumInChan; long lNumInChan;
@ -201,56 +211,24 @@ std::string CSound::PrepareDriver()
if ( ( lNumInChan < NUM_IN_OUT_CHANNELS ) || if ( ( lNumInChan < NUM_IN_OUT_CHANNELS ) ||
( lNumOutChan < NUM_IN_OUT_CHANNELS ) ) ( lNumOutChan < NUM_IN_OUT_CHANNELS ) )
{ {
// clean up and return error string // return error string
ASIOExit();
asioDrivers->removeCurrentDriver();
return "The audio device does not support the " return "The audio device does not support the "
"required number of channels."; "required number of channels.";
} }
// set the sample rate and check if sample rate is supported // check sample format
ASIOSetSampleRate ( SND_CRD_SAMPLE_RATE ); for ( int i = 0; i < 2 * NUM_IN_OUT_CHANNELS; i++ )
ASIOSampleRate sampleRate;
ASIOGetSampleRate ( &sampleRate );
if ( sampleRate != SND_CRD_SAMPLE_RATE )
{ {
// clean up and return error string // check all used input and output channels
ASIOExit(); channelInfos[i].channel = i % NUM_IN_OUT_CHANNELS;
asioDrivers->removeCurrentDriver(); if ( i < NUM_IN_OUT_CHANNELS )
return "The audio device does not support the " {
"required sample rate."; channelInfos[i].isInput = ASIOTrue;
} }
else
// TEST
iASIOBufferSizeMono = GetActualBufferSize ( iBufferSizeMono );
for ( i = 0; i < NUM_IN_OUT_CHANNELS; i++ )
{ {
// prepare input channels channelInfos[i].isInput = ASIOFalse;
bufferInfos[i].isInput = ASIOTrue;
bufferInfos[i].channelNum = i;
bufferInfos[i].buffers[0] = 0;
bufferInfos[i].buffers[1] = 0;
// prepare output channels
bufferInfos[NUM_IN_OUT_CHANNELS + i].isInput = ASIOFalse;
bufferInfos[NUM_IN_OUT_CHANNELS + i].channelNum = i;
bufferInfos[NUM_IN_OUT_CHANNELS + i].buffers[0] = 0;
bufferInfos[NUM_IN_OUT_CHANNELS + i].buffers[1] = 0;
} }
// create and activate ASIO buffers (buffer size in samples)
ASIOCreateBuffers ( bufferInfos, 2 /* in/out */ * NUM_IN_OUT_CHANNELS /* stereo */,
iASIOBufferSizeMono, &asioCallbacks );
// now get some buffer details
for ( i = 0; i < 2 * NUM_IN_OUT_CHANNELS; i++ )
{
channelInfos[i].channel = bufferInfos[i].channelNum;
channelInfos[i].isInput = bufferInfos[i].isInput;
ASIOGetChannelInfo ( &channelInfos[i] ); ASIOGetChannelInfo ( &channelInfos[i] );
// only 16/24/32 LSB is supported // only 16/24/32 LSB is supported
@ -258,18 +236,12 @@ iASIOBufferSizeMono = GetActualBufferSize ( iBufferSizeMono );
( channelInfos[i].type != ASIOSTInt24LSB ) && ( channelInfos[i].type != ASIOSTInt24LSB ) &&
( channelInfos[i].type != ASIOSTInt32LSB ) ) ( channelInfos[i].type != ASIOSTInt32LSB ) )
{ {
// clean up and return error string // return error string
ASIODisposeBuffers(); return "Required audio sample format not "
ASIOExit(); "available (16/24/32 bit LSB).";
asioDrivers->removeCurrentDriver();
return "Required audio sample format not available (16/24/32 bit LSB).";
} }
} }
// check wether the driver requires the ASIOOutputReady() optimization
// (can be used by the driver to reduce output latency by one block)
bASIOPostOutput = ( ASIOOutputReady() == ASE_OK );
return ""; return "";
} }
@ -359,9 +331,6 @@ int CSound::Init ( const int iNewPrefMonoBufferSize )
iBufferSizeMono = iNewPrefMonoBufferSize; iBufferSizeMono = iNewPrefMonoBufferSize;
iBufferSizeStereo = 2 * iBufferSizeMono; iBufferSizeStereo = 2 * iBufferSizeMono;
// TEST
PrepareDriver();
// TODO possible BUG!!!!!!!!!!!!!!!!!!!!! // TODO possible BUG!!!!!!!!!!!!!!!!!!!!!
// iBufferSizeMono must not be the same as iASIOBufferSizeMono // iBufferSizeMono must not be the same as iASIOBufferSizeMono
@ -369,6 +338,47 @@ PrepareDriver();
// create memory for intermediate audio buffer // create memory for intermediate audio buffer
vecsTmpAudioSndCrdStereo.Init ( iBufferSizeStereo ); vecsTmpAudioSndCrdStereo.Init ( iBufferSizeStereo );
int i;
// set the sample rate and check if sample rate is supported
ASIOSetSampleRate ( SND_CRD_SAMPLE_RATE );
// TEST
iASIOBufferSizeMono = GetActualBufferSize ( iBufferSizeMono );
for ( i = 0; i < NUM_IN_OUT_CHANNELS; i++ )
{
// prepare input channels
bufferInfos[i].isInput = ASIOTrue;
bufferInfos[i].channelNum = i;
bufferInfos[i].buffers[0] = 0;
bufferInfos[i].buffers[1] = 0;
// prepare output channels
bufferInfos[NUM_IN_OUT_CHANNELS + i].isInput = ASIOFalse;
bufferInfos[NUM_IN_OUT_CHANNELS + i].channelNum = i;
bufferInfos[NUM_IN_OUT_CHANNELS + i].buffers[0] = 0;
bufferInfos[NUM_IN_OUT_CHANNELS + i].buffers[1] = 0;
}
// create and activate ASIO buffers (buffer size in samples)
ASIOCreateBuffers ( bufferInfos, 2 /* in/out */ * NUM_IN_OUT_CHANNELS /* stereo */,
iASIOBufferSizeMono, &asioCallbacks );
// check wether the driver requires the ASIOOutputReady() optimization
// (can be used by the driver to reduce output latency by one block)
bASIOPostOutput = ( ASIOOutputReady() == ASE_OK );
} }
ASIOMutex.unlock(); ASIOMutex.unlock();
@ -407,7 +417,6 @@ pSound = this;
{ {
throw CGenErr ( "No ASIO audio device (driver) found." ); throw CGenErr ( "No ASIO audio device (driver) found." );
} }
asioDrivers->removeCurrentDriver(); asioDrivers->removeCurrentDriver();
// init device index with illegal value to show that driver is not initialized // init device index with illegal value to show that driver is not initialized

View file

@ -73,8 +73,8 @@ public:
protected: protected:
bool LoadAndInitializeFirstValidDriver(); bool LoadAndInitializeFirstValidDriver();
std::string LoadAndInitializeDriver ( int iIdx ); std::string LoadAndInitializeDriver ( int iIdx );
std::string PrepareDriver();
int GetActualBufferSize ( const int iDesiredBufferSizeMono ); int GetActualBufferSize ( const int iDesiredBufferSizeMono );
std::string CheckDeviceCapabilities();
// audio hardware buffer info // audio hardware buffer info
struct sHWBufferInfo struct sHWBufferInfo