further changes should probably be considered safed by now, switched to 2 channels, added reset state and lowered framepackets from 5 to 2

This commit is contained in:
jenz 2025-10-30 18:33:52 +00:00
parent fa34037aa4
commit b987a8207d

View File

@ -300,20 +300,20 @@ bool CVoice::SDK_OnLoad(char *error, size_t maxlength, bool late)
//opus edit //opus edit
int err; int err;
m_OpusEncoder = opus_encoder_create(48000, 1, OPUS_APPLICATION_AUDIO, &err); //m_OpusEncoder = opus_encoder_create(24000, 2, OPUS_APPLICATION_AUDIO, &err);
m_OpusEncoder = opus_encoder_create(48000, 2, OPUS_APPLICATION_AUDIO, &err);
if (err<0) if (err<0)
{ {
smutils->LogError(myself, "failed to create encode: %s", opus_strerror(err)); smutils->LogError(myself, "failed to create encode: %s", opus_strerror(err));
return false; return false;
} }
opus_encoder_ctl(m_OpusEncoder, OPUS_SET_BITRATE(512000)); opus_encoder_ctl(m_OpusEncoder, OPUS_SET_BITRATE(510000));
opus_encoder_ctl(m_OpusEncoder, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND)); opus_encoder_ctl(m_OpusEncoder, OPUS_SET_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND));
opus_encoder_ctl(m_OpusEncoder, OPUS_SET_MAX_BANDWIDTH(OPUS_BANDWIDTH_FULLBAND)); opus_encoder_ctl(m_OpusEncoder, OPUS_SET_SIGNAL(OPUS_SIGNAL_MUSIC)); //MDCT mode
opus_encoder_ctl(m_OpusEncoder, OPUS_SET_COMPLEXITY(10));
opus_encoder_ctl(m_OpusEncoder, OPUS_SET_SIGNAL(OPUS_SIGNAL_MUSIC));
opus_encoder_ctl(m_OpusEncoder, OPUS_SET_LSB_DEPTH(16)); opus_encoder_ctl(m_OpusEncoder, OPUS_SET_LSB_DEPTH(16));
opus_encoder_ctl(m_OpusEncoder, OPUS_SET_PACKET_LOSS_PERC(0));
opus_encoder_ctl(m_OpusEncoder, OPUS_SET_FORCE_CHANNELS(2));
if (err<0) if (err<0)
{ {
@ -501,7 +501,9 @@ bool CVoice::OnBroadcastVoiceData(IClient *pClient, int nBytes, char *data)
g_aFrameVoiceBytes[client] += 5 + nBytes; g_aFrameVoiceBytes[client] += 5 + nBytes;
if(g_aFrameVoiceBytes[client] > NET_MAX_VOICE_BYTES_FRAME) if(g_aFrameVoiceBytes[client] > NET_MAX_VOICE_BYTES_FRAME)
{
return false; return false;
}
g_fLastVoiceData[client] = gpGlobals->curtime; g_fLastVoiceData[client] = gpGlobals->curtime;
@ -687,36 +689,40 @@ void CVoice::OnDataReceived(CClient *pClient, int16_t *pData, size_t Samples)
pClient->m_LastValidData = getTime(); pClient->m_LastValidData = getTime();
} }
struct SteamVoiceHeader
{
uint32_t iSteamAccountID : 32;
uint32_t iSteamCommunity : 32;
uint32_t nPayload1 : 8;
uint32_t iSampleRate : 16;
uint32_t nPayload2 : 8;
uint32_t iDataLength : 16;
};
void CVoice::HandleVoiceData() void CVoice::HandleVoiceData()
{ {
const int SampleRate = 48000; //uint32_t sampleRate = 24000;
uint32_t sampleRate = 48000;
const int SamplesPerChannel = 480; const int SamplesPerChannel = 480;
const int Channels = 1; const int Channels = 2;
int TotalSamplesPerFrame = SamplesPerChannel * Channels; int TotalSamplesPerFrame = SamplesPerChannel * Channels;
int FramesAvailable = m_Buffer.TotalLength() / TotalSamplesPerFrame; int FramesAvailable = m_Buffer.TotalLength() / TotalSamplesPerFrame;
float TimeAvailable = (float)m_Buffer.TotalLength() / SampleRate;
if(!FramesAvailable) if(!FramesAvailable)
return; return;
if(m_AvailableTime < getTime() && TimeAvailable < 0.05)
return; int FramesMax = 2; //used to be 5
if(m_AvailableTime > getTime() + 0.02) bool reset_state = false;
return; if (FramesAvailable <= FramesMax)
{
reset_state = true;
}
FramesAvailable = min_ext(FramesAvailable, FramesMax);
// Allow less buffering after audio has started playing
if (m_Buffer.TotalLength() < TotalSamplesPerFrame) if (m_Buffer.TotalLength() < TotalSamplesPerFrame)
return; return;
FramesAvailable = min_ext(FramesAvailable, 5); float TimeAvailable = (float)m_Buffer.TotalLength() / sampleRate;
if(m_AvailableTime < getTime() && TimeAvailable < 0.2)
//if(m_AvailableTime < getTime() && TimeAvailable < 0.1)
return;
double maxBuffer = (m_AvailableTime < getTime()) ? 0.2 : 0.04;
//double maxBuffer = (m_AvailableTime < getTime()) ? 0.1 : 0.02;
if(m_AvailableTime > getTime() + maxBuffer)
return;
IClient *pClient = iserver->GetClient(0); IClient *pClient = iserver->GetClient(0);
if(!pClient) if(!pClient)
@ -738,8 +744,8 @@ void CVoice::HandleVoiceData()
// 3. Payload Type 11 (1 byte) // 3. Payload Type 11 (1 byte)
aFinal[FinalSize++] = 0x0B; aFinal[FinalSize++] = 0x0B;
// 4. Sample Rate (2 bytes little-endian) // 4. Sample Rate (2 bytes little-endian)
uint16_t sampleRate = 48000;
memcpy(&aFinal[FinalSize], &sampleRate, sizeof(uint16_t)); memcpy(&aFinal[FinalSize], &sampleRate, sizeof(uint16_t));
FinalSize += sizeof(uint16_t); FinalSize += sizeof(uint16_t);
@ -756,6 +762,10 @@ void CVoice::HandleVoiceData()
{ {
int16_t aBuffer[TotalSamplesPerFrame]; int16_t aBuffer[TotalSamplesPerFrame];
size_t OldReadIdx = m_Buffer.m_ReadIndex;
size_t OldCurLength = m_Buffer.CurrentLength();
size_t OldTotalLength = m_Buffer.TotalLength();
if(!m_Buffer.Pop(aBuffer, TotalSamplesPerFrame)) if(!m_Buffer.Pop(aBuffer, TotalSamplesPerFrame))
{ {
smutils->LogError(myself, "Buffer pop failed!"); smutils->LogError(myself, "Buffer pop failed!");
@ -769,7 +779,6 @@ void CVoice::HandleVoiceData()
// Encode with Opus // Encode with Opus
int nbBytes = opus_encode(m_OpusEncoder, (const opus_int16*)aBuffer, SamplesPerChannel, int nbBytes = opus_encode(m_OpusEncoder, (const opus_int16*)aBuffer, SamplesPerChannel,
&aFinal[FinalSize], *pFrameSize); &aFinal[FinalSize], *pFrameSize);
if (nbBytes <= 1) if (nbBytes <= 1)
{ {
smutils->LogError(myself, "Opus encode failed: %s", opus_strerror(nbBytes)); smutils->LogError(myself, "Opus encode failed: %s", opus_strerror(nbBytes));
@ -780,6 +789,23 @@ void CVoice::HandleVoiceData()
*pFrameSize = (uint16_t)nbBytes; *pFrameSize = (uint16_t)nbBytes;
*pTotalDataLength += sizeof(uint16_t) + nbBytes; *pTotalDataLength += sizeof(uint16_t) + nbBytes;
FinalSize += nbBytes; FinalSize += nbBytes;
// Check for buffer underruns
for(int Client = 0; Client < MAX_CLIENTS; Client++)
{
CClient *pClient = &m_aClients[Client];
if(pClient->m_Socket == -1 || pClient->m_New == true)
continue;
m_Buffer.SetWriteIndex(pClient->m_BufferWriteIndex);
if(m_Buffer.CurrentLength() > pClient->m_LastLength)
{
pClient->m_BufferWriteIndex = m_Buffer.GetReadIndex();
m_Buffer.SetWriteIndex(pClient->m_BufferWriteIndex);
pClient->m_LastLength = m_Buffer.CurrentLength();
}
}
} }
// 8. Add CRC32 // 8. Add CRC32
@ -788,10 +814,16 @@ void CVoice::HandleVoiceData()
FinalSize += sizeof(uint32_t); FinalSize += sizeof(uint32_t);
BroadcastVoiceData(pClient, FinalSize, aFinal); BroadcastVoiceData(pClient, FinalSize, aFinal);
//smutils->LogMessage(myself, "FinalSize: %d", FinalSize);
if (m_AvailableTime < getTime()) if (m_AvailableTime < getTime())
m_AvailableTime = getTime(); m_AvailableTime = getTime();
m_AvailableTime += (double)FramesAvailable * 0.01; m_AvailableTime += (double)FramesAvailable * 0.01;
if (reset_state)
{
opus_encoder_ctl(m_OpusEncoder, OPUS_RESET_STATE);
}
} }
void CVoice::BroadcastVoiceData(IClient *pClient, int nBytes, unsigned char *pData) void CVoice::BroadcastVoiceData(IClient *pClient, int nBytes, unsigned char *pData)