2
0
mirror of https://github.com/rehlds/revoice.git synced 2024-12-27 23:25:53 +03:00

Main logic

This commit is contained in:
thecrock 2015-12-13 18:55:11 +04:00
parent 1ed90219f9
commit 01dab99480
9 changed files with 183 additions and 23 deletions

View File

@ -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
}

View File

@ -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;
}

View File

@ -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 */

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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();

View File

@ -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];

View File

@ -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;
}

View File

@ -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();