for ASIO and 4 channel input, support mixing channels 1&2 with 3&4
This commit is contained in:
parent
0b906f8498
commit
a7454095d3
1 changed files with 95 additions and 10 deletions
|
@ -44,6 +44,7 @@ QString CSound::LoadAndInitializeDriver ( int iDriverIdx )
|
||||||
{
|
{
|
||||||
// load driver
|
// load driver
|
||||||
loadAsioDriver ( cDriverNames[iDriverIdx] );
|
loadAsioDriver ( cDriverNames[iDriverIdx] );
|
||||||
|
|
||||||
if ( ASIOInit ( &driverInfo ) != ASE_OK )
|
if ( ASIOInit ( &driverInfo ) != ASE_OK )
|
||||||
{
|
{
|
||||||
// clean up and return error string
|
// clean up and return error string
|
||||||
|
@ -125,6 +126,8 @@ QString CSound::CheckDeviceCapabilities()
|
||||||
}
|
}
|
||||||
|
|
||||||
// query channel infos for all available input channels
|
// query channel infos for all available input channels
|
||||||
|
bool bInputChMixingSupported = true;
|
||||||
|
|
||||||
for ( int i = 0; i < lNumInChan; i++ )
|
for ( int i = 0; i < lNumInChan; i++ )
|
||||||
{
|
{
|
||||||
// setup for input channels
|
// setup for input channels
|
||||||
|
@ -144,6 +147,14 @@ QString CSound::CheckDeviceCapabilities()
|
||||||
// return error string
|
// return error string
|
||||||
return tr ( "Required audio sample format not available." );
|
return tr ( "Required audio sample format not available." );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// store the name of the channel and check if channel mixing is supported
|
||||||
|
channelInputName[i] = channelInfosInput[i].name;
|
||||||
|
|
||||||
|
if ( !CheckSampleTypeSupportedForCHMixing ( channelInfosInput[i].type ) )
|
||||||
|
{
|
||||||
|
bInputChMixingSupported = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// query channel infos for all available output channels
|
// query channel infos for all available output channels
|
||||||
|
@ -168,6 +179,32 @@ QString CSound::CheckDeviceCapabilities()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// special case with 4 input channels: support adding channels
|
||||||
|
if ( ( lNumInChan == 4 ) && bInputChMixingSupported )
|
||||||
|
{
|
||||||
|
// add four mixed channels (i.e. 4 normal, 4 mixed channels)
|
||||||
|
lNumInChanPlusAddChan = 8;
|
||||||
|
|
||||||
|
for ( int iCh = 0; iCh < lNumInChanPlusAddChan; iCh++ )
|
||||||
|
{
|
||||||
|
int iSelCH, iSelAddCH;
|
||||||
|
|
||||||
|
GetSelCHAndAddCH ( iCh, lNumInChan, iSelCH, iSelAddCH );
|
||||||
|
|
||||||
|
if ( iSelAddCH >= 0 )
|
||||||
|
{
|
||||||
|
// for mixed channels, show both audio channel names to be mixed
|
||||||
|
channelInputName[iCh] =
|
||||||
|
channelInputName[iSelCH] + " + " + channelInputName[iSelAddCH];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// regular case: no mixing input channels used
|
||||||
|
lNumInChanPlusAddChan = lNumInChan;
|
||||||
|
}
|
||||||
|
|
||||||
// everything is ok, return empty string for "no error" case
|
// everything is ok, return empty string for "no error" case
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
@ -175,8 +212,7 @@ QString CSound::CheckDeviceCapabilities()
|
||||||
void CSound::SetLeftInputChannel ( const int iNewChan )
|
void CSound::SetLeftInputChannel ( const int iNewChan )
|
||||||
{
|
{
|
||||||
// apply parameter after input parameter check
|
// apply parameter after input parameter check
|
||||||
if ( ( iNewChan >= 0 ) && ( iNewChan < lNumInChan ) &&
|
if ( ( iNewChan >= 0 ) && ( iNewChan < lNumInChanPlusAddChan ) )
|
||||||
( iNewChan != vSelectedInputChannels[1] ) )
|
|
||||||
{
|
{
|
||||||
vSelectedInputChannels[0] = iNewChan;
|
vSelectedInputChannels[0] = iNewChan;
|
||||||
}
|
}
|
||||||
|
@ -185,8 +221,7 @@ void CSound::SetLeftInputChannel ( const int iNewChan )
|
||||||
void CSound::SetRightInputChannel ( const int iNewChan )
|
void CSound::SetRightInputChannel ( const int iNewChan )
|
||||||
{
|
{
|
||||||
// apply parameter after input parameter check
|
// apply parameter after input parameter check
|
||||||
if ( ( iNewChan >= 0 ) && ( iNewChan < lNumInChan ) &&
|
if ( ( iNewChan >= 0 ) && ( iNewChan < lNumInChanPlusAddChan ) )
|
||||||
( iNewChan != vSelectedInputChannels[0] ) )
|
|
||||||
{
|
{
|
||||||
vSelectedInputChannels[1] = iNewChan;
|
vSelectedInputChannels[1] = iNewChan;
|
||||||
}
|
}
|
||||||
|
@ -195,8 +230,7 @@ void CSound::SetRightInputChannel ( const int iNewChan )
|
||||||
void CSound::SetLeftOutputChannel ( const int iNewChan )
|
void CSound::SetLeftOutputChannel ( const int iNewChan )
|
||||||
{
|
{
|
||||||
// apply parameter after input parameter check
|
// apply parameter after input parameter check
|
||||||
if ( ( iNewChan >= 0 ) && ( iNewChan < lNumOutChan ) &&
|
if ( ( iNewChan >= 0 ) && ( iNewChan < lNumOutChan ) )
|
||||||
( iNewChan != vSelectedOutputChannels[1] ) )
|
|
||||||
{
|
{
|
||||||
vSelectedOutputChannels[0] = iNewChan;
|
vSelectedOutputChannels[0] = iNewChan;
|
||||||
}
|
}
|
||||||
|
@ -205,8 +239,7 @@ void CSound::SetLeftOutputChannel ( const int iNewChan )
|
||||||
void CSound::SetRightOutputChannel ( const int iNewChan )
|
void CSound::SetRightOutputChannel ( const int iNewChan )
|
||||||
{
|
{
|
||||||
// apply parameter after input parameter check
|
// apply parameter after input parameter check
|
||||||
if ( ( iNewChan >= 0 ) && ( iNewChan < lNumOutChan ) &&
|
if ( ( iNewChan >= 0 ) && ( iNewChan < lNumOutChan ) )
|
||||||
( iNewChan != vSelectedOutputChannels[0] ) )
|
|
||||||
{
|
{
|
||||||
vSelectedOutputChannels[1] = iNewChan;
|
vSelectedOutputChannels[1] = iNewChan;
|
||||||
}
|
}
|
||||||
|
@ -421,6 +454,7 @@ CSound::CSound ( void (*fpNewCallback) ( CVector<int16_t>& psData, void* arg ),
|
||||||
vSelectedInputChannels ( NUM_IN_OUT_CHANNELS ),
|
vSelectedInputChannels ( NUM_IN_OUT_CHANNELS ),
|
||||||
vSelectedOutputChannels ( NUM_IN_OUT_CHANNELS ),
|
vSelectedOutputChannels ( NUM_IN_OUT_CHANNELS ),
|
||||||
lNumInChan ( 0 ),
|
lNumInChan ( 0 ),
|
||||||
|
lNumInChanPlusAddChan ( 0 ),
|
||||||
lNumOutChan ( 0 ),
|
lNumOutChan ( 0 ),
|
||||||
dInOutLatencyMs ( 0.0 ) // "0.0" means that no latency value is available
|
dInOutLatencyMs ( 0.0 ) // "0.0" means that no latency value is available
|
||||||
{
|
{
|
||||||
|
@ -516,6 +550,14 @@ bool CSound::CheckSampleTypeSupported ( const ASIOSampleType SamType )
|
||||||
( SamType == ASIOSTInt32MSB24 ) );
|
( SamType == ASIOSTInt32MSB24 ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CSound::CheckSampleTypeSupportedForCHMixing ( const ASIOSampleType SamType )
|
||||||
|
{
|
||||||
|
// check for supported sample types for audio channel mixing (see bufferSwitch)
|
||||||
|
return ( ( SamType == ASIOSTInt16LSB ) ||
|
||||||
|
( SamType == ASIOSTInt24LSB ) ||
|
||||||
|
( SamType == ASIOSTInt32LSB ) );
|
||||||
|
}
|
||||||
|
|
||||||
void CSound::bufferSwitch ( long index, ASIOBool )
|
void CSound::bufferSwitch ( long index, ASIOBool )
|
||||||
{
|
{
|
||||||
int iCurSample;
|
int iCurSample;
|
||||||
|
@ -530,7 +572,10 @@ void CSound::bufferSwitch ( long index, ASIOBool )
|
||||||
// CAPTURE -------------------------------------------------------------
|
// CAPTURE -------------------------------------------------------------
|
||||||
for ( int i = 0; i < NUM_IN_OUT_CHANNELS; i++ )
|
for ( int i = 0; i < NUM_IN_OUT_CHANNELS; i++ )
|
||||||
{
|
{
|
||||||
const int iSelCH = pSound->vSelectedInputChannels[i];
|
int iSelCH, iSelAddCH;
|
||||||
|
|
||||||
|
GetSelCHAndAddCH ( pSound->vSelectedInputChannels[i], pSound->lNumInChan,
|
||||||
|
iSelCH, iSelAddCH );
|
||||||
|
|
||||||
// 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)
|
||||||
|
@ -545,11 +590,23 @@ void CSound::bufferSwitch ( long index, ASIOBool )
|
||||||
{
|
{
|
||||||
vecsTmpAudioSndCrdStereo[2 * iCurSample + i] = pASIOBuf[iCurSample];
|
vecsTmpAudioSndCrdStereo[2 * iCurSample + i] = pASIOBuf[iCurSample];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( iSelAddCH >= 0 )
|
||||||
|
{
|
||||||
|
// mix input channels case:
|
||||||
|
int16_t* pASIOBufAdd = static_cast<int16_t*> ( pSound->bufferInfos[iSelAddCH].buffers[index] );
|
||||||
|
|
||||||
|
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ )
|
||||||
|
{
|
||||||
|
vecsTmpAudioSndCrdStereo[2 * iCurSample + i] =
|
||||||
|
Double2Short ( (double) vecsTmpAudioSndCrdStereo[2 * iCurSample + i] +
|
||||||
|
(double) pASIOBufAdd[iCurSample] );
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ASIOSTInt24LSB:
|
case ASIOSTInt24LSB:
|
||||||
// NOT YET TESTED
|
|
||||||
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ )
|
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ )
|
||||||
{
|
{
|
||||||
int iCurSam = 0;
|
int iCurSam = 0;
|
||||||
|
@ -558,6 +615,21 @@ void CSound::bufferSwitch ( long index, ASIOBool )
|
||||||
|
|
||||||
vecsTmpAudioSndCrdStereo[2 * iCurSample + i] = static_cast<int16_t> ( iCurSam );
|
vecsTmpAudioSndCrdStereo[2 * iCurSample + i] = static_cast<int16_t> ( iCurSam );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( iSelAddCH >= 0 )
|
||||||
|
{
|
||||||
|
// mix input channels case:
|
||||||
|
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ )
|
||||||
|
{
|
||||||
|
int iCurSam = 0;
|
||||||
|
memcpy ( &iCurSam, ( (char*) pSound->bufferInfos[iSelAddCH].buffers[index] ) + iCurSample * 3, 3 );
|
||||||
|
iCurSam >>= 8;
|
||||||
|
|
||||||
|
vecsTmpAudioSndCrdStereo[2 * iCurSample + i] =
|
||||||
|
Double2Short ( (double) vecsTmpAudioSndCrdStereo[2 * iCurSample + i] +
|
||||||
|
(double) static_cast<int16_t> ( iCurSam ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ASIOSTInt32LSB:
|
case ASIOSTInt32LSB:
|
||||||
|
@ -569,6 +641,19 @@ void CSound::bufferSwitch ( long index, ASIOBool )
|
||||||
vecsTmpAudioSndCrdStereo[2 * iCurSample + i] =
|
vecsTmpAudioSndCrdStereo[2 * iCurSample + i] =
|
||||||
static_cast<int16_t> ( pASIOBuf[iCurSample] >> 16 );
|
static_cast<int16_t> ( pASIOBuf[iCurSample] >> 16 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( iSelAddCH >= 0 )
|
||||||
|
{
|
||||||
|
// mix input channels case:
|
||||||
|
int32_t* pASIOBufAdd = static_cast<int32_t*> ( pSound->bufferInfos[iSelAddCH].buffers[index] );
|
||||||
|
|
||||||
|
for ( iCurSample = 0; iCurSample < iASIOBufferSizeMono; iCurSample++ )
|
||||||
|
{
|
||||||
|
vecsTmpAudioSndCrdStereo[2 * iCurSample + i] =
|
||||||
|
Double2Short ( (double) vecsTmpAudioSndCrdStereo[2 * iCurSample + i] +
|
||||||
|
(double) static_cast<int16_t> ( pASIOBufAdd[iCurSample] >> 16 ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue