bug fix in socket buffer, fix in channel, ASIO buffer size setting should work now, some other small fixes

This commit is contained in:
Volker Fischer 2009-03-05 20:07:41 +00:00
parent 56c91ce201
commit ee28e3bc8e
8 changed files with 132 additions and 96 deletions

View file

@ -380,10 +380,13 @@ void CNetBuf::Clear ( const EClearType eClearType )
void CNetBuf::FadeInAudioDataBlock ( CVector<double>& vecdData ) void CNetBuf::FadeInAudioDataBlock ( CVector<double>& vecdData )
{ {
// correct fading length if necessary
const int iCurFadingLen = min ( vecdData.Size(), iNumSamFading );
// apply linear fading // apply linear fading
for ( int i = 0; i < iNumSamFading; i++ ) for ( int i = 0; i < iCurFadingLen; i++ )
{ {
vecdData[i] *= ( (double) i / iNumSamFading ); vecdData[i] *= ( (double) i / iCurFadingLen );
} }
// reset flag // reset flag
@ -394,14 +397,17 @@ void CNetBuf::FadeOutExtrapolateAudioDataBlock ( CVector<double>& vecdData,
const double dExPDiff, const double dExPDiff,
const double dExPLastV ) const double dExPLastV )
{ {
// correct fading length if necessary
const int iCurFadingLenExtra = min ( vecdData.Size(), iNumSamFadingExtra );
// apply linear extrapolation and linear fading // apply linear extrapolation and linear fading
for ( int i = 0; i < iNumSamFadingExtra; i++ ) for ( int i = 0; i < iCurFadingLenExtra; i++ )
{ {
// calculate extrapolated value // calculate extrapolated value
vecdData[i] = ( ( i + 1 ) * dExPDiff + dExPLastV ); vecdData[i] = ( ( i + 1 ) * dExPDiff + dExPLastV );
// linear fading // linear fading
vecdData[i] *= ( (double) ( iNumSamFadingExtra - i ) / iNumSamFadingExtra ); vecdData[i] *= ( (double) ( iCurFadingLenExtra - i ) / iCurFadingLenExtra );
} }
} }

View file

@ -622,11 +622,19 @@ CChannel::CChannel ( const bool bNIsServer ) : bIsServer ( bNIsServer ),
MIN_SERVER_BLOCK_SIZE_SAMPLES * DEF_NET_BLOCK_SIZE_FACTOR, MIN_SERVER_BLOCK_SIZE_SAMPLES * DEF_NET_BLOCK_SIZE_FACTOR,
CT_MSADPCM ); CT_MSADPCM );
SetNetwBufSizeFactOut ( DEF_NET_BLOCK_SIZE_FACTOR ); if ( bIsServer )
{
SetNetwBufSizeFactOut ( DEF_NET_BLOCK_SIZE_FACTOR );
}
else
{
SetNetwBufSizeOut ( MIN_SERVER_BLOCK_SIZE_SAMPLES );
}
// set initial audio compression format for output // set initial audio compression format for output
SetAudioCompressionOut ( CT_MSADPCM ); SetAudioCompressionOut ( CT_MSADPCM );
// connections ------------------------------------------------------------- // connections -------------------------------------------------------------
QObject::connect ( &Protocol, QObject::connect ( &Protocol,
SIGNAL ( MessReadyForSending ( CVector<uint8_t> ) ), SIGNAL ( MessReadyForSending ( CVector<uint8_t> ) ),
@ -730,11 +738,16 @@ void CChannel::SetNetwBufSizeOut ( const int iNewAudioBlockSizeOut )
// this function is intended for the client (not the server) // this function is intended for the client (not the server)
QMutexLocker locker ( &Mutex ); QMutexLocker locker ( &Mutex );
// store new value // direct setting of audio buffer (without buffer size factor) is
iCurAudioBlockSizeOut = iNewAudioBlockSizeOut; // right now only intendet for the client, not the server
if ( !bIsServer )
{
// store new value
iCurAudioBlockSizeOut = iNewAudioBlockSizeOut;
iAudComprSizeOut = iAudComprSizeOut =
AudioCompressionOut.Init ( iNewAudioBlockSizeOut, eAudComprTypeOut ); AudioCompressionOut.Init ( iNewAudioBlockSizeOut, eAudComprTypeOut );
}
} }
void CChannel::SetNetwBufSizeFactOut ( const int iNewNetwBlSiFactOut ) void CChannel::SetNetwBufSizeFactOut ( const int iNewNetwBlSiFactOut )

View file

@ -150,29 +150,40 @@ bool CClient::SetServerAddr ( QString strNAddr )
return true; return true;
} }
void CClient::SetSndCrdPreferredMonoBlSizeIndex ( const int iNewIdx ) void CClient::SetSndCrdPreferredMonoBlSizeIndex ( const int iNewIdx )
{ {
// right now we simply set the internal value // right now we simply set the internal value
if ( ( iNewIdx >= 0 ) && ( CSndCrdBufferSizes::GetNumOfBufferSizes() ) ) if ( ( iNewIdx >= 0 ) && ( CSndCrdBufferSizes::GetNumOfBufferSizes() ) )
{ {
iSndCrdPreferredMonoBlSizeIndex = iNewIdx; iSndCrdPreferredMonoBlSizeIndex = iNewIdx;
}
// init with new parameter, if client was running then first
// stop it and restart again after new initialization
const bool bWasRunning = Sound.IsRunning();
if ( bWasRunning )
{
Sound.Stop();
}
// init with new block size index parameter
Init ( iSndCrdPreferredMonoBlSizeIndex );
if ( bWasRunning )
{
Sound.Start();
}
// tell the server that audio coding has changed (it
// is important to call this function AFTER we have applied
// the new setting to the channel!)
Channel.CreateNetTranspPropsMessFromCurrentSettings();
} }
// TODO take action on new parameter
}
void CClient::Start() void CClient::Start()
{ {
// init object // init object
Init ( iSndCrdPreferredMonoBlSizeIndex );
// TEST
Init ( 192 );
// enable channel // enable channel
Channel.SetEnable ( true ); Channel.SetEnable ( true );
@ -203,8 +214,12 @@ void CClient::AudioCallback ( CVector<short>& psData, void* arg )
pMyClientObj->ProcessAudioData ( psData ); pMyClientObj->ProcessAudioData ( psData );
} }
void CClient::Init ( const int iPrefMonoBlockSizeSamAtSndCrdSamRate ) void CClient::Init ( const int iPrefMonoBlockSizeSamIndexAtSndCrdSamRate )
{ {
// translate block size index in actual block size
const int iPrefMonoBlockSizeSamAtSndCrdSamRate = CSndCrdBufferSizes::
GetBufferSizeFromIndex ( iPrefMonoBlockSizeSamIndexAtSndCrdSamRate );
// get actual sound card buffer size using preferred size // get actual sound card buffer size using preferred size
iSndCrdMonoBlockSizeSam = Sound.Init ( iPrefMonoBlockSizeSamAtSndCrdSamRate ); iSndCrdMonoBlockSizeSam = Sound.Init ( iPrefMonoBlockSizeSamAtSndCrdSamRate );
iSndCrdStereoBlockSizeSam = 2 * iSndCrdMonoBlockSizeSam; iSndCrdStereoBlockSizeSam = 2 * iSndCrdMonoBlockSizeSam;

View file

@ -156,7 +156,7 @@ protected:
// callback function must be static, otherwise it does not work // callback function must be static, otherwise it does not work
static void AudioCallback ( CVector<short>& psData, void* arg ); static void AudioCallback ( CVector<short>& psData, void* arg );
void Init ( const int iPrefMonoBlockSizeSamAtSndCrdSamRate ); void Init ( const int iPrefMonoBlockSizeSamIndexAtSndCrdSamRate );
void ProcessAudioData ( CVector<short>& vecsStereoSndCrd ); void ProcessAudioData ( CVector<short>& vecsStereoSndCrd );
void UpdateTimeResponseMeasurement(); void UpdateTimeResponseMeasurement();
void UpdateSocketBufferSize(); void UpdateSocketBufferSize();

View file

@ -251,7 +251,7 @@
<property name="minimumSize" > <property name="minimumSize" >
<size> <size>
<width>110</width> <width>110</width>
<height>0</height> <height>20</height>
</size> </size>
</property> </property>
<property name="frameShape" > <property name="frameShape" >
@ -281,7 +281,7 @@
<property name="minimumSize" > <property name="minimumSize" >
<size> <size>
<width>110</width> <width>110</width>
<height>0</height> <height>20</height>
</size> </size>
</property> </property>
<property name="frameShape" > <property name="frameShape" >
@ -386,7 +386,7 @@
<property name="minimumSize" > <property name="minimumSize" >
<size> <size>
<width>50</width> <width>50</width>
<height>0</height> <height>20</height>
</size> </size>
</property> </property>
<property name="frameShape" > <property name="frameShape" >
@ -427,7 +427,7 @@
<property name="minimumSize" > <property name="minimumSize" >
<size> <size>
<width>50</width> <width>50</width>
<height>0</height> <height>20</height>
</size> </size>
</property> </property>
<property name="font" > <property name="font" >
@ -484,6 +484,12 @@
</item> </item>
<item> <item>
<widget class="QLabel" name="TextUpstreamValue" > <widget class="QLabel" name="TextUpstreamValue" >
<property name="minimumSize" >
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="font" > <property name="font" >
<font> <font>
<weight>75</weight> <weight>75</weight>

View file

@ -61,11 +61,6 @@ void CSoundBase::Stop()
{ {
wait ( 5000 ); wait ( 5000 );
} }
// TODO stop audio interface (previously done in Close function, we
// better should implement a stop function in derived sound classes
Close();
} }
void CSoundBase::run() void CSoundBase::run()

