From 034530474c2c3bf33e25a57484fd689406fa8e4b Mon Sep 17 00:00:00 2001 From: Volker Fischer Date: Fri, 24 Jul 2009 14:31:25 +0000 Subject: [PATCH] start work for supporting CELT codec, code does not compile at the moment (backup checkin) --- src/buffer.cpp | 150 ++------------------ src/buffer.h | 33 +---- src/channel.cpp | 227 +++++++----------------------- src/channel.h | 30 ++-- src/client.cpp | 130 ++++++++++-------- src/client.h | 29 ++-- src/clientsettingsdlg.cpp | 6 +- src/global.h | 45 ++---- src/main.cpp | 51 ++++--- src/protocol.cpp | 1 + src/protocol.h | 23 ++-- src/res/frontpicture.xcf | Bin 81256 -> 84437 bytes src/res/gig.png | Bin 105024 -> 49004 bytes src/server.cpp | 6 +- src/server.h | 3 +- src/soundbase.h | 12 +- src/util.cpp | 27 ++-- src/util.h | 19 ++- windows/llcon.vcproj | 282 +++++++++++++++++++++++++++++++++----- windows/sound.cpp | 4 +- windows/sound.h | 4 +- 21 files changed, 499 insertions(+), 583 deletions(-) diff --git a/src/buffer.cpp b/src/buffer.cpp index 5c3a23dc..18769283 100755 --- a/src/buffer.cpp +++ b/src/buffer.cpp @@ -35,40 +35,14 @@ void CNetBuf::Init ( const int iNewBlockSize, const int iNewNumBlocks ) iBlockSize = iNewBlockSize; iMemSize = iNewBlockSize * iNewNumBlocks; - // fade in first block added to the buffer - bFadeInNewPutData = true; - // allocate and clear memory for actual data buffer - vecdMemory.Init ( iMemSize ); + vecbyMemory.Init ( iMemSize ); // use the "get" flag to make sure the buffer is cleared Clear ( CT_GET ); - - // initialize number of samples for fading effect - if ( FADE_IN_OUT_NUM_SAM < iBlockSize ) - { - iNumSamFading = iBlockSize; - } - else - { - iNumSamFading = FADE_IN_OUT_NUM_SAM; - } - - if ( FADE_IN_OUT_NUM_SAM_EXTRA > iBlockSize ) - { - iNumSamFadingExtra = iBlockSize; - } - else - { - iNumSamFadingExtra = FADE_IN_OUT_NUM_SAM_EXTRA; - } - - // init variables for extrapolation (in case a fade out is needed) - dExPDiff = 0.0; - dExPLastV = 0.0; } -bool CNetBuf::Put ( CVector& vecdData ) +bool CNetBuf::Put ( const CVector& vecbyData ) { #ifdef _DEBUG_ static FILE* pFileBI = fopen("bufferin.dat", "w"); @@ -79,7 +53,7 @@ fflush(pFileBI); bool bPutOK = true; // get size of data to be added to the buffer - const int iInSize = vecdData.Size(); + const int iInSize = vecbyData.Size(); // Check if there is not enough space available -> correct if ( GetAvailSpace() < iInSize ) @@ -88,9 +62,6 @@ fflush(pFileBI); // prepare for new data Clear ( CT_PUT ); - // set flag to fade in new block to avoid clicks - bFadeInNewPutData = true; - bPutOK = false; // return error flag // check for special case: buffer memory is not sufficient @@ -101,12 +72,6 @@ fflush(pFileBI); } } - // fade in new block if required - if ( bFadeInNewPutData ) - { - FadeInAudioDataBlock ( vecdData ); - } - // copy new data in internal buffer int iCurPos = 0; if ( iPutPos + iInSize > iMemSize ) @@ -117,12 +82,12 @@ fflush(pFileBI); // data must be written in two steps because of wrap around while ( iPutPos < iMemSize ) { - vecdMemory[iPutPos++] = vecdData[iCurPos++]; + vecbyMemory[iPutPos++] = vecbyData[iCurPos++]; } for ( iPutPos = 0; iPutPos < iRemSpace; iPutPos++ ) { - vecdMemory[iPutPos] = vecdData[iCurPos++]; + vecbyMemory[iPutPos] = vecbyData[iCurPos++]; } } else @@ -131,7 +96,7 @@ fflush(pFileBI); const int iEnd = iPutPos + iInSize; while ( iPutPos < iEnd ) { - vecdMemory[iPutPos++] = vecdData[iCurPos++]; + vecbyMemory[iPutPos++] = vecbyData[iCurPos++]; } } @@ -148,13 +113,12 @@ fflush(pFileBI); return bPutOK; } -bool CNetBuf::Get ( CVector& vecdData ) +bool CNetBuf::Get ( CVector& vecbyData ) { - bool bGetOK = true; // init return value - bool bFadeOutExtrap = false; + bool bGetOK = true; // init return value // get size of data to be get from the buffer - const int iInSize = vecdData.Size(); + const int iInSize = vecbyData.Size(); // Check if there is not enough data available -> correct if ( GetAvailData() < iInSize ) @@ -163,11 +127,6 @@ bool CNetBuf::Get ( CVector& vecdData ) // prepare for getting data Clear ( CT_GET ); - // set flag to fade in next new block in buffer and fade out last - // block by extrapolation to avoid clicks - bFadeInNewPutData = true; - bFadeOutExtrap = true; - bGetOK = false; // return error flag // check for special case: buffer memory is not sufficient @@ -188,12 +147,12 @@ bool CNetBuf::Get ( CVector& vecdData ) // data must be read in two steps because of wrap around while ( iGetPos < iMemSize ) { - vecdData[iCurPos++] = vecdMemory[iGetPos++]; + vecbyData[iCurPos++] = vecbyMemory[iGetPos++]; } for ( iGetPos = 0; iGetPos < iRemData; iGetPos++ ) { - vecdData[iCurPos++] = vecdMemory[iGetPos]; + vecbyData[iCurPos++] = vecbyMemory[iGetPos]; } } else @@ -202,7 +161,7 @@ bool CNetBuf::Get ( CVector& vecdData ) const int iEnd = iGetPos + iInSize; while ( iGetPos < iEnd ) { - vecdData[iCurPos++] = vecdMemory[iGetPos++]; + vecbyData[iCurPos++] = vecbyMemory[iGetPos++]; } } @@ -216,23 +175,6 @@ bool CNetBuf::Get ( CVector& vecdData ) eBufState = CNetBuf::BS_OK; } - - /* extrapolate data from old block to avoid "clicks" - we have to do this method since we cannot fade out the old block - anymore since it is already gone (processed or send through the - network) */ - if ( bFadeOutExtrap ) - { - FadeOutExtrapolateAudioDataBlock ( vecdData, dExPDiff, dExPLastV ); - } - - /* save some paramters from last block which is needed in case we do not - have enough data for next "get" operation and need to extrapolate the - signal to avoid "clicks" - we assume here that "iBlockSize" is larger than 1! */ - dExPDiff = vecdData[iInSize - 1] - vecdData[iInSize - 2]; - dExPLastV = vecdData[iInSize - 1]; - return bGetOK; } @@ -303,7 +245,7 @@ void CNetBuf::Clear ( const EClearType eClearType ) if ( eClearType == CT_GET ) { // clear buffer - vecdMemory.Reset ( 0.0 ); + vecbyMemory.Reset ( 0 ); // correct buffer so that after the current get operation the pointer // are at maximum distance @@ -334,38 +276,6 @@ void CNetBuf::Clear ( const EClearType eClearType ) iPutPos -= iMemSize; } - // fade out old data right before new put pointer - int iCurPos = iPutPos - iNumSamFading; - int i = iNumSamFading; - - if ( iCurPos < 0 ) - { - // wrap around - iCurPos += iMemSize; - - // data must be processed in two steps because of wrap around - while ( iCurPos < iMemSize ) - { - vecdMemory[iCurPos++] *= ( (double) i / iNumSamFading ); - i--; - } - - for ( iCurPos = 0; iCurPos < iPutPos; iCurPos++ ) - { - vecdMemory[iCurPos] *= ( (double) i / iNumSamFading ); - i--; - } - } - else - { - // data can be processed in one step - while ( iCurPos < iPutPos ) - { - vecdMemory[iCurPos++] *= ( (double) i / iNumSamFading ); - i--; - } - } - // check for special case if ( iPutPos == iGetPos ) { @@ -378,40 +288,6 @@ 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 < iCurFadingLen; i++ ) - { - vecdData[i] *= ( (double) i / iCurFadingLen ); - } - - // reset flag - bFadeInNewPutData = false; -} - -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 < iCurFadingLenExtra; i++ ) - { - // calculate extrapolated value - vecdData[i] = ( ( i + 1 ) * dExPDiff + dExPLastV ); - - // linear fading - vecdData[i] *= ( (double) ( iCurFadingLenExtra - i ) / iCurFadingLenExtra ); - } -} - - /* conversion buffer implementation *******************************************/ void CConvBuf::Init ( const int iNewMemSize ) diff --git a/src/buffer.h b/src/buffer.h index 291ea4f5..3e7f1716 100755 --- a/src/buffer.h +++ b/src/buffer.h @@ -29,15 +29,6 @@ #include "global.h" -/* Definitions ****************************************************************/ -// time for fading effect for masking drop outs -#define FADE_IN_OUT_TIME ( (double) 2 ) // ms -#define FADE_IN_OUT_NUM_SAM ( (int) ( SYSTEM_SAMPLE_RATE * FADE_IN_OUT_TIME ) / 1000 ) - -// for extrapolation a shorter time for fading -#define FADE_IN_OUT_NUM_SAM_EXTRA 10 // samples - - /* Classes ********************************************************************/ class CNetBuf { @@ -48,8 +39,8 @@ public: void Init ( const int iNewBlockSize, const int iNewNumBlocks ); int GetSize() { return iMemSize / iBlockSize; } - bool Put ( CVector& vecdData ); - bool Get ( CVector& vecdData ); + bool Put ( const CVector& vecbyData ); + bool Get ( CVector& vecbyData ); protected: enum EBufState { BS_OK, BS_FULL, BS_EMPTY }; @@ -57,22 +48,12 @@ protected: void Clear ( const EClearType eClearType ); int GetAvailSpace() const; int GetAvailData() const; - void FadeInAudioDataBlock ( CVector& vecdData ); - void FadeOutExtrapolateAudioDataBlock ( CVector& vecdData, - const double dExPDiff, const double dExPLastV ); - CVector vecdMemory; - int iMemSize; - int iBlockSize; - int iGetPos, iPutPos; - EBufState eBufState; - bool bFadeInNewPutData; - int iNumSamFading; - int iNumSamFadingExtra; - - // extrapolation parameters - double dExPDiff; - double dExPLastV; + CVector vecbyMemory; + int iMemSize; + int iBlockSize; + int iGetPos, iPutPos; + EBufState eBufState; }; diff --git a/src/channel.cpp b/src/channel.cpp index 328729a0..3c7b2200 100755 --- a/src/channel.cpp +++ b/src/channel.cpp @@ -28,9 +28,8 @@ /******************************************************************************\ * CChannelSet * \******************************************************************************/ -CChannelSet::CChannelSet ( const int iNewUploadRateLimitKbps ) : - bWriteStatusHTMLFile ( false ), - iUploadRateLimitKbps ( iNewUploadRateLimitKbps ) +CChannelSet::CChannelSet() : + bWriteStatusHTMLFile ( false ) { // enable all channels (for the server all channel must be enabled the // entire life time of the software @@ -492,7 +491,8 @@ void CChannelSet::GetBlockAllConC ( CVector& vecChanID, { // read out all input buffers to decrease timeout counter on // disconnected channels - const EGetDataStat eGetStat = vecChannels[i].GetData ( vecdData ); +// const EGetDataStat eGetStat = vecChannels[i].GetData ( vecdData ); +const EGetDataStat eGetStat=GS_BUFFER_OK;//TEST // if channel was just disconnected, set flag that connected // client list is sent to all other clients @@ -668,56 +668,9 @@ CChannel::CChannel ( const bool bNIsServer ) : bIsEnabled ( false ), iCurNetwOutBlSiFact ( DEF_NET_BLOCK_SIZE_FACTOR ) { - // query all possible network in buffer sizes for determining if an - // audio packet was received (the following code only works if all - // possible network buffer sizes are different!) - // we add a special entry for network modes which are managed via the - // protocol -> "+ 1" - const int iNumSupportedAudComprTypes = 3; - vecNetwBufferInProps.Init ( iNumSupportedAudComprTypes * - MAX_NET_BLOCK_SIZE_FACTOR + 1 ); - - // init special mode (with invalid data) - vecNetwBufferInProps[0].iAudioBlockSize = 0; - vecNetwBufferInProps[0].eAudComprType = CT_NONE; - vecNetwBufferInProps[0].iNetwInBufSize = 0; - - for ( int i = 0; i < MAX_NET_BLOCK_SIZE_FACTOR; i++ ) - { - // (consider the special mode -> "1 +") - const int iNoneIdx = 1 + iNumSupportedAudComprTypes * i; - const int iIMAIdx = 1 + iNumSupportedAudComprTypes * i + 1; - const int iMSIdx = 1 + iNumSupportedAudComprTypes * i + 2; - - // network block size factor must start from 1 -> i + 1 - const int iCurNetBlockSizeFact = i + 1; - vecNetwBufferInProps[iNoneIdx].iAudioBlockSize = - iCurNetBlockSizeFact * MIN_SERVER_BLOCK_SIZE_SAMPLES; - - vecNetwBufferInProps[iIMAIdx].iAudioBlockSize = - iCurNetBlockSizeFact * MIN_SERVER_BLOCK_SIZE_SAMPLES; - - vecNetwBufferInProps[iMSIdx].iAudioBlockSize = - iCurNetBlockSizeFact * MIN_SERVER_BLOCK_SIZE_SAMPLES; - - // None (no audio compression) - vecNetwBufferInProps[iNoneIdx].eAudComprType = CT_NONE; - vecNetwBufferInProps[iNoneIdx].iNetwInBufSize = AudioCompressionIn.Init ( - vecNetwBufferInProps[iNoneIdx].iAudioBlockSize, - vecNetwBufferInProps[iNoneIdx].eAudComprType ); - - // IMA ADPCM - vecNetwBufferInProps[iIMAIdx].eAudComprType = CT_IMAADPCM; - vecNetwBufferInProps[iIMAIdx].iNetwInBufSize = AudioCompressionIn.Init ( - vecNetwBufferInProps[iIMAIdx].iAudioBlockSize, - vecNetwBufferInProps[iIMAIdx].eAudComprType ); - - // MS ADPCM - vecNetwBufferInProps[iMSIdx].eAudComprType = CT_MSADPCM; - vecNetwBufferInProps[iMSIdx].iNetwInBufSize = AudioCompressionIn.Init ( - vecNetwBufferInProps[iMSIdx].iAudioBlockSize, - vecNetwBufferInProps[iMSIdx].eAudComprType ); - } + // init network input properties + NetwBufferInProps.iAudioBlockSize = 0; + NetwBufferInProps.iNetwInBufSize = 0; // initial value for connection time out counter, we calculate the total // number of samples here and subtract the number of samples of the block @@ -730,11 +683,7 @@ CChannel::CChannel ( const bool bNIsServer ) : // init the socket buffer SetSockBufSize ( DEF_NET_BUF_SIZE_NUM_BL ); - // set initial input and output block size factors - SetAudioBlockSizeAndComprIn ( - MIN_SERVER_BLOCK_SIZE_SAMPLES * DEF_NET_BLOCK_SIZE_FACTOR, - CT_MSADPCM ); - + // set initial output block size factors if ( bIsServer ) { SetNetwBufSizeFactOut ( DEF_NET_BLOCK_SIZE_FACTOR ); @@ -824,53 +773,20 @@ void CChannel::SetEnable ( const bool bNEnStat ) } } -void CChannel::SetAudioBlockSizeAndComprIn ( const int iNewBlockSize, - const EAudComprType eNewAudComprType ) -{ - QMutexLocker locker ( &Mutex ); - - // store block size value - iCurAudioBlockSizeIn = iNewBlockSize; - - // init audio compression unit - AudioCompressionIn.Init ( iNewBlockSize, eNewAudComprType ); -} - -void CChannel::SetNetwBufSizeOut ( const int iNewAudioBlockSizeOut ) -{ - // this function is intended for the client (not the server) - QMutexLocker locker ( &Mutex ); - - // 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 ); - } -} - void CChannel::SetNetwBufSizeFactOut ( const int iNewNetwBlSiFactOut ) { // this function is intended for the server (not the client) QMutexLocker locker ( &Mutex ); - // use the network block size factor only for the server - if ( bIsServer ) - { - // store new value - iCurNetwOutBlSiFact = iNewNetwBlSiFactOut; + // store new value + iCurNetwOutBlSiFact = iNewNetwBlSiFactOut; - // init audio compression and get audio compression block size - iAudComprSizeOut = AudioCompressionOut.Init ( - iNewNetwBlSiFactOut * MIN_SERVER_BLOCK_SIZE_SAMPLES, eAudComprTypeOut ); + // init audio compression and get audio compression block size + iAudComprSizeOut = AudioCompressionOut.Init ( + iNewNetwBlSiFactOut * MIN_SERVER_BLOCK_SIZE_SAMPLES, eAudComprTypeOut ); - // init conversion buffer - ConvBuf.Init ( iNewNetwBlSiFactOut * MIN_SERVER_BLOCK_SIZE_SAMPLES ); - } + // init conversion buffer + ConvBuf.Init ( iNewNetwBlSiFactOut * MIN_SERVER_BLOCK_SIZE_SAMPLES ); } void CChannel::SetAudioCompressionOut ( const EAudComprType eNewAudComprTypeOut ) @@ -1021,11 +937,22 @@ void CChannel::OnNetTranspPropsReceived ( CNetworkTransportProps NetworkTranspor QMutexLocker locker ( &Mutex ); // apply received parameters to internal data struct - vecNetwBufferInProps[0].iAudioBlockSize = NetworkTransportProps.iMonoAudioBlockSize; - vecNetwBufferInProps[0].eAudComprType = NetworkTransportProps.eAudioCodingType; - vecNetwBufferInProps[0].iNetwInBufSize = AudioCompressionIn.Init ( - vecNetwBufferInProps[0].iAudioBlockSize, - vecNetwBufferInProps[0].eAudComprType ); + NetwBufferInProps.iAudioBlockSize = NetworkTransportProps.iMonoAudioBlockSize; + NetwBufferInProps.eAudComprType = NetworkTransportProps.eAudioCodingType; + NetwBufferInProps.iNetwInBufSize = NetworkTransportProps.iNetworkPacketSize; + + // re-initialize cycle time variance measurement if necessary + if ( NetwBufferInProps.iAudioBlockSize != CycleTimeVariance.GetBlockLength() ) + { + // re-init (we have to use the buffer size which works + // on the system sample rate, therefore we use the + // decompressed audio buffer size instead of the network + // buffer size) + CycleTimeVariance.Init ( NetwBufferInProps.iAudioBlockSize, + SYSTEM_SAMPLE_RATE, TIME_MOV_AV_RESPONSE ); + + CycleTimeVariance.Reset(); + } } void CChannel::OnReqNetTranspProps() @@ -1040,7 +967,7 @@ void CChannel::CreateNetTranspPropsMessFromCurrentSettings() iCurAudioBlockSizeOut, 1, // right now we only use mono SYSTEM_SAMPLE_RATE, // right now only one sample rate is supported - AudioCompressionOut.GetType(), + CT_CELT, // always CELT coding 0 ); // send current network transport properties @@ -1064,11 +991,6 @@ EPutDataStat CChannel::PutData ( const CVector& vecbyData, bool bIsProtocolPacket = false; bool bIsAudioPacket = false; bool bNewConnection = false; - bool bReinitializeIn = false; - - // intermediate storage for new parameters - int iNewAudioBlockSize; - EAudComprType eNewAudComprType; if ( bIsEnabled ) { @@ -1088,62 +1010,16 @@ EPutDataStat CChannel::PutData ( const CVector& vecbyData, // only try to parse audio if it was not a protocol packet if ( !bIsProtocolPacket ) { - Mutex.lock(); - { - // check if this is an audio packet by checking all possible lengths - const int iPossNetwSizes = vecNetwBufferInProps.Size(); - - for ( int i = 0; i < iPossNetwSizes; i++ ) - { - // check for low/high quality audio packets and set flags - if ( iNumBytes == vecNetwBufferInProps[i].iNetwInBufSize ) - { - bIsAudioPacket = true; - - // check if we are correctly initialized - iNewAudioBlockSize = - vecNetwBufferInProps[i].iAudioBlockSize; - - eNewAudComprType = - vecNetwBufferInProps[i].eAudComprType; - - if ( ( iNewAudioBlockSize != iCurAudioBlockSizeIn ) || - ( eNewAudComprType != AudioCompressionIn.GetType() ) ) - { - bReinitializeIn = true; - } - } - } - } - Mutex.unlock(); - - // actual initialization call has to be made - // outside the mutex region since it internally - // usees the same mutex, too - if ( bReinitializeIn ) - { - // re-initialize to new value - SetAudioBlockSizeAndComprIn ( - iNewAudioBlockSize, eNewAudComprType ); - } - Mutex.lock(); { // only process audio if packet has correct size - if ( bIsAudioPacket ) + if ( iNumBytes == NetwBufferInProps.iNetwInBufSize ) { - // decompress audio - CVector vecsDecomprAudio ( AudioCompressionIn.Decode ( vecbyData ) ); + // set audio packet flag + bIsAudioPacket = true; - // convert received data from short to double - const int iAudioSize = vecsDecomprAudio.Size(); - CVector vecdDecomprAudio ( iAudioSize ); - for ( int i = 0; i < iAudioSize; i++ ) - { - vecdDecomprAudio[i] = static_cast ( vecsDecomprAudio[i] ); - } - - if ( SockBuf.Put ( vecdDecomprAudio ) ) + // store new packet in jitter buffer + if ( SockBuf.Put ( vecbyData ) ) { eRet = PS_AUDIO_OK; } @@ -1152,28 +1028,13 @@ EPutDataStat CChannel::PutData ( const CVector& vecbyData, eRet = PS_AUDIO_ERR; } - // update cycle time variance measurement, take care of - // re-initialization, too, if necessary - if ( iAudioSize != CycleTimeVariance.GetBlockLength() ) - { - // re-init (we have to use the buffer size which works - // on the system sample rate, therefore we use the - // decompressed audio buffer size instead of the network - // buffer size) - CycleTimeVariance.Init ( iAudioSize, - SYSTEM_SAMPLE_RATE, TIME_MOV_AV_RESPONSE ); - - CycleTimeVariance.Reset(); - } - else - { + // update cycle time variance measurement // TODO only update if time difference of received packets is below // a limit to avoid having short network troubles incorporated in the // statistic - CycleTimeVariance.Update(); - } + CycleTimeVariance.Update(); } else { @@ -1219,20 +1080,24 @@ EPutDataStat CChannel::PutData ( const CVector& vecbyData, return eRet; } -EGetDataStat CChannel::GetData ( CVector& vecdData ) +EGetDataStat CChannel::GetData ( CVector& vecbyData ) { QMutexLocker locker ( &Mutex ); EGetDataStat eGetStatus; - const bool bSockBufState = SockBuf.Get ( vecdData ); + const bool bSockBufState = SockBuf.Get ( vecbyData ); // decrease time-out counter if ( iConTimeOut > 0 ) { + +// TODO + + // subtract the number of samples of the current block since the // time out counter is based on samples not on blocks - iConTimeOut -= vecdData.Size(); + iConTimeOut -= vecbyData.Size(); if ( iConTimeOut <= 0 ) { diff --git a/src/channel.h b/src/channel.h index 99bc6647..aa037a44 100755 --- a/src/channel.h +++ b/src/channel.h @@ -62,10 +62,6 @@ enum EGetDataStat GS_CHAN_NOT_CONNECTED }; -// low upload data rate settings -#define LOW_UPL_SET_AUDIO_COMPRESSION CT_MSADPCM -#define LOW_UPL_SET_BLOCK_SIZE_FACTOR_OUT MAX_NET_BLOCK_SIZE_FACTOR - /* Classes ********************************************************************/ // CChannel -------------------------------------------------------------------- @@ -81,7 +77,7 @@ public: EPutDataStat PutData ( const CVector& vecbyData, int iNumBytes ); - EGetDataStat GetData ( CVector& vecdData ); + EGetDataStat GetData ( CVector& vecbyData ); CVector PrepSendPacket ( const CVector& vecsNPacket ); @@ -111,7 +107,7 @@ public: void SetNetwBufSizeOut ( const int iNewAudioBlockSizeOut ); int GetNetwBufSizeOut() { return iCurAudioBlockSizeOut; } - int GetAudioBlockSizeIn() { return iCurAudioBlockSizeIn; } + int GetAudioBlockSizeIn() { return NetwBufferInProps.iAudioBlockSize; } int GetUploadRateKbps(); double GetTimingStdDev() { return CycleTimeVariance.GetStdDev(); } @@ -152,9 +148,6 @@ public: void CreateDisconnectionMes() { Protocol.CreateDisconnectionMes(); } protected: - void SetAudioBlockSizeAndComprIn ( const int iNewBlockSize, - const EAudComprType eNewAudComprType ); - bool ProtocolIsEnabled(); // audio compression @@ -189,19 +182,17 @@ protected: bool bIsEnabled; bool bIsServer; - int iCurAudioBlockSizeIn; int iCurNetwOutBlSiFact; int iCurAudioBlockSizeOut; QMutex Mutex; - struct sNetwBufferInProps + struct sNetwProperties { - int iNetwInBufSize; - int iAudioBlockSize; - EAudComprType eAudComprType; + int iNetwInBufSize; + int iAudioBlockSize; }; - CVector vecNetwBufferInProps; + sNetwProperties NetwBufferInProps; EAudComprType eAudComprTypeOut; @@ -233,7 +224,7 @@ class CChannelSet : public QObject Q_OBJECT public: - CChannelSet ( const int iNewUploadRateLimitKbps = DEF_MAX_UPLOAD_RATE_KBPS ); + CChannelSet(); virtual ~CChannelSet() {} bool PutData ( const CVector& vecbyRecBuf, @@ -267,9 +258,6 @@ public: void StartStatusHTMLFileWriting ( const QString& strNewFileName, const QString& strNewServerNameWithPort ); - void SetUploadRateLimitKbps ( const int iNewUploadRateLimitKbps ) - { iUploadRateLimitKbps = iNewUploadRateLimitKbps; } - protected: CVector CreateChannelList(); void CreateAndSendChanListForAllConChannels(); @@ -278,7 +266,7 @@ protected: void CreateAndSendChatTextForAllConChannels ( const int iCurChanID, const QString& strChatText ); void WriteHTMLChannelList(); void SetOutputParameters(); - int CalculateTotalUploadRateKbps(); + int CalculateTotalUploadRateKbps(); /* do not use the vector class since CChannel does not have appropriate copy constructor/operator */ @@ -287,8 +275,6 @@ protected: CVector vstrChatColors; - int iUploadRateLimitKbps; - // HTML file server status bool bWriteStatusHTMLFile; QString strServerHTMLFileListName; diff --git a/src/client.cpp b/src/client.cpp index 774f17fb..515bdebc 100755 --- a/src/client.cpp +++ b/src/client.cpp @@ -36,9 +36,7 @@ CClient::CClient ( const quint16 iPortNumber ) : vstrIPAddress ( MAX_NUM_SERVER_ADDR_ITEMS, "" ), strName ( "" ), bOpenChatOnNewMessage ( true ), bDoAutoSockBufSize ( true ), - iSndCrdPreferredMonoBlSizeIndex ( CSndCrdBufferSizes::GetDefaultIndex() ), - iClientSampleRate ( SYSTEM_SAMPLE_RATE ), - iSndCrdMonoBlockSizeSam ( 0 ) + iSndCrdPreferredMonoBlSizeIndex ( CSndCrdBufferSizes::GetDefaultIndex() ) { // connection for protocol QObject::connect ( &Channel, @@ -164,7 +162,7 @@ void CClient::SetSndCrdPreferredMonoBlSizeIndex ( const int iNewIdx ) } // init with new block size index parameter - Init ( iClientSampleRate, iSndCrdPreferredMonoBlSizeIndex ); + Init ( iSndCrdPreferredMonoBlSizeIndex ); if ( bWasRunning ) { @@ -191,7 +189,7 @@ QString CClient::SetSndCrdDev ( const int iNewDev ) // init again because the sound card actual buffer size might // be changed on new device - Init ( iClientSampleRate, iSndCrdPreferredMonoBlSizeIndex ); + Init ( iSndCrdPreferredMonoBlSizeIndex ); if ( bWasRunning ) { @@ -214,7 +212,7 @@ void CClient::OnSndCrdReinitRequest() // reinit the driver (we use the currently selected driver) and // init client object, too Sound.SetDev ( Sound.GetDev() ); - Init ( iClientSampleRate, iSndCrdPreferredMonoBlSizeIndex ); + Init ( iSndCrdPreferredMonoBlSizeIndex ); if ( bWasRunning ) { @@ -225,7 +223,7 @@ void CClient::OnSndCrdReinitRequest() void CClient::Start() { // init object - Init ( iClientSampleRate, iSndCrdPreferredMonoBlSizeIndex ); + Init ( iSndCrdPreferredMonoBlSizeIndex ); // enable channel Channel.SetEnable ( true ); @@ -254,7 +252,7 @@ void CClient::Stop() PostWinMessage ( MS_RESET_ALL, 0 ); } -void CClient::AudioCallback ( CVector& psData, void* arg ) +void CClient::AudioCallback ( CVector& psData, void* arg ) { // get the pointer to the object CClient* pMyClientObj = reinterpret_cast ( arg ); @@ -263,70 +261,62 @@ void CClient::AudioCallback ( CVector& psData, void* arg ) pMyClientObj->ProcessAudioData ( psData ); } -void CClient::Init ( const int iSampleRate, - const int iPrefMonoBlockSizeSamIndexAtSndCrdSamRate ) +void CClient::Init ( const int iPrefMonoBlockSizeSamIndexAtSndCrdSamRate ) { - // store new sample rate - iClientSampleRate = iSampleRate; - // 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; - - iMonoBlockSizeSam = iSndCrdMonoBlockSizeSam * iClientSampleRate / SND_CRD_SAMPLE_RATE; + iMonoBlockSizeSam = Sound.Init ( iPrefMonoBlockSizeSamAtSndCrdSamRate ); iStereoBlockSizeSam = 2 * iMonoBlockSizeSam; - // the channel works on the same block size as the sound interface - Channel.SetNetwBufSizeOut ( iMonoBlockSizeSam ); - - vecsAudioSndCrdStereo.Init ( iSndCrdStereoBlockSizeSam ); - vecdAudioSndCrdMono.Init ( iSndCrdMonoBlockSizeSam ); - vecdAudioSndCrdStereo.Init ( iSndCrdStereoBlockSizeSam ); + vecsAudioSndCrdStereo.Init ( iStereoBlockSizeSam ); vecdAudioStereo.Init ( iStereoBlockSizeSam ); - // resample objects are always initialized with the input block size - // record - ResampleObjDown.Init ( iSndCrdMonoBlockSizeSam, - SND_CRD_SAMPLE_RATE, iClientSampleRate ); - - // playback - ResampleObjUp.Init ( iMonoBlockSizeSam, - iClientSampleRate, SND_CRD_SAMPLE_RATE ); - - // init network buffers - vecsNetwork.Init ( iMonoBlockSizeSam ); - vecdNetwData.Init ( iMonoBlockSizeSam ); - // init response time evaluation CycleTimeVariance.Init ( iMonoBlockSizeSam, - iClientSampleRate, TIME_MOV_AV_RESPONSE ); + SYSTEM_SAMPLE_RATE, TIME_MOV_AV_RESPONSE ); CycleTimeVariance.Reset(); // init reverberation - AudioReverb.Init ( iClientSampleRate ); + AudioReverb.Init ( SYSTEM_SAMPLE_RATE ); + + // init audio endocder/decoder (mono) + CeltMode = celt_mode_create ( + SYSTEM_SAMPLE_RATE, 1, iMonoBlockSizeSam, NULL ); + + CeltEncoder = celt_encoder_create ( CeltMode ); + CeltDecoder = celt_decoder_create ( CeltMode ); + + // 16: low/normal quality 132 kbsp (128) / 90 kbps (256) + // 40: high good 204 kbps (128) / 162 kbps (256) + iCeltNumCodedBytes = 16; + + vecCeltData.Init ( iCeltNumCodedBytes ); + + // init network buffers + vecsNetwork.Init ( iMonoBlockSizeSam ); + vecbyNetwData.Init ( iCeltNumCodedBytes ); + + // the channel works on the audio coded block size + Channel.SetNetwBufSizeOut ( iCeltNumCodedBytes ); } -void CClient::ProcessAudioData ( CVector& vecsStereoSndCrd ) +void CClient::ProcessAudioData ( CVector& vecsStereoSndCrd ) { int i, j; - // convert data from short to double - for ( i = 0; i < iSndCrdStereoBlockSizeSam; i++ ) - { - vecdAudioSndCrdStereo[i] = (double) vecsStereoSndCrd[i]; - } - - // resample data for each channel seaparately - ResampleObjDown.ResampleStereo ( vecdAudioSndCrdStereo, vecdAudioStereo ); - // update stereo signal level meter - SignalLevelMeter.Update ( vecdAudioStereo ); + SignalLevelMeter.Update ( vecsStereoSndCrd ); + + // convert data from short to double + for ( i = 0; i < iStereoBlockSizeSam; i++ ) + { + vecdAudioStereo[i] = (double) vecsStereoSndCrd[i]; + } // add reverberation effect if activated if ( iReverbLevel != 0 ) @@ -395,11 +385,17 @@ void CClient::ProcessAudioData ( CVector& vecsStereoSndCrd ) } // send it through the network - Socket.SendPacket ( Channel.PrepSendPacket ( vecsNetwork ), - Channel.GetAddress() ); +// Socket.SendPacket ( Channel.PrepSendPacket ( vecsNetwork ), +// Channel.GetAddress() ); + +celt_encode(CeltEncoder, &vecsNetwork[0], NULL, &vecCeltData[0], iCeltNumCodedBytes); +Socket.SendPacket ( vecCeltData, Channel.GetAddress() ); + + + // receive a new block - if ( Channel.GetData ( vecdNetwData ) == GS_BUFFER_OK ) + if ( Channel.GetData ( vecbyNetwData ) == GS_BUFFER_OK ) { PostWinMessage ( MS_JIT_BUF_GET, MUL_COL_LED_GREEN ); } @@ -424,16 +420,36 @@ fflush(pFileDelay); // check if channel is connected if ( Channel.IsConnected() ) { - // resample data - ResampleObjUp.ResampleMono ( vecdNetwData, vecdAudioSndCrdMono ); - +/* // convert data from double to short type and copy mono // received data in both sound card channels for ( i = 0, j = 0; i < iSndCrdMonoBlockSizeSam; i++, j += 2 ) { vecsStereoSndCrd[j] = vecsStereoSndCrd[j + 1] = - Double2Short ( vecdAudioSndCrdMono[i] ); + Double2Short ( vecdNetwData[i] ); } +*/ + +CVector vecsAudioSndCrdMono ( iMonoBlockSizeSam ); +/* +for ( i = 0; i < iMonoBlockSizeSam; i++ ) +{ + vecsAudioSndCrdMono[i] = Double2Short ( vecdNetwData[i] ); +} +*/ +// TEST CELT +//celt_encode(CeltEncoder, &vecsAudioSndCrdMono[0], NULL, &vecCeltData[0], iCeltNumCodedBytes); +celt_decode(CeltDecoder, &vecbyNetwData[0], iCeltNumCodedBytes, &vecsAudioSndCrdMono[0]); + + +for ( i = 0, j = 0; i < iMonoBlockSizeSam; i++, j += 2 ) +{ + vecsStereoSndCrd[j] = vecsStereoSndCrd[j + 1] = + vecsAudioSndCrdMono[i]; +} + + + } else { @@ -472,7 +488,7 @@ void CClient::UpdateSocketBufferSize() // a minimum buffer size of the sum of both sizes const double dAudioBufferDurationMs = ( iMonoBlockSizeSam + Channel.GetAudioBlockSizeIn() ) * 1000 / - iClientSampleRate; + SYSTEM_SAMPLE_RATE; // accumulate the standard deviations of input network stream and // internal timer, diff --git a/src/client.h b/src/client.h index d80495d2..28f3b574 100755 --- a/src/client.h +++ b/src/client.h @@ -31,9 +31,9 @@ #include #include #include +#include "celt.h" #include "global.h" #include "socket.h" -#include "resample.h" #include "channel.h" #include "audiocompr.h" #include "util.h" @@ -125,7 +125,7 @@ public: void SetSndCrdPreferredMonoBlSizeIndex ( const int iNewIdx ); int GetSndCrdPreferredMonoBlSizeIndex() { return iSndCrdPreferredMonoBlSizeIndex; } - int GetSndCrdActualMonoBlSize() { return iSndCrdMonoBlockSizeSam; } + int GetSndCrdActualMonoBlSize() { return iMonoBlockSizeSam; } void SetAudioCompressionOut ( const EAudComprType eNewAudComprTypeOut ) { @@ -160,8 +160,7 @@ protected: // callback function must be static, otherwise it does not work static void AudioCallback ( CVector& psData, void* arg ); - void Init ( const int iSampleRate, - const int iPrefMonoBlockSizeSamIndexAtSndCrdSamRate ); + void Init ( const int iPrefMonoBlockSizeSamIndexAtSndCrdSamRate ); void ProcessAudioData ( CVector& vecsStereoSndCrd ); void UpdateSocketBufferSize(); @@ -169,11 +168,18 @@ protected: CChannel Channel; bool bDoAutoSockBufSize; + // audio encoder/decoder + CELTMode* CeltMode; + CELTEncoder* CeltEncoder; + CELTDecoder* CeltDecoder; + int iCeltNumCodedBytes; + CVector vecCeltData; + CSocket Socket; CSound Sound; CStereoSignalLevelMeter SignalLevelMeter; - CVector vecdNetwData; + CVector vecbyNetwData; int iAudioInFader; bool bReverbOnLeftChan; @@ -181,24 +187,15 @@ protected: CAudioReverb AudioReverb; int iSndCrdPreferredMonoBlSizeIndex; - int iClientSampleRate; - int iSndCrdMonoBlockSizeSam; - int iSndCrdStereoBlockSizeSam; int iMonoBlockSizeSam; int iStereoBlockSizeSam; bool bOpenChatOnNewMessage; - CVector vecsAudioSndCrdStereo; - CVector vecdAudioSndCrdMono; - CVector vecdAudioSndCrdStereo; + CVector vecsAudioSndCrdStereo; CVector vecdAudioStereo; - CVector vecsNetwork; - - // resample objects - CStereoAudioResample ResampleObjDown; - CStereoAudioResample ResampleObjUp; + CVector vecsNetwork; // for ping measurement CPreciseTime PreciseTime; diff --git a/src/clientsettingsdlg.cpp b/src/clientsettingsdlg.cpp index b28e7748..bf5d6e3e 100755 --- a/src/clientsettingsdlg.cpp +++ b/src/clientsettingsdlg.cpp @@ -177,13 +177,13 @@ void CClientSettingsDlg::UpdateSoundCardFrame() // we have input and output TextLabelPreferredSndCrdBufDelay->setText ( QString().setNum ( (double) iPrefBufSize * 2 * - 1000 / SND_CRD_SAMPLE_RATE, 'f', 2 ) + " ms (" + + 1000 / SYSTEM_SAMPLE_RATE, 'f', 2 ) + " ms (" + QString().setNum ( iPrefBufSize ) + ")" ); // actual size (use yellow color if different from preferred size) const QString strActSizeValues = QString().setNum ( (double) iCurActualBufSize * 2 * - 1000 / SND_CRD_SAMPLE_RATE, 'f', 2 ) + " ms (" + + 1000 / SYSTEM_SAMPLE_RATE, 'f', 2 ) + " ms (" + QString().setNum ( iCurActualBufSize ) + ")"; if ( iPrefBufSize != iCurActualBufSize ) @@ -299,7 +299,7 @@ void CClientSettingsDlg::OnPingTimeResult ( int iPingTime ) // the actual sound card buffer size const int iTotalSoundCardDelayMS = 3 * pClient->GetSndCrdActualMonoBlSize() * - 1000 / SND_CRD_SAMPLE_RATE; + 1000 / SYSTEM_SAMPLE_RATE; const int iDelayToFillNetworkPackets = ( pClient->GetNetwBufSizeOut() + pClient->GetAudioBlockSizeIn() ) * diff --git a/src/global.h b/src/global.h index cd31d91e..54f643b7 100755 --- a/src/global.h +++ b/src/global.h @@ -38,12 +38,12 @@ /* Definitions ****************************************************************/ // define this macro to get debug output -#define _DEBUG_ +//#define _DEBUG_ #undef _DEBUG_ // version and application name (always use this version) #undef VERSION -#define VERSION "2.3.1cvs" +#define VERSION "3.0.0cvs" #define APP_NAME "llcon" // file name for logging file @@ -53,34 +53,20 @@ #define DEFAULT_SERVER_ADDRESS "llcon.dyndns.org" // defined port number for client and server -#define LLCON_DEFAULT_PORT_NUMBER 22123 +#define LLCON_DEFAULT_PORT_NUMBER 22124 -// system sample rate -#define SYSTEM_SAMPLE_RATE 33000 +// system sample rate (the sound card and audio coder works on this sample rate) +#define SYSTEM_SAMPLE_RATE 48000 -// sound card sample rate. Should be always 48 kHz to avoid sound card driver -// internal sample rate conversion which might be buggy -#define SND_CRD_SAMPLE_RATE 48000 - -// minimum server block duration - all other buffer durations must be a multiple -// of this duration -#define MIN_SERVER_BLOCK_DURATION_MS 2 // ms - -#define MIN_SERVER_BLOCK_SIZE_SAMPLES ( MIN_SERVER_BLOCK_DURATION_MS * SYSTEM_SAMPLE_RATE / 1000 ) +// System block size, this is the block size on which the audio coder works. +// All other block sizes must be a multiple of this size +#define SYSTEM_BLOCK_SIZE_SAMPLES 128 // define the maximum mono audio buffer size at a sample rate // of 48 kHz, this is important for defining the maximum number -// of bytes to be expected from the network interface (we assume -// here that "MAX_NET_BLOCK_SIZE_FACTOR * MIN_SERVER_BLOCK_SIZE_SAMPLES" -// is smaller than this value here) +// of bytes to be expected from the network interface #define MAX_MONO_AUD_BUFF_SIZE_AT_48KHZ 4096 -// maximum value of factor for network block size -#define MAX_NET_BLOCK_SIZE_FACTOR 3 - -// default network block size factor (only used for server) -#define DEF_NET_BLOCK_SIZE_FACTOR 2 - // minimum/maximum network buffer size (which can be chosen by slider) #define MIN_NET_BUF_SIZE_NUM_BL 1 // number of blocks #define MAX_NET_BUF_SIZE_NUM_BL 20 // number of blocks @@ -88,9 +74,6 @@ // default network buffer size #define DEF_NET_BUF_SIZE_NUM_BL 10 // number of blocks -// default maximum upload rate at server (typical DSL upload for good DSL) -#define DEF_MAX_UPLOAD_RATE_KBPS 800 // kbps - // maximum number of recognized sound cards installed in the system, // definition for "no device" #define MAX_NUMBER_SOUND_CARDS 10 @@ -130,10 +113,12 @@ #elif HAVE_INTTYPES_H # include #elif defined ( _WIN32 ) +typedef __int16 int16_t; typedef unsigned __int32 uint32_t; typedef unsigned __int16 uint16_t; typedef unsigned __int8 uint8_t; #else +typedef short int16_t; typedef unsigned int uint32_t; typedef unsigned short uint16_t; typedef unsigned char uint8_t; @@ -196,10 +181,10 @@ public: /* Prototypes for global functions ********************************************/ // command line parsing, TODO do not declare functions globally but in a class -std::string UsageArguments ( char **argv ); -bool GetFlagArgument ( int, char **argv, int &i, std::string strShortOpt, std::string strLongOpt ); -bool GetStringArgument ( int argc, char **argv, int &i, std::string strShortOpt, std::string strLongOpt, std::string & strArg ); -bool GetNumericArgument ( int argc, char **argv, int &i, std::string strShortOpt, std::string strLongOpt, double rRangeStart, double rRangeStop, double & rValue); +std::string UsageArguments ( char** argv ); +bool GetFlagArgument ( int argc, char** argv, int& i, std::string strShortOpt, std::string strLongOpt ); +bool GetStringArgument ( int argc, char** argv, int& i, std::string strShortOpt, std::string strLongOpt, std::string& strArg ); +bool GetNumericArgument ( int argc, char** argv, int& i, std::string strShortOpt, std::string strLongOpt, double rRangeStart, double rRangeStop, double& rValue); // posting a window message void PostWinMessage ( const _MESSAGE_IDENT MessID, const int iMessageParam = 0, diff --git a/src/main.cpp b/src/main.cpp index 357d0e64..0b39b8eb 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -48,7 +48,6 @@ int main ( int argc, char** argv ) bool bUseGUI = true; bool bConnectOnStartup = false; bool bDisalbeLEDs = false; - int iUploadRateLimitKbps = DEF_MAX_UPLOAD_RATE_KBPS; quint16 iPortNumber = LLCON_DEFAULT_PORT_NUMBER; std::string strIniFileName = ""; std::string strHTMLStatusFileName = ""; @@ -97,17 +96,6 @@ int main ( int argc, char** argv ) } - // force low upload data rate flag ------------------------------------- - if ( GetNumericArgument ( argc, argv, i, "-u", "--maxuploadrate", - 100, 1000000, rDbleArgument ) ) - { - iUploadRateLimitKbps = static_cast ( rDbleArgument ); - cout << "maximum upload rate: " << iUploadRateLimitKbps << - " kbps" << std::endl; - continue; - } - - // port number --------------------------------------------------------- if ( GetNumericArgument ( argc, argv, i, "-p", "--port", 0, 65535, rDbleArgument ) ) @@ -246,8 +234,7 @@ int main ( int argc, char** argv ) iPortNumber, strHTMLStatusFileName.c_str(), strHistoryFileName.c_str(), - strServerName.c_str(), - iUploadRateLimitKbps ); + strServerName.c_str() ); if ( bUseGUI ) { @@ -307,10 +294,11 @@ std::string UsageArguments ( char **argv ) " client)\n" " -p, --port local port number (only avaiable for server)\n" " -m, --htmlstatus enable HTML status file, set file name (only\n" - " avaiable for server)\n" + " available for server)\n" + " -a, --servername server name required for HTML status (only\n" + " available for server)\n" " -y, --history enable connection history and set file\n" " name (only available for server)\n" - " -u, --maxuploadrate maximum upload rate (only avaiable for server)\n" " -c, --connect connect to last server on startup (only\n" " available for client)\n" " -d, --disableleds disable LEDs in main window (only available\n" @@ -319,8 +307,11 @@ std::string UsageArguments ( char **argv ) "Example: " + std::string ( argv[0] ) + " -l -inifile myinifile.ini\n"; } -bool GetFlagArgument ( int, char **argv, int &i, - std::string strShortOpt, std::string strLongOpt ) +bool GetFlagArgument ( int argc, + char** argv, + int& i, + std::string strShortOpt, + std::string strLongOpt ) { if ( ( !strShortOpt.compare ( argv[i] ) ) || ( !strLongOpt.compare ( argv[i] ) ) ) { @@ -332,9 +323,12 @@ bool GetFlagArgument ( int, char **argv, int &i, } } -bool GetStringArgument ( int argc, char **argv, int &i, - std::string strShortOpt, std::string strLongOpt, - std::string & strArg ) +bool GetStringArgument ( int argc, + char** argv, + int& i, + std::string strShortOpt, + std::string strLongOpt, + std::string& strArg ) { if ( ( !strShortOpt.compare ( argv[i] ) ) || ( !strLongOpt.compare ( argv[i] ) ) ) { @@ -355,10 +349,14 @@ bool GetStringArgument ( int argc, char **argv, int &i, } } -bool GetNumericArgument ( int argc, char **argv, int &i, - std::string strShortOpt, std::string strLongOpt, - double rRangeStart, double rRangeStop, - double & rValue) +bool GetNumericArgument ( int argc, + char** argv, + int& i, + std::string strShortOpt, + std::string strLongOpt, + double rRangeStart, + double rRangeStop, + double& rValue) { if ( ( !strShortOpt.compare ( argv[i] ) ) || ( !strLongOpt.compare ( argv[i] ) ) ) { @@ -392,7 +390,8 @@ bool GetNumericArgument ( int argc, char **argv, int &i, /******************************************************************************\ * Window Message System * \******************************************************************************/ -void PostWinMessage ( const _MESSAGE_IDENT MessID, const int iMessageParam, +void PostWinMessage ( const _MESSAGE_IDENT MessID, + const int iMessageParam, const int iChanNum ) { // first check if application is initialized diff --git a/src/protocol.cpp b/src/protocol.cpp index 0dd30304..f7ed3781 100755 --- a/src/protocol.cpp +++ b/src/protocol.cpp @@ -124,6 +124,7 @@ MESSAGES - 0: none, no audio coding applied - 1: IMA-ADPCM - 2: MS-ADPCM + - 3: CELT - "audiocod arg": argument for the audio coder, if not used this value shall be set to 0 diff --git a/src/protocol.h b/src/protocol.h index 0ec164bf..8f830628 100755 --- a/src/protocol.h +++ b/src/protocol.h @@ -40,18 +40,17 @@ #define PROTMESSID_ACKN 1 // acknowledge #define PROTMESSID_JITT_BUF_SIZE 10 // jitter buffer size #define PROTMESSID_REQ_JITT_BUF_SIZE 11 // request jitter buffer size -#define PROTMESSID_PING 12 // OLD, not used anymore -#define PROTMESSID_NET_BLSI_FACTOR 13 // network buffer size factor -#define PROTMESSID_CHANNEL_GAIN 14 // set channel gain for mix -#define PROTMESSID_CONN_CLIENTS_LIST 15 // connected client list -#define PROTMESSID_SERVER_FULL 16 // server full message -#define PROTMESSID_REQ_CONN_CLIENTS_LIST 17 // request connected client list -#define PROTMESSID_CHANNEL_NAME 18 // set channel name for fader tag -#define PROTMESSID_CHAT_TEXT 19 // contains a chat text -#define PROTMESSID_PING_MS 20 // for measuring ping time -#define PROTMESSID_NETW_TRANSPORT_PROPS 21 // properties for network transport -#define PROTMESSID_REQ_NETW_TRANSPORT_PROPS 22 // request properties for network transport -#define PROTMESSID_DISCONNECTION 23 // disconnection +#define PROTMESSID_NET_BLSI_FACTOR 12 // network buffer size factor +#define PROTMESSID_CHANNEL_GAIN 13 // set channel gain for mix +#define PROTMESSID_CONN_CLIENTS_LIST 14 // connected client list +#define PROTMESSID_SERVER_FULL 15 // server full message +#define PROTMESSID_REQ_CONN_CLIENTS_LIST 16 // request connected client list +#define PROTMESSID_CHANNEL_NAME 17 // set channel name for fader tag +#define PROTMESSID_CHAT_TEXT 18 // contains a chat text +#define PROTMESSID_PING_MS 19 // for measuring ping time +#define PROTMESSID_NETW_TRANSPORT_PROPS 20 // properties for network transport +#define PROTMESSID_REQ_NETW_TRANSPORT_PROPS 21 // request properties for network transport +#define PROTMESSID_DISCONNECTION 22 // disconnection // lengths of message as defined in protocol.cpp file #define MESS_HEADER_LENGTH_BYTE 7 // TAG (2), ID (2), cnt (1), length (2) diff --git a/src/res/frontpicture.xcf b/src/res/frontpicture.xcf index a37c58ede1f0b3bfcf863716e4b8f361be5483d3..d5de666e1e1a07f92a0ba369a2b01cfdba66de23 100755 GIT binary patch delta 3216 zcmai02~d<*67GKv5K$5FV8yL6ZVbdEMxrJryAH-{6N9@RpvGv{tPbOms3;7IB!4YB zM9m>ecEKaY>_$Ac@Ipn1CW8lv$P8!z1$7X0Km}$PV2=Ol?FSx7YHRmZb-kYc`t|Gg zy?#A^qoAqG(5CCS?nk3maicB)blVRQ6b>*T1R!h`JRSQ;?MK3q^hjK-Up;v6;0cqW zV={^Z7DWDuj5A66Ni-yE^d(_>canjRbhem+aKkgAyAKTI`a~q?*CY%cvSj(f4-*$X z4S7;Ef*X_3psM1J(*iag?@j^L<&Fyw6;%IsNJ6-iWX7h&SU3 zXt8t-$B~6Xawtz?f!*T)dVW&lEgTFgibi(ffeN5=gR6uK{{oonLp3T^;zbOR92yGX zb0WI@T9~&}3lkbyhBbss6L1fxcxalBj^+LQQ}KI<6x$Z{@r!JYXYf4S2WpVs#T*LK zHXjediym*%fWX;qhVHF6>6mvVR?m_!bth9d&q? z1(=Lxpp_{hs=jlpt}=W)0cvQPineY&-#mmxj2J#hJL)u&Ke4Dru?2v!DYbM?vU3Y+ zc@z&Ys~<{En8&!gMjmp@Hlj&t%IaL(!q(DujA+RWj7pbTo%EAOY&bEOE}(^0yUoC* z*nO6d`Vs0jYd6&Uei%9jf#>*NRSE!Iz(jb1szY{Yco+jhblxod4qgL?-(JK`7z5CM zeTBE9XgVFpJMpB$dwgyU41tb+;?(O&&09*ull&>NX>a9l}8_erND7d>C=?xL}ZiZeXR2q58 zLx)k$6YBCIJ=gO9_i=4Mj;hnMMo#H7YBRdn(keXlq6X2Kj9QiqrB%z)N+nErkF*Xm zEH3v7jU_vx*six09?pT+;W@L=)_F4uyK$wI z;55Gu zu?JM*Xr4Se8s`86xZ4Mm-D2;izucl>UU#o_|2W}icL&rzHW5c$Bs%CrEd5a_v!k+$=G*|%sHcR+_g&EqRfrXQlFUFt=fxcQzF z&))!e1#8GEh0=aBO{KR;(JF?D z#Rz}~b`eFin7RZxn1P38pusvQ>y~UhPojkZojUkvT0+9wr}lBv9s^I12U906lg2Ad;|OVgXwT`jGLWi_Tj>c3<#D>0bb5kvsX@o-k-KbhG#^Fbdi)ESb0#ZM1&Bt zGwbiWd3YJ5MpKkdqmyHf5f{?K4N*FkPM&#;X!16vM(K1jjYs0#*2|x4 zs;sW4VI(`Rl)136%yJ=@%XObTd*SpYtF_!lOu8z|OD&fx$}E=Byn=i}eJ4t+)@lbM zxw@jX)S|YCmn~(d2@&`cW!7>#qY@nzC1nOWk;*Mv2^dj@3QkRmaJcudB$SptS^JZo@LM*;`yXFy*~Ns&Dz_H;-;_T z^cuZvEMye7?26N?^m1Y$yvl>uxsx0d3K_@kJD5Tod$Z3z<=B3pfN@;E+mw;dIJSLb z;!HB>#PQ8N8+T^!*z{FCAQ<=+HAKDWacx5tGvF_ zX^}6)=8)}dRz64$zKtm6vYN$AdBtBN!-u6*+irc6-Pl;)#3;U+{NXL7c(GwdI2Z1o zyrt+;jm=i)WOe+YezRdo$`XTN*{l!NM1&6;ooBN(`WVAa_iA{9%HUdRuB+P|5gz_} zg{{85lVD$ib)|tb2-`0fB}Pz0A=PH%@5_Wel$>{K6AgyADZ^iid`&lg#WkDF&dOM5 zZ_apk`o!op$E~|QJNi={GY-}U@*|Z9b{{rvwK9Tz`PMFiJF7U%7Rwk8yMb~HV>s+Oy(w9oNvq|7RrF~f z`=(P^`8QXo>B^oz6T6anaUJ~!$?mB{tdfe|(bw?~g#ETJ@hOjYVIT_aB?9&O=Rpp2 zVQ*AS#Ex8Xhg7+(AL+_%3`SmA$2@v2#~_q%_%mI5k96fU9bX(BA8*AT?8k75QbGF( z?sdn_v+2A~bD_MRn^kWm-#$J`mJ zrQ93AzkAfs>u3%pp=KW(MPDo;ebTc(3O4FU2n&7>AcVdu`fexu*<80e(f_&7E6jn0 zj${xCtq-*`1C2+vPsG) delta 441 zcmcaQnf1jlmI-!@EF0~M7zK|pFmP^SVBiyE00BmulF7>a9+Mr!JvMLV&tkM3U{zI|o|9U=$|Mgr*m{alpWPW}L0NMaa(*OVf diff --git a/src/res/gig.png b/src/res/gig.png index 970d0f48a9a2758867083163a37a44e895776ce7..19df1db1fc7ec674765fe4169785ffea0ef86248 100755 GIT binary patch literal 49004 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 literal 105024 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 D%0usQ diff --git a/src/server.cpp b/src/server.cpp index a498489f..7805b84a 100755 --- a/src/server.cpp +++ b/src/server.cpp @@ -30,10 +30,8 @@ CServer::CServer ( const QString& strLoggingFileName, const quint16 iPortNumber, const QString& strHTMLStatusFileName, const QString& strHistoryFileName, - const QString& strServerNameForHTMLStatusFile, - const int iNewUploadRateLimitKbps ) : - Socket ( &ChannelSet, this, iPortNumber ), - ChannelSet ( iNewUploadRateLimitKbps ) + const QString& strServerNameForHTMLStatusFile ) : + Socket ( &ChannelSet, this, iPortNumber ) { vecsSendData.Init ( MIN_SERVER_BLOCK_SIZE_SAMPLES ); diff --git a/src/server.h b/src/server.h index 38f7ab46..109592cc 100755 --- a/src/server.h +++ b/src/server.h @@ -46,8 +46,7 @@ public: const quint16 iPortNumber, const QString& strHTMLStatusFileName, const QString& strHistoryFileName, - const QString& strServerNameForHTMLStatusFile, - const int iNewUploadRateLimitKbps ); + const QString& strServerNameForHTMLStatusFile ); virtual ~CServer() {} void Start(); diff --git a/src/soundbase.h b/src/soundbase.h index 6f4414f5..e8e58954 100755 --- a/src/soundbase.h +++ b/src/soundbase.h @@ -37,7 +37,7 @@ class CSoundBase : public QThread public: CSoundBase ( const bool bNewIsCallbackAudioInterface, - void (*fpNewProcessCallback) ( CVector& psData, void* pParg ), + void (*fpNewProcessCallback) ( CVector& psData, void* pParg ), void* pParg ) : fpProcessCallback ( fpNewProcessCallback ), pProcessCallbackArg ( pParg ), bRun ( false ), bIsCallbackAudioInterface ( bNewIsCallbackAudioInterface ) {} @@ -56,25 +56,25 @@ public: protected: // function pointer to callback function - void (*fpProcessCallback) ( CVector& psData, void* arg ); + void (*fpProcessCallback) ( CVector& psData, void* arg ); void* pProcessCallbackArg; // callback function call for derived classes - void ProcessCallback ( CVector& psData ) + void ProcessCallback ( CVector& psData ) { (*fpProcessCallback) ( psData, pProcessCallbackArg ); } // these functions should be overwritten by derived class for // non callback based audio interfaces - virtual bool Read ( CVector& psData ) { printf ( "no sound!" ); return false; } - virtual bool Write ( CVector& psData ) { printf ( "no sound!" ); return false; } + virtual bool Read ( CVector& psData ) { printf ( "no sound!" ); return false; } + virtual bool Write ( CVector& psData ) { printf ( "no sound!" ); return false; } void run(); bool bRun; bool bIsCallbackAudioInterface; - CVector vecsAudioSndCrdStereo; + CVector vecsAudioSndCrdStereo; signals: void ReinitRequest(); diff --git a/src/util.cpp b/src/util.cpp index d3ef776b..ef628e5c 100755 --- a/src/util.cpp +++ b/src/util.cpp @@ -27,10 +27,10 @@ /* Implementation *************************************************************/ // Input level meter implementation -------------------------------------------- -void CStereoSignalLevelMeter::Update ( CVector& vecdAudio ) +void CStereoSignalLevelMeter::Update ( CVector& vecsAudio ) { // get the stereo vector size - const int iStereoVecSize = vecdAudio.Size(); + const int iStereoVecSize = vecsAudio.Size(); // Get maximum of current block // @@ -43,28 +43,28 @@ void CStereoSignalLevelMeter::Update ( CVector& vecdAudio ) // special cases but for the average music signals the following code // should give good results. // - double dMaxL = 0.0; - double dMaxR = 0.0; + short sMaxL = 0; + short sMaxR = 0; for ( int i = 0; i < iStereoVecSize; i += 6 ) // 2 * 3 = 6 -> stereo { // left channel - if ( dMaxL < vecdAudio[i] ) + if ( sMaxL < vecsAudio[i] ) { - dMaxL = vecdAudio[i]; + sMaxL = vecsAudio[i]; } // right channel - if ( dMaxR < vecdAudio[i + 1] ) + if ( sMaxR < vecsAudio[i + 1] ) { - dMaxR = vecdAudio[i + 1]; + sMaxR = vecsAudio[i + 1]; } } - dCurLevelL = UpdateCurLevel ( dCurLevelL, dMaxL ); - dCurLevelR = UpdateCurLevel ( dCurLevelR, dMaxR ); + dCurLevelL = UpdateCurLevel ( dCurLevelL, sMaxL ); + dCurLevelR = UpdateCurLevel ( dCurLevelR, sMaxR ); } -double CStereoSignalLevelMeter::UpdateCurLevel ( double dCurLevel, const double& dMax ) +double CStereoSignalLevelMeter::UpdateCurLevel ( double dCurLevel, const short& sMax ) { // decrease max with time if ( dCurLevel >= METER_FLY_BACK ) @@ -78,9 +78,9 @@ double CStereoSignalLevelMeter::UpdateCurLevel ( double dCurLevel, const double& } // update current level -> only use maximum - if ( dMax > dCurLevel ) + if ( static_cast ( sMax ) > dCurLevel ) { - return dMax; + return static_cast ( sMax ); } else { @@ -331,6 +331,7 @@ CAboutDlg::CAboutDlg ( QWidget* parent ) : QDialog ( parent ) "

