just redid sampling a bit
This commit is contained in:
parent
ddad8421e7
commit
37c1a4d1b6
105
extension.cpp
105
extension.cpp
@ -320,7 +320,10 @@ CVoice::CVoice()
|
||||
memset(m_nosteamResampleAccum, 0, sizeof(m_nosteamResampleAccum));
|
||||
memset(m_nosteamAvailableTime, 0, sizeof(m_nosteamAvailableTime));
|
||||
for (int i = 0; i <= SM_MAXPLAYERS; i++)
|
||||
{
|
||||
m_nosteamOpusEncoder[i] = NULL;
|
||||
m_nosteamLastSample[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool CVoice::SDK_OnLoad(char *error, size_t maxlength, bool late)
|
||||
@ -1374,6 +1377,34 @@ void CVoice::TranscodeNoSteamToSteam(int playerSlot, int nBytes, char *data)
|
||||
opus_encoder_ctl(m_nosteamOpusEncoder[playerSlot], OPUS_SET_SIGNAL(OPUS_SIGNAL_VOICE));
|
||||
}
|
||||
|
||||
|
||||
// Get current engine time
|
||||
double now = (double)gpGlobals->curtime;
|
||||
double timeSinceLastVoice = now - g_fLastVoiceData[playerSlot + 1];
|
||||
|
||||
if (timeSinceLastVoice > 0.5 && g_fLastVoiceData[playerSlot + 1] != 0.0)
|
||||
{
|
||||
// Clear out stale states
|
||||
if (m_nosteamOpusEncoder[playerSlot])
|
||||
opus_encoder_ctl(m_nosteamOpusEncoder[playerSlot], OPUS_RESET_STATE);
|
||||
if (m_pCeltDecoder[playerSlot])
|
||||
celt_decoder_ctl(m_pCeltDecoder[playerSlot], CELT_RESET_STATE_REQUEST, NULL);
|
||||
|
||||
// Flush the PCM ringbuffer completely
|
||||
while(m_nosteamOpusPCMBuffer[playerSlot].TotalLength() > 0)
|
||||
{
|
||||
int16_t trash[480];
|
||||
size_t toPop = m_nosteamOpusPCMBuffer[playerSlot].TotalLength() > 480 ? 480 : m_nosteamOpusPCMBuffer[playerSlot].TotalLength();
|
||||
m_nosteamOpusPCMBuffer[playerSlot].Pop(trash, toPop);
|
||||
}
|
||||
m_nosteamResampleAccum[playerSlot] = 0;
|
||||
}
|
||||
|
||||
// Mark current arrival time
|
||||
g_fLastVoiceData[playerSlot + 1] = now;
|
||||
|
||||
|
||||
|
||||
int16_t pcmBuf[512];
|
||||
int decoded = celt_decode(m_pCeltDecoder[playerSlot],
|
||||
(const unsigned char *)data, nBytes,
|
||||
@ -1384,6 +1415,76 @@ void CVoice::TranscodeNoSteamToSteam(int playerSlot, int nBytes, char *data)
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// 1. Prepare a temporary buffer for the resampled frame
|
||||
// Max output can be roughly ceil(decoded * 24000 / 22050) + 2. Allocate plenty of room.
|
||||
int16_t resampledFrameBuffer[2048];
|
||||
int totalResampledSamples = 0;
|
||||
|
||||
const int STEP = 24000;
|
||||
const int DIV = 22050;
|
||||
|
||||
// Track the previous sample for linear interpolation (Keep this in your class or use a player state!)
|
||||
// For local tracking inside the block, we can fall back to 0 if i == 0, but ideally
|
||||
// track m_nosteamLastSample[playerSlot] persistently across packets.
|
||||
int16_t lastSample = m_nosteamLastSample[playerSlot];
|
||||
|
||||
for (int i = 0; i < decoded; i++)
|
||||
{
|
||||
int16_t currentSample = pcmBuf[i];
|
||||
|
||||
m_nosteamResampleAccum[playerSlot] += STEP;
|
||||
while (m_nosteamResampleAccum[playerSlot] >= DIV)
|
||||
{
|
||||
// Calculate how far between lastSample and currentSample this new sample lands.
|
||||
// We use the remaining fractional value in the accumulator.
|
||||
float fraction = (float)(DIV - (m_nosteamResampleAccum[playerSlot] - STEP)) / (float)STEP;
|
||||
if (fraction < 0.0f) fraction = 0.0f;
|
||||
if (fraction > 1.0f) fraction = 1.0f;
|
||||
|
||||
// Linearly blend the two points to eliminate stepping edge artifacts
|
||||
int16_t interpolatedSample = (int16_t)((1.0f - fraction) * lastSample + fraction * currentSample);
|
||||
|
||||
// Store into temporary buffer safely
|
||||
if (totalResampledSamples < 2048)
|
||||
{
|
||||
resampledFrameBuffer[totalResampledSamples++] = interpolatedSample;
|
||||
}
|
||||
|
||||
m_nosteamResampleAccum[playerSlot] -= DIV;
|
||||
}
|
||||
|
||||
lastSample = currentSample;
|
||||
}
|
||||
|
||||
// Save the last sample of this packet so the next incoming packet blends flawlessly
|
||||
m_nosteamLastSample[playerSlot] = lastSample;
|
||||
|
||||
// 2. Perform a single high-efficiency push into the ring buffer
|
||||
if (totalResampledSamples > 0)
|
||||
{
|
||||
if (m_nosteamOpusPCMBuffer[playerSlot].CurrentFree() >= (size_t)totalResampledSamples)
|
||||
{
|
||||
m_nosteamOpusPCMBuffer[playerSlot].Push(resampledFrameBuffer, totalResampledSamples);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
// Resample 22050 -> 24000 and push into ring buffer
|
||||
const int STEP = 24000;
|
||||
const int DIV = 22050;
|
||||
@ -1399,6 +1500,7 @@ void CVoice::TranscodeNoSteamToSteam(int playerSlot, int nBytes, char *data)
|
||||
m_nosteamOpusPCMBuffer[playerSlot].Push(&sample, 1);
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void CVoice::HandleNoSteamVoiceData()
|
||||
@ -1456,7 +1558,8 @@ void CVoice::HandleNoSteamVoiceData()
|
||||
size_t subframeStart = FinalSize;
|
||||
int framesEmitted = 0;
|
||||
|
||||
while (m_nosteamOpusPCMBuffer[playerSlot].TotalLength() >= 480)
|
||||
//while (m_nosteamOpusPCMBuffer[playerSlot].TotalLength() >= 480)
|
||||
while (m_nosteamOpusPCMBuffer[playerSlot].TotalLength() >= 480 && framesEmitted < 3)
|
||||
{
|
||||
int16_t opusInput[480];
|
||||
if (!m_nosteamOpusPCMBuffer[playerSlot].Pop(opusInput, 480))
|
||||
|
||||
@ -181,6 +181,7 @@ private:
|
||||
CRingBuffer m_nosteamOpusPCMBuffer[SM_MAXPLAYERS + 1];
|
||||
int m_nosteamResampleAccum[SM_MAXPLAYERS + 1];
|
||||
OpusEncoder *m_nosteamOpusEncoder[SM_MAXPLAYERS + 1];
|
||||
int16_t m_nosteamLastSample[SM_MAXPLAYERS + 1];
|
||||
|
||||
// CELT encoder (shared by both paths, same output format)
|
||||
struct CEncoderSettings
|
||||
|
||||
Loading…
Reference in New Issue
Block a user