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_nosteamResampleAccum, 0, sizeof(m_nosteamResampleAccum));
|
||||||
memset(m_nosteamAvailableTime, 0, sizeof(m_nosteamAvailableTime));
|
memset(m_nosteamAvailableTime, 0, sizeof(m_nosteamAvailableTime));
|
||||||
for (int i = 0; i <= SM_MAXPLAYERS; i++)
|
for (int i = 0; i <= SM_MAXPLAYERS; i++)
|
||||||
|
{
|
||||||
m_nosteamOpusEncoder[i] = NULL;
|
m_nosteamOpusEncoder[i] = NULL;
|
||||||
|
m_nosteamLastSample[i] = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CVoice::SDK_OnLoad(char *error, size_t maxlength, bool late)
|
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));
|
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];
|
int16_t pcmBuf[512];
|
||||||
int decoded = celt_decode(m_pCeltDecoder[playerSlot],
|
int decoded = celt_decode(m_pCeltDecoder[playerSlot],
|
||||||
(const unsigned char *)data, nBytes,
|
(const unsigned char *)data, nBytes,
|
||||||
@ -1384,6 +1415,76 @@ void CVoice::TranscodeNoSteamToSteam(int playerSlot, int nBytes, char *data)
|
|||||||
return;
|
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
|
// Resample 22050 -> 24000 and push into ring buffer
|
||||||
const int STEP = 24000;
|
const int STEP = 24000;
|
||||||
const int DIV = 22050;
|
const int DIV = 22050;
|
||||||
@ -1399,6 +1500,7 @@ void CVoice::TranscodeNoSteamToSteam(int playerSlot, int nBytes, char *data)
|
|||||||
m_nosteamOpusPCMBuffer[playerSlot].Push(&sample, 1);
|
m_nosteamOpusPCMBuffer[playerSlot].Push(&sample, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void CVoice::HandleNoSteamVoiceData()
|
void CVoice::HandleNoSteamVoiceData()
|
||||||
@ -1456,7 +1558,8 @@ void CVoice::HandleNoSteamVoiceData()
|
|||||||
size_t subframeStart = FinalSize;
|
size_t subframeStart = FinalSize;
|
||||||
int framesEmitted = 0;
|
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];
|
int16_t opusInput[480];
|
||||||
if (!m_nosteamOpusPCMBuffer[playerSlot].Pop(opusInput, 480))
|
if (!m_nosteamOpusPCMBuffer[playerSlot].Pop(opusInput, 480))
|
||||||
|
|||||||
@ -181,6 +181,7 @@ private:
|
|||||||
CRingBuffer m_nosteamOpusPCMBuffer[SM_MAXPLAYERS + 1];
|
CRingBuffer m_nosteamOpusPCMBuffer[SM_MAXPLAYERS + 1];
|
||||||
int m_nosteamResampleAccum[SM_MAXPLAYERS + 1];
|
int m_nosteamResampleAccum[SM_MAXPLAYERS + 1];
|
||||||
OpusEncoder *m_nosteamOpusEncoder[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)
|
// CELT encoder (shared by both paths, same output format)
|
||||||
struct CEncoderSettings
|
struct CEncoderSettings
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user