Rawaudio dev#3653
Conversation
…s on audio quality
|
I'd prefer not to check for the Jamulus version number but rather based on capabilities - we don't have 4.0.0 out yet and it might break during the dev process. |
I wanted to reuse information already available as much as possible so I just added the code where there were version checks already implemented. (For sequence number and pan feature) |
|
Tested it and yes, the noise would be unacceptable. What is our fallback if max is selected but the server doesn't support it? |
I just noticed that if you connect to a server with Max selected you get the noise unless you switch audio quality again while connected. The server code is fine and doesn't need changes, I misplaced the check for my introduced bRawAudioSupported in the client code. I'll have a closer look |
Yes, it seems so. I've just done some tests with Wireshark capturing the traffic between a client and a server running without
I have saved the Wireshark captures, but not yet examined them. |
|
I asked VSCode CoPilot: Likely cause identified: a packet-send regression in server mix/encode on this branch. The server can require two sub-blocks per client frame when server runs without fastupdate (128-sample server frame) and a client is on small buffers (64-sample transport). That is set here: server.cpp:771. It is triggered specifically by non-fastupdate server mode (128-frame server path) with 64-frame clients. It supplied this patch @@
- if ( iCeltNumCodedBytes != static_cast<int> ( iClientFrameSizeSamples * vecNumAudioChannels[iChanCnt] * sizeof ( int16_t ) ) )
+ if ( iCeltNumCodedBytes != static_cast<int> ( iClientFrameSizeSamples * vecNumAudioChannels[iChanCnt] * sizeof ( int16_t ) ) )
{
// OPUS encoding
if ( pCurOpusEncoder != nullptr )
{
@@
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 each encoded sub-block (important when vecNumFrameSizeConvBlocks == 2)
+ 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];
memcpy ( &vecvecbyCodedData[iChanCnt][0], &vecsSendData[iOffset], iCeltNumCodedBytes );
+
+ // send each raw sub-block (important when vecNumFrameSizeConvBlocks == 2)
+ vecChannels[iCurChanID].PrepAndSendPacket ( &Socket, vecvecbyCodedData[iChanCnt], iCeltNumCodedBytes );
}
}
- // send separate mix to current clients
- vecChannels[iCurChanID].PrepAndSendPacket ( &Socket, vecvecbyCodedData[iChanCnt], iCeltNumCodedBytes );My fault for saying put the PrepAndSendPacket outside the |
|
Wow, that's impressive! I haven't tried copilot yet. Although I can't see what is different between the two versions of the first line? I'll try the patch a little later and repeat my tests. |
…ent settings for small network buffers
|
I can confirm the issue being fixed with the last commit in which I applied the suggested patch. (actually a revert) |
|
Yes, I can confirm the problem with small buffers enabled connected to a server without Finally understood that the only difference between having |
|
Furthermore I can't reproduce the crash on closing anymore. On linux I was getting crashes very rarely in the first place but I could trigger it by connecting to a server with |
softins
left a comment
There was a problem hiding this comment.
Fixes for the CodeQL warnings
Thanks @softins Co-authored-by: Tony Mountifield <tony@mountifield.org>
Applied! Thank you very much for the suggestions @softins |
|
|
||
| opus_custom_encoder_ctl ( CurOpusEncoder, | ||
| OPUS_SET_BITRATE ( CalcBitRateBitsPerSecFromCodedBytes ( iCeltNumCodedBytes, iOPUSFrameSizeSamples ) ) ); | ||
| if ( !bRawAudioIsSupported ) |
There was a problem hiding this comment.
Shouldn't this happen only if AQ_RAW is also selected? Or is bRawAudioIsSupported never true in that case?
(I mean, if AQ_RAW is not selected, bRawAudioIsSupported shouldn't matter, the control setting should be done. Like line 1468.)
| { | ||
| pCurCodedData = &vecbyNetwData[0]; | ||
| } | ||
| // on any valid received packet, we clear the initialization phase flag |
There was a problem hiding this comment.
Keep the blank lines before the comments to make them more visibly related to the line(s) below, please.
|
|
||
| // OPUS decoding | ||
| if ( CurOpusDecoder != nullptr ) | ||
| if ( ( eAudioQuality != AQ_RAW || !bRawAudioIsSupported ) && CurOpusDecoder != nullptr ) |
There was a problem hiding this comment.
Will CurOpusDecoder != nullptr be true any time other than when ( eAudioQuality != AQ_RAW || !bRawAudioIsSupported ) is true? That is, isn't the first part redundant? If not, maybe it should be.
| if ( bIsRawAudio ) | ||
| { | ||
| memcpy ( &vecvecsData[iChanCnt][iOffset], &vecvecbyCodedData[iChanCnt][0], iCeltNumCodedBytes ); | ||
| pCurCodedData = nullptr; |
There was a problem hiding this comment.
Maybe set this outside the if so it's _definitely nullptr unless eGetStat == GS_BUFFER_OK and not bIsRawAudio. Essentially, it would mean moving (new) lines 909-910 to after (new) line 889.
|
|
||
| // OPUS decode received data stream | ||
| if ( CurOpusDecoder != nullptr ) | ||
| if ( !bIsRawAudio && CurOpusDecoder != nullptr ) |
There was a problem hiding this comment.
Again, the !bIsRawAudio should be redundant.
| } | ||
|
|
||
| // OPUS encoding | ||
| if ( pCurOpusEncoder != nullptr ) |
There was a problem hiding this comment.
So why can't this check be relied on here, like it has been elsewhere?
| // length. Since that is usually not the case but the buffers are usually | ||
| // a bit larger than necessary, we introduce some factor for compensation. | ||
| // Consider the jitter buffer on the client and on the server side, too. | ||
| const float fTotalJitterBufferDelayMs = fSystemBlockDurationMs * ( GetSockBufNumFrames() + GetServerSockBufNumFrames() ) * 0.7f; |
There was a problem hiding this comment.
I'd like that 0.7f moved to global.h and documented, really... It should tie in with the Auto-Jitter sizing calculation, rather than being separately hard-coded here.

Add a new "raw" audio quality setting
This PR adds uncompressed audio ("raw") to the quality settings so there is no Opus compression along the way
Discussion in #3654
This feature improves latency as well. I gained 2ms by using uncompressed audio while having a better audio quality.
CHANGELOG: Add uncompressed audio transmission - dedicated to the memory of Hans Petter Selasky (1982 - 2023)
Does this change need documentation? What needs to be documented and how?
Corresponding PR in jamulussoftware/jamuluswebsite #1133
Checklist