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;
|
const unsigned char *p = (const unsigned char *)data;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
int dumpLen = nBytes < 24 ? nBytes : 24;
|
int dumpLen = nBytes;
|
||||||
char hexBuf[24 * 3 + 1];
|
char hexBuf[dumpLen * 3 + 1];
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
for (int i = 0; i < dumpLen; i++)
|
for (int i = 0; i < dumpLen; i++)
|
||||||
{
|
{
|
||||||
@ -1247,7 +1247,7 @@ void CVoice::PushPlayerVoiceData(int playerSlot, int nBytes, char *data)
|
|||||||
hexBuf[pos++] = ' ';
|
hexBuf[pos++] = ' ';
|
||||||
}
|
}
|
||||||
hexBuf[pos] = '\0';
|
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;
|
uint16_t totalDataLength;
|
||||||
@ -1262,107 +1262,74 @@ void CVoice::PushPlayerVoiceData(int playerSlot, int nBytes, char *data)
|
|||||||
|
|
||||||
int offset = 14;
|
int offset = 14;
|
||||||
int end = 14 + (int)totalDataLength;
|
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;
|
int FrameOffset = offset + 4; //we are now standing on TOC
|
||||||
memcpy(&trueAudioPayloadLen, p + 12, sizeof(uint16_t));
|
int FrameSize = p[offset]; //payload size
|
||||||
|
|
||||||
// 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 samples1 = opus_decode(m_PlayerOpusDecoder[playerSlot],
|
int samples = opus_decode(m_PlayerOpusDecoder[playerSlot],
|
||||||
frame1Ptr, frame1Size,
|
&p[FrameOffset], FrameSize,
|
||||||
&pcmFrameBuffer[0], 480, 0);
|
&pcmFrameBuffer[totalDecodedSamples], 480, 0);
|
||||||
|
if (samples > 0)
|
||||||
if (samples1 > 0) totalDecodedSamples += samples1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process Frame 2 if a second TOC marker was identified
|
|
||||||
if (frame2Start != -1)
|
|
||||||
{
|
{
|
||||||
const unsigned char *frame2Ptr = p + frame2Start;
|
totalDecodedSamples += samples;
|
||||||
int frame2Size = end - frame2Start; // Frame 2 spans to the end of the payload buffer
|
}
|
||||||
|
//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]);
|
// Linear interpolate between the two closest matching input samples
|
||||||
|
int16_t sampleA = pcmFrameBuffer[srcIndex];
|
||||||
int samples2 = opus_decode(m_PlayerOpusDecoder[playerSlot],
|
int16_t sampleB = pcmFrameBuffer[srcIndex + 1];
|
||||||
frame2Ptr, frame2Size,
|
resampledFrameBuffer[i] = (int16_t)(sampleA + fraction * (sampleB - sampleA));
|
||||||
&pcmFrameBuffer[totalDecodedSamples], 480, 0);
|
}
|
||||||
|
else
|
||||||
if (samples2 > 0) totalDecodedSamples += samples2;
|
{
|
||||||
|
// Handle boundary edge case for the final trailing sample
|
||||||
|
resampledFrameBuffer[i] = pcmFrameBuffer[srcIndex];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
int16_t resampledFrameBuffer[960];
|
if (totalResampledSamples > 0)
|
||||||
int totalResampledSamples = 0;
|
{
|
||||||
|
size_t freeSpace = m_playerVoiceBuffer[playerSlot].CurrentFree();
|
||||||
if (totalDecodedSamples > 0)
|
if ((size_t)totalResampledSamples <= freeSpace)
|
||||||
{
|
{
|
||||||
// The exact conversion ratio factor is 147 / 160
|
// Push the timed 22050Hz stream to the CELT ring buffer
|
||||||
// 480 samples at 24kHz converts precisely into 441 samples at 22.05kHz
|
m_playerVoiceBuffer[playerSlot].Push(resampledFrameBuffer, totalResampledSamples);
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user