From a45adedf7a00a13aab5a3cda638ea18e03da8f4c Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Fri, 17 Apr 2026 19:59:27 +0200 Subject: [PATCH 01/54] Introduce raw audio setting in UI. Opus encoding in client now depends on audio quality --- src/client.cpp | 27 +++++++++++++++------------ src/clientsettingsdlg.cpp | 1 + src/util.h | 3 ++- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index 417f08a404..874c5dfc2e 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1389,23 +1389,26 @@ void CClient::ProcessAudioDataIntern ( CVector& vecsStereoSndCrd ) } } - for ( i = 0, j = 0; i < iSndCrdFrameSizeFactor; i++, j += iNumAudioChannels * iOPUSFrameSizeSamples ) + if ( eAudioQuality != AQ_RAW ) { - // OPUS encoding - if ( CurOpusEncoder != nullptr ) + for ( i = 0, j = 0; i < iSndCrdFrameSizeFactor; i++, j += iNumAudioChannels * iOPUSFrameSizeSamples ) { - if ( bMuteOutStream ) - { - iUnused = opus_custom_encode ( CurOpusEncoder, &vecZeros[j], iOPUSFrameSizeSamples, &vecCeltData[0], iCeltNumCodedBytes ); - } - else + // OPUS encoding + if ( CurOpusEncoder != nullptr ) { - iUnused = opus_custom_encode ( CurOpusEncoder, &vecsStereoSndCrd[j], iOPUSFrameSizeSamples, &vecCeltData[0], iCeltNumCodedBytes ); + if ( bMuteOutStream ) + { + iUnused = opus_custom_encode ( CurOpusEncoder, &vecZeros[j], iOPUSFrameSizeSamples, &vecCeltData[0], iCeltNumCodedBytes ); + } + else + { + iUnused = opus_custom_encode ( CurOpusEncoder, &vecsStereoSndCrd[j], iOPUSFrameSizeSamples, &vecCeltData[0], iCeltNumCodedBytes ); + } } - } - // send coded audio through the network - Channel.PrepAndSendPacket ( &Socket, vecCeltData, iCeltNumCodedBytes ); + // send coded audio through the network + Channel.PrepAndSendPacket ( &Socket, vecCeltData, iCeltNumCodedBytes ); + } } // Receive signal ---------------------------------------------------------- diff --git a/src/clientsettingsdlg.cpp b/src/clientsettingsdlg.cpp index d9f2e6ad11..61468ca2cf 100644 --- a/src/clientsettingsdlg.cpp +++ b/src/clientsettingsdlg.cpp @@ -494,6 +494,7 @@ CClientSettingsDlg::CClientSettingsDlg ( CClient* pNCliP, CClientSettings* pNSet cbxAudioQuality->addItem ( tr ( "Low" ) ); // AQ_LOW cbxAudioQuality->addItem ( tr ( "Normal" ) ); // AQ_NORMAL cbxAudioQuality->addItem ( tr ( "High" ) ); // AQ_HIGH + cbxAudioQuality->addItem ( tr ( "Raw" ) ); // AQ_RAW cbxAudioQuality->setCurrentIndex ( static_cast ( pClient->GetAudioQuality() ) ); // GUI design (skin) combo box diff --git a/src/util.h b/src/util.h index e83e1f764a..ac13d8c37d 100644 --- a/src/util.h +++ b/src/util.h @@ -505,7 +505,8 @@ enum EAudioQuality // used for settings and the comobo box index -> enum values must be fixed! AQ_LOW = 0, AQ_NORMAL = 1, - AQ_HIGH = 2 + AQ_HIGH = 2, + AQ_RAW = 3 }; // Get data status enum -------------------------------------------------------- From 73d983fea45fdfa3176f9b3f0cfe97754a3631fa Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Fri, 17 Apr 2026 20:02:33 +0200 Subject: [PATCH 02/54] addition to last commit --- src/client.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/client.cpp b/src/client.cpp index 874c5dfc2e..ff46c1aceb 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1410,6 +1410,10 @@ void CClient::ProcessAudioDataIntern ( CVector& vecsStereoSndCrd ) Channel.PrepAndSendPacket ( &Socket, vecCeltData, iCeltNumCodedBytes ); } } + else + { + + } // Receive signal ---------------------------------------------------------- // in case of mute stream, store local data From 03f7ab3719d7dbce24b48e43b1124d7f52a6a722 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Fri, 17 Apr 2026 20:14:17 +0200 Subject: [PATCH 03/54] client still sends raw audio to stock servers and causes garbled sound but works --- src/client.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/client.cpp b/src/client.cpp index ff46c1aceb..940851d905 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1156,6 +1156,9 @@ void CClient::Init() case AQ_HIGH: iCeltNumCodedBytes = OPUS_NUM_BYTES_MONO_HIGH_QUALITY_DBLE_FRAMESIZE; break; + case AQ_RAW: + iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof(int16_t); + break; } } else @@ -1175,6 +1178,9 @@ void CClient::Init() case AQ_HIGH: iCeltNumCodedBytes = OPUS_NUM_BYTES_STEREO_HIGH_QUALITY_DBLE_FRAMESIZE; break; + case AQ_RAW: + iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof(int16_t); + break; } } } @@ -1199,6 +1205,9 @@ void CClient::Init() case AQ_HIGH: iCeltNumCodedBytes = OPUS_NUM_BYTES_MONO_HIGH_QUALITY; break; + case AQ_RAW: + iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof(int16_t); + break; } } else @@ -1218,6 +1227,9 @@ void CClient::Init() case AQ_HIGH: iCeltNumCodedBytes = OPUS_NUM_BYTES_STEREO_HIGH_QUALITY; break; + case AQ_RAW: + iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof(int16_t); + break; } } } @@ -1412,7 +1424,9 @@ void CClient::ProcessAudioDataIntern ( CVector& vecsStereoSndCrd ) } else { - + // Send raw samples instead of OPUS + memcpy ( &vecCeltData[0], &vecsStereoSndCrd[0], iCeltNumCodedBytes ); + Channel.PrepAndSendPacket ( &Socket, vecCeltData, iCeltNumCodedBytes ); } // Receive signal ---------------------------------------------------------- From 9a05dd1a28af31ccf56776bacfbc88e2c7f62426 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Fri, 17 Apr 2026 20:33:49 +0200 Subject: [PATCH 04/54] make client opus decoding depend on audio quality (raw audio) --- src/client.cpp | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index 940851d905..8441f15bc4 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1444,24 +1444,41 @@ void CClient::ProcessAudioDataIntern ( CVector& vecsStereoSndCrd ) // get pointer to coded data and manage the flags if ( bReceiveDataOk ) { - pCurCodedData = &vecbyNetwData[0]; - + if ( eAudioQuality == AQ_RAW ) + { + memcpy ( &vecsStereoSndCrd[0], &vecbyNetwData[0], iCeltNumCodedBytes ); + pCurCodedData = nullptr; + } + else + { + pCurCodedData = &vecbyNetwData[0]; + } // on any valid received packet, we clear the initialization phase flag bIsInitializationPhase = false; } else { - // for lost packets use null pointer as coded input data - pCurCodedData = nullptr; - + if ( eAudioQuality == AQ_RAW ) + { + memset ( &vecsStereoSndCrd[0], 0, iCeltNumCodedBytes ); + pCurCodedData = nullptr; + } + else + { + // for lost packets use null pointer as coded input data + pCurCodedData = nullptr; + } // invalidate the buffer OK status flag bJitterBufferOK = false; } - // OPUS decoding - if ( CurOpusDecoder != nullptr ) + if ( eAudioQuality != AQ_RAW ) { - iUnused = opus_custom_decode ( CurOpusDecoder, pCurCodedData, iCeltNumCodedBytes, &vecsStereoSndCrd[j], iOPUSFrameSizeSamples ); + // OPUS decoding + if ( CurOpusDecoder != nullptr ) + { + iUnused = opus_custom_decode ( CurOpusDecoder, pCurCodedData, iCeltNumCodedBytes, &vecsStereoSndCrd[j], iOPUSFrameSizeSamples ); + } } } From 0f22ee96aef61647b4f0d50121f4b91f94534305 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Fri, 17 Apr 2026 22:29:02 +0200 Subject: [PATCH 05/54] no crashes but bad noise on raw audio setting --- src/server.cpp | 87 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 62 insertions(+), 25 deletions(-) diff --git a/src/server.cpp b/src/server.cpp index a477771fde..fc33d419a9 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -23,6 +23,9 @@ \******************************************************************************/ #include "server.h" +#include "global.h" +#include "util.h" +#include // CServer implementation ****************************************************** CServer::CServer ( const int iNewMaxNumChan, @@ -874,27 +877,46 @@ void CServer::DecodeReceiveData ( const int iChanCnt, const int iNumClients ) return; } + const int iOffset = iB * SYSTEM_FRAME_SIZE_SAMPLES * vecNumAudioChannels[iChanCnt]; + const bool bIsRawAudio = ( iCeltNumCodedBytes == iClientFrameSizeSamples * vecNumAudioChannels[iChanCnt] * sizeof(int16_t) ); + // get pointer to coded data if ( eGetStat == GS_BUFFER_OK ) { - pCurCodedData = &vecvecbyCodedData[iChanCnt][0]; + if ( bIsRawAudio ) + { + memcpy ( &vecvecsData[iChanCnt][iOffset], &vecvecbyCodedData[iChanCnt], iCeltNumCodedBytes ); + } + else + { + pCurCodedData = &vecvecbyCodedData[iChanCnt][0]; + } } else { - // for lost packets use null pointer as coded input data - pCurCodedData = nullptr; + if ( bIsRawAudio ) + { + memset ( &vecvecsData[iChanCnt][iOffset], 0, iCeltNumCodedBytes ); + } + else + { + // for lost packets use null pointer as coded input data + pCurCodedData = nullptr; + } } - // OPUS decode received data stream - if ( CurOpusDecoder != nullptr ) + if ( !bIsRawAudio ) { - const int iOffset = iB * SYSTEM_FRAME_SIZE_SAMPLES * vecNumAudioChannels[iChanCnt]; + // OPUS decode received data stream + if ( CurOpusDecoder != nullptr ) + { - iUnused = opus_custom_decode ( CurOpusDecoder, - pCurCodedData, - iCeltNumCodedBytes, - &vecvecsData[iChanCnt][iOffset], - iClientFrameSizeSamples ); + iUnused = opus_custom_decode ( CurOpusDecoder, + pCurCodedData, + iCeltNumCodedBytes, + &vecvecsData[iChanCnt][iOffset], + iClientFrameSizeSamples ); + } } } @@ -1154,30 +1176,45 @@ void CServer::MixEncodeTransmitData ( const int iChanCnt, const int iNumClients DoubleFrameSizeConvBufOut[iCurChanID].GetAll ( vecsSendData, DOUBLE_SYSTEM_FRAME_SIZE_SAMPLES * vecNumAudioChannels[iChanCnt] ); } - // OPUS encoding - if ( pCurOpusEncoder != nullptr ) + if ( iCeltNumCodedBytes != iClientFrameSizeSamples * vecNumAudioChannels[iChanCnt] * sizeof(int16_t)) { - //### TODO: BEGIN ###// - // find a better place than this: the setting does not change all the time so for speed - // optimization it would be better to set it only if the network frame size is changed - opus_custom_encoder_ctl ( pCurOpusEncoder, - OPUS_SET_BITRATE ( CalcBitRateBitsPerSecFromCodedBytes ( iCeltNumCodedBytes, iClientFrameSizeSamples ) ) ); - //### TODO: END ###// + // OPUS encoding + if ( pCurOpusEncoder != nullptr ) + { + //### TODO: BEGIN ###// + // find a better place than this: the setting does not change all the time so for speed + // optimization it would be better to set it only if the network frame size is changed + opus_custom_encoder_ctl ( pCurOpusEncoder, + OPUS_SET_BITRATE ( CalcBitRateBitsPerSecFromCodedBytes ( iCeltNumCodedBytes, iClientFrameSizeSamples ) ) ); + //### TODO: END ###// + + for ( int iB = 0; iB < vecNumFrameSizeConvBlocks[iChanCnt]; iB++ ) + { + const int iOffset = iB * SYSTEM_FRAME_SIZE_SAMPLES * vecNumAudioChannels[iChanCnt]; + + iUnused = opus_custom_encode ( pCurOpusEncoder, + &vecsSendData[iOffset], + iClientFrameSizeSamples, + &vecvecbyCodedData[iChanCnt][0], + iCeltNumCodedBytes ); + // send separate mix to current clients + vecChannels[iCurChanID].PrepAndSendPacket ( &Socket, vecvecbyCodedData[iChanCnt], iCeltNumCodedBytes ); + } + } + } + else + { for ( int iB = 0; iB < vecNumFrameSizeConvBlocks[iChanCnt]; iB++ ) { const int iOffset = iB * SYSTEM_FRAME_SIZE_SAMPLES * vecNumAudioChannels[iChanCnt]; - iUnused = opus_custom_encode ( pCurOpusEncoder, - &vecsSendData[iOffset], - iClientFrameSizeSamples, - &vecvecbyCodedData[iChanCnt][0], - iCeltNumCodedBytes ); + memcpy ( &vecvecbyCodedData[iChanCnt][0], &vecsSendData[iOffset], iCeltNumCodedBytes ); - // send separate mix to current clients vecChannels[iCurChanID].PrepAndSendPacket ( &Socket, vecvecbyCodedData[iChanCnt], iCeltNumCodedBytes ); } } + } Q_UNUSED ( iUnused ) From 7f47dd8a4d47d7635fd57718eca3b036bc26f59d Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Fri, 17 Apr 2026 23:08:26 +0200 Subject: [PATCH 06/54] first working version (needs testing) --- src/server.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server.cpp b/src/server.cpp index fc33d419a9..63c87ad26b 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -885,7 +885,7 @@ void CServer::DecodeReceiveData ( const int iChanCnt, const int iNumClients ) { if ( bIsRawAudio ) { - memcpy ( &vecvecsData[iChanCnt][iOffset], &vecvecbyCodedData[iChanCnt], iCeltNumCodedBytes ); + memcpy ( &vecvecsData[iChanCnt][iOffset], &vecvecbyCodedData[iChanCnt][0], iCeltNumCodedBytes ); } else { From 7734d7531e42357426ab4aa3e36170e2de55c388 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Sat, 18 Apr 2026 00:04:17 +0200 Subject: [PATCH 07/54] fix style --- src/client.cpp | 8 ++++---- src/clientsettingsdlg.cpp | 2 +- src/server.cpp | 25 ++++++++++++------------- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index 8441f15bc4..0d338d28bd 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1157,7 +1157,7 @@ void CClient::Init() iCeltNumCodedBytes = OPUS_NUM_BYTES_MONO_HIGH_QUALITY_DBLE_FRAMESIZE; break; case AQ_RAW: - iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof(int16_t); + iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ); break; } } @@ -1179,7 +1179,7 @@ void CClient::Init() iCeltNumCodedBytes = OPUS_NUM_BYTES_STEREO_HIGH_QUALITY_DBLE_FRAMESIZE; break; case AQ_RAW: - iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof(int16_t); + iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ); break; } } @@ -1206,7 +1206,7 @@ void CClient::Init() iCeltNumCodedBytes = OPUS_NUM_BYTES_MONO_HIGH_QUALITY; break; case AQ_RAW: - iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof(int16_t); + iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ); break; } } @@ -1228,7 +1228,7 @@ void CClient::Init() iCeltNumCodedBytes = OPUS_NUM_BYTES_STEREO_HIGH_QUALITY; break; case AQ_RAW: - iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof(int16_t); + iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ); break; } } diff --git a/src/clientsettingsdlg.cpp b/src/clientsettingsdlg.cpp index 61468ca2cf..c82c236996 100644 --- a/src/clientsettingsdlg.cpp +++ b/src/clientsettingsdlg.cpp @@ -494,7 +494,7 @@ CClientSettingsDlg::CClientSettingsDlg ( CClient* pNCliP, CClientSettings* pNSet cbxAudioQuality->addItem ( tr ( "Low" ) ); // AQ_LOW cbxAudioQuality->addItem ( tr ( "Normal" ) ); // AQ_NORMAL cbxAudioQuality->addItem ( tr ( "High" ) ); // AQ_HIGH - cbxAudioQuality->addItem ( tr ( "Raw" ) ); // AQ_RAW + cbxAudioQuality->addItem ( tr ( "Raw" ) ); // AQ_RAW cbxAudioQuality->setCurrentIndex ( static_cast ( pClient->GetAudioQuality() ) ); // GUI design (skin) combo box diff --git a/src/server.cpp b/src/server.cpp index 63c87ad26b..fe18436949 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -877,8 +877,8 @@ void CServer::DecodeReceiveData ( const int iChanCnt, const int iNumClients ) return; } - const int iOffset = iB * SYSTEM_FRAME_SIZE_SAMPLES * vecNumAudioChannels[iChanCnt]; - const bool bIsRawAudio = ( iCeltNumCodedBytes == iClientFrameSizeSamples * vecNumAudioChannels[iChanCnt] * sizeof(int16_t) ); + const int iOffset = iB * SYSTEM_FRAME_SIZE_SAMPLES * vecNumAudioChannels[iChanCnt]; + const bool bIsRawAudio = ( iCeltNumCodedBytes == iClientFrameSizeSamples * vecNumAudioChannels[iChanCnt] * sizeof ( int16_t ) ); // get pointer to coded data if ( eGetStat == GS_BUFFER_OK ) @@ -912,10 +912,10 @@ void CServer::DecodeReceiveData ( const int iChanCnt, const int iNumClients ) { iUnused = opus_custom_decode ( CurOpusDecoder, - pCurCodedData, - iCeltNumCodedBytes, - &vecvecsData[iChanCnt][iOffset], - iClientFrameSizeSamples ); + pCurCodedData, + iCeltNumCodedBytes, + &vecvecsData[iChanCnt][iOffset], + iClientFrameSizeSamples ); } } } @@ -1176,7 +1176,7 @@ void CServer::MixEncodeTransmitData ( const int iChanCnt, const int iNumClients DoubleFrameSizeConvBufOut[iCurChanID].GetAll ( vecsSendData, DOUBLE_SYSTEM_FRAME_SIZE_SAMPLES * vecNumAudioChannels[iChanCnt] ); } - if ( iCeltNumCodedBytes != iClientFrameSizeSamples * vecNumAudioChannels[iChanCnt] * sizeof(int16_t)) + if ( iCeltNumCodedBytes != iClientFrameSizeSamples * vecNumAudioChannels[iChanCnt] * sizeof( int16_t ) ) { // OPUS encoding if ( pCurOpusEncoder != nullptr ) @@ -1185,7 +1185,7 @@ void CServer::MixEncodeTransmitData ( const int iChanCnt, const int iNumClients // find a better place than this: the setting does not change all the time so for speed // optimization it would be better to set it only if the network frame size is changed opus_custom_encoder_ctl ( pCurOpusEncoder, - OPUS_SET_BITRATE ( CalcBitRateBitsPerSecFromCodedBytes ( iCeltNumCodedBytes, iClientFrameSizeSamples ) ) ); + OPUS_SET_BITRATE ( CalcBitRateBitsPerSecFromCodedBytes ( iCeltNumCodedBytes, iClientFrameSizeSamples ) ) ); //### TODO: END ###// for ( int iB = 0; iB < vecNumFrameSizeConvBlocks[iChanCnt]; iB++ ) @@ -1193,10 +1193,10 @@ void CServer::MixEncodeTransmitData ( const int iChanCnt, const int iNumClients const int iOffset = iB * SYSTEM_FRAME_SIZE_SAMPLES * vecNumAudioChannels[iChanCnt]; iUnused = opus_custom_encode ( pCurOpusEncoder, - &vecsSendData[iOffset], - iClientFrameSizeSamples, - &vecvecbyCodedData[iChanCnt][0], - iCeltNumCodedBytes ); + &vecsSendData[iOffset], + iClientFrameSizeSamples, + &vecvecbyCodedData[iChanCnt][0], + iCeltNumCodedBytes ); // send separate mix to current clients vecChannels[iCurChanID].PrepAndSendPacket ( &Socket, vecvecbyCodedData[iChanCnt], iCeltNumCodedBytes ); @@ -1214,7 +1214,6 @@ void CServer::MixEncodeTransmitData ( const int iChanCnt, const int iNumClients vecChannels[iCurChanID].PrepAndSendPacket ( &Socket, vecvecbyCodedData[iChanCnt], iCeltNumCodedBytes ); } } - } Q_UNUSED ( iUnused ) From fa61b5513fa4f2f6ecd73f023ea1ac1083ff485a Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Sat, 18 Apr 2026 00:06:12 +0200 Subject: [PATCH 08/54] fix style --- src/server.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server.cpp b/src/server.cpp index fe18436949..e1cb67e548 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1176,7 +1176,7 @@ void CServer::MixEncodeTransmitData ( const int iChanCnt, const int iNumClients DoubleFrameSizeConvBufOut[iCurChanID].GetAll ( vecsSendData, DOUBLE_SYSTEM_FRAME_SIZE_SAMPLES * vecNumAudioChannels[iChanCnt] ); } - if ( iCeltNumCodedBytes != iClientFrameSizeSamples * vecNumAudioChannels[iChanCnt] * sizeof( int16_t ) ) + if ( iCeltNumCodedBytes != iClientFrameSizeSamples * vecNumAudioChannels[iChanCnt] * sizeof ( int16_t ) ) { // OPUS encoding if ( pCurOpusEncoder != nullptr ) From 5a467e02eef5227ddd11613655cf89b6bc3ec503 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Sat, 18 Apr 2026 00:34:39 +0200 Subject: [PATCH 09/54] fix mute myself --- src/client.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index 0d338d28bd..164e2ca13e 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1424,8 +1424,15 @@ void CClient::ProcessAudioDataIntern ( CVector& vecsStereoSndCrd ) } else { - // Send raw samples instead of OPUS - memcpy ( &vecCeltData[0], &vecsStereoSndCrd[0], iCeltNumCodedBytes ); + if ( !bMuteOutStream ) + { + // Send raw samples instead of OPUS + memcpy ( &vecCeltData[0], &vecsStereoSndCrd[0], iCeltNumCodedBytes ); + } + else + { + memset ( &vecCeltData[0], 0, iCeltNumCodedBytes ); + } Channel.PrepAndSendPacket ( &Socket, vecCeltData, iCeltNumCodedBytes ); } From 8f53817797295a7b8fb47750bf52dc539fc5ac4a Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Sun, 19 Apr 2026 11:16:12 +0200 Subject: [PATCH 10/54] remove redundant include --- src/server.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/server.cpp b/src/server.cpp index e1cb67e548..ff85cd472b 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -23,9 +23,6 @@ \******************************************************************************/ #include "server.h" -#include "global.h" -#include "util.h" -#include // CServer implementation ****************************************************** CServer::CServer ( const int iNewMaxNumChan, From c77029dcdb7961673043ae7879cefddbae2a0db6 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Mon, 20 Apr 2026 15:47:07 +0200 Subject: [PATCH 11/54] Change audio quality option from 'Raw' to 'Max' --- src/clientsettingsdlg.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/clientsettingsdlg.cpp b/src/clientsettingsdlg.cpp index c82c236996..f1c6af5dbe 100644 --- a/src/clientsettingsdlg.cpp +++ b/src/clientsettingsdlg.cpp @@ -494,7 +494,7 @@ CClientSettingsDlg::CClientSettingsDlg ( CClient* pNCliP, CClientSettings* pNSet cbxAudioQuality->addItem ( tr ( "Low" ) ); // AQ_LOW cbxAudioQuality->addItem ( tr ( "Normal" ) ); // AQ_NORMAL cbxAudioQuality->addItem ( tr ( "High" ) ); // AQ_HIGH - cbxAudioQuality->addItem ( tr ( "Raw" ) ); // AQ_RAW + cbxAudioQuality->addItem ( tr ( "Max" ) ); // AQ_RAW cbxAudioQuality->setCurrentIndex ( static_cast ( pClient->GetAudioQuality() ) ); // GUI design (skin) combo box From d36448a5b8bbd708bd6413c360bf4b2a444d05e4 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Mon, 20 Apr 2026 17:51:05 +0200 Subject: [PATCH 12/54] Only send raw audio if the server supports it (checked by version number) --- src/channel.cpp | 2 ++ src/channel.h | 3 +++ src/client.cpp | 44 ++++++++++++++++++++++++++++++++++++-------- 3 files changed, 41 insertions(+), 8 deletions(-) diff --git a/src/channel.cpp b/src/channel.cpp index 9bd409889a..ccba180486 100644 --- a/src/channel.cpp +++ b/src/channel.cpp @@ -135,6 +135,7 @@ void CChannel::SetEnable ( const bool bNEnStat ) // since the SetEnable(true) is set AFTER the Init() in the client -> we // simply set it regardless of the state which does not hurt. bUseSequenceNumber = false; + bRawAudioIsSupported = false; // if channel is not enabled, reset time out count and protocol if ( !bNEnStat ) @@ -148,6 +149,7 @@ void CChannel::OnVersionAndOSReceived ( COSUtil::EOpSystemType eOSType, QString { // check if audio packet counter is supported by the server (minimum version is 3.6.0) #if QT_VERSION >= QT_VERSION_CHECK( 5, 6, 0 ) + bRawAudioIsSupported = ( QVersionNumber::compare ( QVersionNumber::fromString ( strVersion ), QVersionNumber ( 4, 0, 0 ) ) >= 0 ) ? true : false; if ( QVersionNumber::compare ( QVersionNumber::fromString ( strVersion ), QVersionNumber ( 3, 6, 0 ) ) >= 0 ) { // activate sequence counter and update the audio stream properties (which diff --git a/src/channel.h b/src/channel.h index 1567268307..fc9589c624 100644 --- a/src/channel.h +++ b/src/channel.h @@ -169,6 +169,9 @@ class CChannel : public QObject double UpdateAndGetLevelForMeterdB ( const CVector& vecsAudio, const int iInSize, const bool bIsStereoIn ); + bool bRawAudioIsSupported = false; + + protected: bool ProtocolIsEnabled(); diff --git a/src/client.cpp b/src/client.cpp index 164e2ca13e..543b99aea1 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1157,7 +1157,14 @@ void CClient::Init() iCeltNumCodedBytes = OPUS_NUM_BYTES_MONO_HIGH_QUALITY_DBLE_FRAMESIZE; break; case AQ_RAW: - iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ); + if ( Channel.bRawAudioIsSupported ) + { + iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ); + } + else + { + iCeltNumCodedBytes = OPUS_NUM_BYTES_MONO_HIGH_QUALITY_DBLE_FRAMESIZE; + } break; } } @@ -1179,7 +1186,14 @@ void CClient::Init() iCeltNumCodedBytes = OPUS_NUM_BYTES_STEREO_HIGH_QUALITY_DBLE_FRAMESIZE; break; case AQ_RAW: - iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ); + if ( Channel.bRawAudioIsSupported ) + { + iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ); + } + else + { + iCeltNumCodedBytes = OPUS_NUM_BYTES_STEREO_HIGH_QUALITY_DBLE_FRAMESIZE; + } break; } } @@ -1206,7 +1220,14 @@ void CClient::Init() iCeltNumCodedBytes = OPUS_NUM_BYTES_MONO_HIGH_QUALITY; break; case AQ_RAW: - iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ); + if ( Channel.bRawAudioIsSupported ) + { + iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ); + } + else + { + iCeltNumCodedBytes = OPUS_NUM_BYTES_MONO_HIGH_QUALITY; + } break; } } @@ -1228,7 +1249,14 @@ void CClient::Init() iCeltNumCodedBytes = OPUS_NUM_BYTES_STEREO_HIGH_QUALITY; break; case AQ_RAW: - iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ); + if ( Channel.bRawAudioIsSupported ) + { + iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ); + } + else + { + iCeltNumCodedBytes = OPUS_NUM_BYTES_STEREO_HIGH_QUALITY; + } break; } } @@ -1401,7 +1429,7 @@ void CClient::ProcessAudioDataIntern ( CVector& vecsStereoSndCrd ) } } - if ( eAudioQuality != AQ_RAW ) + if ( eAudioQuality != AQ_RAW || !Channel.bRawAudioIsSupported ) { for ( i = 0, j = 0; i < iSndCrdFrameSizeFactor; i++, j += iNumAudioChannels * iOPUSFrameSizeSamples ) { @@ -1451,7 +1479,7 @@ void CClient::ProcessAudioDataIntern ( CVector& vecsStereoSndCrd ) // get pointer to coded data and manage the flags if ( bReceiveDataOk ) { - if ( eAudioQuality == AQ_RAW ) + if ( eAudioQuality == AQ_RAW && Channel.bRawAudioIsSupported ) { memcpy ( &vecsStereoSndCrd[0], &vecbyNetwData[0], iCeltNumCodedBytes ); pCurCodedData = nullptr; @@ -1465,7 +1493,7 @@ void CClient::ProcessAudioDataIntern ( CVector& vecsStereoSndCrd ) } else { - if ( eAudioQuality == AQ_RAW ) + if ( eAudioQuality == AQ_RAW && Channel.bRawAudioIsSupported ) { memset ( &vecsStereoSndCrd[0], 0, iCeltNumCodedBytes ); pCurCodedData = nullptr; @@ -1479,7 +1507,7 @@ void CClient::ProcessAudioDataIntern ( CVector& vecsStereoSndCrd ) bJitterBufferOK = false; } - if ( eAudioQuality != AQ_RAW ) + if ( eAudioQuality != AQ_RAW || !Channel.bRawAudioIsSupported ) { // OPUS decoding if ( CurOpusDecoder != nullptr ) From 8079eed3ef032bb86d98769e010e340f98a24348 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Mon, 20 Apr 2026 18:12:46 +0200 Subject: [PATCH 13/54] fix style --- src/channel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/channel.cpp b/src/channel.cpp index ccba180486..5d6a979c01 100644 --- a/src/channel.cpp +++ b/src/channel.cpp @@ -134,7 +134,7 @@ void CChannel::SetEnable ( const bool bNEnStat ) // function. NOTE that it is important to reset this parameter on SetEnable(false) // since the SetEnable(true) is set AFTER the Init() in the client -> we // simply set it regardless of the state which does not hurt. - bUseSequenceNumber = false; + bUseSequenceNumber = false; bRawAudioIsSupported = false; // if channel is not enabled, reset time out count and protocol From 5c73b6a9c7d418b36a595b64e03663be3eafd346 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Mon, 20 Apr 2026 18:26:32 +0200 Subject: [PATCH 14/54] fix style --- src/channel.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/channel.h b/src/channel.h index fc9589c624..29114b28bd 100644 --- a/src/channel.h +++ b/src/channel.h @@ -171,7 +171,6 @@ class CChannel : public QObject bool bRawAudioIsSupported = false; - protected: bool ProtocolIsEnabled(); From a59784324d46a0dbe8d3456a90d41cee3c91bd1b Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Mon, 20 Apr 2026 18:40:19 +0200 Subject: [PATCH 15/54] change version --- Jamulus.pro | 2 +- src/channel.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Jamulus.pro b/Jamulus.pro index 28f3bacd74..e20ecd3da6 100644 --- a/Jamulus.pro +++ b/Jamulus.pro @@ -1,4 +1,4 @@ -VERSION = 3.11.0dev +VERSION = 3.11.1rawaudio # Using lrelease and embed_translations only works for Qt 5.12 or later. # See https://github.com/jamulussoftware/jamulus/pull/3288 for these changes. diff --git a/src/channel.cpp b/src/channel.cpp index 5d6a979c01..1d08ad07d2 100644 --- a/src/channel.cpp +++ b/src/channel.cpp @@ -149,7 +149,7 @@ void CChannel::OnVersionAndOSReceived ( COSUtil::EOpSystemType eOSType, QString { // check if audio packet counter is supported by the server (minimum version is 3.6.0) #if QT_VERSION >= QT_VERSION_CHECK( 5, 6, 0 ) - bRawAudioIsSupported = ( QVersionNumber::compare ( QVersionNumber::fromString ( strVersion ), QVersionNumber ( 4, 0, 0 ) ) >= 0 ) ? true : false; + bRawAudioIsSupported = ( QVersionNumber::compare ( QVersionNumber::fromString ( strVersion ), QVersionNumber ( 3, 11, 1 ) ) >= 0 ) ? true : false; if ( QVersionNumber::compare ( QVersionNumber::fromString ( strVersion ), QVersionNumber ( 3, 6, 0 ) ) >= 0 ) { // activate sequence counter and update the audio stream properties (which From 7fa20b7014d7ed2a491cfe8e5c23fa1e729aaba0 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Mon, 20 Apr 2026 18:49:27 +0200 Subject: [PATCH 16/54] Update changelog --- ChangeLog | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ChangeLog b/ChangeLog index 3013fac972..e92a5afe00 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +### 3.11.1rawaudio + +- Add uncompressed audio transmission, improves latency by 2ms + ### 3.11.0dev <- NOTE: the release version number will be 3.12.0 ### - Extended SRV record support (#3556). From b602efac3f4de14abd826534ddd2b198836266c9 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Mon, 20 Apr 2026 19:04:10 +0200 Subject: [PATCH 17/54] fix changelog --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index e92a5afe00..718d4daf94 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,4 @@ -### 3.11.1rawaudio +### 3.11.1rawaudio ### - Add uncompressed audio transmission, improves latency by 2ms From 42af9ab7d3cd011847a14da2f8ae803309bca649 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Mon, 20 Apr 2026 20:27:54 +0200 Subject: [PATCH 18/54] Fix noise issue with rawaudio servers when Max audio quality is selected --- src/channel.cpp | 2 -- src/channel.h | 2 -- src/client.cpp | 27 +++++++++++++++++++-------- src/client.h | 2 ++ 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/channel.cpp b/src/channel.cpp index 5d6a979c01..8641d5a50b 100644 --- a/src/channel.cpp +++ b/src/channel.cpp @@ -135,7 +135,6 @@ void CChannel::SetEnable ( const bool bNEnStat ) // since the SetEnable(true) is set AFTER the Init() in the client -> we // simply set it regardless of the state which does not hurt. bUseSequenceNumber = false; - bRawAudioIsSupported = false; // if channel is not enabled, reset time out count and protocol if ( !bNEnStat ) @@ -149,7 +148,6 @@ void CChannel::OnVersionAndOSReceived ( COSUtil::EOpSystemType eOSType, QString { // check if audio packet counter is supported by the server (minimum version is 3.6.0) #if QT_VERSION >= QT_VERSION_CHECK( 5, 6, 0 ) - bRawAudioIsSupported = ( QVersionNumber::compare ( QVersionNumber::fromString ( strVersion ), QVersionNumber ( 4, 0, 0 ) ) >= 0 ) ? true : false; if ( QVersionNumber::compare ( QVersionNumber::fromString ( strVersion ), QVersionNumber ( 3, 6, 0 ) ) >= 0 ) { // activate sequence counter and update the audio stream properties (which diff --git a/src/channel.h b/src/channel.h index 29114b28bd..1567268307 100644 --- a/src/channel.h +++ b/src/channel.h @@ -169,8 +169,6 @@ class CChannel : public QObject double UpdateAndGetLevelForMeterdB ( const CVector& vecsAudio, const int iInSize, const bool bIsStereoIn ); - bool bRawAudioIsSupported = false; - protected: bool ProtocolIsEnabled(); diff --git a/src/client.cpp b/src/client.cpp index 543b99aea1..e2165cea5a 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -395,6 +395,17 @@ void CClient::OnConClientListMesReceived ( CVector vecChanInfo ) emit ConClientListMesReceived ( vecChanInfo ); } +void CClient::OnVersionAndOSReceived ( COSUtil::EOpSystemType eOSType, QString strVersion ) +{ +#if QT_VERSION >= QT_VERSION_CHECK( 5, 6, 0 ) + if ( QVersionNumber::compare ( QVersionNumber::fromString ( strVersion ), QVersionNumber ( 3, 11, 1 ) ) >= 0 ) + { + bRawAudioIsSupported = true; + Init(); + } +#endif +} + void CClient::CreateServerJitterBufferMessage() { // per definition in the client: if auto jitter buffer is enabled, both, @@ -1157,7 +1168,7 @@ void CClient::Init() iCeltNumCodedBytes = OPUS_NUM_BYTES_MONO_HIGH_QUALITY_DBLE_FRAMESIZE; break; case AQ_RAW: - if ( Channel.bRawAudioIsSupported ) + if ( bRawAudioIsSupported ) { iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ); } @@ -1186,7 +1197,7 @@ void CClient::Init() iCeltNumCodedBytes = OPUS_NUM_BYTES_STEREO_HIGH_QUALITY_DBLE_FRAMESIZE; break; case AQ_RAW: - if ( Channel.bRawAudioIsSupported ) + if ( bRawAudioIsSupported ) { iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ); } @@ -1220,7 +1231,7 @@ void CClient::Init() iCeltNumCodedBytes = OPUS_NUM_BYTES_MONO_HIGH_QUALITY; break; case AQ_RAW: - if ( Channel.bRawAudioIsSupported ) + if ( bRawAudioIsSupported ) { iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ); } @@ -1249,7 +1260,7 @@ void CClient::Init() iCeltNumCodedBytes = OPUS_NUM_BYTES_STEREO_HIGH_QUALITY; break; case AQ_RAW: - if ( Channel.bRawAudioIsSupported ) + if ( bRawAudioIsSupported ) { iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ); } @@ -1429,7 +1440,7 @@ void CClient::ProcessAudioDataIntern ( CVector& vecsStereoSndCrd ) } } - if ( eAudioQuality != AQ_RAW || !Channel.bRawAudioIsSupported ) + if ( eAudioQuality != AQ_RAW || !bRawAudioIsSupported ) { for ( i = 0, j = 0; i < iSndCrdFrameSizeFactor; i++, j += iNumAudioChannels * iOPUSFrameSizeSamples ) { @@ -1479,7 +1490,7 @@ void CClient::ProcessAudioDataIntern ( CVector& vecsStereoSndCrd ) // get pointer to coded data and manage the flags if ( bReceiveDataOk ) { - if ( eAudioQuality == AQ_RAW && Channel.bRawAudioIsSupported ) + if ( eAudioQuality == AQ_RAW && bRawAudioIsSupported ) { memcpy ( &vecsStereoSndCrd[0], &vecbyNetwData[0], iCeltNumCodedBytes ); pCurCodedData = nullptr; @@ -1493,7 +1504,7 @@ void CClient::ProcessAudioDataIntern ( CVector& vecsStereoSndCrd ) } else { - if ( eAudioQuality == AQ_RAW && Channel.bRawAudioIsSupported ) + if ( eAudioQuality == AQ_RAW && bRawAudioIsSupported ) { memset ( &vecsStereoSndCrd[0], 0, iCeltNumCodedBytes ); pCurCodedData = nullptr; @@ -1507,7 +1518,7 @@ void CClient::ProcessAudioDataIntern ( CVector& vecsStereoSndCrd ) bJitterBufferOK = false; } - if ( eAudioQuality != AQ_RAW || !Channel.bRawAudioIsSupported ) + if ( eAudioQuality != AQ_RAW || !bRawAudioIsSupported ) { // OPUS decoding if ( CurOpusDecoder != nullptr ) diff --git a/src/client.h b/src/client.h index 6139ef599e..dce919c675 100644 --- a/src/client.h +++ b/src/client.h @@ -403,6 +403,7 @@ class CClient : public QObject EMeterStyle eMeterStyle; bool bEnableAudioAlerts; bool bEnableOPUS64; + bool bRawAudioIsSupported; bool bJitterBufferOK; bool bEnableIPv6; @@ -456,6 +457,7 @@ protected slots: void OnMuteStateHasChangedReceived ( int iServerChanID, bool bIsMuted ); void OnCLChannelLevelListReceived ( CHostAddress InetAddr, CVector vecLevelList ); void OnConClientListMesReceived ( CVector vecChanInfo ); + void OnVersionAndOSReceived ( COSUtil::EOpSystemType eOSType, QString strVersion ); signals: void ConClientListMesReceived ( CVector vecChanInfo ); From c3b47fd93370a36d6423c44ea3e2571b8ea6269a Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Mon, 20 Apr 2026 20:40:25 +0200 Subject: [PATCH 19/54] fix style (I'll never learn) --- src/channel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/channel.cpp b/src/channel.cpp index 8641d5a50b..9bd409889a 100644 --- a/src/channel.cpp +++ b/src/channel.cpp @@ -134,7 +134,7 @@ void CChannel::SetEnable ( const bool bNEnStat ) // function. NOTE that it is important to reset this parameter on SetEnable(false) // since the SetEnable(true) is set AFTER the Init() in the client -> we // simply set it regardless of the state which does not hurt. - bUseSequenceNumber = false; + bUseSequenceNumber = false; // if channel is not enabled, reset time out count and protocol if ( !bNEnStat ) From 1544eb7b8c72f01d9795a4e5d855d3a82c413964 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Mon, 20 Apr 2026 21:35:01 +0200 Subject: [PATCH 20/54] fix last commit --- src/client.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/client.cpp b/src/client.cpp index e2165cea5a..2d77a3ba3c 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -137,6 +137,8 @@ CClient::CClient ( const quint16 iPortNumber, QObject::connect ( &Channel, &CChannel::VersionAndOSReceived, this, &CClient::VersionAndOSReceived ); + QObject::connect ( &Channel, &CChannel::VersionAndOSReceived, this, &CClient::OnVersionAndOSReceived ); + QObject::connect ( &Channel, &CChannel::RecorderStateReceived, this, &CClient::RecorderStateReceived ); QObject::connect ( &ConnLessProtocol, &CProtocol::CLMessReadyForSending, this, &CClient::OnSendCLProtMessage ); From 23399c5a3cab4fb4e5d366345993cdde742bed1c Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Tue, 21 Apr 2026 13:29:25 +0200 Subject: [PATCH 21/54] Disable bRawAudioIsSupported when leaving a server --- src/client.cpp | 5 +++++ src/client.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/client.cpp b/src/client.cpp index 2d77a3ba3c..5fe06f65ff 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -405,6 +405,11 @@ void CClient::OnVersionAndOSReceived ( COSUtil::EOpSystemType eOSType, QString s bRawAudioIsSupported = true; Init(); } + else + { + bRawAudioIsSupported = false; + Init(); + } #endif } diff --git a/src/client.h b/src/client.h index dce919c675..1f4c23bc83 100644 --- a/src/client.h +++ b/src/client.h @@ -438,6 +438,7 @@ protected slots: { if ( InetAddr == Channel.GetAddress() ) { + bRawAudioIsSupported = false; emit Disconnected(); } } From 5b8a7093c3868901a7d7618746e6c180988826c3 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Tue, 21 Apr 2026 13:38:51 +0200 Subject: [PATCH 22/54] limit rawaudio to server version 3.11.1 only --- src/client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client.cpp b/src/client.cpp index 5fe06f65ff..667de2be91 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -400,7 +400,7 @@ void CClient::OnConClientListMesReceived ( CVector vecChanInfo ) void CClient::OnVersionAndOSReceived ( COSUtil::EOpSystemType eOSType, QString strVersion ) { #if QT_VERSION >= QT_VERSION_CHECK( 5, 6, 0 ) - if ( QVersionNumber::compare ( QVersionNumber::fromString ( strVersion ), QVersionNumber ( 3, 11, 1 ) ) >= 0 ) + if ( QVersionNumber::compare ( QVersionNumber::fromString ( strVersion ), QVersionNumber ( 3, 11, 1 ) ) == 0 ) { bRawAudioIsSupported = true; Init(); From 2aad9b545254f36c3487af80a0f6cd2dddb25516 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Tue, 21 Apr 2026 16:37:57 +0200 Subject: [PATCH 23/54] opus fallback on disconnect --- src/client.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/client.cpp b/src/client.cpp index 667de2be91..188e8823e8 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1035,6 +1035,10 @@ void CClient::Stop() // disable channel Channel.SetEnable ( false ); + // Fall back to opus in case raw was used + bRawAudioIsSupported = false; + Init(); + // wait for approx. 100 ms to make sure no audio packet is still in the // network queue causing the channel to be reconnected right after having // received the disconnect message (seems not to gain much, disconnect is From 754d7b086f7c49b7c29742b7cd026040d0645826 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Tue, 21 Apr 2026 19:35:11 +0200 Subject: [PATCH 24/54] disable raw setting when unconnected to join a new server with forced opus --- src/client.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index 188e8823e8..4b333f8bc6 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1179,7 +1179,7 @@ void CClient::Init() iCeltNumCodedBytes = OPUS_NUM_BYTES_MONO_HIGH_QUALITY_DBLE_FRAMESIZE; break; case AQ_RAW: - if ( bRawAudioIsSupported ) + if ( bRawAudioIsSupported && Channel.IsEnabled() ) { iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ); } @@ -1208,7 +1208,7 @@ void CClient::Init() iCeltNumCodedBytes = OPUS_NUM_BYTES_STEREO_HIGH_QUALITY_DBLE_FRAMESIZE; break; case AQ_RAW: - if ( bRawAudioIsSupported ) + if ( bRawAudioIsSupported && Channel.IsEnabled() ) { iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ); } @@ -1242,7 +1242,7 @@ void CClient::Init() iCeltNumCodedBytes = OPUS_NUM_BYTES_MONO_HIGH_QUALITY; break; case AQ_RAW: - if ( bRawAudioIsSupported ) + if ( bRawAudioIsSupported && Channel.IsEnabled() ) { iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ); } @@ -1271,7 +1271,7 @@ void CClient::Init() iCeltNumCodedBytes = OPUS_NUM_BYTES_STEREO_HIGH_QUALITY; break; case AQ_RAW: - if ( bRawAudioIsSupported ) + if ( bRawAudioIsSupported && Channel.IsEnabled() ) { iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ); } From 14d83ed2e5964c2210a48cad5339d86568e2338a Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Wed, 22 Apr 2026 01:34:17 +0200 Subject: [PATCH 25/54] stop sound before calling client init --- src/client.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/client.cpp b/src/client.cpp index 4b333f8bc6..50dd40c7d7 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -400,6 +400,11 @@ void CClient::OnConClientListMesReceived ( CVector vecChanInfo ) void CClient::OnVersionAndOSReceived ( COSUtil::EOpSystemType eOSType, QString strVersion ) { #if QT_VERSION >= QT_VERSION_CHECK( 5, 6, 0 ) + const bool bWasRunning = Sound.IsRunning(); + if ( bWasRunning ) + { + Sound.Stop(); + } if ( QVersionNumber::compare ( QVersionNumber::fromString ( strVersion ), QVersionNumber ( 3, 11, 1 ) ) == 0 ) { bRawAudioIsSupported = true; @@ -410,6 +415,10 @@ void CClient::OnVersionAndOSReceived ( COSUtil::EOpSystemType eOSType, QString s bRawAudioIsSupported = false; Init(); } + if ( bWasRunning ) + { + Sound.Start(); + } #endif } From d630234162017afd18af2defe39f2158cf487c09 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Wed, 22 Apr 2026 11:09:44 +0200 Subject: [PATCH 26/54] make raw audio quality setting persistent in config file --- src/settings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/settings.cpp b/src/settings.cpp index af594c8bbe..daa2fd5736 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -605,7 +605,7 @@ void CClientSettings::ReadSettingsFromXML ( const QDomDocument& IniXMLDocument, } // audio quality - if ( GetNumericIniSet ( IniXMLDocument, "client", "audioquality", 0, 2 /* AQ_HIGH */, iValue ) ) + if ( GetNumericIniSet ( IniXMLDocument, "client", "audioquality", 0, 3 /* AQ_RAW */, iValue ) ) { pClient->SetAudioQuality ( static_cast ( iValue ) ); } From 32fca21dfbb3c8923efdcb2583121f8783864789 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Wed, 22 Apr 2026 11:10:21 +0200 Subject: [PATCH 27/54] remove redundant setting of bRawAudioIsSupported --- src/client.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/client.h b/src/client.h index 1f4c23bc83..dce919c675 100644 --- a/src/client.h +++ b/src/client.h @@ -438,7 +438,6 @@ protected slots: { if ( InetAddr == Channel.GetAddress() ) { - bRawAudioIsSupported = false; emit Disconnected(); } } From bbe3329028399c0320ebd5f91c7be15ce8b9cf9f Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Thu, 23 Apr 2026 17:59:31 +0200 Subject: [PATCH 28/54] Update changelog --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 718d4daf94..6e7e68cfa0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,6 @@ ### 3.11.1rawaudio ### -- Add uncompressed audio transmission, improves latency by 2ms +- Add uncompressed audio transmission - dedicated to the memory of Hans Petter Selasky (1982 - 2023) ### 3.11.0dev <- NOTE: the release version number will be 3.12.0 ### From 6fa50891c85de6a5cead7279f1ee1a1e8fe8b830 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Thu, 23 Apr 2026 18:41:07 +0200 Subject: [PATCH 29/54] Account for iSndCrdFrameSizeFactor when calculating packet sizes --- src/client.cpp | 10 ++++++---- src/server.cpp | 4 +++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index 50dd40c7d7..0826bc4497 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1190,7 +1190,7 @@ void CClient::Init() case AQ_RAW: if ( bRawAudioIsSupported && Channel.IsEnabled() ) { - iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ); + iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ) * iSndCrdFrameSizeFactor; } else { @@ -1219,7 +1219,7 @@ void CClient::Init() case AQ_RAW: if ( bRawAudioIsSupported && Channel.IsEnabled() ) { - iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ); + iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ) * iSndCrdFrameSizeFactor; } else { @@ -1253,7 +1253,7 @@ void CClient::Init() case AQ_RAW: if ( bRawAudioIsSupported && Channel.IsEnabled() ) { - iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ); + iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ) * iSndCrdFrameSizeFactor; } else { @@ -1282,7 +1282,7 @@ void CClient::Init() case AQ_RAW: if ( bRawAudioIsSupported && Channel.IsEnabled() ) { - iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ); + iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ) * iSndCrdFrameSizeFactor; } else { @@ -1483,6 +1483,8 @@ void CClient::ProcessAudioDataIntern ( CVector& vecsStereoSndCrd ) } else { + // This only works when iSndCrdFrameSizeFactor == 1 (not for buffer size 256) + // TODO: fill network buffer with correct data if ( !bMuteOutStream ) { // Send raw samples instead of OPUS diff --git a/src/server.cpp b/src/server.cpp index ff85cd472b..a944f49ea3 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -875,7 +875,9 @@ void CServer::DecodeReceiveData ( const int iChanCnt, const int iNumClients ) } const int iOffset = iB * SYSTEM_FRAME_SIZE_SAMPLES * vecNumAudioChannels[iChanCnt]; - const bool bIsRawAudio = ( iCeltNumCodedBytes == iClientFrameSizeSamples * vecNumAudioChannels[iChanCnt] * sizeof ( int16_t ) ); + // Recognise a raw audio packet by its size + // Greater or equal is used to account for iSndSndCrdFrameSizeFactor, which is not known to the server. Could modulo be used here insted? + const bool bIsRawAudio = ( iCeltNumCodedBytes >= iClientFrameSizeSamples * vecNumAudioChannels[iChanCnt] * sizeof ( int16_t ) ); // get pointer to coded data if ( eGetStat == GS_BUFFER_OK ) From 28cb2957920b5257a8d2c1bec652762d25dc5c03 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Thu, 23 Apr 2026 18:51:00 +0200 Subject: [PATCH 30/54] here we go again, fix style --- src/server.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server.cpp b/src/server.cpp index a944f49ea3..31313bd417 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -874,7 +874,7 @@ void CServer::DecodeReceiveData ( const int iChanCnt, const int iNumClients ) return; } - const int iOffset = iB * SYSTEM_FRAME_SIZE_SAMPLES * vecNumAudioChannels[iChanCnt]; + const int iOffset = iB * SYSTEM_FRAME_SIZE_SAMPLES * vecNumAudioChannels[iChanCnt]; // Recognise a raw audio packet by its size // Greater or equal is used to account for iSndSndCrdFrameSizeFactor, which is not known to the server. Could modulo be used here insted? const bool bIsRawAudio = ( iCeltNumCodedBytes >= iClientFrameSizeSamples * vecNumAudioChannels[iChanCnt] * sizeof ( int16_t ) ); From 1d402d9522ce8d5ca68ce4ec510e8480f6dc1eb9 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Fri, 24 Apr 2026 00:21:55 +0200 Subject: [PATCH 31/54] Fix compiler warnings --- src/client.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/client.cpp b/src/client.cpp index 0826bc4497..ad94bb1b15 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -420,6 +420,7 @@ void CClient::OnVersionAndOSReceived ( COSUtil::EOpSystemType eOSType, QString s Sound.Start(); } #endif + Q_UNUSED ( eOSType ); } void CClient::CreateServerJitterBufferMessage() From d434d64f83563aba9c91973784b9d80d7c6a0c4a Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Fri, 24 Apr 2026 10:11:08 +0200 Subject: [PATCH 32/54] fix packet size calculation for iSndCrdFrameSizeFactor != 1, makes alls buffer sizes work with raw audio --- src/client.cpp | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index ad94bb1b15..4dac91b3cd 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1191,7 +1191,7 @@ void CClient::Init() case AQ_RAW: if ( bRawAudioIsSupported && Channel.IsEnabled() ) { - iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ) * iSndCrdFrameSizeFactor; + iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ); } else { @@ -1220,7 +1220,7 @@ void CClient::Init() case AQ_RAW: if ( bRawAudioIsSupported && Channel.IsEnabled() ) { - iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ) * iSndCrdFrameSizeFactor; + iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ); } else { @@ -1254,7 +1254,7 @@ void CClient::Init() case AQ_RAW: if ( bRawAudioIsSupported && Channel.IsEnabled() ) { - iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ) * iSndCrdFrameSizeFactor; + iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ); } else { @@ -1283,7 +1283,7 @@ void CClient::Init() case AQ_RAW: if ( bRawAudioIsSupported && Channel.IsEnabled() ) { - iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ) * iSndCrdFrameSizeFactor; + iCeltNumCodedBytes = iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ); } else { @@ -1461,9 +1461,9 @@ void CClient::ProcessAudioDataIntern ( CVector& vecsStereoSndCrd ) } } - if ( eAudioQuality != AQ_RAW || !bRawAudioIsSupported ) + for ( i = 0, j = 0; i < iSndCrdFrameSizeFactor; i++, j += iNumAudioChannels * iOPUSFrameSizeSamples ) { - for ( i = 0, j = 0; i < iSndCrdFrameSizeFactor; i++, j += iNumAudioChannels * iOPUSFrameSizeSamples ) + if ( eAudioQuality != AQ_RAW || !bRawAudioIsSupported ) { // OPUS encoding if ( CurOpusEncoder != nullptr ) @@ -1477,25 +1477,22 @@ void CClient::ProcessAudioDataIntern ( CVector& vecsStereoSndCrd ) iUnused = opus_custom_encode ( CurOpusEncoder, &vecsStereoSndCrd[j], iOPUSFrameSizeSamples, &vecCeltData[0], iCeltNumCodedBytes ); } } - // send coded audio through the network Channel.PrepAndSendPacket ( &Socket, vecCeltData, iCeltNumCodedBytes ); } - } - else - { - // This only works when iSndCrdFrameSizeFactor == 1 (not for buffer size 256) - // TODO: fill network buffer with correct data - if ( !bMuteOutStream ) - { - // Send raw samples instead of OPUS - memcpy ( &vecCeltData[0], &vecsStereoSndCrd[0], iCeltNumCodedBytes ); - } else { - memset ( &vecCeltData[0], 0, iCeltNumCodedBytes ); + if ( !bMuteOutStream ) + { + // Send raw samples instead of OPUS + memcpy ( &vecCeltData[0], &vecsStereoSndCrd[j], iCeltNumCodedBytes ); + } + else + { + memset ( &vecCeltData[0], 0, iCeltNumCodedBytes ); + } + Channel.PrepAndSendPacket ( &Socket, vecCeltData, iCeltNumCodedBytes ); } - Channel.PrepAndSendPacket ( &Socket, vecCeltData, iCeltNumCodedBytes ); } // Receive signal ---------------------------------------------------------- @@ -1515,7 +1512,7 @@ void CClient::ProcessAudioDataIntern ( CVector& vecsStereoSndCrd ) { if ( eAudioQuality == AQ_RAW && bRawAudioIsSupported ) { - memcpy ( &vecsStereoSndCrd[0], &vecbyNetwData[0], iCeltNumCodedBytes ); + memcpy ( &vecsStereoSndCrd[j], &vecbyNetwData[0], iCeltNumCodedBytes ); pCurCodedData = nullptr; } else @@ -1529,7 +1526,7 @@ void CClient::ProcessAudioDataIntern ( CVector& vecsStereoSndCrd ) { if ( eAudioQuality == AQ_RAW && bRawAudioIsSupported ) { - memset ( &vecsStereoSndCrd[0], 0, iCeltNumCodedBytes ); + memset ( &vecsStereoSndCrd[j], 0, iCeltNumCodedBytes ); pCurCodedData = nullptr; } else From d977e0fc2fcad2d8ddb5eee6140277dab7bd71d4 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Fri, 24 Apr 2026 11:04:17 +0200 Subject: [PATCH 33/54] Append hash to build version --- Jamulus.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jamulus.pro b/Jamulus.pro index e20ecd3da6..7e781d4283 100644 --- a/Jamulus.pro +++ b/Jamulus.pro @@ -1,4 +1,4 @@ -VERSION = 3.11.1rawaudio +VERSION = 3.11.1rawaudio-dev # Using lrelease and embed_translations only works for Qt 5.12 or later. # See https://github.com/jamulussoftware/jamulus/pull/3288 for these changes. From 8b5ad531797d1dae75d80b26b3694a263be85e33 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Fri, 24 Apr 2026 11:13:15 +0200 Subject: [PATCH 34/54] Hopefully shorten version enough to be able to register with central servers --- Jamulus.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jamulus.pro b/Jamulus.pro index 7e781d4283..eee82398c4 100644 --- a/Jamulus.pro +++ b/Jamulus.pro @@ -1,4 +1,4 @@ -VERSION = 3.11.1rawaudio-dev +VERSION = 3.11.1dev # Using lrelease and embed_translations only works for Qt 5.12 or later. # See https://github.com/jamulussoftware/jamulus/pull/3288 for these changes. From 8773fb28bf061bef5ce53c561499679d095ab781 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Fri, 24 Apr 2026 11:16:25 +0200 Subject: [PATCH 35/54] Fix changelog --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 6e7e68cfa0..7512ad1045 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,4 @@ -### 3.11.1rawaudio ### +### 3.11.1dev ### - Add uncompressed audio transmission - dedicated to the memory of Hans Petter Selasky (1982 - 2023) From a9549332255404b6c407a334097cb0600e0ba7de Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Fri, 24 Apr 2026 12:15:37 +0200 Subject: [PATCH 36/54] Revert checking for packet sizes greater or equal than iCeltNumCodedBytes. Wrong assumptions were made --- src/server.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/server.cpp b/src/server.cpp index 31313bd417..8d09bb0d7d 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -876,8 +876,9 @@ void CServer::DecodeReceiveData ( const int iChanCnt, const int iNumClients ) const int iOffset = iB * SYSTEM_FRAME_SIZE_SAMPLES * vecNumAudioChannels[iChanCnt]; // Recognise a raw audio packet by its size - // Greater or equal is used to account for iSndSndCrdFrameSizeFactor, which is not known to the server. Could modulo be used here insted? - const bool bIsRawAudio = ( iCeltNumCodedBytes >= iClientFrameSizeSamples * vecNumAudioChannels[iChanCnt] * sizeof ( int16_t ) ); + // TODO: This should be done by prepending bytes to the packet to be identifiable as containing raw audio. + // This is just a placeholder. + const bool bIsRawAudio = ( iCeltNumCodedBytes == iClientFrameSizeSamples * vecNumAudioChannels[iChanCnt] * sizeof ( int16_t ) ); // get pointer to coded data if ( eGetStat == GS_BUFFER_OK ) From d55f50bc8ea5c01e60b5928e04839d70f12a3fc4 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Sun, 26 Apr 2026 11:20:15 +0200 Subject: [PATCH 37/54] Improve readybility/consistency --- src/client.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index 4dac91b3cd..9adb156234 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1482,14 +1482,14 @@ void CClient::ProcessAudioDataIntern ( CVector& vecsStereoSndCrd ) } else { - if ( !bMuteOutStream ) + if ( bMuteOutStream ) { - // Send raw samples instead of OPUS - memcpy ( &vecCeltData[0], &vecsStereoSndCrd[j], iCeltNumCodedBytes ); + memset ( &vecCeltData[0], 0, iCeltNumCodedBytes ); } else { - memset ( &vecCeltData[0], 0, iCeltNumCodedBytes ); + // Send raw samples instead of OPUS + memcpy ( &vecCeltData[0], &vecsStereoSndCrd[j], iCeltNumCodedBytes ); } Channel.PrepAndSendPacket ( &Socket, vecCeltData, iCeltNumCodedBytes ); } From 7a64330e6873c53d98004feebf62914a09856bdd Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Sun, 26 Apr 2026 11:24:44 +0200 Subject: [PATCH 38/54] Remove redundant code --- src/client.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index 9adb156234..29c8395851 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1477,8 +1477,6 @@ void CClient::ProcessAudioDataIntern ( CVector& vecsStereoSndCrd ) iUnused = opus_custom_encode ( CurOpusEncoder, &vecsStereoSndCrd[j], iOPUSFrameSizeSamples, &vecCeltData[0], iCeltNumCodedBytes ); } } - // send coded audio through the network - Channel.PrepAndSendPacket ( &Socket, vecCeltData, iCeltNumCodedBytes ); } else { @@ -1491,8 +1489,9 @@ void CClient::ProcessAudioDataIntern ( CVector& vecsStereoSndCrd ) // Send raw samples instead of OPUS memcpy ( &vecCeltData[0], &vecsStereoSndCrd[j], iCeltNumCodedBytes ); } - Channel.PrepAndSendPacket ( &Socket, vecCeltData, iCeltNumCodedBytes ); } + // send coded audio through the network + Channel.PrepAndSendPacket ( &Socket, vecCeltData, iCeltNumCodedBytes ); } // Receive signal ---------------------------------------------------------- From 763c95d7b9e7271ea7f6e30e22c0cd48b336232f Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Sun, 26 Apr 2026 11:29:40 +0200 Subject: [PATCH 39/54] Refactor conditions, remove redundancy --- src/client.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index 29c8395851..42a5cc56ec 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1526,13 +1526,9 @@ void CClient::ProcessAudioDataIntern ( CVector& vecsStereoSndCrd ) if ( eAudioQuality == AQ_RAW && bRawAudioIsSupported ) { memset ( &vecsStereoSndCrd[j], 0, iCeltNumCodedBytes ); - pCurCodedData = nullptr; - } - else - { - // for lost packets use null pointer as coded input data - pCurCodedData = nullptr; } + // for lost packets use null pointer as coded input data + pCurCodedData = nullptr; // invalidate the buffer OK status flag bJitterBufferOK = false; } From e6888afc6b64550fc8b4ca5b592d5f2892f936da Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Sun, 26 Apr 2026 11:34:30 +0200 Subject: [PATCH 40/54] Refactor condition --- src/client.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index 42a5cc56ec..5fecc93fea 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1533,13 +1533,10 @@ void CClient::ProcessAudioDataIntern ( CVector& vecsStereoSndCrd ) bJitterBufferOK = false; } - if ( eAudioQuality != AQ_RAW || !bRawAudioIsSupported ) + if ( ( eAudioQuality != AQ_RAW || !bRawAudioIsSupported ) && CurOpusDecoder != nullptr ) { // OPUS decoding - if ( CurOpusDecoder != nullptr ) - { - iUnused = opus_custom_decode ( CurOpusDecoder, pCurCodedData, iCeltNumCodedBytes, &vecsStereoSndCrd[j], iOPUSFrameSizeSamples ); - } + iUnused = opus_custom_decode ( CurOpusDecoder, pCurCodedData, iCeltNumCodedBytes, &vecsStereoSndCrd[j], iOPUSFrameSizeSamples ); } } From ac78b16e9418c207f12a017d7c8c0139f257a9ea Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Sun, 26 Apr 2026 11:42:10 +0200 Subject: [PATCH 41/54] Refactor for consistency in client and server --- src/server.cpp | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/src/server.cpp b/src/server.cpp index 8d09bb0d7d..451f6f27b4 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -886,6 +886,7 @@ void CServer::DecodeReceiveData ( const int iChanCnt, const int iNumClients ) if ( bIsRawAudio ) { memcpy ( &vecvecsData[iChanCnt][iOffset], &vecvecbyCodedData[iChanCnt][0], iCeltNumCodedBytes ); + pCurCodedData = nullptr; } else { @@ -898,25 +899,17 @@ void CServer::DecodeReceiveData ( const int iChanCnt, const int iNumClients ) { memset ( &vecvecsData[iChanCnt][iOffset], 0, iCeltNumCodedBytes ); } - else - { - // for lost packets use null pointer as coded input data - pCurCodedData = nullptr; - } + // for lost packets use null pointer as coded input data + pCurCodedData = nullptr; } - if ( !bIsRawAudio ) + if ( !bIsRawAudio && CurOpusDecoder != nullptr ) { - // OPUS decode received data stream - if ( CurOpusDecoder != nullptr ) - { - - iUnused = opus_custom_decode ( CurOpusDecoder, - pCurCodedData, - iCeltNumCodedBytes, - &vecvecsData[iChanCnt][iOffset], - iClientFrameSizeSamples ); - } + iUnused = opus_custom_decode ( CurOpusDecoder, + pCurCodedData, + iCeltNumCodedBytes, + &vecvecsData[iChanCnt][iOffset], + iClientFrameSizeSamples ); } } From 7c11c63dec2262956078848c995020e3d87ee6a3 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Sun, 26 Apr 2026 11:46:26 +0200 Subject: [PATCH 42/54] Refactor conditions --- src/server.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/server.cpp b/src/server.cpp index 451f6f27b4..6b224da8b8 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1191,8 +1191,6 @@ void CServer::MixEncodeTransmitData ( const int iChanCnt, const int iNumClients &vecvecbyCodedData[iChanCnt][0], iCeltNumCodedBytes ); - // send separate mix to current clients - vecChannels[iCurChanID].PrepAndSendPacket ( &Socket, vecvecbyCodedData[iChanCnt], iCeltNumCodedBytes ); } } } @@ -1203,10 +1201,10 @@ void CServer::MixEncodeTransmitData ( const int iChanCnt, const int iNumClients const int iOffset = iB * SYSTEM_FRAME_SIZE_SAMPLES * vecNumAudioChannels[iChanCnt]; memcpy ( &vecvecbyCodedData[iChanCnt][0], &vecsSendData[iOffset], iCeltNumCodedBytes ); - - vecChannels[iCurChanID].PrepAndSendPacket ( &Socket, vecvecbyCodedData[iChanCnt], iCeltNumCodedBytes ); } } + // send separate mix to current clients + vecChannels[iCurChanID].PrepAndSendPacket ( &Socket, vecvecbyCodedData[iChanCnt], iCeltNumCodedBytes ); } Q_UNUSED ( iUnused ) From c3c0b166f91081bc64b63871d0b46687a79216c3 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Sun, 26 Apr 2026 12:15:09 +0200 Subject: [PATCH 43/54] Fix style --- src/server.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/server.cpp b/src/server.cpp index 6b224da8b8..2c5431731c 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1190,7 +1190,6 @@ void CServer::MixEncodeTransmitData ( const int iChanCnt, const int iNumClients iClientFrameSizeSamples, &vecvecbyCodedData[iChanCnt][0], iCeltNumCodedBytes ); - } } } From 5aeb676e2bd7e838753cd2b5d0b0bdb382da2f13 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Sun, 26 Apr 2026 15:09:09 +0200 Subject: [PATCH 44/54] Don't call opus_custom_encoder_ctl when sending raw audio --- src/client.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/client.cpp b/src/client.cpp index 5fecc93fea..dee7abd400 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1301,8 +1301,11 @@ void CClient::Init() vecZeros.Init ( iStereoBlockSizeSam, 0 ); vecsStereoSndCrdMuteStream.Init ( iStereoBlockSizeSam ); - opus_custom_encoder_ctl ( CurOpusEncoder, + if ( !bRawAudioIsSupported ) + { + opus_custom_encoder_ctl ( CurOpusEncoder, OPUS_SET_BITRATE ( CalcBitRateBitsPerSecFromCodedBytes ( iCeltNumCodedBytes, iOPUSFrameSizeSamples ) ) ); + } // inits for network and channel vecbyNetwData.Init ( iCeltNumCodedBytes ); From 43d321cffa84124483e521fb9f913ed17600dffa Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Sun, 26 Apr 2026 15:14:28 +0200 Subject: [PATCH 45/54] Fix style --- src/client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client.cpp b/src/client.cpp index dee7abd400..e82f945c99 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1304,7 +1304,7 @@ void CClient::Init() if ( !bRawAudioIsSupported ) { opus_custom_encoder_ctl ( CurOpusEncoder, - OPUS_SET_BITRATE ( CalcBitRateBitsPerSecFromCodedBytes ( iCeltNumCodedBytes, iOPUSFrameSizeSamples ) ) ); + OPUS_SET_BITRATE ( CalcBitRateBitsPerSecFromCodedBytes ( iCeltNumCodedBytes, iOPUSFrameSizeSamples ) ) ); } // inits for network and channel From bb33cdf9038150f309b192f9cc44e5dad80e5f18 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Sun, 26 Apr 2026 16:37:54 +0200 Subject: [PATCH 46/54] Refactor signalling for VersionAndOSReceived --- src/client.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index e82f945c99..08d3b3ba84 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -135,8 +135,6 @@ CClient::CClient ( const quint16 iPortNumber, QObject::connect ( &Channel, &CChannel::LicenceRequired, this, &CClient::LicenceRequired ); - QObject::connect ( &Channel, &CChannel::VersionAndOSReceived, this, &CClient::VersionAndOSReceived ); - QObject::connect ( &Channel, &CChannel::VersionAndOSReceived, this, &CClient::OnVersionAndOSReceived ); QObject::connect ( &Channel, &CChannel::RecorderStateReceived, this, &CClient::RecorderStateReceived ); @@ -420,7 +418,7 @@ void CClient::OnVersionAndOSReceived ( COSUtil::EOpSystemType eOSType, QString s Sound.Start(); } #endif - Q_UNUSED ( eOSType ); + emit VersionAndOSReceived( eOSType, strVersion ); } void CClient::CreateServerJitterBufferMessage() From 6243d592e386bf3dd7e1b8c39a87a8d9ca528f32 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Sun, 26 Apr 2026 16:41:20 +0200 Subject: [PATCH 47/54] Fix style, who would have thought... --- src/client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client.cpp b/src/client.cpp index 08d3b3ba84..a667ac4047 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -418,7 +418,7 @@ void CClient::OnVersionAndOSReceived ( COSUtil::EOpSystemType eOSType, QString s Sound.Start(); } #endif - emit VersionAndOSReceived( eOSType, strVersion ); + emit VersionAndOSReceived ( eOSType, strVersion ); } void CClient::CreateServerJitterBufferMessage() From b394701c31dc7dcd7d892b0617b967cec3ef235d Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Sun, 26 Apr 2026 17:47:03 +0200 Subject: [PATCH 48/54] Edit comments. Explain packet size calculation --- src/server.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/server.cpp b/src/server.cpp index 2c5431731c..330bae1f70 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -875,9 +875,15 @@ void CServer::DecodeReceiveData ( const int iChanCnt, const int iNumClients ) } const int iOffset = iB * SYSTEM_FRAME_SIZE_SAMPLES * vecNumAudioChannels[iChanCnt]; - // Recognise a raw audio packet by its size - // TODO: This should be done by prepending bytes to the packet to be identifiable as containing raw audio. - // This is just a placeholder. + // Recognise a raw audio packet by its size: + // The client doesn't pass a value for the selected audio quality implicitly. + // Rather the server is passed the length of the data sent by the client in iClientFrameSizeSamples. + // We know the exact size to expect from a client sending raw audio packets. + // The length is calculated in the client by: iNumAudioChannels * iOPUSFrameSizeSamples * sizeof ( int16_t ) + // iOPUSFrameSizeSamples can be either 64 or 128 (small network buffers enabled|disabled) + // iNumAudioChannels is either 1 for mono or 2 for stereo and mono-in/stereo-out + // sizeof ( int16_t ) is the size in bytes for the raw pcm audio data = 2 + // Sizes other than that are considered OPUS coded because those depend on hardcoded sizes in client.h const bool bIsRawAudio = ( iCeltNumCodedBytes == iClientFrameSizeSamples * vecNumAudioChannels[iChanCnt] * sizeof ( int16_t ) ); // get pointer to coded data From e5d822a68757e78704279d298ec07e31cd3db67c Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Sun, 26 Apr 2026 20:16:18 +0200 Subject: [PATCH 49/54] Fix latency calculation for raw audio --- src/client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client.cpp b/src/client.cpp index a667ac4047..bbbbb0bf36 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1616,7 +1616,7 @@ int CClient::EstimatedOverallDelay ( const int iPingTimeMs ) const float fDelayToFillNetworkPacketsMs = GetSystemMonoBlSize() * 1000.0f / SYSTEM_SAMPLE_RATE_HZ; // OPUS additional delay at small frame sizes is half a frame size - const float fAdditionalAudioCodecDelayMs = fSystemBlockDurationMs / 2; + const float fAdditionalAudioCodecDelayMs = ( !bRawAudioIsSupported ) ? fSystemBlockDurationMs / 2 : 0; const float fTotalBufferDelayMs = fDelayToFillNetworkPacketsMs + fTotalJitterBufferDelayMs + fTotalSoundCardDelayMs + fAdditionalAudioCodecDelayMs; From c8a4adc7bed6ef76ce0b336b141fc8cdd03feaa3 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Sun, 26 Apr 2026 20:34:55 +0200 Subject: [PATCH 50/54] Really fix latency calculation --- src/client.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client.cpp b/src/client.cpp index bbbbb0bf36..c606ec2239 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1616,7 +1616,7 @@ int CClient::EstimatedOverallDelay ( const int iPingTimeMs ) const float fDelayToFillNetworkPacketsMs = GetSystemMonoBlSize() * 1000.0f / SYSTEM_SAMPLE_RATE_HZ; // OPUS additional delay at small frame sizes is half a frame size - const float fAdditionalAudioCodecDelayMs = ( !bRawAudioIsSupported ) ? fSystemBlockDurationMs / 2 : 0; + const float fAdditionalAudioCodecDelayMs = ( eAudioQuality == AQ_RAW && bRawAudioIsSupported ) ? 0.0f : fSystemBlockDurationMs / 2; const float fTotalBufferDelayMs = fDelayToFillNetworkPacketsMs + fTotalJitterBufferDelayMs + fTotalSoundCardDelayMs + fAdditionalAudioCodecDelayMs; From 8691f1fa139c52d6c693925f2056bda9ef66e834 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Sun, 26 Apr 2026 21:38:25 +0200 Subject: [PATCH 51/54] Initialise bRawAudioIsSupported in correct order --- src/client.cpp | 3 ++- src/client.h | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index c606ec2239..c6a4b82496 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -70,7 +70,8 @@ CClient::CClient ( const quint16 iPortNumber, bJitterBufferOK ( true ), bEnableIPv6 ( bNEnableIPv6 ), bMuteMeInPersonalMix ( bNMuteMeInPersonalMix ), - iServerSockBufNumFrames ( DEF_NET_BUF_SIZE_NUM_BL ) + iServerSockBufNumFrames ( DEF_NET_BUF_SIZE_NUM_BL ), + bRawAudioIsSupported ( false ) { int iOpusError; diff --git a/src/client.h b/src/client.h index dce919c675..984d5947d0 100644 --- a/src/client.h +++ b/src/client.h @@ -403,7 +403,6 @@ class CClient : public QObject EMeterStyle eMeterStyle; bool bEnableAudioAlerts; bool bEnableOPUS64; - bool bRawAudioIsSupported; bool bJitterBufferOK; bool bEnableIPv6; @@ -411,7 +410,8 @@ class CClient : public QObject QMutex MutexDriverReinit; // server settings - int iServerSockBufNumFrames; + int iServerSockBufNumFrames; + bool bRawAudioIsSupported; // for ping measurement QElapsedTimer PreciseTime; From 6e233aca44e9782e3704d21606e675e2b80136b1 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Sun, 26 Apr 2026 21:46:57 +0200 Subject: [PATCH 52/54] fix compiler warnings --- src/server.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/server.cpp b/src/server.cpp index 330bae1f70..0c1e3cac01 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -884,7 +884,7 @@ void CServer::DecodeReceiveData ( const int iChanCnt, const int iNumClients ) // iNumAudioChannels is either 1 for mono or 2 for stereo and mono-in/stereo-out // sizeof ( int16_t ) is the size in bytes for the raw pcm audio data = 2 // Sizes other than that are considered OPUS coded because those depend on hardcoded sizes in client.h - const bool bIsRawAudio = ( iCeltNumCodedBytes == iClientFrameSizeSamples * vecNumAudioChannels[iChanCnt] * sizeof ( int16_t ) ); + const bool bIsRawAudio = ( iCeltNumCodedBytes == static_cast ( iClientFrameSizeSamples * vecNumAudioChannels[iChanCnt] * sizeof ( int16_t ) ) ); // get pointer to coded data if ( eGetStat == GS_BUFFER_OK ) @@ -1175,7 +1175,7 @@ void CServer::MixEncodeTransmitData ( const int iChanCnt, const int iNumClients DoubleFrameSizeConvBufOut[iCurChanID].GetAll ( vecsSendData, DOUBLE_SYSTEM_FRAME_SIZE_SAMPLES * vecNumAudioChannels[iChanCnt] ); } - if ( iCeltNumCodedBytes != iClientFrameSizeSamples * vecNumAudioChannels[iChanCnt] * sizeof ( int16_t ) ) + if ( iCeltNumCodedBytes != static_cast ( iClientFrameSizeSamples * vecNumAudioChannels[iChanCnt] * sizeof ( int16_t ) ) ) { // OPUS encoding if ( pCurOpusEncoder != nullptr ) From 3f059b34aad08db9c989ab06695da1a873a00c08 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Sun, 26 Apr 2026 22:12:49 +0200 Subject: [PATCH 53/54] Fix style (tough one...) --- src/server.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/server.cpp b/src/server.cpp index 0c1e3cac01..28ed05263c 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -884,7 +884,8 @@ void CServer::DecodeReceiveData ( const int iChanCnt, const int iNumClients ) // iNumAudioChannels is either 1 for mono or 2 for stereo and mono-in/stereo-out // sizeof ( int16_t ) is the size in bytes for the raw pcm audio data = 2 // Sizes other than that are considered OPUS coded because those depend on hardcoded sizes in client.h - const bool bIsRawAudio = ( iCeltNumCodedBytes == static_cast ( iClientFrameSizeSamples * vecNumAudioChannels[iChanCnt] * sizeof ( int16_t ) ) ); + const bool bIsRawAudio = + ( iCeltNumCodedBytes == static_cast ( iClientFrameSizeSamples * vecNumAudioChannels[iChanCnt] * sizeof ( int16_t ) ) ); // get pointer to coded data if ( eGetStat == GS_BUFFER_OK ) From ca1b74f44d9f0f407b1529f31a5d3ece485342e4 Mon Sep 17 00:00:00 2001 From: Nils Brederlow <62596379+dingodoppelt@users.noreply.github.com> Date: Thu, 30 Apr 2026 10:48:12 +0200 Subject: [PATCH 54/54] Fix issue with internal buffering for clients and servers with different settings for small network buffers --- src/server.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/server.cpp b/src/server.cpp index 28ed05263c..a2d0e329e5 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1197,6 +1197,9 @@ void CServer::MixEncodeTransmitData ( const int iChanCnt, const int iNumClients iClientFrameSizeSamples, &vecvecbyCodedData[iChanCnt][0], iCeltNumCodedBytes ); + + // send separate mix to current clients + vecChannels[iCurChanID].PrepAndSendPacket ( &Socket, vecvecbyCodedData[iChanCnt], iCeltNumCodedBytes ); } } } @@ -1207,10 +1210,11 @@ void CServer::MixEncodeTransmitData ( const int iChanCnt, const int iNumClients const int iOffset = iB * SYSTEM_FRAME_SIZE_SAMPLES * vecNumAudioChannels[iChanCnt]; memcpy ( &vecvecbyCodedData[iChanCnt][0], &vecsSendData[iOffset], iCeltNumCodedBytes ); + + // send separate mix to current clients + vecChannels[iCurChanID].PrepAndSendPacket ( &Socket, vecvecbyCodedData[iChanCnt], iCeltNumCodedBytes ); } } - // send separate mix to current clients - vecChannels[iCurChanID].PrepAndSendPacket ( &Socket, vecvecbyCodedData[iChanCnt], iCeltNumCodedBytes ); } Q_UNUSED ( iUnused )