mirror of
https://github.com/rehlds/revoice.git
synced 2024-12-27 23:25:53 +03:00
Main logic
This commit is contained in:
parent
1ed90219f9
commit
01dab99480
@ -42,9 +42,7 @@ cpuinfo_t cpuinfo;
|
||||
|
||||
void Sys_CheckCpuInstructionsSupport(void)
|
||||
{
|
||||
int cpuid_data[4];
|
||||
|
||||
cpuid_ex(cpuid_data, 1, 0);
|
||||
int cpuid_data[4] = { 0,0,0,0 };
|
||||
|
||||
cpuinfo.sse3 = (cpuid_data[2] & SSE3_FLAG) ? 1 : 0; // ecx
|
||||
cpuinfo.ssse3 = (cpuid_data[2] & SSSE3_FLAG) ? 1 : 0;
|
||||
@ -52,7 +50,6 @@ void Sys_CheckCpuInstructionsSupport(void)
|
||||
cpuinfo.sse4_2 = (cpuid_data[2] & SSE4_2_FLAG) ? 1 : 0;
|
||||
cpuinfo.avx = (cpuid_data[2] & AVX_FLAG) ? 1 : 0;
|
||||
|
||||
cpuid_ex(cpuid_data, 7, 0);
|
||||
|
||||
cpuinfo.avx2 = (cpuid_data[1] & AVX2_FLAG) ? 1 : 0; // ebx
|
||||
}
|
@ -4,7 +4,6 @@
|
||||
VoiceEncoder_Silk::VoiceEncoder_Silk() {
|
||||
m_pEncoder = NULL;
|
||||
m_pDecoder = NULL;
|
||||
m_API_fs_Hz = 0;
|
||||
m_targetRate_bps = 25000;
|
||||
m_packetLoss_perc = 0;
|
||||
}
|
||||
@ -22,7 +21,6 @@ VoiceEncoder_Silk::~VoiceEncoder_Silk() {
|
||||
}
|
||||
|
||||
bool VoiceEncoder_Silk::Init(int quality) {
|
||||
m_API_fs_Hz = 16000;
|
||||
m_targetRate_bps = 25000;
|
||||
m_packetLoss_perc = 0;
|
||||
|
||||
@ -64,8 +62,9 @@ int VoiceEncoder_Silk::Compress(const char *pUncompressedIn, int nSamplesIn, cha
|
||||
const char *pWritePosMax; // [sp+2Ch] [bp-40h]@5
|
||||
int nSamplesRemaining; // [sp+38h] [bp-34h]@5
|
||||
|
||||
const int inSampleRate = 8000;
|
||||
const int nSampleDataMinMS = 100;
|
||||
const int nSamplesMin = m_API_fs_Hz * nSampleDataMinMS / 1000;
|
||||
const int nSamplesMin = inSampleRate * nSampleDataMinMS / 1000;
|
||||
|
||||
if ((nSamplesIn + m_bufOverflowBytes.TellPut() / 2) < nSamplesMin && !bFinal) {
|
||||
m_bufOverflowBytes.Put(pUncompressedIn, 2 * nSamplesIn);
|
||||
@ -82,7 +81,7 @@ int VoiceEncoder_Silk::Compress(const char *pUncompressedIn, int nSamplesIn, cha
|
||||
nSamplesToUse = nSamplesIn;
|
||||
}
|
||||
|
||||
nSamplesPerFrame = m_API_fs_Hz / 50;
|
||||
nSamplesPerFrame = inSampleRate / 50;
|
||||
nSamplesRemaining = nSamplesToUse % nSamplesPerFrame;
|
||||
pWritePosMax = pCompressed + maxCompressedBytes;
|
||||
nSamples = nSamplesToUse - nSamplesRemaining;
|
||||
@ -99,9 +98,9 @@ int VoiceEncoder_Silk::Compress(const char *pUncompressedIn, int nSamplesIn, cha
|
||||
this->m_encControl.useDTX = 1;
|
||||
this->m_encControl.maxInternalSampleRate = 16000;
|
||||
this->m_encControl.useInBandFEC = 0;
|
||||
this->m_encControl.API_sampleRate = m_API_fs_Hz;
|
||||
this->m_encControl.API_sampleRate = inSampleRate;
|
||||
this->m_encControl.complexity = 2;
|
||||
this->m_encControl.packetSize = 20 * (m_API_fs_Hz / 1000);
|
||||
this->m_encControl.packetSize = 20 * (inSampleRate / 1000);
|
||||
this->m_encControl.packetLossPercentage = this->m_packetLoss_perc;
|
||||
this->m_encControl.bitRate = (m_targetRate_bps >= 0) ? m_targetRate_bps : 0;
|
||||
|
||||
@ -143,8 +142,10 @@ int VoiceEncoder_Silk::Decompress(const char *pCompressed, int compressedBytes,
|
||||
char *pWritePosMax; // [sp+28h] [bp-44h]@4
|
||||
const char *pReadPosMax; // [sp+3Ch] [bp-30h]@1
|
||||
|
||||
m_decControl.API_sampleRate = m_API_fs_Hz;
|
||||
int nSamplesPerFrame = m_API_fs_Hz / 50;
|
||||
const int outSampleRate = 8000;
|
||||
|
||||
m_decControl.API_sampleRate = outSampleRate;
|
||||
int nSamplesPerFrame = outSampleRate / 50;
|
||||
if (compressedBytes <= 0) {
|
||||
return 0;
|
||||
}
|
||||
@ -157,7 +158,7 @@ int VoiceEncoder_Silk::Decompress(const char *pCompressed, int compressedBytes,
|
||||
|
||||
while (pReadPos < pReadPosMax) {
|
||||
if (pReadPosMax - pReadPos < 2) {
|
||||
return pWritePos - pUncompressed;
|
||||
break;
|
||||
}
|
||||
|
||||
nPayloadSize = *(uint16 *)pReadPos;
|
||||
@ -165,7 +166,7 @@ int VoiceEncoder_Silk::Decompress(const char *pCompressed, int compressedBytes,
|
||||
|
||||
if (nPayloadSize == 0xFFFF) {
|
||||
ResetState();
|
||||
return pWritePos - pUncompressed;
|
||||
break;
|
||||
}
|
||||
|
||||
if (nPayloadSize == 0) {
|
||||
@ -173,7 +174,7 @@ int VoiceEncoder_Silk::Decompress(const char *pCompressed, int compressedBytes,
|
||||
int numEmptySamples = nSamplesPerFrame;
|
||||
short nSamples = (pWritePosMax - pWritePos) / 2;
|
||||
if (nSamples < numEmptySamples) {
|
||||
return pWritePos - pUncompressed;
|
||||
break;
|
||||
}
|
||||
memset(pWritePos, 0, numEmptySamples * 2);
|
||||
pWritePos += numEmptySamples * 2;
|
||||
@ -181,19 +182,19 @@ int VoiceEncoder_Silk::Decompress(const char *pCompressed, int compressedBytes,
|
||||
}
|
||||
|
||||
if ((pReadPos + nPayloadSize) > pReadPosMax) {
|
||||
return pWritePos - pUncompressed;
|
||||
break;
|
||||
}
|
||||
|
||||
do {
|
||||
short nSamples = (pWritePosMax - pWritePos) / 2;
|
||||
int decodeRes = SKP_Silk_SDK_Decode(m_pDecoder, &m_decControl, 0, (const unsigned char*)pReadPos, nPayloadSize, (__int16 *)pWritePos, &nSamples);
|
||||
if (SKP_SILK_NO_ERROR != decodeRes) {
|
||||
return pWritePos - pUncompressed;
|
||||
return (pWritePos - pUncompressed) / 2;
|
||||
}
|
||||
pWritePos += nSamples * sizeof(int16);
|
||||
} while (m_decControl.moreInternalDecoderFrames);
|
||||
pReadPos += nPayloadSize;
|
||||
}
|
||||
|
||||
return pWritePos - pUncompressed;
|
||||
return (pWritePos - pUncompressed) / 2;
|
||||
}
|
@ -7,7 +7,7 @@
|
||||
class VoiceEncoder_Silk : public IVoiceCodec {
|
||||
private:
|
||||
void * m_pEncoder; /* 4 4 */
|
||||
int m_API_fs_Hz; /* 8 4 */
|
||||
//int m_API_fs_Hz; /* 8 4 */
|
||||
int m_targetRate_bps; /* 12 4 */
|
||||
int m_packetLoss_perc; /* 16 4 */
|
||||
SKP_SILK_SDK_EncControlStruct m_encControl; /* 20 32 */
|
||||
|
@ -121,6 +121,11 @@ bool Revoice_Load() {
|
||||
return false;
|
||||
}
|
||||
|
||||
Revoice_Init_Players();
|
||||
if (!Revoice_Main_Init()) {
|
||||
LCPrintf(true, "Initialization failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
int g_ClientBeingConnected_Protocol = 0;
|
||||
cvar_t* pcv_sv_voiceenable = NULL;
|
||||
|
||||
void SV_ConnectClient_hook(IRehldsHook_SV_ConnectClient* chain) {
|
||||
g_ClientBeingConnected_Protocol = atoi(g_engfuncs.pfnCmd_Argv(1));
|
||||
@ -15,14 +16,20 @@ void Rehlds_ClientConnected_Hook(IRehldsHook_ClientConnected* chain, IGameClient
|
||||
|
||||
if (g_ClientBeingConnected_Protocol == 47) {
|
||||
plr->InitVoice(vct_speex);
|
||||
} else {
|
||||
g_engfuncs.pfnQueryClientCvarValue2(cl->GetEdict(), "sv_version", 0);
|
||||
}
|
||||
|
||||
//for p48 we will query sv_version cvar value later in mm_ClientConnect
|
||||
}
|
||||
|
||||
chain->callNext(cl);
|
||||
}
|
||||
|
||||
void SV_DropClient_hook(IRehldsHook_SV_DropClient* chain, IGameClient* cl, bool crash, const char* msg) {
|
||||
CRevoicePlayer* plr = GetPlayerByClientPtr(cl);
|
||||
plr->OnDisconected();
|
||||
chain->callNext(cl, crash, msg);
|
||||
}
|
||||
|
||||
void mm_CvarValue2(const edict_t *pEnt, int requestID, const char *cvarName, const char *value) {
|
||||
if (!strcmp("sv_version", cvarName)) {
|
||||
// ] sv_version
|
||||
@ -45,12 +52,149 @@ void mm_CvarValue2(const edict_t *pEnt, int requestID, const char *cvarName, con
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
int TranscodeVoice(const char* srcBuf, int srcBufLen, IVoiceCodec* srcCodec, IVoiceCodec* dstCodec, char* dstBuf, int dstBufSize) {
|
||||
char decodedBuf[32768];
|
||||
int numDecodedSamples = srcCodec->Decompress(srcBuf, srcBufLen, decodedBuf, sizeof(decodedBuf));
|
||||
if (numDecodedSamples <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return dstCodec->Compress(decodedBuf, numDecodedSamples, dstBuf, dstBufSize, false);
|
||||
}
|
||||
|
||||
void SV_ParseVoiceData_emu(IGameClient* cl) {
|
||||
char chReceived[4096];
|
||||
unsigned int nDataLength = g_RehldsFuncs->MSG_ReadShort();
|
||||
|
||||
if (nDataLength > sizeof(chReceived))
|
||||
{
|
||||
g_RehldsFuncs->DropClient(cl, FALSE, "Invalid voice data\n");
|
||||
return;
|
||||
}
|
||||
|
||||
g_RehldsFuncs->MSG_ReadBuf(nDataLength, chReceived);
|
||||
//cl->m_lastvoicetime = g_RehldsSv->GetTime();
|
||||
|
||||
if (pcv_sv_voiceenable->value == 0.0f)
|
||||
return;
|
||||
|
||||
CRevoicePlayer* srcPlayer = GetPlayerByClientPtr(cl);
|
||||
if (srcPlayer->GetCodecType() == vct_none) {
|
||||
return;
|
||||
}
|
||||
|
||||
char transcodedBuf[4096];
|
||||
char* speexData; int speexDataLen;
|
||||
char* silkData; int silkDataLen;
|
||||
|
||||
switch (srcPlayer->GetCodecType()) {
|
||||
case vct_silk:
|
||||
silkData = chReceived; silkDataLen = nDataLength;
|
||||
speexData = transcodedBuf;
|
||||
speexDataLen = TranscodeVoice(silkData, silkDataLen, srcPlayer->GetSilkCodec(), srcPlayer->GetSpeexCodec(), transcodedBuf, sizeof(transcodedBuf));
|
||||
break;
|
||||
|
||||
case vct_speex:
|
||||
speexData = chReceived; speexDataLen = nDataLength;
|
||||
silkData = transcodedBuf;
|
||||
silkDataLen = TranscodeVoice(speexData, speexDataLen, srcPlayer->GetSpeexCodec(), srcPlayer->GetSilkCodec(), transcodedBuf, sizeof(transcodedBuf));
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < g_RehldsSvs->GetMaxClients(); i++) {
|
||||
CRevoicePlayer* dstPlayer = &g_Players[i];
|
||||
IGameClient* dstClient = dstPlayer->GetClient();
|
||||
|
||||
if (!((1 << (i & 0x1F)) & cl->GetVoiceStreams(i >> 5)) && i != cl->GetId())
|
||||
continue;
|
||||
|
||||
if (!dstClient->IsActive() && !dstClient->IsConnected() && i != cl->GetId())
|
||||
continue;
|
||||
|
||||
char* sendBuf; int nSendLen;
|
||||
|
||||
switch (dstPlayer->GetCodecType()) {
|
||||
case vct_silk:
|
||||
sendBuf = silkData; nSendLen = silkDataLen;
|
||||
break;
|
||||
|
||||
case vct_speex:
|
||||
sendBuf = speexData; nSendLen = speexDataLen;
|
||||
break;
|
||||
|
||||
default:
|
||||
sendBuf = NULL; nSendLen = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sendBuf == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i == cl->GetId() && !dstClient->GetLoopback())
|
||||
nSendLen = 0;
|
||||
|
||||
sizebuf_t* dstDatagram = dstClient->GetDatagram();
|
||||
if (dstDatagram->cursize + nSendLen + 6 < dstDatagram->maxsize)
|
||||
{
|
||||
g_RehldsFuncs->MSG_WriteByte(dstDatagram, 53); //svc_voicedata
|
||||
g_RehldsFuncs->MSG_WriteByte(dstDatagram, cl->GetId());
|
||||
g_RehldsFuncs->MSG_WriteShort(dstDatagram, nSendLen);
|
||||
g_RehldsFuncs->MSG_WriteBuf(dstDatagram, nSendLen, sendBuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Rehlds_HandleNetCommand(IRehldsHook_HandleNetCommand* chain, IGameClient* cl, int8 opcode) {
|
||||
if (opcode == 8) { //clc_voicedata
|
||||
SV_ParseVoiceData_emu(cl);
|
||||
return;
|
||||
}
|
||||
|
||||
chain->callNext(cl, opcode);
|
||||
}
|
||||
|
||||
qboolean mm_ClientConnect(edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[128]) {
|
||||
CRevoicePlayer* plr = GetPlayerByEdict(pEntity);
|
||||
if (plr->GetProtocol() == 48) {
|
||||
g_engfuncs.pfnQueryClientCvarValue2(pEntity, "sv_version", 0);
|
||||
}
|
||||
RETURN_META_VALUE(MRES_IGNORED, 1);
|
||||
}
|
||||
|
||||
void SV_WriteVoiceCodec_hooked(IRehldsHook_SV_WriteVoiceCodec* chain, sizebuf_t* sb) {
|
||||
IGameClient* cl = g_RehldsFuncs->GetHostClient();
|
||||
CRevoicePlayer* plr = GetPlayerByClientPtr(cl);
|
||||
|
||||
switch (plr->GetCodecType()) {
|
||||
case vct_silk:
|
||||
g_RehldsFuncs->MSG_WriteByte(sb, 52); //svc_voiceinit
|
||||
g_RehldsFuncs->MSG_WriteString(sb, ""); //codec id
|
||||
g_RehldsFuncs->MSG_WriteByte(sb, 0); //quality
|
||||
break;
|
||||
|
||||
case vct_speex:
|
||||
g_RehldsFuncs->MSG_WriteByte(sb, 52); //svc_voiceinit
|
||||
g_RehldsFuncs->MSG_WriteString(sb, "speex"); //codec id
|
||||
g_RehldsFuncs->MSG_WriteByte(sb, 5); //quality
|
||||
break;
|
||||
|
||||
default:
|
||||
LCPrintf(true, "SV_WriteVoiceCodec() called on client(%d) with unknown voice codec\n", cl->GetId());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool Revoice_Main_Init() {
|
||||
g_RehldsHookchains->SV_ConnectClient()->registerHook(SV_ConnectClient_hook);
|
||||
g_RehldsHookchains->ClientConnected()->registerHook(Rehlds_ClientConnected_Hook);
|
||||
g_RehldsHookchains->SV_DropClient()->registerHook(SV_DropClient_hook);
|
||||
g_RehldsHookchains->HandleNetCommand()->registerHook(Rehlds_HandleNetCommand);
|
||||
g_RehldsHookchains->SV_WriteVoiceCodec()->registerHook(SV_WriteVoiceCodec_hooked);
|
||||
pcv_sv_voiceenable = g_engfuncs.pfnCVarGetPointer("sv_voiceenable");
|
||||
|
||||
return true;
|
||||
}
|
@ -28,7 +28,12 @@ void CRevoicePlayer::InitVoice(revoice_codec_type codecType) {
|
||||
void CRevoicePlayer::OnConnected(int protocol) {
|
||||
m_Protocol = protocol;
|
||||
m_CodecType = vct_none;
|
||||
}
|
||||
}
|
||||
|
||||
void CRevoicePlayer::OnDisconected() {
|
||||
m_Protocol = 0;
|
||||
m_CodecType = vct_none;
|
||||
}
|
||||
|
||||
void Revoice_Init_Players() {
|
||||
int maxclients = g_RehldsSvs->GetMaxClients();
|
||||
|
@ -17,9 +17,14 @@ public:
|
||||
CRevoicePlayer();
|
||||
void Initialize(IGameClient* cl);
|
||||
void OnConnected(int protocol);
|
||||
void OnDisconected();
|
||||
void InitVoice(revoice_codec_type codecType);
|
||||
|
||||
|
||||
int GetProtocol() const { return m_Protocol; }
|
||||
revoice_codec_type GetCodecType() const { return m_CodecType; }
|
||||
VoiceEncoder_Silk* GetSilkCodec() const { return m_SilkCodec; }
|
||||
VoiceCodec_Frame* GetSpeexCodec() const { return m_SpeexCodec; }
|
||||
IGameClient* GetClient() const { return m_RehldsClient; }
|
||||
};
|
||||
|
||||
extern CRevoicePlayer g_Players[MAX_PLAYERS];
|
||||
|
@ -4,6 +4,7 @@ IRehldsApi* g_RehldsApi;
|
||||
const RehldsFuncs_t* g_RehldsFuncs;
|
||||
IRehldsHookchains* g_RehldsHookchains;
|
||||
IRehldsServerStatic* g_RehldsSvs;
|
||||
IRehldsServerData* g_RehldsSv;
|
||||
|
||||
bool Revoice_RehldsApi_TryInit(CSysModule* engineModule, char* failureReason)
|
||||
{
|
||||
@ -41,6 +42,7 @@ bool Revoice_RehldsApi_TryInit(CSysModule* engineModule, char* failureReason)
|
||||
g_RehldsFuncs = g_RehldsApi->GetFuncs();
|
||||
g_RehldsHookchains = g_RehldsApi->GetHookchains();
|
||||
g_RehldsSvs = g_RehldsApi->GetServerStatic();
|
||||
g_RehldsSv = g_RehldsApi->GetServerData();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -6,5 +6,6 @@ extern IRehldsApi* g_RehldsApi;
|
||||
extern const RehldsFuncs_t* g_RehldsFuncs;
|
||||
extern IRehldsHookchains* g_RehldsHookchains;
|
||||
extern IRehldsServerStatic* g_RehldsSvs;
|
||||
extern IRehldsServerData* g_RehldsSv;
|
||||
|
||||
extern bool Revoice_RehldsApi_Init();
|
||||
|
Loading…
Reference in New Issue
Block a user