finally getting all the subframes correctly
This commit is contained in:
parent
009962f120
commit
718284e7dd
157
extension.cpp
157
extension.cpp
@ -1236,8 +1236,8 @@ void CVoice::PushPlayerVoiceData(int playerSlot, int nBytes, char *data)
|
||||
const unsigned char *p = (const unsigned char *)data;
|
||||
|
||||
/*
|
||||
int dumpLen = nBytes < 24 ? nBytes : 24;
|
||||
char hexBuf[24 * 3 + 1];
|
||||
int dumpLen = nBytes;
|
||||
char hexBuf[dumpLen * 3 + 1];
|
||||
int pos = 0;
|
||||
for (int i = 0; i < dumpLen; i++)
|
||||
{
|
||||
@ -1247,7 +1247,7 @@ void CVoice::PushPlayerVoiceData(int playerSlot, int nBytes, char *data)
|
||||
hexBuf[pos++] = ' ';
|
||||
}
|
||||
hexBuf[pos] = '\0';
|
||||
smutils->LogMessage(myself, "[INBOUND STEAM] nBytes=%d, First bytes: %s", nBytes, hexBuf);
|
||||
smutils->LogMessage(myself, "[INBOUND STEAM] nBytes=%d, hexBuf: %s", nBytes, hexBuf);
|
||||
*/
|
||||
|
||||
uint16_t totalDataLength;
|
||||
@ -1262,107 +1262,74 @@ void CVoice::PushPlayerVoiceData(int playerSlot, int nBytes, char *data)
|
||||
|
||||
int offset = 14;
|
||||
int end = 14 + (int)totalDataLength;
|
||||
/*
|
||||
subframe header layout
|
||||
0: payload_size EXCLUDING this 4-byte header
|
||||
1: 0x00
|
||||
2: sequence_number
|
||||
3: 0x00
|
||||
4: 0x68 (TOC)
|
||||
*/
|
||||
//frame 1 always starts at offset 18.
|
||||
int MaxFrames = 16;
|
||||
int16_t pcmFrameBuffer[480 * MaxFrames];
|
||||
int totalDecodedSamples = 0;
|
||||
|
||||
if (offset + 4 <= end)
|
||||
while (offset + 4 <= end)
|
||||
{
|
||||
uint16_t trueAudioPayloadLen;
|
||||
memcpy(&trueAudioPayloadLen, p + 12, sizeof(uint16_t));
|
||||
|
||||
// Frame 1 always starts exactly at offset 18
|
||||
int frame1Start = 18;
|
||||
if (frame1Start >= end) return;
|
||||
|
||||
const unsigned char *frame1Ptr = p + frame1Start;
|
||||
|
||||
// Find the start of Frame 2 by scanning for the next 0x68 TOC marker
|
||||
int frame2Start = -1;
|
||||
|
||||
// A standard 24kHz Opus frame will practically never be shorter than 30 bytes
|
||||
for (int i = frame1Start + 30; i < end - 4; i++)
|
||||
{
|
||||
if (p[i] == 0x68) //TOC -> 0x68
|
||||
{
|
||||
// Verify if this is the start of Frame 2
|
||||
frame2Start = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int16_t pcmFrameBuffer[960];
|
||||
int totalDecodedSamples = 0;
|
||||
|
||||
// Calculate explicit size for Frame 1
|
||||
int frame1Size = (frame2Start != -1) ? (frame2Start - frame1Start) : (end - frame1Start);
|
||||
|
||||
if (frame1Size > 0)
|
||||
{
|
||||
//smutils->LogMessage(myself, "[VOICE-FIX] Frame 1 Determined Size: %d bytes. TOC: 0x%02X", frame1Size, frame1Ptr[0]);
|
||||
int FrameOffset = offset + 4; //we are now standing on TOC
|
||||
int FrameSize = p[offset]; //payload size
|
||||
|
||||
int samples1 = opus_decode(m_PlayerOpusDecoder[playerSlot],
|
||||
frame1Ptr, frame1Size,
|
||||
&pcmFrameBuffer[0], 480, 0);
|
||||
|
||||
if (samples1 > 0) totalDecodedSamples += samples1;
|
||||
}
|
||||
|
||||
// Process Frame 2 if a second TOC marker was identified
|
||||
if (frame2Start != -1)
|
||||
int samples = opus_decode(m_PlayerOpusDecoder[playerSlot],
|
||||
&p[FrameOffset], FrameSize,
|
||||
&pcmFrameBuffer[totalDecodedSamples], 480, 0);
|
||||
if (samples > 0)
|
||||
{
|
||||
const unsigned char *frame2Ptr = p + frame2Start;
|
||||
int frame2Size = end - frame2Start; // Frame 2 spans to the end of the payload buffer
|
||||
totalDecodedSamples += samples;
|
||||
}
|
||||
//moving to next subframe
|
||||
offset = FrameOffset + FrameSize;
|
||||
}
|
||||
|
||||
if (frame2Size > 0)
|
||||
int16_t resampledFrameBuffer[480 * MaxFrames];
|
||||
int totalResampledSamples = 0;
|
||||
|
||||
//obviously the resampling here is AI code. i dont actually know how to resample
|
||||
if (totalDecodedSamples > 0)
|
||||
{
|
||||
// The exact conversion ratio factor is 147 / 160
|
||||
// 480 samples at 24kHz converts precisely into 441 samples at 22.05kHz
|
||||
// 960 samples (2 frames) converts precisely into 882 samples
|
||||
totalResampledSamples = (totalDecodedSamples * 147) / 160;
|
||||
|
||||
for (int i = 0; i < totalResampledSamples; i++)
|
||||
{
|
||||
// Determine where this output sample lands on the input timeline
|
||||
double srcPosition = (double)i * 160.0 / 147.0;
|
||||
int srcIndex = (int)srcPosition;
|
||||
double fraction = srcPosition - (double)srcIndex;
|
||||
|
||||
if (srcIndex + 1 < totalDecodedSamples)
|
||||
{
|
||||
//smutils->LogMessage(myself, "[VOICE-FIX] Frame 2 Determined Size: %d bytes. TOC: 0x%02X", frame2Size, frame2Ptr[0]);
|
||||
|
||||
int samples2 = opus_decode(m_PlayerOpusDecoder[playerSlot],
|
||||
frame2Ptr, frame2Size,
|
||||
&pcmFrameBuffer[totalDecodedSamples], 480, 0);
|
||||
|
||||
if (samples2 > 0) totalDecodedSamples += samples2;
|
||||
// Linear interpolate between the two closest matching input samples
|
||||
int16_t sampleA = pcmFrameBuffer[srcIndex];
|
||||
int16_t sampleB = pcmFrameBuffer[srcIndex + 1];
|
||||
resampledFrameBuffer[i] = (int16_t)(sampleA + fraction * (sampleB - sampleA));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Handle boundary edge case for the final trailing sample
|
||||
resampledFrameBuffer[i] = pcmFrameBuffer[srcIndex];
|
||||
}
|
||||
}
|
||||
|
||||
int16_t resampledFrameBuffer[960];
|
||||
int totalResampledSamples = 0;
|
||||
|
||||
if (totalDecodedSamples > 0)
|
||||
}
|
||||
if (totalResampledSamples > 0)
|
||||
{
|
||||
size_t freeSpace = m_playerVoiceBuffer[playerSlot].CurrentFree();
|
||||
if ((size_t)totalResampledSamples <= freeSpace)
|
||||
{
|
||||
// The exact conversion ratio factor is 147 / 160
|
||||
// 480 samples at 24kHz converts precisely into 441 samples at 22.05kHz
|
||||
// 960 samples (2 frames) converts precisely into 882 samples
|
||||
totalResampledSamples = (totalDecodedSamples * 147) / 160;
|
||||
|
||||
for (int i = 0; i < totalResampledSamples; i++)
|
||||
{
|
||||
// Determine where this output sample lands on the input timeline
|
||||
double srcPosition = (double)i * 160.0 / 147.0;
|
||||
int srcIndex = (int)srcPosition;
|
||||
double fraction = srcPosition - (double)srcIndex;
|
||||
|
||||
if (srcIndex + 1 < totalDecodedSamples)
|
||||
{
|
||||
// Linear interpolate between the two closest matching input samples
|
||||
int16_t sampleA = pcmFrameBuffer[srcIndex];
|
||||
int16_t sampleB = pcmFrameBuffer[srcIndex + 1];
|
||||
resampledFrameBuffer[i] = (int16_t)(sampleA + fraction * (sampleB - sampleA));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Handle boundary edge case for the final trailing sample
|
||||
resampledFrameBuffer[i] = pcmFrameBuffer[srcIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
// --- PUSH SOUND TIMELINES SEQUENTIALLY ---
|
||||
if (totalResampledSamples > 0)
|
||||
{
|
||||
size_t freeSpace = m_playerVoiceBuffer[playerSlot].CurrentFree();
|
||||
if ((size_t)totalResampledSamples <= freeSpace)
|
||||
{
|
||||
// Push the perfectly timed 22050Hz stream to the CELT ring buffer
|
||||
m_playerVoiceBuffer[playerSlot].Push(resampledFrameBuffer, totalResampledSamples);
|
||||
}
|
||||
// Push the timed 22050Hz stream to the CELT ring buffer
|
||||
m_playerVoiceBuffer[playerSlot].Push(resampledFrameBuffer, totalResampledSamples);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user