mirror of
https://github.com/rehlds/revoice.git
synced 2025-01-15 08:08:01 +03:00
Added voice rate limiter
This commit is contained in:
parent
639e79e766
commit
fec9126f34
@ -32,7 +32,7 @@ int CSteamP2PCodec::StreamDecode(const char *pCompressed, int compressedBytes, c
|
|||||||
readPos += 2;
|
readPos += 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x04: //Voice payoad
|
case 0x04: //Voice payload
|
||||||
{
|
{
|
||||||
if (readPos + 2 > maxReadPos) {
|
if (readPos + 2 > maxReadPos) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -5,7 +5,7 @@ cvar_t* pcv_sv_voiceenable = NULL;
|
|||||||
|
|
||||||
void Rehlds_ClientConnected_Hook(IRehldsHook_ClientConnected* chain, IGameClient* cl) {
|
void Rehlds_ClientConnected_Hook(IRehldsHook_ClientConnected* chain, IGameClient* cl) {
|
||||||
int protocol = g_ReunionApi->GetClientProtocol(cl->GetId());
|
int protocol = g_ReunionApi->GetClientProtocol(cl->GetId());
|
||||||
if (protocol >= 47 && protocol <= 48) {
|
if (protocol == 47 || protocol == 48) {
|
||||||
CRevoicePlayer* plr = GetPlayerByClientPtr(cl);
|
CRevoicePlayer* plr = GetPlayerByClientPtr(cl);
|
||||||
plr->OnConnected(protocol);
|
plr->OnConnected(protocol);
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ void Rehlds_ClientConnected_Hook(IRehldsHook_ClientConnected* chain, IGameClient
|
|||||||
|
|
||||||
void SV_DropClient_hook(IRehldsHook_SV_DropClient* chain, IGameClient* cl, bool crash, const char* msg) {
|
void SV_DropClient_hook(IRehldsHook_SV_DropClient* chain, IGameClient* cl, bool crash, const char* msg) {
|
||||||
CRevoicePlayer* plr = GetPlayerByClientPtr(cl);
|
CRevoicePlayer* plr = GetPlayerByClientPtr(cl);
|
||||||
plr->OnDisconected();
|
plr->OnDisconnected();
|
||||||
chain->callNext(cl, crash, msg);
|
chain->callNext(cl, crash, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +54,6 @@ int TranscodeVoice(const char* srcBuf, int srcBufLen, IVoiceCodec* srcCodec, IVo
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int compressedSize = dstCodec->Compress(decodedBuf, numDecodedSamples, dstBuf, dstBufSize, false);
|
int compressedSize = dstCodec->Compress(decodedBuf, numDecodedSamples, dstBuf, dstBufSize, false);
|
||||||
if (compressedSize <= 0) {
|
if (compressedSize <= 0) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -77,25 +76,23 @@ int TranscodeVoice(const char* srcBuf, int srcBufLen, IVoiceCodec* srcCodec, IVo
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SV_ParseVoiceData_emu(IGameClient* cl) {
|
void SV_ParseVoiceData_emu(IGameClient* cl) {
|
||||||
if (pcv_sv_voiceenable->value == 0.0f)
|
if (pcv_sv_voiceenable->value == 0.0f) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
char chReceived[4096];
|
char chReceived[4096];
|
||||||
unsigned int nDataLength = g_RehldsFuncs->MSG_ReadShort();
|
unsigned int nDataLength = g_RehldsFuncs->MSG_ReadShort();
|
||||||
|
|
||||||
if (nDataLength > sizeof(chReceived))
|
if (nDataLength > sizeof(chReceived)) {
|
||||||
{
|
|
||||||
g_RehldsFuncs->DropClient(cl, FALSE, "Invalid voice data\n");
|
g_RehldsFuncs->DropClient(cl, FALSE, "Invalid voice data\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_RehldsFuncs->MSG_ReadBuf(nDataLength, chReceived);
|
g_RehldsFuncs->MSG_ReadBuf(nDataLength, chReceived);
|
||||||
//cl->m_lastvoicetime = g_RehldsSv->GetTime();
|
|
||||||
|
|
||||||
CRevoicePlayer* srcPlayer = GetPlayerByClientPtr(cl);
|
CRevoicePlayer* srcPlayer = GetPlayerByClientPtr(cl);
|
||||||
if (srcPlayer->GetCodecType() == vct_none) {
|
srcPlayer->SetLastVoiceTime(g_RehldsSv->GetTime());
|
||||||
return;
|
srcPlayer->IncreaseVoiceRate(nDataLength);
|
||||||
}
|
|
||||||
|
|
||||||
char transcodedBuf[4096];
|
char transcodedBuf[4096];
|
||||||
char* speexData; int speexDataLen;
|
char* speexData; int speexDataLen;
|
||||||
@ -104,6 +101,9 @@ void SV_ParseVoiceData_emu(IGameClient* cl) {
|
|||||||
switch (srcPlayer->GetCodecType()) {
|
switch (srcPlayer->GetCodecType()) {
|
||||||
case vct_silk:
|
case vct_silk:
|
||||||
{
|
{
|
||||||
|
//if (nDataLength > MAX_SILK_DATA_LEN || srcPlayer->GetVoiceRate() > MAX_SILK_VOICE_RATE)
|
||||||
|
//return;
|
||||||
|
|
||||||
silkData = chReceived; silkDataLen = nDataLength;
|
silkData = chReceived; silkDataLen = nDataLength;
|
||||||
speexData = transcodedBuf;
|
speexData = transcodedBuf;
|
||||||
speexDataLen = TranscodeVoice(silkData, silkDataLen, srcPlayer->GetSilkCodec(), srcPlayer->GetSpeexCodec(), transcodedBuf, sizeof(transcodedBuf));
|
speexDataLen = TranscodeVoice(silkData, silkDataLen, srcPlayer->GetSilkCodec(), srcPlayer->GetSpeexCodec(), transcodedBuf, sizeof(transcodedBuf));
|
||||||
@ -111,6 +111,9 @@ void SV_ParseVoiceData_emu(IGameClient* cl) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case vct_speex:
|
case vct_speex:
|
||||||
|
//if (nDataLength > MAX_SPEEX_DATA_LEN || srcPlayer->GetVoiceRate() > MAX_SPEEX_VOICE_RATE)
|
||||||
|
//return;
|
||||||
|
|
||||||
speexData = chReceived; speexDataLen = nDataLength;
|
speexData = chReceived; speexDataLen = nDataLength;
|
||||||
silkData = transcodedBuf;
|
silkData = transcodedBuf;
|
||||||
silkDataLen = TranscodeVoice(speexData, speexDataLen, srcPlayer->GetSpeexCodec(), srcPlayer->GetSilkCodec(), transcodedBuf, sizeof(transcodedBuf));
|
silkDataLen = TranscodeVoice(speexData, speexDataLen, srcPlayer->GetSpeexCodec(), srcPlayer->GetSilkCodec(), transcodedBuf, sizeof(transcodedBuf));
|
||||||
@ -120,14 +123,16 @@ void SV_ParseVoiceData_emu(IGameClient* cl) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < g_RehldsSvs->GetMaxClients(); i++) {
|
int maxclients = g_RehldsSvs->GetMaxClients();
|
||||||
|
|
||||||
|
for (int i = 0; i < maxclients; i++) {
|
||||||
CRevoicePlayer* dstPlayer = &g_Players[i];
|
CRevoicePlayer* dstPlayer = &g_Players[i];
|
||||||
IGameClient* dstClient = dstPlayer->GetClient();
|
IGameClient* dstClient = dstPlayer->GetClient();
|
||||||
|
|
||||||
if (!((1 << (i & 0x1F)) & cl->GetVoiceStream(i >> 5)) && i != cl->GetId())
|
if (!((1 << i) & cl->GetVoiceStream(0)) && dstPlayer != srcPlayer)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!dstClient->IsActive() && !dstClient->IsConnected() && i != cl->GetId())
|
if (!dstClient->IsActive() && !dstClient->IsConnected() && dstPlayer != srcPlayer)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
char* sendBuf; int nSendLen;
|
char* sendBuf; int nSendLen;
|
||||||
@ -146,17 +151,15 @@ void SV_ParseVoiceData_emu(IGameClient* cl) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sendBuf == NULL || nSendLen == 0) {
|
if (sendBuf == NULL || nSendLen == 0)
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
if (i == cl->GetId() && !dstClient->GetLoopback())
|
if (dstPlayer == srcPlayer && !dstClient->GetLoopback())
|
||||||
nSendLen = 0;
|
nSendLen = 0;
|
||||||
|
|
||||||
sizebuf_t* dstDatagram = dstClient->GetDatagram();
|
sizebuf_t* dstDatagram = dstClient->GetDatagram();
|
||||||
if (dstDatagram->cursize + nSendLen + 6 < dstDatagram->maxsize)
|
if (dstDatagram->cursize + nSendLen + 6 < dstDatagram->maxsize) {
|
||||||
{
|
g_RehldsFuncs->MSG_WriteByte(dstDatagram, svc_voicedata); //svc_voicedata
|
||||||
g_RehldsFuncs->MSG_WriteByte(dstDatagram, 53); //svc_voicedata
|
|
||||||
g_RehldsFuncs->MSG_WriteByte(dstDatagram, cl->GetId());
|
g_RehldsFuncs->MSG_WriteByte(dstDatagram, cl->GetId());
|
||||||
g_RehldsFuncs->MSG_WriteShort(dstDatagram, nSendLen);
|
g_RehldsFuncs->MSG_WriteShort(dstDatagram, nSendLen);
|
||||||
g_RehldsFuncs->MSG_WriteBuf(dstDatagram, nSendLen, sendBuf);
|
g_RehldsFuncs->MSG_WriteBuf(dstDatagram, nSendLen, sendBuf);
|
||||||
@ -187,13 +190,13 @@ void SV_WriteVoiceCodec_hooked(IRehldsHook_SV_WriteVoiceCodec* chain, sizebuf_t*
|
|||||||
|
|
||||||
switch (plr->GetCodecType()) {
|
switch (plr->GetCodecType()) {
|
||||||
case vct_silk:
|
case vct_silk:
|
||||||
g_RehldsFuncs->MSG_WriteByte(sb, 52); //svc_voiceinit
|
g_RehldsFuncs->MSG_WriteByte(sb, svc_voiceinit); //svc_voiceinit
|
||||||
g_RehldsFuncs->MSG_WriteString(sb, ""); //codec id
|
g_RehldsFuncs->MSG_WriteString(sb, ""); //codec id
|
||||||
g_RehldsFuncs->MSG_WriteByte(sb, 0); //quality
|
g_RehldsFuncs->MSG_WriteByte(sb, 0); //quality
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case vct_speex:
|
case vct_speex:
|
||||||
g_RehldsFuncs->MSG_WriteByte(sb, 52); //svc_voiceinit
|
g_RehldsFuncs->MSG_WriteByte(sb, svc_voiceinit); //svc_voiceinit
|
||||||
g_RehldsFuncs->MSG_WriteString(sb, "voice_speex"); //codec id
|
g_RehldsFuncs->MSG_WriteString(sb, "voice_speex"); //codec id
|
||||||
g_RehldsFuncs->MSG_WriteByte(sb, 5); //quality
|
g_RehldsFuncs->MSG_WriteByte(sb, 5); //quality
|
||||||
break;
|
break;
|
||||||
|
@ -8,8 +8,8 @@ CRevoicePlayer::CRevoicePlayer() {
|
|||||||
m_SpeexCodec = new VoiceCodec_Frame(new VoiceEncoder_Speex());
|
m_SpeexCodec = new VoiceCodec_Frame(new VoiceEncoder_Speex());
|
||||||
m_SilkCodec = new CSteamP2PCodec(new VoiceEncoder_Silk());
|
m_SilkCodec = new CSteamP2PCodec(new VoiceEncoder_Silk());
|
||||||
|
|
||||||
m_SpeexCodec->Init(5);
|
m_SpeexCodec->Init(SPEEX_VOICE_QUALITY);
|
||||||
m_SilkCodec->Init(5);
|
m_SilkCodec->Init(SILK_VOICE_QUALITY);
|
||||||
|
|
||||||
m_RehldsClient = NULL;
|
m_RehldsClient = NULL;
|
||||||
m_Protocol = 0;
|
m_Protocol = 0;
|
||||||
@ -28,11 +28,13 @@ void CRevoicePlayer::InitVoice(revoice_codec_type codecType) {
|
|||||||
void CRevoicePlayer::OnConnected(int protocol) {
|
void CRevoicePlayer::OnConnected(int protocol) {
|
||||||
m_Protocol = protocol;
|
m_Protocol = protocol;
|
||||||
m_CodecType = vct_none;
|
m_CodecType = vct_none;
|
||||||
|
m_VoiceRate = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRevoicePlayer::OnDisconected() {
|
void CRevoicePlayer::OnDisconnected() {
|
||||||
m_Protocol = 0;
|
m_Protocol = 0;
|
||||||
m_CodecType = vct_none;
|
m_CodecType = vct_none;
|
||||||
|
m_VoiceRate = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Revoice_Init_Players() {
|
void Revoice_Init_Players() {
|
||||||
@ -55,3 +57,42 @@ CRevoicePlayer* GetPlayerByEdict(const edict_t* ed) {
|
|||||||
|
|
||||||
return &g_Players[clientId];
|
return &g_Players[clientId];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CRevoicePlayer::SetLastVoiceTime(double time)
|
||||||
|
{
|
||||||
|
UpdateVoiceRate(time - m_RehldsClient->GetLastVoiceTime());
|
||||||
|
m_RehldsClient->SetLastVoiceTime(time);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRevoicePlayer::UpdateVoiceRate(double delta)
|
||||||
|
{
|
||||||
|
if (m_VoiceRate)
|
||||||
|
{
|
||||||
|
switch (m_CodecType)
|
||||||
|
{
|
||||||
|
case vct_silk:
|
||||||
|
m_VoiceRate -= int(delta * MAX_SILK_VOICE_RATE) + MAX_SILK_DATA_LEN;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case vct_speex:
|
||||||
|
m_VoiceRate -= int(delta * MAX_SPEEX_VOICE_RATE) + MAX_SPEEX_DATA_LEN;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_VoiceRate < 0)
|
||||||
|
m_VoiceRate = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CRevoicePlayer::IncreaseVoiceRate(int dataLength)
|
||||||
|
{
|
||||||
|
m_VoiceRate += dataLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CRevoicePlayer::GetVoiceRate()
|
||||||
|
{
|
||||||
|
return m_VoiceRate;
|
||||||
|
}
|
@ -14,13 +14,18 @@ private:
|
|||||||
CSteamP2PCodec* m_SilkCodec;
|
CSteamP2PCodec* m_SilkCodec;
|
||||||
VoiceCodec_Frame* m_SpeexCodec;
|
VoiceCodec_Frame* m_SpeexCodec;
|
||||||
int m_Protocol;
|
int m_Protocol;
|
||||||
|
int m_VoiceRate;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CRevoicePlayer();
|
CRevoicePlayer();
|
||||||
void Initialize(IGameClient* cl);
|
void Initialize(IGameClient* cl);
|
||||||
void OnConnected(int protocol);
|
void OnConnected(int protocol);
|
||||||
void OnDisconected();
|
void OnDisconnected();
|
||||||
void InitVoice(revoice_codec_type codecType);
|
void InitVoice(revoice_codec_type codecType);
|
||||||
|
void SetLastVoiceTime(double time);
|
||||||
|
void UpdateVoiceRate(double delta);
|
||||||
|
void IncreaseVoiceRate(int dataLength);
|
||||||
|
int GetVoiceRate();
|
||||||
|
|
||||||
int GetProtocol() const { return m_Protocol; }
|
int GetProtocol() const { return m_Protocol; }
|
||||||
revoice_codec_type GetCodecType() const { return m_CodecType; }
|
revoice_codec_type GetCodecType() const { return m_CodecType; }
|
||||||
|
@ -3,13 +3,16 @@
|
|||||||
#include "rehlds_api.h"
|
#include "rehlds_api.h"
|
||||||
|
|
||||||
#define MAX_PLAYERS 32
|
#define MAX_PLAYERS 32
|
||||||
#define MAX_STEAMIDSALTLEN 64
|
|
||||||
|
|
||||||
#define LOG_PREFIX "[REVOICE]: "
|
#define LOG_PREFIX "[REVOICE]: "
|
||||||
|
|
||||||
#define HLDS_APPID 10
|
#define MAX_SILK_DATA_LEN 650
|
||||||
#define HLDS_APPVERSION "1.1.2.7/Stdio"
|
#define MAX_SPEEX_DATA_LEN 228
|
||||||
|
#define MAX_SILK_VOICE_RATE 3800
|
||||||
|
#define MAX_SPEEX_VOICE_RATE 2014
|
||||||
|
|
||||||
|
#define SILK_VOICE_QUALITY 5
|
||||||
|
#define SPEEX_VOICE_QUALITY 5
|
||||||
|
|
||||||
enum revoice_log_mode {
|
enum revoice_log_mode {
|
||||||
rl_none = 0,
|
rl_none = 0,
|
||||||
@ -23,6 +26,11 @@ enum revoice_codec_type {
|
|||||||
vct_speex,
|
vct_speex,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum svc_messages {
|
||||||
|
svc_voiceinit = 52,
|
||||||
|
svc_voicedata = 53
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T _min(T a, T b) {
|
T _min(T a, T b) {
|
||||||
return (a < b) ? a : b;
|
return (a < b) ? a : b;
|
||||||
|
@ -69,7 +69,6 @@ uint32 crc32(const void* buf, unsigned int bufLen) {
|
|||||||
return hCrc;
|
return hCrc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void util_syserror(const char* fmt, ...)
|
void util_syserror(const char* fmt, ...)
|
||||||
{
|
{
|
||||||
va_list argptr;
|
va_list argptr;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user