reorganize ASIO sound interface, not yet ready!
This commit is contained in:
parent
bc43ed3605
commit
56c91ce201
3 changed files with 112 additions and 100 deletions
|
@ -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" >
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue