From ee28e3bc8e3cc55570a50812e5f6ac4c3a09f3fa Mon Sep 17 00:00:00 2001 From: Volker Fischer Date: Thu, 5 Mar 2009 20:07:41 +0000 Subject: [PATCH] bug fix in socket buffer, fix in channel, ASIO buffer size setting should work now, some other small fixes --- src/buffer.cpp | 14 +++-- src/channel.cpp | 23 +++++-- src/client.cpp | 49 ++++++++++----- src/client.h | 2 +- src/clientsettingsdlgbase.ui | 14 +++-- src/soundbase.cpp | 5 -- windows/sound.cpp | 119 +++++++++++++++++------------------ windows/sound.h | 2 + 8 files changed, 132 insertions(+), 96 deletions(-) diff --git a/src/buffer.cpp b/src/buffer.cpp index 655cf9ff..5c3a23dc 100755 --- a/src/buffer.cpp +++ b/src/buffer.cpp @@ -380,10 +380,13 @@ void CNetBuf::Clear ( const EClearType eClearType ) void CNetBuf::FadeInAudioDataBlock ( CVector& vecdData ) { + // correct fading length if necessary + const int iCurFadingLen = min ( vecdData.Size(), iNumSamFading ); + // 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 @@ -394,14 +397,17 @@ void CNetBuf::FadeOutExtrapolateAudioDataBlock ( CVector& vecdData, const double dExPDiff, const double dExPLastV ) { + // correct fading length if necessary + const int iCurFadingLenExtra = min ( vecdData.Size(), iNumSamFadingExtra ); + // apply linear extrapolation and linear fading - for ( int i = 0; i < iNumSamFadingExtra; i++ ) + for ( int i = 0; i < iCurFadingLenExtra; i++ ) { // calculate extrapolated value vecdData[i] = ( ( i + 1 ) * dExPDiff + dExPLastV ); // linear fading - vecdData[i] *= ( (double) ( iNumSamFadingExtra - i ) / iNumSamFadingExtra ); + vecdData[i] *= ( (double) ( iCurFadingLenExtra - i ) / iCurFadingLenExtra ); } } diff --git a/src/channel.cpp b/src/channel.cpp index 6026eaca..ffa7c81b 100755 --- a/src/channel.cpp +++ b/src/channel.cpp @@ -622,11 +622,19 @@ CChannel::CChannel ( const bool bNIsServer ) : bIsServer ( bNIsServer ), MIN_SERVER_BLOCK_SIZE_SAMPLES * DEF_NET_BLOCK_SIZE_FACTOR, 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 SetAudioCompressionOut ( CT_MSADPCM ); + // connections ------------------------------------------------------------- QObject::connect ( &Protocol, SIGNAL ( MessReadyForSending ( CVector ) ), @@ -730,11 +738,16 @@ void CChannel::SetNetwBufSizeOut ( const int iNewAudioBlockSizeOut ) // this function is intended for the client (not the server) QMutexLocker locker ( &Mutex ); - // store new value - iCurAudioBlockSizeOut = iNewAudioBlockSizeOut; + // direct setting of audio buffer (without buffer size factor) is + // right now only intendet for the client, not the server + if ( !bIsServer ) + { + // store new value + iCurAudioBlockSizeOut = iNewAudioBlockSizeOut; - iAudComprSizeOut = - AudioCompressionOut.Init ( iNewAudioBlockSizeOut, eAudComprTypeOut ); + iAudComprSizeOut = + AudioCompressionOut.Init ( iNewAudioBlockSizeOut, eAudComprTypeOut ); + } } void CChannel::SetNetwBufSizeFactOut ( const int iNewNetwBlSiFactOut ) diff --git a/src/client.cpp b/src/client.cpp index 292480b3..be5b7502 100755 --- a/src/client.cpp +++ b/src/client.cpp @@ -150,29 +150,40 @@ bool CClient::SetServerAddr ( QString strNAddr ) return true; } - - - void CClient::SetSndCrdPreferredMonoBlSizeIndex ( const int iNewIdx ) { -// right now we simply set the internal value -if ( ( iNewIdx >= 0 ) && ( CSndCrdBufferSizes::GetNumOfBufferSizes() ) ) -{ - iSndCrdPreferredMonoBlSizeIndex = iNewIdx; + // right now we simply set the internal value + if ( ( iNewIdx >= 0 ) && ( CSndCrdBufferSizes::GetNumOfBufferSizes() ) ) + { + 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() { // init object - -// TEST -Init ( 192 ); + Init ( iSndCrdPreferredMonoBlSizeIndex ); // enable channel Channel.SetEnable ( true ); @@ -203,8 +214,12 @@ void CClient::AudioCallback ( CVector& psData, void* arg ) 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 iSndCrdMonoBlockSizeSam = Sound.Init ( iPrefMonoBlockSizeSamAtSndCrdSamRate ); iSndCrdStereoBlockSizeSam = 2 * iSndCrdMonoBlockSizeSam; diff --git a/src/client.h b/src/client.h index 90f6d641..f25f0448 100755 --- a/src/client.h +++ b/src/client.h @@ -156,7 +156,7 @@ protected: // callback function must be static, otherwise it does not work static void AudioCallback ( CVector& psData, void* arg ); - void Init ( const int iPrefMonoBlockSizeSamAtSndCrdSamRate ); + void Init ( const int iPrefMonoBlockSizeSamIndexAtSndCrdSamRate ); void ProcessAudioData ( CVector& vecsStereoSndCrd ); void UpdateTimeResponseMeasurement(); void UpdateSocketBufferSize(); diff --git a/src/clientsettingsdlgbase.ui b/src/clientsettingsdlgbase.ui index 6c4f0456..be4840e5 100755 --- a/src/clientsettingsdlgbase.ui +++ b/src/clientsettingsdlgbase.ui @@ -251,7 +251,7 @@ 110 - 0 + 20 @@ -281,7 +281,7 @@ 110 - 0 + 20 @@ -386,7 +386,7 @@ 50 - 0 + 20 @@ -427,7 +427,7 @@ 50 - 0 + 20 @@ -484,6 +484,12 @@ + + + 0 + 20 + + 75 diff --git a/src/soundbase.cpp b/src/soundbase.cpp index 9f440c4b..7227024e 100755 --- a/src/soundbase.cpp +++ b/src/soundbase.cpp @@ -61,11 +61,6 @@ void CSoundBase::Stop() { 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() diff --git a/windows/sound.cpp b/windows/sound.cpp index 9765850a..7b19dc20 100755 --- a/windows/sound.cpp +++ b/windows/sound.cpp @@ -43,9 +43,8 @@ ASIOBufferInfo bufferInfos[2 * NUM_IN_OUT_CHANNELS]; // for input and output b ASIOChannelInfo channelInfos[2 * NUM_IN_OUT_CHANNELS]; bool bASIOPostOutput; ASIOCallbacks asioCallbacks; -int iBufferSizeMono; -int iBufferSizeStereo; int iASIOBufferSizeMono; +int iASIOBufferSizeStereo; CVector vecsTmpAudioSndCrdStereo; @@ -88,12 +87,12 @@ void CSound::SetDev ( const int iNewDev ) // loading and initializing the new driver failed, go back to original // driver and display error message LoadAndInitializeDriver ( lCurDev ); - Init ( iBufferSizeStereo ); + Init ( iASIOBufferSizeStereo ); throw CGenErr ( strErrorMessage.c_str() ); } - Init ( iBufferSizeStereo ); + Init ( iASIOBufferSizeStereo ); } else { @@ -319,92 +318,75 @@ int CSound::GetActualBufferSize ( const int iDesiredBufferSizeMono ) int CSound::Init ( const int iNewPrefMonoBufferSize ) { - // first, stop audio and dispose ASIO buffers - ASIOStop(); - 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 - CSoundBase::Init ( iNewPrefMonoBufferSize ); + CSoundBase::Init ( iASIOBufferSizeMono ); // set internal buffer size value and calculate stereo buffer size - iBufferSizeMono = iNewPrefMonoBufferSize; - iBufferSizeStereo = 2 * iBufferSizeMono; - - -// TODO possible BUG!!!!!!!!!!!!!!!!!!!!! -// iBufferSizeMono must not be the same as iASIOBufferSizeMono + iASIOBufferSizeStereo = 2 * iASIOBufferSizeMono; + // set the sample rate + ASIOSetSampleRate ( SND_CRD_SAMPLE_RATE ); // create memory for intermediate audio buffer - vecsTmpAudioSndCrdStereo.Init ( iBufferSizeStereo ); - - - - - int i; - - // set the sample rate and check if sample rate is supported - ASIOSetSampleRate ( SND_CRD_SAMPLE_RATE ); - - -// TEST -iASIOBufferSizeMono = GetActualBufferSize ( iBufferSizeMono ); - - - for ( i = 0; i < NUM_IN_OUT_CHANNELS; i++ ) - { - // prepare input channels - bufferInfos[i].isInput = ASIOTrue; - bufferInfos[i].channelNum = i; - bufferInfos[i].buffers[0] = 0; - bufferInfos[i].buffers[1] = 0; - - // prepare output channels - bufferInfos[NUM_IN_OUT_CHANNELS + i].isInput = ASIOFalse; - bufferInfos[NUM_IN_OUT_CHANNELS + i].channelNum = i; - bufferInfos[NUM_IN_OUT_CHANNELS + i].buffers[0] = 0; - bufferInfos[NUM_IN_OUT_CHANNELS + i].buffers[1] = 0; - } - - // create and activate ASIO buffers (buffer size in samples) - ASIOCreateBuffers ( bufferInfos, 2 /* in/out */ * NUM_IN_OUT_CHANNELS /* stereo */, - iASIOBufferSizeMono, &asioCallbacks ); - - - - // check wether the driver requires the ASIOOutputReady() optimization - // (can be used by the driver to reduce output latency by one block) - bASIOPostOutput = ( ASIOOutputReady() == ASE_OK ); - + vecsTmpAudioSndCrdStereo.Init ( iASIOBufferSizeStereo ); + // 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(); - // initialization is done, (re)start audio + return iASIOBufferSizeMono; +} + +void CSound::Start() +{ + // start audio ASIOStart(); -// TEST -return iNewPrefMonoBufferSize; + // call base class + CSoundBase::Start(); +} + +void CSound::Stop() +{ + // stop audio + ASIOStop(); + + // call base class + CSoundBase::Stop(); } void CSound::Close() { - // stop driver - ASIOStop(); + +// TODO + } CSound::CSound ( void (*fpNewCallback) ( CVector& psData, void* arg ), void* arg ) : CSoundBase ( true, fpNewCallback, arg ) { + int i; // TEST pSound = this; // 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]; } @@ -422,6 +404,23 @@ pSound = this; // init device index with illegal value to show that driver is not initialized 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 asioCallbacks.bufferSwitch = &bufferSwitch; asioCallbacks.sampleRateDidChange = &sampleRateChanged; diff --git a/windows/sound.h b/windows/sound.h index 4a57a4d6..d9b8f66d 100755 --- a/windows/sound.h +++ b/windows/sound.h @@ -60,6 +60,8 @@ public: virtual ~CSound(); virtual int Init ( const int iNewPrefMonoBufferSize ); + virtual void Start(); + virtual void Stop(); virtual void Close(); virtual void OpenDriverSetup() { ASIOControlPanel(); }