diff --git a/src/channel.cpp b/src/channel.cpp index 4de885cb..455e5416 100755 --- a/src/channel.cpp +++ b/src/channel.cpp @@ -97,6 +97,11 @@ QObject::connect( &Protocol, SIGNAL ( PingReceived ( int ) ), SIGNAL ( PingReceived ( int ) ) ); +// #### COMPATIBILITY OLD VERSION, TO BE REMOVED #### +QObject::connect ( &Protocol, + SIGNAL ( OpusSupported() ), + SIGNAL ( OpusSupported() ) ); + QObject::connect ( &Protocol, SIGNAL ( DetectedCLMessage ( CVector, int ) ), SIGNAL ( DetectedCLMessage ( CVector, int ) ) ); @@ -141,7 +146,8 @@ void CChannel::SetEnable ( const bool bNEnStat ) } } -void CChannel::SetAudioStreamProperties ( const int iNewNetwFrameSize, +void CChannel::SetAudioStreamProperties ( const EAudComprType eNewAudComprType, + const int iNewNetwFrameSize, const int iNewNetwFrameSizeFact, const int iNewNumAudioChannels ) { @@ -149,9 +155,10 @@ void CChannel::SetAudioStreamProperties ( const int iNewNetwFrameSize, QMutexLocker locker ( &Mutex ); // store new values - iNumAudioChannels = iNewNumAudioChannels; - iNetwFrameSize = iNewNetwFrameSize; - iNetwFrameSizeFact = iNewNetwFrameSizeFact; + eAudioCompressionType = eNewAudComprType; + iNumAudioChannels = iNewNumAudioChannels; + iNetwFrameSize = iNewNetwFrameSize; + iNetwFrameSizeFact = iNewNetwFrameSizeFact; // init socket buffer SockBuf.Init ( iNetwFrameSize, iCurSockBufNumFrames ); @@ -346,20 +353,30 @@ void CChannel::OnNetTranspPropsReceived ( CNetworkTransportProps NetworkTranspor // only the server shall act on network transport properties message if ( bIsServer ) { - QMutexLocker locker ( &Mutex ); + Mutex.lock(); + { + // store received parameters + eAudioCompressionType = NetworkTransportProps.eAudioCodingType; + iNumAudioChannels = NetworkTransportProps.iNumAudioChannels; + iNetwFrameSizeFact = NetworkTransportProps.iBlockSizeFact; + iNetwFrameSize = + NetworkTransportProps.iBaseNetworkPacketSize; - // store received parameters - iNumAudioChannels = NetworkTransportProps.iNumAudioChannels; - iNetwFrameSizeFact = NetworkTransportProps.iBlockSizeFact; - iNetwFrameSize = - NetworkTransportProps.iBaseNetworkPacketSize; + // update socket buffer (the network block size is a multiple of the + // minimum network frame size + SockBuf.Init ( iNetwFrameSize, iCurSockBufNumFrames ); - // update socket buffer (the network block size is a multiple of the - // minimum network frame size - SockBuf.Init ( iNetwFrameSize, iCurSockBufNumFrames ); + // init conversion buffer + ConvBuf.Init ( iNetwFrameSize * iNetwFrameSizeFact ); + } + Mutex.unlock(); - // init conversion buffer - ConvBuf.Init ( iNetwFrameSize * iNetwFrameSizeFact ); + // if old CELT codec is used, inform the client that the new OPUS codec + // is supported + if ( eAudioCompressionType != CT_OPUS ) + { + Protocol.CreateOpusSupportedMes(); + } } } @@ -375,7 +392,7 @@ void CChannel::CreateNetTranspPropsMessFromCurrentSettings() iNetwFrameSizeFact, iNumAudioChannels, SYSTEM_SAMPLE_RATE_HZ, - CT_CELT, // always CELT coding + eAudioCompressionType, 0, // version of the codec 0 ); diff --git a/src/channel.h b/src/channel.h index 240497a3..6e4a9db8 100755 --- a/src/channel.h +++ b/src/channel.h @@ -110,7 +110,8 @@ Protocol.CreateChanNameMes ( ChInfo.strName ); int GetUploadRateKbps(); // set/get network out buffer size and size factor - void SetAudioStreamProperties ( const int iNewNetwFrameSize, + void SetAudioStreamProperties ( const EAudComprType eNewAudComprType, + const int iNewNetwFrameSize, const int iNewNetwFrameSizeFact, const int iNewNumAudioChannels ); @@ -122,6 +123,7 @@ Protocol.CreateChanNameMes ( ChInfo.strName ); int GetNetwFrameSizeFact() const { return iNetwFrameSizeFact; } int GetNetwFrameSize() const { return iNetwFrameSize; } + EAudComprType GetAudioCompressionType() { return eAudioCompressionType; } int GetNumAudioChannels() const { return iNumAudioChannels; } // network protocol interface @@ -153,10 +155,11 @@ protected: { // set it to a state were no decoding is ever possible (since we want // only to decode data when a network transport property message is - // received with the correct values - iNetwFrameSizeFact = FRAME_SIZE_FACTOR_PREFERRED; - iNetwFrameSize = CELT_MINIMUM_NUM_BYTES; - iNumAudioChannels = 1; // mono + // received with the correct values) + eAudioCompressionType = CT_NONE; + iNetwFrameSizeFact = FRAME_SIZE_FACTOR_PREFERRED; + iNetwFrameSize = CELT_MINIMUM_NUM_BYTES; + iNumAudioChannels = 1; // mono } // connection parameters @@ -188,6 +191,7 @@ protected: int iNetwFrameSizeFact; int iNetwFrameSize; + EAudComprType eAudioCompressionType; int iNumAudioChannels; QMutex Mutex; @@ -212,6 +216,7 @@ signals: void ConClientListMesReceived ( CVector vecChanInfo ); void ChanInfoHasChanged(); void ReqChanInfo(); + void OpusSupported(); void ChatTextReceived ( QString strChatText ); void PingReceived ( int iMs ); void ReqNetTranspProps(); diff --git a/src/client.cpp b/src/client.cpp index 0ac74f69..0396f9f5 100755 --- a/src/client.cpp +++ b/src/client.cpp @@ -30,6 +30,7 @@ CClient::CClient ( const quint16 iPortNumber ) : vstrIPAddress ( MAX_NUM_SERVER_ADDR_ITEMS, "" ), ChannelInfo (), Channel ( false ), /* we need a client channel -> "false" */ + eAudioCompressionType ( CT_OPUS ), iCeltNumCodedBytes ( CELT_NUM_BYTES_MONO_NORMAL_QUALITY ), bCeltDoHighQuality ( false ), bUseStereo ( false ), @@ -75,6 +76,10 @@ CClient::CClient ( const quint16 iPortNumber ) : 1, &iOpusError ); + // we require a constant bit rate + opus_encoder_ctl ( OpusEncoderMono, + OPUS_SET_VBR ( 0 ) ); + #ifdef USE_LOW_COMPLEXITY_CELT_ENC // set encoder low complexity opus_encoder_ctl ( OpusEncoderMono, @@ -103,6 +108,10 @@ CClient::CClient ( const quint16 iPortNumber ) : 2, &iOpusError ); + // we require a constant bit rate + opus_encoder_ctl ( OpusEncoderStereo, + OPUS_SET_VBR ( 0 ) ); + #ifdef USE_LOW_COMPLEXITY_CELT_ENC // set encoder low complexity opus_encoder_ctl ( OpusEncoderStereo, @@ -148,6 +157,12 @@ CClient::CClient ( const quint16 iPortNumber ) : SIGNAL ( ChatTextReceived ( QString ) ), SIGNAL ( ChatTextReceived ( QString ) ) ); + +// #### COMPATIBILITY OLD VERSION, TO BE REMOVED #### +QObject::connect ( &Channel, SIGNAL ( OpusSupported() ), + this, SLOT ( OnOpusSupported() ) ); + + QObject::connect ( &ConnLessProtocol, SIGNAL ( CLMessReadyForSending ( CHostAddress, CVector ) ), this, SLOT ( OnSendCLProtMessage ( CHostAddress, CVector ) ) ); @@ -334,6 +349,36 @@ void CClient::SetSndCrdPrefFrameSizeFactor ( const int iNewFactor ) } } +// #### COMPATIBILITY OLD VERSION, TO BE REMOVED #### +void CClient::OnOpusSupported() +{ + if ( eAudioCompressionType != CT_OPUS ) + { + SetAudoCompressiontype ( CT_OPUS ); + } +} + +// #### COMPATIBILITY OLD VERSION, TO BE REMOVED #### +void CClient::SetAudoCompressiontype ( const EAudComprType eNAudCompressionType ) +{ + // 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(); + } + + // set new parameter + eAudioCompressionType = eNAudCompressionType; + Init(); + + if ( bWasRunning ) + { + Sound.Start(); + } +} + void CClient::SetCELTHighQuality ( const bool bNCeltHighQualityFlag ) { // init with new parameter, if client was running then first @@ -518,6 +563,11 @@ void CClient::OnSndCrdReinitRequest ( int iSndCrdResetType ) void CClient::Start() { + +// #### COMPATIBILITY OLD VERSION, TO BE REMOVED #### +// our first attempt is always to use the old code +eAudioCompressionType = CT_CELT; + // init object Init(); @@ -674,6 +724,22 @@ void CClient::Init() } vecCeltData.Init ( iCeltNumCodedBytes ); + // calculate and set the bit rate + const int iCeltBitRateBitsPerSec = + ( SYSTEM_SAMPLE_RATE_HZ * iCeltNumCodedBytes * 8 ) / + SYSTEM_FRAME_SIZE_SAMPLES; + + if ( bUseStereo ) + { + opus_encoder_ctl ( OpusEncoderStereo, + OPUS_SET_BITRATE ( iCeltBitRateBitsPerSec ) ); + } + else + { + opus_encoder_ctl ( OpusEncoderMono, + OPUS_SET_BITRATE ( iCeltBitRateBitsPerSec ) ); + } + // inits for network and channel vecbyNetwData.Init ( iCeltNumCodedBytes ); if ( bUseStereo ) @@ -681,7 +747,8 @@ void CClient::Init() vecsNetwork.Init ( iStereoBlockSizeSam ); // set the channel network properties - Channel.SetAudioStreamProperties ( iCeltNumCodedBytes, + Channel.SetAudioStreamProperties ( eAudioCompressionType, + iCeltNumCodedBytes, iSndCrdFrameSizeFactor, 2 ); } @@ -690,7 +757,8 @@ void CClient::Init() vecsNetwork.Init ( iMonoBlockSizeSam ); // set the channel network properties - Channel.SetAudioStreamProperties ( iCeltNumCodedBytes, + Channel.SetAudioStreamProperties ( eAudioCompressionType, + iCeltNumCodedBytes, iSndCrdFrameSizeFactor, 1 ); } @@ -892,21 +960,43 @@ void CClient::ProcessAudioDataIntern ( CVector& vecsStereoSndCrd ) { if ( bUseStereo ) { - // encode current audio frame with CELT encoder - cc6_celt_encode ( CeltEncoderStereo, + // encode current audio frame + if ( eAudioCompressionType == CT_CELT ) + { + cc6_celt_encode ( CeltEncoderStereo, + &vecsNetwork[i * 2 * SYSTEM_FRAME_SIZE_SAMPLES], + NULL, + &vecCeltData[0], + iCeltNumCodedBytes ); + } + else + { + opus_encode ( OpusEncoderStereo, &vecsNetwork[i * 2 * SYSTEM_FRAME_SIZE_SAMPLES], - NULL, + SYSTEM_FRAME_SIZE_SAMPLES, &vecCeltData[0], iCeltNumCodedBytes ); + } } else { - // encode current audio frame with CELT encoder - cc6_celt_encode ( CeltEncoderMono, + // encode current audio frame + if ( eAudioCompressionType == CT_CELT ) + { + cc6_celt_encode ( CeltEncoderMono, + &vecsNetwork[i * SYSTEM_FRAME_SIZE_SAMPLES], + NULL, + &vecCeltData[0], + iCeltNumCodedBytes ); + } + else + { + opus_encode ( OpusEncoderMono, &vecsNetwork[i * SYSTEM_FRAME_SIZE_SAMPLES], - NULL, + SYSTEM_FRAME_SIZE_SAMPLES, &vecCeltData[0], iCeltNumCodedBytes ); + } } // send coded audio through the network @@ -936,17 +1026,41 @@ void CClient::ProcessAudioDataIntern ( CVector& vecsStereoSndCrd ) { if ( bUseStereo ) { - cc6_celt_decode ( CeltDecoderStereo, + if ( eAudioCompressionType == CT_CELT ) + { + cc6_celt_decode ( CeltDecoderStereo, + &vecbyNetwData[0], + iCeltNumCodedBytes, + &vecsStereoSndCrd[i * 2 * SYSTEM_FRAME_SIZE_SAMPLES] ); + } + else + { + opus_decode ( OpusDecoderStereo, &vecbyNetwData[0], iCeltNumCodedBytes, - &vecsStereoSndCrd[i * 2 * SYSTEM_FRAME_SIZE_SAMPLES] ); + &vecsStereoSndCrd[i * 2 * SYSTEM_FRAME_SIZE_SAMPLES], + SYSTEM_FRAME_SIZE_SAMPLES, + 0 ); + } } else { - cc6_celt_decode ( CeltDecoderMono, + if ( eAudioCompressionType == CT_CELT ) + { + cc6_celt_decode ( CeltDecoderMono, + &vecbyNetwData[0], + iCeltNumCodedBytes, + &vecsAudioSndCrdMono[i * SYSTEM_FRAME_SIZE_SAMPLES] ); + } + else + { + opus_decode ( OpusDecoderMono, &vecbyNetwData[0], iCeltNumCodedBytes, - &vecsAudioSndCrdMono[i * SYSTEM_FRAME_SIZE_SAMPLES] ); + &vecsAudioSndCrdMono[i * SYSTEM_FRAME_SIZE_SAMPLES], + SYSTEM_FRAME_SIZE_SAMPLES, + 0 ); + } } } else @@ -954,17 +1068,41 @@ void CClient::ProcessAudioDataIntern ( CVector& vecsStereoSndCrd ) // lost packet if ( bUseStereo ) { - cc6_celt_decode ( CeltDecoderStereo, + if ( eAudioCompressionType == CT_CELT ) + { + cc6_celt_decode ( CeltDecoderStereo, + NULL, + 0, + &vecsStereoSndCrd[i * 2 * SYSTEM_FRAME_SIZE_SAMPLES] ); + } + else + { + opus_decode ( OpusDecoderStereo, NULL, - 0, - &vecsStereoSndCrd[i * 2 * SYSTEM_FRAME_SIZE_SAMPLES] ); + iCeltNumCodedBytes, + &vecsStereoSndCrd[i * 2 * SYSTEM_FRAME_SIZE_SAMPLES], + SYSTEM_FRAME_SIZE_SAMPLES, + 0 ); + } } else { - cc6_celt_decode ( CeltDecoderMono, + if ( eAudioCompressionType == CT_CELT ) + { + cc6_celt_decode ( CeltDecoderMono, + NULL, + 0, + &vecsAudioSndCrdMono[i * SYSTEM_FRAME_SIZE_SAMPLES] ); + } + else + { + opus_decode ( OpusDecoderMono, NULL, - 0, - &vecsAudioSndCrdMono[i * SYSTEM_FRAME_SIZE_SAMPLES] ); + iCeltNumCodedBytes, + &vecsAudioSndCrdMono[i * SYSTEM_FRAME_SIZE_SAMPLES], + SYSTEM_FRAME_SIZE_SAMPLES, + 0 ); + } } } } diff --git a/src/client.h b/src/client.h index 18c4ed08..9135db0f 100755 --- a/src/client.h +++ b/src/client.h @@ -261,6 +261,9 @@ protected: int EvaluatePingMessage ( const int iMs ); void CreateServerJitterBufferMessage(); +// #### COMPATIBILITY OLD VERSION, TO BE REMOVED #### +void SetAudoCompressiontype ( const EAudComprType eNAudCompressionType ); + // only one channel is needed for client application CChannel Channel; CProtocol ConnLessProtocol; @@ -276,6 +279,7 @@ protected: OpusDecoder* OpusDecoderMono; OpusEncoder* OpusEncoderStereo; OpusDecoder* OpusDecoderStereo; + EAudComprType eAudioCompressionType; int iCeltNumCodedBytes; bool bCeltDoHighQuality; bool bUseStereo; @@ -342,6 +346,9 @@ public slots: void OnSndCrdReinitRequest ( int iSndCrdResetType ); +// #### COMPATIBILITY OLD VERSION, TO BE REMOVED #### +void OnOpusSupported(); + signals: void ConClientListNameMesReceived ( CVector vecChanInfo ); void ConClientListMesReceived ( CVector vecChanInfo );