View file

@ -43,9 +43,8 @@ ASIOBufferInfo bufferInfos[2 * NUM_IN_OUT_CHANNELS]; // for input and output b
ASIOChannelInfo channelInfos[2 * NUM_IN_OUT_CHANNELS]; ASIOChannelInfo channelInfos[2 * NUM_IN_OUT_CHANNELS];
bool bASIOPostOutput; bool bASIOPostOutput;
ASIOCallbacks asioCallbacks; ASIOCallbacks asioCallbacks;
int iBufferSizeMono;
int iBufferSizeStereo;
int iASIOBufferSizeMono; int iASIOBufferSizeMono;
int iASIOBufferSizeStereo;
CVector<short> vecsTmpAudioSndCrdStereo; CVector<short> vecsTmpAudioSndCrdStereo;
@ -88,12 +87,12 @@ void CSound::SetDev ( const int iNewDev )
// loading and initializing the new driver failed, go back to original // loading and initializing the new driver failed, go back to original
// driver and display error message // driver and display error message
LoadAndInitializeDriver ( lCurDev ); LoadAndInitializeDriver ( lCurDev );
Init ( iBufferSizeStereo ); Init ( iASIOBufferSizeStereo );
throw CGenErr ( strErrorMessage.c_str() ); throw CGenErr ( strErrorMessage.c_str() );
} }
Init ( iBufferSizeStereo ); Init ( iASIOBufferSizeStereo );
} }
else else
{ {
@ -319,92 +318,75 @@ int CSound::GetActualBufferSize ( const int iDesiredBufferSizeMono )
int CSound::Init ( const int iNewPrefMonoBufferSize ) int CSound::Init ( const int iNewPrefMonoBufferSize )
{ {
// first, stop audio and dispose ASIO buffers
ASIOStop();
ASIOMutex.lock(); // get mutex lock ASIOMutex.lock(); // get mutex lock
{ {
// get the actual sound card buffer size which is supported
// by the audio hardware
iASIOBufferSizeMono =
GetActualBufferSize ( iNewPrefMonoBufferSize );
// init base clasee // init base clasee
CSoundBase::Init ( iNewPrefMonoBufferSize ); CSoundBase::Init ( iASIOBufferSizeMono );
// set internal buffer size value and calculate stereo buffer size // set internal buffer size value and calculate stereo buffer size
iBufferSizeMono = iNewPrefMonoBufferSize; iASIOBufferSizeStereo = 2 * iASIOBufferSizeMono;
iBufferSizeStereo = 2 * iBufferSizeMono;
// TODO possible BUG!!!!!!!!!!!!!!!!!!!!!
// iBufferSizeMono must not be the same as iASIOBufferSizeMono
// set the sample rate
ASIOSetSampleRate ( SND_CRD_SAMPLE_RATE );
// create memory for intermediate audio buffer // create memory for intermediate audio buffer
vecsTmpAudioSndCrdStereo.Init ( iBufferSizeStereo ); vecsTmpAudioSndCrdStereo.Init ( iASIOBufferSizeStereo );
int i;
// set the sample rate and check if sample rate is supported
ASIOSetSampleRate ( SND_CRD_SAMPLE_RATE );
// TEST
iASIOBufferSizeMono = GetActualBufferSize ( iBufferSizeMono );
for ( i = 0; i < NUM_IN_OUT_CHANNELS; i++ )
{
// prepare input channels
bufferInfos[i].isInput = ASIOTrue;
bufferInfos[i].channelNum = i;
bufferInfos[i].buffers[0] = 0;
bufferInfos[i].buffers[1] = 0;
// prepare output channels
bufferInfos[NUM_IN_OUT_CHANNELS + i].isInput = ASIOFalse;
bufferInfos[NUM_IN_OUT_CHANNELS + i].channelNum = i;
bufferInfos[NUM_IN_OUT_CHANNELS + i].buffers[0] = 0;
bufferInfos[NUM_IN_OUT_CHANNELS + i].buffers[1] = 0;
}
// create and activate ASIO buffers (buffer size in samples)
ASIOCreateBuffers ( bufferInfos, 2 /* in/out */ * NUM_IN_OUT_CHANNELS /* stereo */,
iASIOBufferSizeMono, &asioCallbacks );
// check wether the driver requires the ASIOOutputReady() optimization
// (can be used by the driver to reduce output latency by one block)
bASIOPostOutput = ( ASIOOutputReady() == ASE_OK );
// create and activate ASIO buffers (buffer size in samples)
ASIOCreateBuffers ( bufferInfos,
2 /* in/out */ * NUM_IN_OUT_CHANNELS /* stereo */,
iASIOBufferSizeMono, &asioCallbacks );
// check wether the driver requires the ASIOOutputReady() optimization
// (can be used by the driver to reduce output latency by one block)
bASIOPostOutput = ( ASIOOutputReady() == ASE_OK );
} }
ASIOMutex.unlock(); ASIOMutex.unlock();
// initialization is done, (re)start audio return iASIOBufferSizeMono;
}
void CSound::Start()
{
// start audio
ASIOStart(); ASIOStart();
// TEST // call base class
return iNewPrefMonoBufferSize; CSoundBase::Start();
}
void CSound::Stop()
{
// stop audio
ASIOStop();
// call base class
CSoundBase::Stop();
} }
void CSound::Close() void CSound::Close()
{ {
// stop driver
ASIOStop(); // TODO
} }
CSound::CSound ( void (*fpNewCallback) ( CVector<short>& psData, void* arg ), void* arg ) : CSound::CSound ( void (*fpNewCallback) ( CVector<short>& psData, void* arg ), void* arg ) :
CSoundBase ( true, fpNewCallback, arg ) CSoundBase ( true, fpNewCallback, arg )
{ {
int i;
// TEST // TEST
pSound = this; pSound = this;
// get available ASIO driver names in system // get available ASIO driver names in system
for ( int i = 0; i < MAX_NUMBER_SOUND_CARDS; i++ ) for ( i = 0; i < MAX_NUMBER_SOUND_CARDS; i++ )
{ {
cDriverNames[i] = new char[32]; cDriverNames[i] = new char[32];
} }
@ -422,6 +404,23 @@ 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
// two output channels
for ( i = 0; i < NUM_IN_OUT_CHANNELS; i++ )
{
// prepare input channels
bufferInfos[i].isInput = ASIOTrue;
bufferInfos[i].channelNum = i;
bufferInfos[i].buffers[0] = 0;
bufferInfos[i].buffers[1] = 0;
// prepare output channels
bufferInfos[NUM_IN_OUT_CHANNELS + i].isInput = ASIOFalse;
bufferInfos[NUM_IN_OUT_CHANNELS + i].channelNum = i;
bufferInfos[NUM_IN_OUT_CHANNELS + i].buffers[0] = 0;
bufferInfos[NUM_IN_OUT_CHANNELS + i].buffers[1] = 0;
}
// set up the asioCallback structure // set up the asioCallback structure
asioCallbacks.bufferSwitch = &bufferSwitch; asioCallbacks.bufferSwitch = &bufferSwitch;
asioCallbacks.sampleRateDidChange = &sampleRateChanged; asioCallbacks.sampleRateDidChange = &sampleRateChanged;

View file

@ -60,6 +60,8 @@ public:
virtual ~CSound(); virtual ~CSound();
virtual int Init ( const int iNewPrefMonoBufferSize ); virtual int Init ( const int iNewPrefMonoBufferSize );
virtual void Start();
virtual void Stop();
virtual void Close(); virtual void Close();
virtual void OpenDriverSetup() { ASIOControlPanel(); } virtual void OpenDriverSetup() { ASIOControlPanel(); }