" "
    " "
  • Qt cross-platform application framework: http://trolltech.com
  • " + "
  • The CELT ultra-low delay audio codec: http://www.celt-codec.org
  • " "
  • Audio reverberation code: by Perry R. Cook and Gary P. Scavone, " "1995 - 2004 (taken from The Synthesis ToolKit in C++ (STK))
  • " "
  • ADPCM coders by Erik de Castro Lopo
  • " diff --git a/src/util.h b/src/util.h index 66f212d9..23f31d14 100755 --- a/src/util.h +++ b/src/util.h @@ -363,14 +363,14 @@ public: CStereoSignalLevelMeter() { Reset(); } virtual ~CStereoSignalLevelMeter() {} - void Update ( CVector& vecdAudio ); + void Update ( CVector& vecsAudio ); double MicLevelLeft() { return CalcLogResult ( dCurLevelL ); } double MicLevelRight() { return CalcLogResult ( dCurLevelR ); } void Reset() { dCurLevelL = 0.0; dCurLevelR = 0.0; } protected: double CalcLogResult ( const double& dLinearLevel ); - double UpdateCurLevel ( double dCurLevel, const double& dMax ); + double UpdateCurLevel ( double dCurLevel, const short& sMax ); double dCurLevelL; double dCurLevelR; @@ -417,7 +417,8 @@ enum EAudComprType { CT_NONE = 0, CT_IMAADPCM = 1, - CT_MSADPCM = 2 + CT_MSADPCM = 2, + CT_CELT = 3 }; class CNetworkTransportProps @@ -448,17 +449,15 @@ public: // we use a conservative value as default, this value does not // give perfekt latency results but should work ok on most // sound cards and drivers - static int GetDefaultIndex() { return 5; } + static int GetDefaultIndex() { return 1; } - static int GetNumOfBufferSizes() { return 16; } + static int GetNumOfBufferSizes() { return 4; } static int GetBufferSizeFromIndex ( const int iIdx ) { - if ( ( iIdx >= 0 ) && ( iIdx < 16 ) ) + if ( ( iIdx >= 0 ) && ( iIdx < 4 ) ) { - const int pSizes[16] = { - 96, 128, 160, 192, 224, 256, 288, 320, 352, - 384, 416, 448, 480, 512, 768, 1024 }; - + const int pSizes[4] = { 128, 256, 512, 1024 }; + return pSizes[iIdx]; } else diff --git a/windows/llcon.vcproj b/windows/llcon.vcproj index 0b38c831..49b943eb 100755 --- a/windows/llcon.vcproj +++ b/windows/llcon.vcproj @@ -48,8 +48,8 @@ - - - - - - - - @@ -945,6 +923,250 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - diff --git a/windows/sound.cpp b/windows/sound.cpp index a20b5c27..74a60a3f 100755 --- a/windows/sound.cpp +++ b/windows/sound.cpp @@ -188,7 +188,7 @@ std::string CSound::CheckDeviceCapabilities() // message is returned. // check the sample rate - const ASIOError CanSaRateReturn = ASIOCanSampleRate ( SND_CRD_SAMPLE_RATE ); + const ASIOError CanSaRateReturn = ASIOCanSampleRate ( SYSTEM_SAMPLE_RATE ); if ( ( CanSaRateReturn == ASE_NoClock ) || ( CanSaRateReturn == ASE_NotPresent ) ) { @@ -327,7 +327,7 @@ int CSound::Init ( const int iNewPrefMonoBufferSize ) iASIOBufferSizeStereo = 2 * iASIOBufferSizeMono; // set the sample rate - ASIOSetSampleRate ( SND_CRD_SAMPLE_RATE ); + ASIOSetSampleRate ( SYSTEM_SAMPLE_RATE ); // create memory for intermediate audio buffer vecsTmpAudioSndCrdStereo.Init ( iASIOBufferSizeStereo ); diff --git a/windows/sound.h b/windows/sound.h index 866d6e1a..cc2feaa0 100755 --- a/windows/sound.h +++ b/windows/sound.h @@ -55,7 +55,7 @@ class CSound : public CSoundBase { public: - CSound ( void (*fpNewCallback) ( CVector& psData, void* arg ), void* arg ); + CSound ( void (*fpNewCallback) ( CVector& psData, void* arg ), void* arg ); virtual ~CSound(); virtual int Init ( const int iNewPrefMonoBufferSize ); @@ -87,7 +87,7 @@ protected: // callbacks 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 ); static void sampleRateChanged ( ASIOSampleRate sRate ) {} static long asioMessages ( long selector, long value, void* message, double* opt );