@@ -70,7 +70,9 @@ CClient::CClient ( const quint16 iPortNumber,
7070 bJitterBufferOK ( true ),
7171 bEnableIPv6 ( bNEnableIPv6 ),
7272 bMuteMeInPersonalMix ( bNMuteMeInPersonalMix ),
73- iServerSockBufNumFrames ( DEF_NET_BUF_SIZE_NUM_BL )
73+ iServerSockBufNumFrames ( DEF_NET_BUF_SIZE_NUM_BL ),
74+ bRawAudioIsSupported ( false ),
75+ bUseRawAudio ( false )
7476{
7577 int iOpusError;
7678
@@ -135,7 +137,7 @@ CClient::CClient ( const quint16 iPortNumber,
135137
136138 QObject::connect ( &Channel, &CChannel::LicenceRequired, this , &CClient::LicenceRequired );
137139
138- QObject::connect ( &Channel, &CChannel::VersionAndOSReceived, this , &CClient::VersionAndOSReceived );
140+ QObject::connect ( &Channel, &CChannel::VersionAndOSReceived, this , &CClient::OnVersionAndOSReceived );
139141
140142 QObject::connect ( &Channel, &CChannel::RecorderStateReceived, this , &CClient::RecorderStateReceived );
141143
@@ -395,6 +397,32 @@ void CClient::OnConClientListMesReceived ( CVector<CChannelInfo> vecChanInfo )
395397 emit ConClientListMesReceived ( vecChanInfo );
396398}
397399
400+ void CClient::OnVersionAndOSReceived ( COSUtil::EOpSystemType eOSType, QString strVersion )
401+ {
402+ #if QT_VERSION >= QT_VERSION_CHECK( 5, 6, 0 )
403+ const bool bWasRunning = Sound.IsRunning ();
404+ if ( bWasRunning )
405+ {
406+ Sound.Stop ();
407+ }
408+ if ( QVersionNumber::compare ( QVersionNumber::fromString ( strVersion ), QVersionNumber ( 3 , 11 , 1 ) ) == 0 )
409+ {
410+ bRawAudioIsSupported = true ;
411+ Init ();
412+ }
413+ else
414+ {
415+ bRawAudioIsSupported = false ;
416+ Init ();
417+ }
418+ if ( bWasRunning )
419+ {
420+ Sound.Start ();
421+ }
422+ #endif
423+ emit VersionAndOSReceived ( eOSType, strVersion );
424+ }
425+
398426void CClient::CreateServerJitterBufferMessage ()
399427{
400428 // per definition in the client: if auto jitter buffer is enabled, both,
@@ -1017,6 +1045,11 @@ void CClient::Stop()
10171045 // disable channel
10181046 Channel.SetEnable ( false );
10191047
1048+ // Fall back to opus in case raw was used
1049+ bRawAudioIsSupported = false ;
1050+ bUseRawAudio = false ;
1051+ Init ();
1052+
10201053 // wait for approx. 100 ms to make sure no audio packet is still in the
10211054 // network queue causing the channel to be reconnected right after having
10221055 // received the disconnect message (seems not to gain much, disconnect is
@@ -1156,6 +1189,16 @@ void CClient::Init()
11561189 case AQ_HIGH :
11571190 iCeltNumCodedBytes = OPUS_NUM_BYTES_MONO_HIGH_QUALITY_DBLE_FRAMESIZE ;
11581191 break ;
1192+ case AQ_RAW :
1193+ if ( bRawAudioIsSupported && Channel.IsEnabled () )
1194+ {
1195+ iCeltNumCodedBytes = sizeof ( int16_t ) * iNumAudioChannels * iOPUSFrameSizeSamples;
1196+ }
1197+ else
1198+ {
1199+ iCeltNumCodedBytes = OPUS_NUM_BYTES_MONO_HIGH_QUALITY_DBLE_FRAMESIZE ;
1200+ }
1201+ break ;
11591202 }
11601203 }
11611204 else
@@ -1175,6 +1218,16 @@ void CClient::Init()
11751218 case AQ_HIGH :
11761219 iCeltNumCodedBytes = OPUS_NUM_BYTES_STEREO_HIGH_QUALITY_DBLE_FRAMESIZE ;
11771220 break ;
1221+ case AQ_RAW :
1222+ if ( bRawAudioIsSupported && Channel.IsEnabled () )
1223+ {
1224+ iCeltNumCodedBytes = sizeof ( int16_t ) * iNumAudioChannels * iOPUSFrameSizeSamples;
1225+ }
1226+ else
1227+ {
1228+ iCeltNumCodedBytes = OPUS_NUM_BYTES_STEREO_HIGH_QUALITY_DBLE_FRAMESIZE ;
1229+ }
1230+ break ;
11781231 }
11791232 }
11801233 }
@@ -1199,6 +1252,16 @@ void CClient::Init()
11991252 case AQ_HIGH :
12001253 iCeltNumCodedBytes = OPUS_NUM_BYTES_MONO_HIGH_QUALITY ;
12011254 break ;
1255+ case AQ_RAW :
1256+ if ( bRawAudioIsSupported && Channel.IsEnabled () )
1257+ {
1258+ iCeltNumCodedBytes = sizeof ( int16_t ) * iNumAudioChannels * iOPUSFrameSizeSamples;
1259+ }
1260+ else
1261+ {
1262+ iCeltNumCodedBytes = OPUS_NUM_BYTES_MONO_HIGH_QUALITY ;
1263+ }
1264+ break ;
12021265 }
12031266 }
12041267 else
@@ -1218,19 +1281,36 @@ void CClient::Init()
12181281 case AQ_HIGH :
12191282 iCeltNumCodedBytes = OPUS_NUM_BYTES_STEREO_HIGH_QUALITY ;
12201283 break ;
1284+ case AQ_RAW :
1285+ if ( bRawAudioIsSupported && Channel.IsEnabled () )
1286+ {
1287+ iCeltNumCodedBytes = sizeof ( int16_t ) * iNumAudioChannels * iOPUSFrameSizeSamples;
1288+ }
1289+ else
1290+ {
1291+ iCeltNumCodedBytes = OPUS_NUM_BYTES_STEREO_HIGH_QUALITY ;
1292+ }
1293+ break ;
12211294 }
12221295 }
12231296 }
12241297
1298+ // determine whether to use raw audio
1299+ bUseRawAudio = bRawAudioIsSupported && eAudioQuality == AQ_RAW ;
1300+
12251301 // calculate stereo (two channels) buffer size
12261302 iStereoBlockSizeSam = 2 * iMonoBlockSizeSam;
12271303
12281304 vecCeltData.Init ( iCeltNumCodedBytes );
12291305 vecZeros.Init ( iStereoBlockSizeSam, 0 );
12301306 vecsStereoSndCrdMuteStream.Init ( iStereoBlockSizeSam );
12311307
1232- opus_custom_encoder_ctl ( CurOpusEncoder,
1233- OPUS_SET_BITRATE ( CalcBitRateBitsPerSecFromCodedBytes ( iCeltNumCodedBytes, iOPUSFrameSizeSamples ) ) );
1308+ // In case we are connected to a non raw audio server or we don't use raw audio we need to initialze the codec
1309+ if ( !bUseRawAudio )
1310+ {
1311+ opus_custom_encoder_ctl ( CurOpusEncoder,
1312+ OPUS_SET_BITRATE ( CalcBitRateBitsPerSecFromCodedBytes ( iCeltNumCodedBytes, iOPUSFrameSizeSamples ) ) );
1313+ }
12341314
12351315 // inits for network and channel
12361316 vecbyNetwData.Init ( iCeltNumCodedBytes );
@@ -1391,19 +1471,33 @@ void CClient::ProcessAudioDataIntern ( CVector<int16_t>& vecsStereoSndCrd )
13911471
13921472 for ( i = 0 , j = 0 ; i < iSndCrdFrameSizeFactor; i++, j += iNumAudioChannels * iOPUSFrameSizeSamples )
13931473 {
1394- // OPUS encoding
1395- if ( CurOpusEncoder != nullptr )
1474+ if ( !bUseRawAudio )
1475+ {
1476+ // OPUS encoding
1477+ if ( CurOpusEncoder != nullptr )
1478+ {
1479+ if ( bMuteOutStream )
1480+ {
1481+ iUnused = opus_custom_encode ( CurOpusEncoder, &vecZeros[j], iOPUSFrameSizeSamples, &vecCeltData[0 ], iCeltNumCodedBytes );
1482+ }
1483+ else
1484+ {
1485+ iUnused = opus_custom_encode ( CurOpusEncoder, &vecsStereoSndCrd[j], iOPUSFrameSizeSamples, &vecCeltData[0 ], iCeltNumCodedBytes );
1486+ }
1487+ }
1488+ }
1489+ else
13961490 {
13971491 if ( bMuteOutStream )
13981492 {
1399- iUnused = opus_custom_encode ( CurOpusEncoder, &vecZeros[j ], iOPUSFrameSizeSamples, &vecCeltData[ 0 ] , iCeltNumCodedBytes );
1493+ memset ( &vecCeltData[ 0 ], 0 , iCeltNumCodedBytes );
14001494 }
14011495 else
14021496 {
1403- iUnused = opus_custom_encode ( CurOpusEncoder, &vecsStereoSndCrd[j], iOPUSFrameSizeSamples, &vecCeltData[0 ], iCeltNumCodedBytes );
1497+ // Send raw samples instead of OPUS
1498+ memcpy ( &vecCeltData[0 ], &vecsStereoSndCrd[j], iCeltNumCodedBytes );
14041499 }
14051500 }
1406-
14071501 // send coded audio through the network
14081502 Channel.PrepAndSendPacket ( &Socket, vecCeltData, iCeltNumCodedBytes );
14091503 }
@@ -1423,23 +1517,36 @@ void CClient::ProcessAudioDataIntern ( CVector<int16_t>& vecsStereoSndCrd )
14231517 // get pointer to coded data and manage the flags
14241518 if ( bReceiveDataOk )
14251519 {
1426- pCurCodedData = &vecbyNetwData[0 ];
1520+ if ( eAudioQuality == AQ_RAW && bRawAudioIsSupported )
1521+ {
1522+ memcpy ( &vecsStereoSndCrd[j], &vecbyNetwData[0 ], iCeltNumCodedBytes );
1523+ pCurCodedData = nullptr ;
1524+ }
1525+ else
1526+ {
1527+ pCurCodedData = &vecbyNetwData[0 ];
1528+ }
14271529
14281530 // on any valid received packet, we clear the initialization phase flag
14291531 bIsInitializationPhase = false ;
14301532 }
14311533 else
14321534 {
1535+ if ( eAudioQuality == AQ_RAW && bRawAudioIsSupported )
1536+ {
1537+ memset ( &vecsStereoSndCrd[j], 0 , iCeltNumCodedBytes );
1538+ }
1539+
14331540 // for lost packets use null pointer as coded input data
14341541 pCurCodedData = nullptr ;
14351542
14361543 // invalidate the buffer OK status flag
14371544 bJitterBufferOK = false ;
14381545 }
14391546
1440- // OPUS decoding
1441- if ( CurOpusDecoder != nullptr )
1547+ if ( !bUseRawAudio && CurOpusDecoder != nullptr )
14421548 {
1549+ // OPUS decoding
14431550 iUnused = opus_custom_decode ( CurOpusDecoder, pCurCodedData, iCeltNumCodedBytes, &vecsStereoSndCrd[j], iOPUSFrameSizeSamples );
14441551 }
14451552 }
@@ -1488,7 +1595,7 @@ int CClient::EstimatedOverallDelay ( const int iPingTimeMs )
14881595 // length. Since that is usually not the case but the buffers are usually
14891596 // a bit larger than necessary, we introduce some factor for compensation.
14901597 // Consider the jitter buffer on the client and on the server side, too.
1491- const float fTotalJitterBufferDelayMs = fSystemBlockDurationMs * ( GetSockBufNumFrames () + GetServerSockBufNumFrames () ) * 0 . 7f ;
1598+ const float fTotalJitterBufferDelayMs = fSystemBlockDurationMs * ( GetSockBufNumFrames () + GetServerSockBufNumFrames () ) * JITTBUF_COMP_FACTOR ;
14921599
14931600 // consider delay introduced by the sound card conversion buffer by using
14941601 // "GetSndCrdConvBufAdditionalDelayMonoBlSize()"
@@ -1519,7 +1626,7 @@ int CClient::EstimatedOverallDelay ( const int iPingTimeMs )
15191626 const float fDelayToFillNetworkPacketsMs = GetSystemMonoBlSize () * 1000 .0f / SYSTEM_SAMPLE_RATE_HZ ;
15201627
15211628 // OPUS additional delay at small frame sizes is half a frame size
1522- const float fAdditionalAudioCodecDelayMs = fSystemBlockDurationMs / 2 ;
1629+ const float fAdditionalAudioCodecDelayMs = ( eAudioQuality == AQ_RAW && bRawAudioIsSupported ) ? 0 . 0f : fSystemBlockDurationMs / 2 ;
15231630
15241631 const float fTotalBufferDelayMs =
15251632 fDelayToFillNetworkPacketsMs + fTotalJitterBufferDelayMs + fTotalSoundCardDelayMs + fAdditionalAudioCodecDelayMs ;
0 commit comments