fix issues, add voice stats
This commit is contained in:
parent
39fb1f70f8
commit
fa3a80c9dc
@ -13,28 +13,28 @@
|
|||||||
|
|
||||||
void DemHandlers::CreateDemMsgStructs(DemDataStructArray& demDataStructs)
|
void DemHandlers::CreateDemMsgStructs(DemDataStructArray& demDataStructs)
|
||||||
{
|
{
|
||||||
demDataStructs[0] = new DemMsg::Dem_Unknown();
|
demDataStructs[dem_unknown] = new DemMsg::Dem_Unknown();
|
||||||
demDataStructs[1] = new DemMsg::Dem_Packet();
|
demDataStructs[dem_signon] = new DemMsg::Dem_Packet();
|
||||||
demDataStructs[2] = new DemMsg::Dem_Packet();
|
demDataStructs[dem_packet] = new DemMsg::Dem_Packet();
|
||||||
demDataStructs[3] = new DemMsg::Dem_SyncTick();
|
demDataStructs[dem_synctick] = new DemMsg::Dem_SyncTick();
|
||||||
demDataStructs[4] = new DemMsg::Dem_ConsoleCmd();
|
demDataStructs[dem_consolecmd] = new DemMsg::Dem_ConsoleCmd();
|
||||||
demDataStructs[5] = new DemMsg::Dem_UserCmd();
|
demDataStructs[dem_usercmd] = new DemMsg::Dem_UserCmd();
|
||||||
demDataStructs[6] = new DemMsg::Dem_DataTables();
|
demDataStructs[dem_datatables] = new DemMsg::Dem_DataTables();
|
||||||
demDataStructs[7] = new DemMsg::Dem_Stop();
|
demDataStructs[dem_stop] = new DemMsg::Dem_Stop();
|
||||||
demDataStructs[8] = new DemMsg::Dem_StringTables();
|
demDataStructs[dem_stringtables] = new DemMsg::Dem_StringTables();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DemHandlers::DestroyDemMsgStructs(DemDataStructArray& demDataStructs)
|
void DemHandlers::DestroyDemMsgStructs(DemDataStructArray& demDataStructs)
|
||||||
{
|
{
|
||||||
delete reinterpret_cast<DemMsg::Dem_Unknown*>(demDataStructs[0]);
|
delete reinterpret_cast<DemMsg::Dem_Unknown*>(demDataStructs[dem_unknown]);
|
||||||
delete reinterpret_cast<DemMsg::Dem_Packet*>(demDataStructs[1]);
|
delete reinterpret_cast<DemMsg::Dem_Packet*>(demDataStructs[dem_signon]);
|
||||||
delete reinterpret_cast<DemMsg::Dem_Packet*>(demDataStructs[2]);
|
delete reinterpret_cast<DemMsg::Dem_Packet*>(demDataStructs[dem_packet]);
|
||||||
delete reinterpret_cast<DemMsg::Dem_SyncTick*>(demDataStructs[3]);
|
delete reinterpret_cast<DemMsg::Dem_SyncTick*>(demDataStructs[dem_synctick]);
|
||||||
delete reinterpret_cast<DemMsg::Dem_ConsoleCmd*>(demDataStructs[4]);
|
delete reinterpret_cast<DemMsg::Dem_ConsoleCmd*>(demDataStructs[dem_consolecmd]);
|
||||||
delete reinterpret_cast<DemMsg::Dem_UserCmd*>(demDataStructs[5]);
|
delete reinterpret_cast<DemMsg::Dem_UserCmd*>(demDataStructs[dem_usercmd]);
|
||||||
delete reinterpret_cast<DemMsg::Dem_DataTables*>(demDataStructs[6]);
|
delete reinterpret_cast<DemMsg::Dem_DataTables*>(demDataStructs[dem_datatables]);
|
||||||
delete reinterpret_cast<DemMsg::Dem_Stop*>(demDataStructs[7]);
|
delete reinterpret_cast<DemMsg::Dem_Stop*>(demDataStructs[dem_stop]);
|
||||||
delete reinterpret_cast<DemMsg::Dem_StringTables*>(demDataStructs[8]);
|
delete reinterpret_cast<DemMsg::Dem_StringTables*>(demDataStructs[dem_stringtables]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DECLARE_DEM_HANDLER_ARRAY(funcname) \
|
#define DECLARE_DEM_HANDLER_ARRAY(funcname) \
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
#include "logic.h"
|
#include "logic.h"
|
||||||
#include "netmessages/svc_serverinfo.h"
|
#include "netmessages/svc_serverinfo.h"
|
||||||
|
#include "io/voicewriter/voicedatawriter.h"
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
@ -13,7 +14,8 @@ Logic::Logic(SourceGameContext* context):
|
|||||||
{"header", {}},
|
{"header", {}},
|
||||||
{"serverinfo", {}},
|
{"serverinfo", {}},
|
||||||
{"players", {}},
|
{"players", {}},
|
||||||
{"chat", {}}
|
{"chat", {}},
|
||||||
|
{"voice", {}}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,6 +62,9 @@ void Logic::Finish(bool dirty)
|
|||||||
data["demoheader"]["playback_frames"] = context->curFrame;
|
data["demoheader"]["playback_frames"] = context->curFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data["voice"]["total_time"] = voiceTotalTime;
|
||||||
|
data["voice"]["active_time"] = voiceActiveTime;
|
||||||
|
|
||||||
std::string out = data.dump(2, ' ', false, json::error_handler_t::replace);
|
std::string out = data.dump(2, ' ', false, json::error_handler_t::replace);
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
fwrite(out.c_str(), out.size(), 1, context->outputFp);
|
fwrite(out.c_str(), out.size(), 1, context->outputFp);
|
||||||
@ -101,6 +106,7 @@ void Logic::OnServerInfo(NetMsg::SVC_ServerInfo* serverInfo)
|
|||||||
|
|
||||||
void Logic::OnClientConnected(int client)
|
void Logic::OnClientConnected(int client)
|
||||||
{
|
{
|
||||||
|
assert(client >= 0 && client < MAX_PLAYERS);
|
||||||
assert(clients[client].connected == -1);
|
assert(clients[client].connected == -1);
|
||||||
|
|
||||||
const auto& info = context->players[client].info;
|
const auto& info = context->players[client].info;
|
||||||
@ -124,6 +130,7 @@ void Logic::OnClientConnected(int client)
|
|||||||
|
|
||||||
void Logic::OnClientDisconnected(int client, const char* reason)
|
void Logic::OnClientDisconnected(int client, const char* reason)
|
||||||
{
|
{
|
||||||
|
assert(client >= 0 && client < MAX_PLAYERS);
|
||||||
assert(clients[client].connected != -1);
|
assert(clients[client].connected != -1);
|
||||||
|
|
||||||
const auto& info = context->players[client].info;
|
const auto& info = context->players[client].info;
|
||||||
@ -146,6 +153,7 @@ void Logic::OnClientDisconnected(int client, const char* reason)
|
|||||||
|
|
||||||
void Logic::OnClientSettingsChanged(int client)
|
void Logic::OnClientSettingsChanged(int client)
|
||||||
{
|
{
|
||||||
|
assert(client >= 0 && client < MAX_PLAYERS);
|
||||||
assert(clients[client].connected != -1);
|
assert(clients[client].connected != -1);
|
||||||
|
|
||||||
const auto& info = context->players[client].info;
|
const auto& info = context->players[client].info;
|
||||||
@ -167,6 +175,9 @@ void Logic::OnClientSettingsChanged(int client)
|
|||||||
|
|
||||||
void Logic::OnClientChat(int client, bool bWantsToChat, const char* msgName, const char* msgSender, const char* msgText)
|
void Logic::OnClientChat(int client, bool bWantsToChat, const char* msgName, const char* msgSender, const char* msgText)
|
||||||
{
|
{
|
||||||
|
assert(client >= 0 && client < MAX_PLAYERS);
|
||||||
|
assert(clients[client].connected != -1);
|
||||||
|
|
||||||
const auto& info = context->players[client].info;
|
const auto& info = context->players[client].info;
|
||||||
json chat = {
|
json chat = {
|
||||||
{"tick", curTick},
|
{"tick", curTick},
|
||||||
@ -181,14 +192,29 @@ void Logic::OnClientChat(int client, bool bWantsToChat, const char* msgName, con
|
|||||||
|
|
||||||
void Logic::OnClientVoiceChat(int client, float length)
|
void Logic::OnClientVoiceChat(int client, float length)
|
||||||
{
|
{
|
||||||
|
assert(client >= 0 && client < MAX_PLAYERS);
|
||||||
assert(clients[client].connected != -1);
|
assert(clients[client].connected != -1);
|
||||||
|
|
||||||
clients[client].voiceTime += length;
|
clients[client].voiceTime += length;
|
||||||
|
voiceTotalTime += length;
|
||||||
|
|
||||||
|
float now = curTick * context->fTickRate;
|
||||||
|
float endtime = now + length;
|
||||||
|
if (now >= voiceEndTime)
|
||||||
|
{
|
||||||
|
voiceEndTime = endtime;
|
||||||
|
voiceActiveTime += length;
|
||||||
|
}
|
||||||
|
else if (endtime > voiceEndTime)
|
||||||
|
{
|
||||||
|
voiceActiveTime += (endtime - voiceEndTime);
|
||||||
|
voiceEndTime = endtime;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Logic::OnVoiceCodec(const char* codec, int quality, int sampleRate)
|
void Logic::OnVoiceCodec(const char* codec, int quality, int sampleRate)
|
||||||
{
|
{
|
||||||
data["voice_init"] = json({
|
data["voice"] = json({
|
||||||
{"codec", codec},
|
{"codec", codec},
|
||||||
{"quality", quality},
|
{"quality", quality},
|
||||||
{"sampleRate", sampleRate}
|
{"sampleRate", sampleRate}
|
||||||
|
@ -34,6 +34,9 @@ struct Logic
|
|||||||
void OnVoiceCodec(const char* codec, int quality, int sampleRate);
|
void OnVoiceCodec(const char* codec, int quality, int sampleRate);
|
||||||
|
|
||||||
int32_t curTick = 0;
|
int32_t curTick = 0;
|
||||||
|
float voiceTotalTime = 0.0f;
|
||||||
|
float voiceActiveTime = 0.0f;
|
||||||
|
float voiceEndTime = 0.0f;
|
||||||
SourceGameContext* context = nullptr;
|
SourceGameContext* context = nullptr;
|
||||||
json data;
|
json data;
|
||||||
};
|
};
|
||||||
|
@ -19,11 +19,12 @@ SourceGameContext::SourceGameContext(std::string outputDir, std::string outputDi
|
|||||||
outputDirVoice(outputDirVoice)
|
outputDirVoice(outputDirVoice)
|
||||||
{
|
{
|
||||||
stringTables = new StringTableContainer(this);
|
stringTables = new StringTableContainer(this);
|
||||||
memset(players, 0, sizeof(players));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceGameContext::~SourceGameContext()
|
SourceGameContext::~SourceGameContext()
|
||||||
{
|
{
|
||||||
|
delete voiceWriter;
|
||||||
|
voiceWriter = nullptr;
|
||||||
delete logic;
|
delete logic;
|
||||||
logic = nullptr;
|
logic = nullptr;
|
||||||
|
|
||||||
@ -101,7 +102,7 @@ void SourceGameContext::OnNetPacket(NetPacket& packet)
|
|||||||
|
|
||||||
if(umsg->msgType == UserMsg::SayText2)
|
if(umsg->msgType == UserMsg::SayText2)
|
||||||
{
|
{
|
||||||
int client = msg.ReadByte();
|
int client = msg.ReadByte() - 1;
|
||||||
bool bWantsToChat = msg.ReadByte();
|
bool bWantsToChat = msg.ReadByte();
|
||||||
|
|
||||||
char msgName[2048] = {0};
|
char msgName[2048] = {0};
|
||||||
@ -120,7 +121,6 @@ void SourceGameContext::OnNetPacket(NetPacket& packet)
|
|||||||
{
|
{
|
||||||
voiceWriter->OnNetPacket(packet);
|
voiceWriter->OnNetPacket(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SourceGameContext::OnGameEvent(const char *name, GameEvents::EventDataMap &data)
|
void SourceGameContext::OnGameEvent(const char *name, GameEvents::EventDataMap &data)
|
||||||
|
@ -105,7 +105,7 @@ struct SourceGameContext
|
|||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
bool connected;
|
bool connected = false;
|
||||||
player_info_t info;
|
player_info_t info;
|
||||||
} players[MAX_PLAYERS];
|
} players[MAX_PLAYERS];
|
||||||
};
|
};
|
||||||
|
@ -24,6 +24,7 @@ public:
|
|||||||
void Init(const char* file, uint32_t sampleRate)
|
void Init(const char* file, uint32_t sampleRate)
|
||||||
{
|
{
|
||||||
assert(!m_Enc);
|
assert(!m_Enc);
|
||||||
|
m_SampleRate = sampleRate;
|
||||||
m_Samples = 0;
|
m_Samples = 0;
|
||||||
|
|
||||||
m_Comments = ope_comments_create();
|
m_Comments = ope_comments_create();
|
||||||
@ -56,8 +57,9 @@ public:
|
|||||||
m_Samples += numSamples;
|
m_Samples += numSamples;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PadSilence(uint64_t numSamples)
|
void PadSilence(uint64_t milliseconds)
|
||||||
{
|
{
|
||||||
|
uint64_t numSamples = (milliseconds * (uint64_t)m_SampleRate) / 1000UL;
|
||||||
if(!m_Enc || m_Samples >= numSamples)
|
if(!m_Enc || m_Samples >= numSamples)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -75,6 +77,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
OggOpusComments *m_Comments = nullptr;
|
OggOpusComments *m_Comments = nullptr;
|
||||||
OggOpusEnc *m_Enc = nullptr;
|
OggOpusEnc *m_Enc = nullptr;
|
||||||
|
uint32_t m_SampleRate = 0;
|
||||||
uint64_t m_Samples = 0;
|
uint64_t m_Samples = 0;
|
||||||
|
|
||||||
static const uint32_t bytesPerSample = 2;
|
static const uint32_t bytesPerSample = 2;
|
||||||
|
@ -87,11 +87,11 @@ void CeltVoiceDecoder::DecodeFrame(const uint8_t* compressedData, int16_t* uncom
|
|||||||
|
|
||||||
bool SilkVoiceDecoder::DoInit(int32_t sampleRate)
|
bool SilkVoiceDecoder::DoInit(int32_t sampleRate)
|
||||||
{
|
{
|
||||||
m_Silk_DecoderControl.API_sampleRate = sampleRate;
|
|
||||||
if(m_Silk_DecoderState)
|
if(m_Silk_DecoderState)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
m_Silk_DecoderControl.API_sampleRate = sampleRate;
|
||||||
|
|
||||||
int decoderSize;
|
int decoderSize;
|
||||||
SKP_Silk_SDK_Get_Decoder_Size(&decoderSize);
|
SKP_Silk_SDK_Get_Decoder_Size(&decoderSize);
|
||||||
@ -154,7 +154,7 @@ void VoiceDataWriter::Finish()
|
|||||||
state.second.celt_decoder.Destroy();
|
state.second.celt_decoder.Destroy();
|
||||||
state.second.silk_decoder.Destroy();
|
state.second.silk_decoder.Destroy();
|
||||||
|
|
||||||
state.second.fileWriter.PadSilence(((uint64_t)(m_curTick - m_silenceTicks) * state.second.sampleRate) / context->fTickRate);
|
state.second.fileWriter.PadSilence((((uint64_t)m_curTick - m_silenceTicks) * 1000000UL) / (uint64_t)(context->fTickRate * 1000UL));
|
||||||
state.second.fileWriter.Close();
|
state.second.fileWriter.Close();
|
||||||
state.second.lastVoiceDataTick = -1;
|
state.second.lastVoiceDataTick = -1;
|
||||||
}
|
}
|
||||||
@ -174,22 +174,22 @@ void VoiceDataWriter::StartCommandPacket(const CommandPacket& packet)
|
|||||||
|
|
||||||
void VoiceDataWriter::EndCommandPacket(const PacketTrailingBits& trailingBits)
|
void VoiceDataWriter::EndCommandPacket(const PacketTrailingBits& trailingBits)
|
||||||
{
|
{
|
||||||
const int tickMargin = context->fTickRate / 10.0; // 100ms
|
const int tickMargin = context->fTickInterval * 150.0; // ms
|
||||||
if (m_curTick <= tickMargin)
|
if (m_curTick <= tickMargin)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Skip silence if noone talks for at least 5 seconds
|
// Skip silence if noone talks for at least 3 seconds
|
||||||
if((m_curTick - m_lastVoiceTick) / context->fTickRate > 5.0)
|
if((m_curTick - m_lastVoiceTick) / context->fTickRate > 3.0)
|
||||||
m_silenceTicks += (m_curTick - m_lastTick);
|
m_silenceTicks += (m_curTick - m_lastTick);
|
||||||
|
|
||||||
for(auto& state : m_playerVoiceStates)
|
for(auto& state : m_playerVoiceStates)
|
||||||
{
|
{
|
||||||
if((m_curTick - state.second.lastVoiceDataTick) > tickMargin)
|
if((m_curTick - state.second.lastVoiceDataTick) > tickMargin)
|
||||||
state.second.fileWriter.PadSilence(((uint64_t)(m_curTick - m_silenceTicks) * state.second.sampleRate) / context->fTickRate);
|
state.second.fileWriter.PadSilence((((uint64_t)m_curTick - m_silenceTicks) * 1000000UL) / (uint64_t)(context->fTickRate * 1000UL));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int VoiceDataWriter::ParseSteamVoicePacket(uint8_t* bytes, int numBytes, PlayerVoiceState& state)
|
int VoiceDataWriter::ParseSteamVoicePacket(const uint8_t* bytes, int numBytes, PlayerVoiceState& state)
|
||||||
{
|
{
|
||||||
int numDecompressedSamples = 0;
|
int numDecompressedSamples = 0;
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
@ -222,9 +222,9 @@ int VoiceDataWriter::ParseSteamVoicePacket(uint8_t* bytes, int numBytes, PlayerV
|
|||||||
{
|
{
|
||||||
if(pos + 2 > dataLen)
|
if(pos + 2 > dataLen)
|
||||||
return numDecompressedSamples;
|
return numDecompressedSamples;
|
||||||
short rate = *((int16_t *)&bytes[pos]);
|
uint16_t rate = *((int16_t *)&bytes[pos]);
|
||||||
pos += 2;
|
pos += 2;
|
||||||
state.silk_decoder.DoInit(rate);
|
if(state.silk_decoder.DoInit(rate))
|
||||||
state.sampleRate = rate;
|
state.sampleRate = rate;
|
||||||
} break;
|
} break;
|
||||||
case 10: // Unknown / Unused
|
case 10: // Unknown / Unused
|
||||||
@ -241,14 +241,16 @@ int VoiceDataWriter::ParseSteamVoicePacket(uint8_t* bytes, int numBytes, PlayerV
|
|||||||
{
|
{
|
||||||
if(pos + 2 > dataLen)
|
if(pos + 2 > dataLen)
|
||||||
return numDecompressedSamples;
|
return numDecompressedSamples;
|
||||||
short length = *((int16_t *)&bytes[pos]);
|
uint16_t length = *((int16_t *)&bytes[pos]);
|
||||||
pos += 2;
|
pos += 2;
|
||||||
|
|
||||||
if(pos + length > dataLen)
|
if(pos + length > dataLen)
|
||||||
return numDecompressedSamples;
|
return numDecompressedSamples;
|
||||||
|
|
||||||
|
int freeSamples = (sizeof(m_decodeBuffer) / sizeof(int16_t)) - numDecompressedSamples;
|
||||||
if(payloadType == 3)
|
if(payloadType == 3)
|
||||||
{
|
{
|
||||||
|
length = MIN(freeSamples * 2, length);
|
||||||
memcpy(&m_decodeBuffer[numDecompressedSamples], &bytes[pos], length);
|
memcpy(&m_decodeBuffer[numDecompressedSamples], &bytes[pos], length);
|
||||||
numDecompressedSamples += length / sizeof(int16_t);
|
numDecompressedSamples += length / sizeof(int16_t);
|
||||||
}
|
}
|
||||||
@ -258,10 +260,10 @@ int VoiceDataWriter::ParseSteamVoicePacket(uint8_t* bytes, int numBytes, PlayerV
|
|||||||
int maxpos = tpos + length;
|
int maxpos = tpos + length;
|
||||||
while(tpos <= (maxpos - 2))
|
while(tpos <= (maxpos - 2))
|
||||||
{
|
{
|
||||||
short chunkLength = *((int16_t *)&bytes[tpos]);
|
int16_t chunkLength = *((int16_t *)&bytes[tpos]);
|
||||||
tpos += 2;
|
tpos += 2;
|
||||||
|
|
||||||
if(chunkLength == -1)
|
if(chunkLength < 0)
|
||||||
{
|
{
|
||||||
state.silk_decoder.Reset();
|
state.silk_decoder.Reset();
|
||||||
continue;
|
continue;
|
||||||
@ -270,6 +272,7 @@ int VoiceDataWriter::ParseSteamVoicePacket(uint8_t* bytes, int numBytes, PlayerV
|
|||||||
{
|
{
|
||||||
// DTX (discontinued transmission)
|
// DTX (discontinued transmission)
|
||||||
int numEmptySamples = state.sampleRate / 50;
|
int numEmptySamples = state.sampleRate / 50;
|
||||||
|
numEmptySamples = MIN(freeSamples, numEmptySamples);
|
||||||
memset(&m_decodeBuffer[numDecompressedSamples], 0, numEmptySamples * sizeof(int16_t));
|
memset(&m_decodeBuffer[numDecompressedSamples], 0, numEmptySamples * sizeof(int16_t));
|
||||||
numDecompressedSamples += numEmptySamples;
|
numDecompressedSamples += numEmptySamples;
|
||||||
continue;
|
continue;
|
||||||
@ -278,8 +281,7 @@ int VoiceDataWriter::ParseSteamVoicePacket(uint8_t* bytes, int numBytes, PlayerV
|
|||||||
if(tpos + chunkLength > maxpos)
|
if(tpos + chunkLength > maxpos)
|
||||||
return numDecompressedSamples;
|
return numDecompressedSamples;
|
||||||
|
|
||||||
int ret = state.silk_decoder.Decompress(&bytes[tpos], chunkLength, &m_decodeBuffer[numDecompressedSamples],
|
int ret = state.silk_decoder.Decompress(&bytes[tpos], chunkLength, &m_decodeBuffer[numDecompressedSamples], freeSamples);
|
||||||
(sizeof(m_decodeBuffer) / sizeof(int16_t)) - numDecompressedSamples);
|
|
||||||
numDecompressedSamples += ret;
|
numDecompressedSamples += ret;
|
||||||
tpos += chunkLength;
|
tpos += chunkLength;
|
||||||
}
|
}
|
||||||
@ -291,7 +293,9 @@ int VoiceDataWriter::ParseSteamVoicePacket(uint8_t* bytes, int numBytes, PlayerV
|
|||||||
{
|
{
|
||||||
if(pos + 2 > dataLen)
|
if(pos + 2 > dataLen)
|
||||||
return numDecompressedSamples;
|
return numDecompressedSamples;
|
||||||
short numSamples = *((int16_t *)&bytes[pos]);
|
uint16_t numSamples = *((uint16_t *)&bytes[pos]);
|
||||||
|
int freeSamples = (sizeof(m_decodeBuffer) / sizeof(int16_t)) - numDecompressedSamples;
|
||||||
|
numSamples = MIN(freeSamples, numSamples);
|
||||||
memset(&m_decodeBuffer[numDecompressedSamples], 0, numSamples * sizeof(int16_t));
|
memset(&m_decodeBuffer[numDecompressedSamples], 0, numSamples * sizeof(int16_t));
|
||||||
numDecompressedSamples += numSamples;
|
numDecompressedSamples += numSamples;
|
||||||
pos += 2;
|
pos += 2;
|
||||||
@ -329,7 +333,7 @@ void VoiceDataWriter::OnNetPacket(NetPacket& packet)
|
|||||||
assert(voiceData->fromClientIndex < MAX_PLAYERS);
|
assert(voiceData->fromClientIndex < MAX_PLAYERS);
|
||||||
const char* guid = context->players[voiceData->fromClientIndex].info.guid;
|
const char* guid = context->players[voiceData->fromClientIndex].info.guid;
|
||||||
|
|
||||||
uint8_t* bytes = voiceData->data.get();
|
const uint8_t* bytes = voiceData->data.get();
|
||||||
assert((voiceData->dataLengthInBits % 8) == 0);
|
assert((voiceData->dataLengthInBits % 8) == 0);
|
||||||
const int numBytes = voiceData->dataLengthInBits / 8;
|
const int numBytes = voiceData->dataLengthInBits / 8;
|
||||||
|
|
||||||
@ -343,7 +347,7 @@ void VoiceDataWriter::OnNetPacket(NetPacket& packet)
|
|||||||
state.sampleRate = config.sampleRate;
|
state.sampleRate = config.sampleRate;
|
||||||
|
|
||||||
state.celt_decoder.DoInit(m_celtMode, config.frameSizeSamples, config.encodedFrameSizeBytes);
|
state.celt_decoder.DoInit(m_celtMode, config.frameSizeSamples, config.encodedFrameSizeBytes);
|
||||||
numDecompressedSamples = state.celt_decoder.Decompress(bytes, numBytes, m_decodeBuffer, sizeof(m_decodeBuffer));
|
numDecompressedSamples = state.celt_decoder.Decompress(bytes, numBytes, m_decodeBuffer, sizeof(m_decodeBuffer) / sizeof(int16_t));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -366,7 +370,7 @@ void VoiceDataWriter::OnNetPacket(NetPacket& packet)
|
|||||||
{
|
{
|
||||||
std::string name = std::string(m_outputPath) + "/" + std::string(guid) + ".opus";
|
std::string name = std::string(m_outputPath) + "/" + std::string(guid) + ".opus";
|
||||||
state.fileWriter.Init(name.c_str(), state.sampleRate);
|
state.fileWriter.Init(name.c_str(), state.sampleRate);
|
||||||
state.fileWriter.PadSilence(((uint64_t)(m_curTick - m_silenceTicks) * state.sampleRate) / context->fTickRate);
|
state.fileWriter.PadSilence((((uint64_t)m_curTick - m_silenceTicks) * 1000000UL) / (uint64_t)(context->fTickRate * 1000UL));
|
||||||
}
|
}
|
||||||
|
|
||||||
state.fileWriter.WriteSamples(m_decodeBuffer, numDecompressedSamples);
|
state.fileWriter.WriteSamples(m_decodeBuffer, numDecompressedSamples);
|
||||||
|
@ -74,7 +74,7 @@ private:
|
|||||||
int sampleRate = 0;
|
int sampleRate = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
int ParseSteamVoicePacket(uint8_t* bytes, int numBytes, PlayerVoiceState& state);
|
int ParseSteamVoicePacket(const uint8_t* bytes, int numBytes, PlayerVoiceState& state);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SourceGameContext *context = nullptr;
|
SourceGameContext *context = nullptr;
|
||||||
@ -88,7 +88,7 @@ private:
|
|||||||
int32_t m_silenceTicks = 0;
|
int32_t m_silenceTicks = 0;
|
||||||
const char* m_outputPath = nullptr;
|
const char* m_outputPath = nullptr;
|
||||||
|
|
||||||
int16_t m_decodeBuffer[8192];
|
int16_t m_decodeBuffer[16384];
|
||||||
|
|
||||||
static const int sQuality = 3;
|
static const int sQuality = 3;
|
||||||
eCodec m_Codec = CODEC_NONE;
|
eCodec m_Codec = CODEC_NONE;
|
||||||
|
Loading…
Reference in New Issue
Block a user