put ASIO member variables in class, prepared for ASIO input/output channel selection
This commit is contained in:
parent
29eb59d464
commit
9828ceec81
2 changed files with 557 additions and 511 deletions
|
@ -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,
|
||||||
|
|
|
@ -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 );
|
||||||
|
|
Loading…
Reference in a new issue