put ASIO member variables in class, prepared for ASIO input/output channel selection

This commit is contained in:
Volker Fischer 2010-03-19 20:23:31 +00:00
parent 29eb59d464
commit 9828ceec81
2 changed files with 557 additions and 511 deletions

View file

@ -33,24 +33,7 @@
extern AsioDrivers* asioDrivers; extern AsioDrivers* asioDrivers;
bool loadAsioDriver ( char *name ); bool loadAsioDriver ( char *name );
// TODO the following variables should be in the class definition but we cannot // pointer to our sound object
// do it here since we have static callback functions which cannot access the
// class members :-(((
// ASIO stuff
ASIODriverInfo driverInfo;
ASIOBufferInfo bufferInfos[2 * NUM_IN_OUT_CHANNELS]; // for input and output buffers -> "2 *"
ASIOChannelInfo channelInfos[2 * NUM_IN_OUT_CHANNELS];
bool bASIOPostOutput;
ASIOCallbacks asioCallbacks;
int iASIOBufferSizeMono;
int iASIOBufferSizeStereo;
CVector<int16_t> vecsTmpAudioSndCrdStereo;
QMutex ASIOMutex;
// TEST
CSound* pSound; CSound* pSound;
@ -115,7 +98,7 @@ QString CSound::SetDev ( const int iNewDev )
// the first available driver in the system. If this fails, too, we // the first available driver in the system. If this fails, too, we
// throw an error that no driver is available -> it does not make // throw an error that no driver is available -> it does not make
// sense to start the llcon software if no audio hardware is // sense to start the llcon software if no audio hardware is
// available // available.
if ( !LoadAndInitializeDriver ( iNewDev ).isEmpty() ) if ( !LoadAndInitializeDriver ( iNewDev ).isEmpty() )
{ {
// loading and initializing the new driver failed, try to find // loading and initializing the new driver failed, try to find
@ -257,43 +240,58 @@ QString CSound::CheckDeviceCapabilities()
// return error string // return error string
return tr ( "The audio device does not support the " return tr ( "The audio device does not support the "
"required number of channels. The required number of channels " "required number of channels. The required number of channels "
"is: " ) + QString().setNum ( NUM_IN_OUT_CHANNELS ); "for input and output is: " ) +
QString().setNum ( NUM_IN_OUT_CHANNELS );
} }
// check sample format // clip number of input/output channels to our maximum
for ( int i = 0; i < 2 * NUM_IN_OUT_CHANNELS; i++ ) if ( lNumInChan > MAX_NUM_IN_OUT_CHANNELS )
{ {
// check all used input and output channels lNumInChan = MAX_NUM_IN_OUT_CHANNELS;
channelInfos[i].channel = i % NUM_IN_OUT_CHANNELS;
if ( i < NUM_IN_OUT_CHANNELS )
{
channelInfos[i].isInput = ASIOTrue;
} }
else if ( lNumOutChan > MAX_NUM_IN_OUT_CHANNELS )
{ {
channelInfos[i].isInput = ASIOFalse; lNumOutChan = MAX_NUM_IN_OUT_CHANNELS;
} }
ASIOGetChannelInfo ( &channelInfos[i] );
// check supported sample formats // query channel infos for all available input channels
if ( ( channelInfos[i].type != ASIOSTInt16LSB ) && for ( int i = 0; i < lNumInChan; i++ )
( channelInfos[i].type != ASIOSTInt24LSB ) && {
( channelInfos[i].type != ASIOSTInt32LSB ) && // setup for input channels
( channelInfos[i].type != ASIOSTFloat32LSB ) && channelInfosInput[i].isInput = ASIOTrue;
( channelInfos[i].type != ASIOSTFloat64LSB ) && channelInfosInput[i].channel = i;
( channelInfos[i].type != ASIOSTInt32LSB16 ) &&
( channelInfos[i].type != ASIOSTInt32LSB18 ) && ASIOGetChannelInfo ( &channelInfosInput[i] );
( channelInfos[i].type != ASIOSTInt32LSB20 ) &&
( channelInfos[i].type != ASIOSTInt32LSB24 ) && // Check supported sample formats.
( channelInfos[i].type != ASIOSTInt16MSB ) && // Actually, it would be enough to have at least two channels which
( channelInfos[i].type != ASIOSTInt24MSB ) && // support the required sample format. But since we have support for
( channelInfos[i].type != ASIOSTInt32MSB ) && // all known sample types, the following check should always pass and
( channelInfos[i].type != ASIOSTFloat32MSB ) && // therefore we throw the error message on any channel which does not
( channelInfos[i].type != ASIOSTFloat64MSB ) && // fullfill the sample format requirement (quick hack solution).
( channelInfos[i].type != ASIOSTInt32MSB16 ) && if ( !CheckSampleTypeSupported ( channelInfosInput[i].type ) )
( channelInfos[i].type != ASIOSTInt32MSB18 ) && {
( channelInfos[i].type != ASIOSTInt32MSB20 ) && // return error string
( channelInfos[i].type != ASIOSTInt32MSB24 ) ) return tr ( "Required audio sample format not available." );
}
}
// query channel infos for all available output channels
for ( int i = 0; i < lNumOutChan; i++ )
{
// setup for output channels
channelInfosOutput[i].isInput = ASIOFalse;
channelInfosOutput[i].channel = i;
ASIOGetChannelInfo ( &channelInfosOutput[i] );
// Check supported sample formats.
// Actually, it would be enough to have at least two channels which
// support the required sample format. But since we have support for
// all known sample types, the following check should always pass and
// therefore we throw the error message on any channel which does not
// fullfill the sample format requirement (quick hack solution).
if ( !CheckSampleTypeSupported ( channelInfosOutput[i].type ) )
{ {
// return error string // return error string
return tr ( "Required audio sample format not available." ); return tr ( "Required audio sample format not available." );
@ -435,6 +433,24 @@ int CSound::Init ( const int iNewPrefMonoBufferSize )
// create and activate ASIO buffers (buffer size in samples), // create and activate ASIO buffers (buffer size in samples),
// dispose old buffers (if any) // dispose old buffers (if any)
ASIODisposeBuffers(); ASIODisposeBuffers();
// init buffer infos, we always want to have two input and
// two output channels
for ( int i = 0; i < NUM_IN_OUT_CHANNELS; i++ )
{
// prepare input channels
bufferInfos[i].isInput = ASIOTrue;
bufferInfos[i].channelNum = vSelectedInputChannels[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 = vSelectedOutputChannels[i];
bufferInfos[NUM_IN_OUT_CHANNELS + i].buffers[0] = 0;
bufferInfos[NUM_IN_OUT_CHANNELS + i].buffers[1] = 0;
}
ASIOCreateBuffers ( bufferInfos, ASIOCreateBuffers ( bufferInfos,
2 /* in/out */ * NUM_IN_OUT_CHANNELS /* stereo */, 2 /* in/out */ * NUM_IN_OUT_CHANNELS /* stereo */,
iASIOBufferSizeMono, &asioCallbacks ); iASIOBufferSizeMono, &asioCallbacks );
@ -467,13 +483,14 @@ void CSound::Stop()
} }
CSound::CSound ( void (*fpNewCallback) ( CVector<int16_t>& psData, void* arg ), void* arg ) : CSound::CSound ( void (*fpNewCallback) ( CVector<int16_t>& psData, void* arg ), void* arg ) :
CSoundBase ( true, fpNewCallback, arg ) CSoundBase ( true, fpNewCallback, arg ),
vSelectedInputChannels ( NUM_IN_OUT_CHANNELS ),
vSelectedOutputChannels ( NUM_IN_OUT_CHANNELS )
{ {
int i; int i;
// TEST // init pointer to our sound object
pSound = this; pSound = this;
// get available ASIO driver names in system // get available ASIO driver names in system
for ( i = 0; i < MAX_NUMBER_SOUND_CARDS; i++ ) for ( i = 0; i < MAX_NUMBER_SOUND_CARDS; i++ )
@ -500,22 +517,12 @@ pSound = this;
// 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
lCurDev = -1; lCurDev = -1;
// init buffer infos, we always want to have two input and // init selected channel numbers with defaults: use first available
// two output channels // channels for input and output
for ( i = 0; i < NUM_IN_OUT_CHANNELS; i++ ) vSelectedInputChannels[0] = 0;
{ vSelectedInputChannels[1] = 1;
// prepare input channels vSelectedOutputChannels[0] = 0;
bufferInfos[i].isInput = ASIOTrue; vSelectedOutputChannels[1] = 1;
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;
}
// set up the asioCallback structure // set up the asioCallback structure
asioCallbacks.bufferSwitch = &bufferSwitch; asioCallbacks.bufferSwitch = &bufferSwitch;
@ -542,336 +549,357 @@ ASIOTime* CSound::bufferSwitchTimeInfo ( ASIOTime* timeInfo,
return 0L; return 0L;
} }
bool CSound::CheckSampleTypeSupported ( const ASIOSampleType SamType )
{
// check for supported sample types
return ( ( SamType == ASIOSTInt16LSB ) ||
( SamType == ASIOSTInt24LSB ) ||
( SamType == ASIOSTInt32LSB ) ||
( SamType == ASIOSTFloat32LSB ) ||
( SamType == ASIOSTFloat64LSB ) ||
( SamType == ASIOSTInt32LSB16 ) ||
( SamType == ASIOSTInt32LSB18 ) ||
( SamType == ASIOSTInt32LSB20 ) ||
( SamType == ASIOSTInt32LSB24 ) ||
( SamType == ASIOSTInt16MSB ) ||
( SamType == ASIOSTInt24MSB ) ||
( SamType == ASIOSTInt32MSB ) ||
( SamType == ASIOSTFloat32MSB ) ||
( SamType == ASIOSTFloat64MSB ) ||
( SamType == ASIOSTInt32MSB16 ) ||
( SamType == ASIOSTInt32MSB18 ) ||
( SamType == ASIOSTInt32MSB20 ) ||
( SamType == ASIOSTInt32MSB24 ) );
}
void CSound::bufferSwitch ( long index, ASIOBool processNow ) void CSound::bufferSwitch ( long index, ASIOBool processNow )
{ {
int iCurSample; int iCurSample;
ASIOMutex.lock(); // get mutex lock
{
// perform the processing for input and output // perform the processing for input and output
for ( int i = 0; i < 2 * NUM_IN_OUT_CHANNELS; i++ ) // stereo pSound->ASIOMutex.lock(); // get mutex lock
{ {
if ( bufferInfos[i].isInput == ASIOTrue ) // CAPTURE -------------------------------------------------------------
for ( int i = 0; i < NUM_IN_OUT_CHANNELS; i++ )
{ {
// CAPTURE ----------------------------------------------------- const int iInChNum = i;
// copy new captured block in thread transfer buffer (copy // copy new captured block in thread transfer buffer (copy
// mono data interleaved in stereo buffer) // mono data interleaved in stereo buffer)
switch ( channelInfos[i].type ) switch ( pSound->channelInfosInput[pSound->vSelectedInputChannels[i]].type )
{ {
case ASIOSTInt16LSB: case ASIOSTInt16LSB:
// no type conversion required, just copy operation // no type conversion required, just copy operation
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] = pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iInChNum] =
static_cast<int16_t*> ( bufferInfos[i].buffers[index] )[iCurSample]; static_cast<int16_t*> ( pSound->bufferInfos[i].buffers[index] )[iCurSample];
} }
break; break;
case ASIOSTInt24LSB: case ASIOSTInt24LSB:
// NOT YET TESTED // NOT YET TESTED
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
int iCurSam = 0; int iCurSam = 0;
memcpy ( &iCurSam, ( (char*) bufferInfos[i].buffers[index] ) + iCurSample * 3, 3 ); memcpy ( &iCurSam, ( (char*) pSound->bufferInfos[i].buffers[index] ) + iCurSample * 3, 3 );
iCurSam >>= 8; iCurSam >>= 8;
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] = pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iInChNum] =
static_cast<int16_t> ( iCurSam ); static_cast<int16_t> ( iCurSam );
} }
break; break;
case ASIOSTInt32LSB: case ASIOSTInt32LSB:
// NOT YET TESTED // NOT YET TESTED
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] = pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iInChNum] =
static_cast<int16_t> ( static_cast<int32_t*> ( static_cast<int16_t> ( static_cast<int32_t*> (
bufferInfos[i].buffers[index] )[iCurSample] >> 16 ); pSound->bufferInfos[i].buffers[index] )[iCurSample] >> 16 );
} }
break; break;
case ASIOSTFloat32LSB: // IEEE 754 32 bit float, as found on Intel x86 architecture case ASIOSTFloat32LSB: // IEEE 754 32 bit float, as found on Intel x86 architecture
// NOT YET TESTED // NOT YET TESTED
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] = pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iInChNum] =
static_cast<int16_t> ( static_cast<float*> ( static_cast<int16_t> ( static_cast<float*> (
bufferInfos[i].buffers[index] )[iCurSample] * _MAXSHORT ); pSound->bufferInfos[i].buffers[index] )[iCurSample] * _MAXSHORT );
} }
break; break;
case ASIOSTFloat64LSB: // IEEE 754 64 bit double float, as found on Intel x86 architecture case ASIOSTFloat64LSB: // IEEE 754 64 bit double float, as found on Intel x86 architecture
// NOT YET TESTED // NOT YET TESTED
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] = pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iInChNum] =
static_cast<int16_t> ( static_cast<double*> ( static_cast<int16_t> ( static_cast<double*> (
bufferInfos[i].buffers[index] )[iCurSample] * _MAXSHORT ); pSound->bufferInfos[i].buffers[index] )[iCurSample] * _MAXSHORT );
} }
break; break;
case ASIOSTInt32LSB16: // 32 bit data with 16 bit alignment case ASIOSTInt32LSB16: // 32 bit data with 16 bit alignment
// NOT YET TESTED // NOT YET TESTED
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] = pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iInChNum] =
static_cast<int16_t> ( static_cast<int32_t*> ( static_cast<int16_t> ( static_cast<int32_t*> (
bufferInfos[i].buffers[index] )[iCurSample] & 0xFFFF ); pSound->bufferInfos[i].buffers[index] )[iCurSample] & 0xFFFF );
} }
break; break;
case ASIOSTInt32LSB18: // 32 bit data with 18 bit alignment case ASIOSTInt32LSB18: // 32 bit data with 18 bit alignment
// NOT YET TESTED // NOT YET TESTED
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] = pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iInChNum] =
static_cast<int16_t> ( ( static_cast<int32_t*> ( static_cast<int16_t> ( ( static_cast<int32_t*> (
bufferInfos[i].buffers[index] )[iCurSample] & 0x3FFFF ) >> 2 ); pSound->bufferInfos[i].buffers[index] )[iCurSample] & 0x3FFFF ) >> 2 );
} }
break; break;
case ASIOSTInt32LSB20: // 32 bit data with 20 bit alignment case ASIOSTInt32LSB20: // 32 bit data with 20 bit alignment
// NOT YET TESTED // NOT YET TESTED
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] = pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iInChNum] =
static_cast<int16_t> ( ( static_cast<int32_t*> ( static_cast<int16_t> ( ( static_cast<int32_t*> (
bufferInfos[i].buffers[index] )[iCurSample] & 0xFFFFF ) >> 4 ); pSound->bufferInfos[i].buffers[index] )[iCurSample] & 0xFFFFF ) >> 4 );
} }
break; break;
case ASIOSTInt32LSB24: // 32 bit data with 24 bit alignment case ASIOSTInt32LSB24: // 32 bit data with 24 bit alignment
// NOT YET TESTED // NOT YET TESTED
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] = pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iInChNum] =
static_cast<int16_t> ( ( static_cast<int32_t*> ( static_cast<int16_t> ( ( static_cast<int32_t*> (
bufferInfos[i].buffers[index] )[iCurSample] & 0xFFFFFF ) >> 8 ); pSound->bufferInfos[i].buffers[index] )[iCurSample] & 0xFFFFFF ) >> 8 );
} }
break; break;
case ASIOSTInt16MSB: case ASIOSTInt16MSB:
// NOT YET TESTED // NOT YET TESTED
// flip bits // flip bits
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] = pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iInChNum] =
Flip16Bits ( ( static_cast<int16_t*> ( Flip16Bits ( ( static_cast<int16_t*> (
bufferInfos[i].buffers[index] ) )[iCurSample] ); pSound->bufferInfos[i].buffers[index] ) )[iCurSample] );
} }
break; break;
case ASIOSTInt24MSB: case ASIOSTInt24MSB:
// NOT YET TESTED // NOT YET TESTED
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
// because the bits are flipped, we do not have to perform the // because the bits are flipped, we do not have to perform the
// shift by 8 bits // shift by 8 bits
int iCurSam = 0; int iCurSam = 0;
memcpy ( &iCurSam, ( (char*) bufferInfos[i].buffers[index] ) + iCurSample * 3, 3 ); memcpy ( &iCurSam, ( (char*) pSound->bufferInfos[i].buffers[index] ) + iCurSample * 3, 3 );
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] = pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iInChNum] =
Flip16Bits ( static_cast<int16_t> ( iCurSam ) ); Flip16Bits ( static_cast<int16_t> ( iCurSam ) );
} }
break; break;
case ASIOSTInt32MSB: case ASIOSTInt32MSB:
// NOT YET TESTED // NOT YET TESTED
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
// flip bits and convert to 16 bit // flip bits and convert to 16 bit
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] = pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iInChNum] =
static_cast<int16_t> ( Flip32Bits ( static_cast<int32_t*> ( static_cast<int16_t> ( Flip32Bits ( static_cast<int32_t*> (
bufferInfos[i].buffers[index] )[iCurSample] ) >> 16 ); pSound->bufferInfos[i].buffers[index] )[iCurSample] ) >> 16 );
} }
break; break;
case ASIOSTFloat32MSB: // IEEE 754 32 bit float, as found on Intel x86 architecture case ASIOSTFloat32MSB: // IEEE 754 32 bit float, as found on Intel x86 architecture
// NOT YET TESTED // NOT YET TESTED
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] = pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iInChNum] =
static_cast<int16_t> ( static_cast<float> ( static_cast<int16_t> ( static_cast<float> (
Flip32Bits ( static_cast<int32_t*> ( Flip32Bits ( static_cast<int32_t*> (
bufferInfos[i].buffers[index] )[iCurSample] ) ) * _MAXSHORT ); pSound->bufferInfos[i].buffers[index] )[iCurSample] ) ) * _MAXSHORT );
} }
break; break;
case ASIOSTFloat64MSB: // IEEE 754 64 bit double float, as found on Intel x86 architecture case ASIOSTFloat64MSB: // IEEE 754 64 bit double float, as found on Intel x86 architecture
// NOT YET TESTED // NOT YET TESTED
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] = pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iInChNum] =
static_cast<int16_t> ( static_cast<double> ( static_cast<int16_t> ( static_cast<double> (
Flip64Bits ( static_cast<int64_t*> ( Flip64Bits ( static_cast<int64_t*> (
bufferInfos[i].buffers[index] )[iCurSample] ) ) * _MAXSHORT ); pSound->bufferInfos[i].buffers[index] )[iCurSample] ) ) * _MAXSHORT );
} }
break; break;
case ASIOSTInt32MSB16: // 32 bit data with 16 bit alignment case ASIOSTInt32MSB16: // 32 bit data with 16 bit alignment
// NOT YET TESTED // NOT YET TESTED
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] = pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iInChNum] =
static_cast<int16_t> ( Flip32Bits ( static_cast<int32_t*> ( static_cast<int16_t> ( Flip32Bits ( static_cast<int32_t*> (
bufferInfos[i].buffers[index] )[iCurSample] ) & 0xFFFF ); pSound->bufferInfos[i].buffers[index] )[iCurSample] ) & 0xFFFF );
} }
break; break;
case ASIOSTInt32MSB18: // 32 bit data with 18 bit alignment case ASIOSTInt32MSB18: // 32 bit data with 18 bit alignment
// NOT YET TESTED // NOT YET TESTED
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] = pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iInChNum] =
static_cast<int16_t> ( ( Flip32Bits ( static_cast<int32_t*> ( static_cast<int16_t> ( ( Flip32Bits ( static_cast<int32_t*> (
bufferInfos[i].buffers[index] )[iCurSample] ) & 0x3FFFF ) >> 2 ); pSound->bufferInfos[i].buffers[index] )[iCurSample] ) & 0x3FFFF ) >> 2 );
} }
break; break;
case ASIOSTInt32MSB20: // 32 bit data with 20 bit alignment case ASIOSTInt32MSB20: // 32 bit data with 20 bit alignment
// NOT YET TESTED // NOT YET TESTED
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] = pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iInChNum] =
static_cast<int16_t> ( ( Flip32Bits ( static_cast<int32_t*> ( static_cast<int16_t> ( ( Flip32Bits ( static_cast<int32_t*> (
bufferInfos[i].buffers[index] )[iCurSample] ) & 0xFFFFF ) >> 4 ); pSound->bufferInfos[i].buffers[index] )[iCurSample] ) & 0xFFFFF ) >> 4 );
} }
break; break;
case ASIOSTInt32MSB24: // 32 bit data with 24 bit alignment case ASIOSTInt32MSB24: // 32 bit data with 24 bit alignment
// NOT YET TESTED // NOT YET TESTED
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] = pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iInChNum] =
static_cast<int16_t> ( ( Flip32Bits ( static_cast<int32_t*> ( static_cast<int16_t> ( ( Flip32Bits ( static_cast<int32_t*> (
bufferInfos[i].buffers[index] )[iCurSample] ) & 0xFFFFFF ) >> 8 ); pSound->bufferInfos[i].buffers[index] )[iCurSample] ) & 0xFFFFFF ) >> 8 );
} }
break; break;
} }
} }
}
// call processing callback function // call processing callback function
pSound->ProcessCallback ( vecsTmpAudioSndCrdStereo ); pSound->ProcessCallback ( pSound->vecsTmpAudioSndCrdStereo );
// perform the processing for input and output // PLAYBACK ------------------------------------------------------------
for ( int i = 0; i < 2 * NUM_IN_OUT_CHANNELS; i++ ) // stereo for ( int i = NUM_IN_OUT_CHANNELS; i < 2 * NUM_IN_OUT_CHANNELS; i++ )
{ {
if ( bufferInfos[i].isInput != ASIOTrue ) const int iOutChNum = i - NUM_IN_OUT_CHANNELS;
{
// PLAYBACK ----------------------------------------------------
// copy data from sound card in output buffer (copy // copy data from sound card in output buffer (copy
// interleaved stereo data in mono sound card buffer) // interleaved stereo data in mono sound card buffer)
switch ( channelInfos[i].type ) switch ( pSound->channelInfosOutput[pSound->vSelectedOutputChannels[iOutChNum]].type )
{ {
case ASIOSTInt16LSB: case ASIOSTInt16LSB:
// no type conversion required, just copy operation // no type conversion required, just copy operation
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
static_cast<int16_t*> ( bufferInfos[i].buffers[index] )[iCurSample] = static_cast<int16_t*> ( pSound->bufferInfos[i].buffers[index] )[iCurSample] =
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum]; pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iOutChNum];
} }
break; break;
case ASIOSTInt24LSB: case ASIOSTInt24LSB:
// NOT YET TESTED // NOT YET TESTED
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
// convert current sample in 24 bit format // convert current sample in 24 bit format
int32_t iCurSam = static_cast<int32_t> ( int32_t iCurSam = static_cast<int32_t> (
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] ); pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iOutChNum] );
iCurSam <<= 8; iCurSam <<= 8;
memcpy ( ( (char*) bufferInfos[i].buffers[index] ) + iCurSample * 3, &iCurSam, 3 ); memcpy ( ( (char*) pSound->bufferInfos[i].buffers[index] ) + iCurSample * 3, &iCurSam, 3 );
} }
break; break;
case ASIOSTInt32LSB: case ASIOSTInt32LSB:
// NOT YET TESTED // NOT YET TESTED
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
// convert to 32 bit // convert to 32 bit
const int32_t iCurSam = static_cast<int32_t> ( const int32_t iCurSam = static_cast<int32_t> (
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] ); pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iOutChNum] );
static_cast<int32_t*> ( bufferInfos[i].buffers[index] )[iCurSample] = static_cast<int32_t*> ( pSound->bufferInfos[i].buffers[index] )[iCurSample] =
( iCurSam << 16 ); ( iCurSam << 16 );
} }
break; break;
case ASIOSTFloat32LSB: // IEEE 754 32 bit float, as found on Intel x86 architecture case ASIOSTFloat32LSB: // IEEE 754 32 bit float, as found on Intel x86 architecture
// NOT YET TESTED // NOT YET TESTED
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
const float fCurSam = static_cast<float> ( const float fCurSam = static_cast<float> (
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] ); pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iOutChNum] );
static_cast<float*> ( bufferInfos[i].buffers[index] )[iCurSample] = static_cast<float*> ( pSound->bufferInfos[i].buffers[index] )[iCurSample] =
fCurSam / _MAXSHORT; fCurSam / _MAXSHORT;
} }
break; break;
case ASIOSTFloat64LSB: // IEEE 754 64 bit double float, as found on Intel x86 architecture case ASIOSTFloat64LSB: // IEEE 754 64 bit double float, as found on Intel x86 architecture
// NOT YET TESTED // NOT YET TESTED
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
const double fCurSam = static_cast<double> ( const double fCurSam = static_cast<double> (
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] ); pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iOutChNum] );
static_cast<double*> ( bufferInfos[i].buffers[index] )[iCurSample] = static_cast<double*> ( pSound->bufferInfos[i].buffers[index] )[iCurSample] =
fCurSam / _MAXSHORT; fCurSam / _MAXSHORT;
} }
break; break;
case ASIOSTInt32LSB16: // 32 bit data with 16 bit alignment case ASIOSTInt32LSB16: // 32 bit data with 16 bit alignment
// NOT YET TESTED // NOT YET TESTED
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
// convert to 32 bit // convert to 32 bit
const int32_t iCurSam = static_cast<int32_t> ( const int32_t iCurSam = static_cast<int32_t> (
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] ); pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iOutChNum] );
static_cast<int32_t*> ( bufferInfos[i].buffers[index] )[iCurSample] = static_cast<int32_t*> ( pSound->bufferInfos[i].buffers[index] )[iCurSample] =
iCurSam; iCurSam;
} }
break; break;
case ASIOSTInt32LSB18: // 32 bit data with 18 bit alignment case ASIOSTInt32LSB18: // 32 bit data with 18 bit alignment
// NOT YET TESTED // NOT YET TESTED
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
// convert to 32 bit // convert to 32 bit
const int32_t iCurSam = static_cast<int32_t> ( const int32_t iCurSam = static_cast<int32_t> (
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] ); pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iOutChNum] );
static_cast<int32_t*> ( bufferInfos[i].buffers[index] )[iCurSample] = static_cast<int32_t*> ( pSound->bufferInfos[i].buffers[index] )[iCurSample] =
( iCurSam << 2 ); ( iCurSam << 2 );
} }
break; break;
case ASIOSTInt32LSB20: // 32 bit data with 20 bit alignment case ASIOSTInt32LSB20: // 32 bit data with 20 bit alignment
// NOT YET TESTED // NOT YET TESTED
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
// convert to 32 bit // convert to 32 bit
const int32_t iCurSam = static_cast<int32_t> ( const int32_t iCurSam = static_cast<int32_t> (
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] ); pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iOutChNum] );
static_cast<int32_t*> ( bufferInfos[i].buffers[index] )[iCurSample] = static_cast<int32_t*> ( pSound->bufferInfos[i].buffers[index] )[iCurSample] =
( iCurSam << 4 ); ( iCurSam << 4 );
} }
break; break;
case ASIOSTInt32LSB24: // 32 bit data with 24 bit alignment case ASIOSTInt32LSB24: // 32 bit data with 24 bit alignment
// NOT YET TESTED // NOT YET TESTED
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
// convert to 32 bit // convert to 32 bit
const int32_t iCurSam = static_cast<int32_t> ( const int32_t iCurSam = static_cast<int32_t> (
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] ); pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iOutChNum] );
static_cast<int32_t*> ( bufferInfos[i].buffers[index] )[iCurSample] = static_cast<int32_t*> ( pSound->bufferInfos[i].buffers[index] )[iCurSample] =
( iCurSam << 8 ); ( iCurSam << 8 );
} }
break; break;
@ -879,47 +907,47 @@ void CSound::bufferSwitch ( long index, ASIOBool processNow )
case ASIOSTInt16MSB: case ASIOSTInt16MSB:
// NOT YET TESTED // NOT YET TESTED
// flip bits // flip bits
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
( (int16_t*) bufferInfos[i].buffers[index] )[iCurSample] = ( (int16_t*) pSound->bufferInfos[i].buffers[index] )[iCurSample] =
Flip16Bits ( vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] ); Flip16Bits ( pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iOutChNum] );
} }
break; break;
case ASIOSTInt24MSB: case ASIOSTInt24MSB:
// NOT YET TESTED // NOT YET TESTED
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
// because the bits are flipped, we do not have to perform the // because the bits are flipped, we do not have to perform the
// shift by 8 bits // shift by 8 bits
int32_t iCurSam = static_cast<int32_t> ( Flip16Bits ( int32_t iCurSam = static_cast<int32_t> ( Flip16Bits (
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] ) ); pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iOutChNum] ) );
memcpy ( ( (char*) bufferInfos[i].buffers[index] ) + iCurSample * 3, &iCurSam, 3 ); memcpy ( ( (char*) pSound->bufferInfos[i].buffers[index] ) + iCurSample * 3, &iCurSam, 3 );
} }
break; break;
case ASIOSTInt32MSB: case ASIOSTInt32MSB:
// NOT YET TESTED // NOT YET TESTED
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
// convert to 32 bit and flip bits // convert to 32 bit and flip bits
int iCurSam = static_cast<int32_t> ( int iCurSam = static_cast<int32_t> (
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] ); pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iOutChNum] );
static_cast<int32_t*> ( bufferInfos[i].buffers[index] )[iCurSample] = static_cast<int32_t*> ( pSound->bufferInfos[i].buffers[index] )[iCurSample] =
Flip32Bits ( iCurSam << 16 ); Flip32Bits ( iCurSam << 16 );
} }
break; break;
case ASIOSTFloat32MSB: // IEEE 754 32 bit float, as found on Intel x86 architecture case ASIOSTFloat32MSB: // IEEE 754 32 bit float, as found on Intel x86 architecture
// NOT YET TESTED // NOT YET TESTED
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
const float fCurSam = static_cast<float> ( const float fCurSam = static_cast<float> (
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] ); pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iOutChNum] );
static_cast<float*> ( bufferInfos[i].buffers[index] )[iCurSample] = static_cast<float*> ( pSound->bufferInfos[i].buffers[index] )[iCurSample] =
static_cast<float> ( Flip32Bits ( static_cast<int32_t> ( static_cast<float> ( Flip32Bits ( static_cast<int32_t> (
fCurSam / _MAXSHORT ) ) ); fCurSam / _MAXSHORT ) ) );
} }
@ -927,12 +955,12 @@ void CSound::bufferSwitch ( long index, ASIOBool processNow )
case ASIOSTFloat64MSB: // IEEE 754 64 bit double float, as found on Intel x86 architecture case ASIOSTFloat64MSB: // IEEE 754 64 bit double float, as found on Intel x86 architecture
// NOT YET TESTED // NOT YET TESTED
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
const double fCurSam = static_cast<double> ( const double fCurSam = static_cast<double> (
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] ); pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iOutChNum] );
static_cast<float*> ( bufferInfos[i].buffers[index] )[iCurSample] = static_cast<float*> ( pSound->bufferInfos[i].buffers[index] )[iCurSample] =
static_cast<double> ( Flip64Bits ( static_cast<int64_t> ( static_cast<double> ( Flip64Bits ( static_cast<int64_t> (
fCurSam / _MAXSHORT ) ) ); fCurSam / _MAXSHORT ) ) );
} }
@ -940,67 +968,66 @@ void CSound::bufferSwitch ( long index, ASIOBool processNow )
case ASIOSTInt32MSB16: // 32 bit data with 16 bit alignment case ASIOSTInt32MSB16: // 32 bit data with 16 bit alignment
// NOT YET TESTED // NOT YET TESTED
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
// convert to 32 bit // convert to 32 bit
const int32_t iCurSam = static_cast<int32_t> ( const int32_t iCurSam = static_cast<int32_t> (
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] ); pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iOutChNum] );
static_cast<int32_t*> ( bufferInfos[i].buffers[index] )[iCurSample] = static_cast<int32_t*> ( pSound->bufferInfos[i].buffers[index] )[iCurSample] =
Flip32Bits ( iCurSam ); Flip32Bits ( iCurSam );
} }
break; break;
case ASIOSTInt32MSB18: // 32 bit data with 18 bit alignment case ASIOSTInt32MSB18: // 32 bit data with 18 bit alignment
// NOT YET TESTED // NOT YET TESTED
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
// convert to 32 bit // convert to 32 bit
const int32_t iCurSam = static_cast<int32_t> ( const int32_t iCurSam = static_cast<int32_t> (
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] ); pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iOutChNum] );
static_cast<int32_t*> ( bufferInfos[i].buffers[index] )[iCurSample] = static_cast<int32_t*> ( pSound->bufferInfos[i].buffers[index] )[iCurSample] =
Flip32Bits ( iCurSam << 2 ); Flip32Bits ( iCurSam << 2 );
} }
break; break;
case ASIOSTInt32MSB20: // 32 bit data with 20 bit alignment case ASIOSTInt32MSB20: // 32 bit data with 20 bit alignment
// NOT YET TESTED // NOT YET TESTED
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
// convert to 32 bit // convert to 32 bit
const int32_t iCurSam = static_cast<int32_t> ( const int32_t iCurSam = static_cast<int32_t> (
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] ); pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iOutChNum] );
static_cast<int32_t*> ( bufferInfos[i].buffers[index] )[iCurSample] = static_cast<int32_t*> ( pSound->bufferInfos[i].buffers[index] )[iCurSample] =
Flip32Bits ( iCurSam << 4 ); Flip32Bits ( iCurSam << 4 );
} }
break; break;
case ASIOSTInt32MSB24: // 32 bit data with 24 bit alignment case ASIOSTInt32MSB24: // 32 bit data with 24 bit alignment
// NOT YET TESTED // NOT YET TESTED
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ ) for ( iCurSample = 0; iCurSample < pSound->iASIOBufferSizeMono; iCurSample++ )
{ {
// convert to 32 bit // convert to 32 bit
const int32_t iCurSam = static_cast<int32_t> ( const int32_t iCurSam = static_cast<int32_t> (
vecsTmpAudioSndCrdStereo[2 * iCurSample + bufferInfos[i].channelNum] ); pSound->vecsTmpAudioSndCrdStereo[2 * iCurSample + iOutChNum] );
static_cast<int32_t*> ( bufferInfos[i].buffers[index] )[iCurSample] = static_cast<int32_t*> ( pSound->bufferInfos[i].buffers[index] )[iCurSample] =
Flip32Bits ( iCurSam << 8 ); Flip32Bits ( iCurSam << 8 );
} }
break; break;
} }
} }
}
// finally if the driver supports the ASIOOutputReady() optimization, // finally if the driver supports the ASIOOutputReady() optimization,
// do it here, all data are in place ----------------------------------- // do it here, all data are in place -----------------------------------
if ( bASIOPostOutput ) if ( pSound->bASIOPostOutput )
{ {
ASIOOutputReady(); ASIOOutputReady();
} }
} }
ASIOMutex.unlock(); pSound->ASIOMutex.unlock();
} }
long CSound::asioMessages ( long selector, long CSound::asioMessages ( long selector,

View file

@ -40,14 +40,14 @@
/* Definitions ****************************************************************/ /* Definitions ****************************************************************/
#define NUM_IN_OUT_CHANNELS 2 /* Stereo recording (but we only // stereo for input and output
use one channel for recording) */ #define NUM_IN_OUT_CHANNELS 2
#define MAX_SND_BUF_IN 100 // define the maximum number of audio channel for input/output we can store
#define MAX_SND_BUF_OUT 100 // channel infos for (and therefore this is the maximum number of entries in
// the channel selection combo box regardless of the actual available number
#define NUM_SOUND_BUFFERS_IN 4 // of channels by the audio device)
#define NUM_SOUND_BUFFERS_OUT 4 #define MAX_NUM_IN_OUT_CHANNELS 32
/* Classes ********************************************************************/ /* Classes ********************************************************************/
@ -74,6 +74,17 @@ protected:
QString LoadAndInitializeDriver ( int iIdx ); QString LoadAndInitializeDriver ( int iIdx );
int GetActualBufferSize ( const int iDesiredBufferSizeMono ); int GetActualBufferSize ( const int iDesiredBufferSizeMono );
QString CheckDeviceCapabilities(); QString CheckDeviceCapabilities();
bool CheckSampleTypeSupported ( const ASIOSampleType SamType );
int iASIOBufferSizeMono;
int iASIOBufferSizeStereo;
CVector<int> vSelectedInputChannels;
CVector<int> vSelectedOutputChannels;
CVector<int16_t> vecsTmpAudioSndCrdStereo;
QMutex ASIOMutex;
// utility functions // utility functions
static int16_t Flip16Bits ( const int16_t iIn ); static int16_t Flip16Bits ( const int16_t iIn );
@ -89,6 +100,14 @@ protected:
long lGranularity; long lGranularity;
} HWBufferInfo; } HWBufferInfo;
// ASIO stuff
ASIODriverInfo driverInfo;
ASIOBufferInfo bufferInfos[2 * NUM_IN_OUT_CHANNELS]; // for input and output buffers -> "2 *"
ASIOChannelInfo channelInfosInput[MAX_NUM_IN_OUT_CHANNELS];
ASIOChannelInfo channelInfosOutput[MAX_NUM_IN_OUT_CHANNELS];
bool bASIOPostOutput;
ASIOCallbacks asioCallbacks;
// callbacks // callbacks
static void bufferSwitch ( long index, ASIOBool processNow ); static void bufferSwitch ( long index, ASIOBool processNow );
static ASIOTime* bufferSwitchTimeInfo ( ASIOTime* timeInfo, long index, ASIOBool processNow ); static ASIOTime* bufferSwitchTimeInfo ( ASIOTime* timeInfo, long index, ASIOBool processNow );