mirror of
https://github.com/rehlds/revoice.git
synced 2025-03-03 17:15:25 +03:00
Implement simple voice playback for codecs testing purposes
This commit is contained in:
parent
15780dfcaf
commit
f0b5d960b3
@ -1,27 +1,27 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, (subject to the limitations in the disclaimer below)
|
||||
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, (subject to the limitations in the disclaimer below)
|
||||
are permitted provided that the following conditions are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Skype Limited, nor the names of specific
|
||||
contributors, may be used to endorse or promote products derived from
|
||||
- Neither the name of Skype Limited, nor the names of specific
|
||||
contributors, may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
|
||||
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
|
||||
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
|
||||
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
@ -73,7 +73,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
# define SKP_STR_CASEINSENSITIVE_COMPARE(x, y) _stricmp(x, y)
|
||||
#else
|
||||
# define SKP_STR_CASEINSENSITIVE_COMPARE(x, y) strcasecmp(x, y)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define SKP_int64_MAX ((SKP_int64)0x7FFFFFFFFFFFFFFFLL) /* 2^63 - 1 */
|
||||
#define SKP_int64_MIN ((SKP_int64)0x8000000000000000LL) /* -2^63 */
|
||||
|
@ -1,27 +1,27 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, (subject to the limitations in the disclaimer below)
|
||||
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, (subject to the limitations in the disclaimer below)
|
||||
are permitted provided that the following conditions are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Skype Limited, nor the names of specific
|
||||
contributors, may be used to endorse or promote products derived from
|
||||
- Neither the name of Skype Limited, nor the names of specific
|
||||
contributors, may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
|
||||
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
|
||||
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
|
||||
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
@ -41,9 +41,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
SKP_int SKP_Silk_SDK_Get_Encoder_Size( SKP_int32 *encSizeBytes )
|
||||
{
|
||||
SKP_int ret = 0;
|
||||
|
||||
|
||||
*encSizeBytes = sizeof( SKP_Silk_encoder_state_FLP );
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -83,7 +83,7 @@ SKP_int SKP_Silk_SDK_InitEncoder(
|
||||
SKP_Silk_encoder_state_FLP *psEnc;
|
||||
SKP_int ret = 0;
|
||||
|
||||
|
||||
|
||||
psEnc = ( SKP_Silk_encoder_state_FLP* )encState;
|
||||
|
||||
/* Reset Encoder */
|
||||
@ -103,7 +103,7 @@ SKP_int SKP_Silk_SDK_InitEncoder(
|
||||
/**************************/
|
||||
/* Encode frame with Silk */
|
||||
/**************************/
|
||||
SKP_int SKP_Silk_SDK_Encode(
|
||||
SKP_int SKP_Silk_SDK_Encode(
|
||||
void *encState, /* I/O: State */
|
||||
const SKP_Silk_EncodeControlStruct *encControl, /* I: Control structure */
|
||||
const SKP_int16 *samplesIn, /* I: Speech sample input vector */
|
||||
@ -124,7 +124,7 @@ SKP_int SKP_Silk_SDK_Encode(
|
||||
if( ( ( encControl->API_sampleRate != 8000 ) &&
|
||||
( encControl->API_sampleRate != 12000 ) &&
|
||||
( encControl->API_sampleRate != 16000 ) &&
|
||||
( encControl->API_sampleRate != 24000 ) &&
|
||||
( encControl->API_sampleRate != 24000 ) &&
|
||||
( encControl->API_sampleRate != 32000 ) &&
|
||||
( encControl->API_sampleRate != 44100 ) &&
|
||||
( encControl->API_sampleRate != 48000 ) ) ||
|
||||
@ -161,7 +161,7 @@ SKP_int SKP_Silk_SDK_Encode(
|
||||
}
|
||||
|
||||
TargetRate_bps = SKP_LIMIT( TargetRate_bps, MIN_TARGET_RATE_BPS, MAX_TARGET_RATE_BPS );
|
||||
if( ( ret = SKP_Silk_control_encoder_FLP( psEnc, PacketSize_ms, TargetRate_bps,
|
||||
if( ( ret = SKP_Silk_control_encoder_FLP( psEnc, PacketSize_ms, TargetRate_bps,
|
||||
PacketLoss_perc, UseDTX, Complexity) ) != 0 ) {
|
||||
SKP_assert( 0 );
|
||||
return( ret );
|
||||
@ -176,8 +176,8 @@ SKP_int SKP_Silk_SDK_Encode(
|
||||
|
||||
#if MAX_FS_KHZ > 16
|
||||
/* Detect energy above 8 kHz */
|
||||
if( SKP_min( API_fs_Hz, 1000 * max_internal_fs_kHz ) == 24000 &&
|
||||
psEnc->sCmn.sSWBdetect.SWB_detected == 0 &&
|
||||
if( SKP_min( API_fs_Hz, 1000 * max_internal_fs_kHz ) == 24000 &&
|
||||
psEnc->sCmn.sSWBdetect.SWB_detected == 0 &&
|
||||
psEnc->sCmn.sSWBdetect.WB_detected == 0 ) {
|
||||
SKP_Silk_detect_SWB_input( &psEnc->sCmn.sSWBdetect, samplesIn, ( SKP_int )nSamplesIn );
|
||||
}
|
||||
@ -187,18 +187,18 @@ SKP_int SKP_Silk_SDK_Encode(
|
||||
MaxBytesOut = 0; /* return 0 output bytes if no encoder called */
|
||||
while( 1 ) {
|
||||
nSamplesToBuffer = psEnc->sCmn.frame_length - psEnc->sCmn.inputBufIx;
|
||||
if( API_fs_Hz == SKP_SMULBB( 1000, psEnc->sCmn.fs_kHz ) ) {
|
||||
if( API_fs_Hz == SKP_SMULBB( 1000, psEnc->sCmn.fs_kHz ) ) {
|
||||
nSamplesToBuffer = SKP_min_int( nSamplesToBuffer, nSamplesIn );
|
||||
nSamplesFromInput = nSamplesToBuffer;
|
||||
/* Copy to buffer */
|
||||
SKP_memcpy( &psEnc->sCmn.inputBuf[ psEnc->sCmn.inputBufIx ], samplesIn, nSamplesFromInput * sizeof( SKP_int16 ) );
|
||||
} else {
|
||||
} else {
|
||||
nSamplesToBuffer = SKP_min( nSamplesToBuffer, 10 * input_10ms * psEnc->sCmn.fs_kHz );
|
||||
nSamplesFromInput = SKP_DIV32_16( nSamplesToBuffer * API_fs_Hz, psEnc->sCmn.fs_kHz * 1000 );
|
||||
/* Resample and write to buffer */
|
||||
ret += SKP_Silk_resampler( &psEnc->sCmn.resampler_state,
|
||||
ret += SKP_Silk_resampler( &psEnc->sCmn.resampler_state,
|
||||
&psEnc->sCmn.inputBuf[ psEnc->sCmn.inputBufIx ], samplesIn, nSamplesFromInput );
|
||||
}
|
||||
}
|
||||
samplesIn += nSamplesFromInput;
|
||||
nSamplesIn -= nSamplesFromInput;
|
||||
psEnc->sCmn.inputBufIx += nSamplesToBuffer;
|
||||
|
@ -1,27 +1,27 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, (subject to the limitations in the disclaimer below)
|
||||
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, (subject to the limitations in the disclaimer below)
|
||||
are permitted provided that the following conditions are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Skype Limited, nor the names of specific
|
||||
contributors, may be used to endorse or promote products derived from
|
||||
- Neither the name of Skype Limited, nor the names of specific
|
||||
contributors, may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
|
||||
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
|
||||
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
|
||||
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
@ -57,7 +57,7 @@ typedef struct {
|
||||
|
||||
/* Struct for Low BitRate Redundant (LBRR) information */
|
||||
typedef struct {
|
||||
SKP_uint8 payload[ MAX_ARITHM_BYTES ];
|
||||
SKP_uint8 payload[ MAX_ARITHM_BYTES ];
|
||||
SKP_int nBytes; /* Number of bytes in payload */
|
||||
SKP_int usage; /* Tells how the payload should be used as FEC */
|
||||
} SKP_SILK_LBRR_struct;
|
||||
@ -190,7 +190,7 @@ typedef struct {
|
||||
|
||||
const SKP_Silk_NLSF_CB_struct *psNLSF_CB[ 2 ]; /* Pointers to voiced/unvoiced NLSF codebooks */
|
||||
|
||||
/* Struct for Inband LBRR */
|
||||
/* Struct for Inband LBRR */
|
||||
SKP_SILK_LBRR_struct LBRR_buffer[ MAX_LBRR_DELAY ];
|
||||
SKP_int oldest_LBRR_idx;
|
||||
SKP_int useInBandFEC; /* Saves the API setting for query */
|
||||
@ -310,7 +310,7 @@ typedef struct {
|
||||
/* Parameters used to investigate if inband FEC is used */
|
||||
SKP_int vadFlag;
|
||||
SKP_int no_FEC_counter; /* Counts number of frames wo inband FEC */
|
||||
SKP_int inband_FEC_offset; /* 0: no FEC, 1: FEC with 1 packet offset, 2: FEC w 2 packets offset */
|
||||
SKP_int inband_FEC_offset; /* 0: no FEC, 1: FEC with 1 packet offset, 2: FEC w 2 packets offset */
|
||||
|
||||
/* CNG state */
|
||||
SKP_Silk_CNG_struct sCNG;
|
||||
|
@ -1,27 +1,27 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, (subject to the limitations in the disclaimer below)
|
||||
Copyright (c) 2006-2012, Skype Limited. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, (subject to the limitations in the disclaimer below)
|
||||
are permitted provided that the following conditions are met:
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
- Neither the name of Skype Limited, nor the names of specific
|
||||
contributors, may be used to endorse or promote products derived from
|
||||
- Neither the name of Skype Limited, nor the names of specific
|
||||
contributors, may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
|
||||
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED
|
||||
BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
|
||||
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
|
BIN
revoice/dist/c2a2_ba_launch.wav
vendored
Normal file
BIN
revoice/dist/c2a2_ba_launch.wav
vendored
Normal file
Binary file not shown.
BIN
revoice/dist/cslig_nuages.wav
vendored
Normal file
BIN
revoice/dist/cslig_nuages.wav
vendored
Normal file
Binary file not shown.
BIN
revoice/dist/dance.wav
vendored
Normal file
BIN
revoice/dist/dance.wav
vendored
Normal file
Binary file not shown.
BIN
revoice/dist/kolshik.wav
vendored
Normal file
BIN
revoice/dist/kolshik.wav
vendored
Normal file
Binary file not shown.
BIN
revoice/dist/pchela.wav
vendored
Normal file
BIN
revoice/dist/pchela.wav
vendored
Normal file
Binary file not shown.
@ -145,7 +145,7 @@
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)../src/;$(ProjectDir)../public/;$(ProjectDir)../version/;$(ProjectDir)../include/;$(SolutionDir)../dep/rehlsdk/common/;$(SolutionDir)../dep/rehlsdk/dlls/;$(SolutionDir)../dep/rehlsdk/engine/;$(SolutionDir)../dep/rehlsdk/public/;$(SolutionDir)../dep/silk/include/;$(SolutionDir)../dep/opus/include/;$(SolutionDir)../dep/speex/include/;$(SolutionDir)../dep/metamod/;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(ProjectDir)../src/;$(ProjectDir)../public/;$(ProjectDir)../version/;$(ProjectDir)../include/;$(SolutionDir)../dep/rehlsdk/common/;$(SolutionDir)../dep/rehlsdk/dlls/;$(SolutionDir)../dep/rehlsdk/engine/;$(SolutionDir)../dep/rehlsdk/public/;$(SolutionDir)../dep/silk/include/;$(SolutionDir)../dep/opus/include/;$(SolutionDir)../dep/speex/include/;$(SolutionDir)../dep/metamod/;$(SolutionDir)../dep/opus/silk/;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PrecompiledHeaderFile>precompiled.h</PrecompiledHeaderFile>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
|
@ -12,6 +12,7 @@ public:
|
||||
// Initialize the object. The uncompressed format is always 8-bit signed mono.
|
||||
virtual bool Init(int quality) = 0;
|
||||
virtual void Release() = 0;
|
||||
virtual int GetSamplesPerFrame() { return 0; }
|
||||
|
||||
// Compress the voice data.
|
||||
// pUncompressed - 16-bit signed mono voice data.
|
||||
|
188
revoice/public/counter.h
Normal file
188
revoice/public/counter.h
Normal file
@ -0,0 +1,188 @@
|
||||
/*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* In addition, as a special exception, the author gives permission to
|
||||
* link the code of this program with the Half-Life Game Engine ("HL
|
||||
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
||||
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
||||
* respects for all of the code used other than the HL Engine and MODs
|
||||
* from Valve. If you modify this file, you may extend this exception
|
||||
* to your version of the file, but you are not obligated to do so. If
|
||||
* you do not wish to do so, delete this exception statement from your
|
||||
* version.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
#include <windows.h>
|
||||
#include <io.h>
|
||||
#include <direct.h>
|
||||
#else
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#ifdef OSX
|
||||
#include <limits.h>
|
||||
#else
|
||||
#include <linux/limits.h>
|
||||
#endif
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
class CCounter
|
||||
{
|
||||
public:
|
||||
CCounter();
|
||||
|
||||
bool Init();
|
||||
double GetCurTime();
|
||||
|
||||
private:
|
||||
int m_iLowShift;
|
||||
double m_flPerfCounterFreq;
|
||||
double m_flCurrentTime;
|
||||
double m_flLastCurrentTime;
|
||||
};
|
||||
|
||||
inline CCounter::CCounter() :
|
||||
m_iLowShift(0),
|
||||
m_flPerfCounterFreq(0),
|
||||
m_flCurrentTime(0),
|
||||
m_flLastCurrentTime(0)
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
inline bool CCounter::Init()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
LARGE_INTEGER performanceFreq;
|
||||
if (!QueryPerformanceFrequency(&performanceFreq))
|
||||
return false;
|
||||
|
||||
// get 32 out of the 64 time bits such that we have around
|
||||
// 1 microsecond resolution
|
||||
unsigned int lowpart, highpart;
|
||||
lowpart = (unsigned int)performanceFreq.LowPart;
|
||||
highpart = (unsigned int)performanceFreq.HighPart;
|
||||
m_iLowShift = 0;
|
||||
|
||||
while (highpart || (lowpart > 2000000.0))
|
||||
{
|
||||
m_iLowShift++;
|
||||
lowpart >>= 1;
|
||||
lowpart |= (highpart & 1) << 31;
|
||||
highpart >>= 1;
|
||||
}
|
||||
|
||||
m_flPerfCounterFreq = 1.0 / (double)lowpart;
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline double CCounter::GetCurTime()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
static int sametimecount;
|
||||
static unsigned int oldtime;
|
||||
static int first = 1;
|
||||
LARGE_INTEGER PerformanceCount;
|
||||
unsigned int temp, t2;
|
||||
double time;
|
||||
|
||||
QueryPerformanceCounter(&PerformanceCount);
|
||||
if (m_iLowShift == 0)
|
||||
{
|
||||
temp = (unsigned int)PerformanceCount.LowPart;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp = ((unsigned int)PerformanceCount.LowPart >> m_iLowShift) |
|
||||
((unsigned int)PerformanceCount.HighPart << (32 - m_iLowShift));
|
||||
}
|
||||
|
||||
if (first)
|
||||
{
|
||||
oldtime = temp;
|
||||
first = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// check for turnover or backward time
|
||||
if ((temp <= oldtime) && ((oldtime - temp) < 0x10000000))
|
||||
{
|
||||
// so we can't get stuck
|
||||
oldtime = temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
t2 = temp - oldtime;
|
||||
|
||||
time = (double)t2 * m_flPerfCounterFreq;
|
||||
oldtime = temp;
|
||||
|
||||
m_flCurrentTime += time;
|
||||
|
||||
if (m_flCurrentTime == m_flLastCurrentTime)
|
||||
{
|
||||
if (++sametimecount > 100000)
|
||||
{
|
||||
m_flCurrentTime += 1.0;
|
||||
sametimecount = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sametimecount = 0;
|
||||
}
|
||||
|
||||
m_flLastCurrentTime = m_flCurrentTime;
|
||||
}
|
||||
}
|
||||
|
||||
return m_flCurrentTime;
|
||||
|
||||
#else // _WIN32
|
||||
|
||||
struct timeval tp;
|
||||
static int secbase = 0;
|
||||
|
||||
gettimeofday(&tp, NULL);
|
||||
|
||||
if (!secbase)
|
||||
{
|
||||
secbase = tp.tv_sec;
|
||||
return (tp.tv_usec / 1000000.0);
|
||||
}
|
||||
|
||||
return ((tp.tv_sec - secbase) + tp.tv_usec / 1000000.0);
|
||||
|
||||
#endif // _WIN32
|
||||
}
|
@ -90,10 +90,10 @@ int CSteamP2PCodec::StreamEncode(const char *pUncompressedBytes, int nSamples, c
|
||||
}
|
||||
|
||||
*(writePos++) = PLT_SamplingRate; // Set sampling rate
|
||||
*(uint16 *)writePos = 16000;
|
||||
*(uint16 *)writePos = 8000;
|
||||
writePos += 2;
|
||||
|
||||
*(writePos++) = PLT_Silk; // Voice payload
|
||||
*(writePos++) = PLT_Silk;//PLT_Silk; // Voice payload
|
||||
|
||||
int compressRes = m_BackendCodec->Compress(pUncompressedBytes, nSamples, writePos + 2, maxCompressedBytes - (1 + 2 + 1 + 2), bFinal);
|
||||
if (compressRes == 0) {
|
||||
@ -123,18 +123,37 @@ int CSteamP2PCodec::Decompress(const char *pCompressed, int compressedBytes, cha
|
||||
return StreamDecode(pCompressed + 8, compressedBytes - 12, pUncompressed, maxUncompressedBytes);
|
||||
}
|
||||
|
||||
extern uint64_t g_ulSteamIdCurrent;
|
||||
|
||||
int CSteamP2PCodec::Compress(const char *pUncompressedBytes, int nSamples, char *pCompressed, int maxCompressedBytes, bool bFinal)
|
||||
{
|
||||
if (maxCompressedBytes < 12) { // no room
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*union CSteamID
|
||||
{
|
||||
uint64 allbits64;
|
||||
struct
|
||||
{
|
||||
uint32 lo;
|
||||
uint32 hi;
|
||||
};
|
||||
};
|
||||
|
||||
CSteamID steamid;
|
||||
steamid.allbits64 = 76561198051972183;
|
||||
|
||||
char *writePos = pCompressed;
|
||||
*(uint32 *)writePos = 0x00000011; // steamid (low part)
|
||||
*(uint32 *)writePos = steamid.lo; // steamid (low part)
|
||||
writePos += 4;
|
||||
|
||||
*(uint32 *)writePos = 0x01100001; // steamid (high part)
|
||||
writePos += 4;
|
||||
*(uint32 *)writePos = steamid.hi; // steamid (high part)
|
||||
writePos += 4;*/
|
||||
|
||||
char *writePos = pCompressed;
|
||||
*(uint64 *)writePos = g_ulSteamIdCurrent;//76561198051972183;
|
||||
writePos += 8;
|
||||
|
||||
int encodeRes = StreamEncode(pUncompressedBytes, nSamples, writePos, maxCompressedBytes - 12, bFinal);
|
||||
if (encodeRes <= 0) {
|
||||
|
@ -59,82 +59,88 @@ bool VoiceEncoder_Silk::ResetState()
|
||||
|
||||
int VoiceEncoder_Silk::Compress(const char *pUncompressedIn, int nSamplesIn, char *pCompressed, int maxCompressedBytes, bool bFinal)
|
||||
{
|
||||
signed int nSamplesToUse; // edi@4
|
||||
const __int16 *psRead; // ecx@4
|
||||
int nSamples; // edi@5
|
||||
int nSamplesToEncode; // esi@6
|
||||
char *pWritePos; // ebp@6
|
||||
int nSamplesPerFrame; // [sp+28h] [bp-44h]@5
|
||||
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 = inSampleRate * nSampleDataMinMS / 1000;
|
||||
const int nSampleDataMinMS = 20;
|
||||
const int nSamplesMin = (nSampleDataMinMS * inSampleRate) / 1000;
|
||||
|
||||
/*
|
||||
if ((nSamplesIn + m_bufOverflowBytes.TellPut() / 2) < nSamplesMin && !bFinal) {
|
||||
m_bufOverflowBytes.Put(pUncompressedIn, 2 * nSamplesIn);
|
||||
if (nSamplesIn + GetNumQueuedEncodingSamples() < nSamplesMin && !bFinal)
|
||||
{
|
||||
m_bufOverflowBytes.Put(pUncompressedIn, nSamplesIn * BYTES_PER_SAMPLE);
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
if (m_bufOverflowBytes.TellPut()) {
|
||||
m_bufOverflowBytes.Put(pUncompressedIn, 2 * nSamplesIn);
|
||||
const int16_t *psRead = (const int16_t *)pUncompressedIn;
|
||||
|
||||
psRead = (const __int16 *)m_bufOverflowBytes.Base();
|
||||
nSamplesToUse = m_bufOverflowBytes.TellPut() / 2;
|
||||
} else {
|
||||
psRead = (const __int16 *)pUncompressedIn;
|
||||
nSamplesToUse = nSamplesIn;
|
||||
int nSamplesToUse = nSamplesIn;
|
||||
int nSamplesPerFrame = nSamplesMin;
|
||||
int nSamplesRemaining = nSamplesIn % nSamplesMin;
|
||||
|
||||
if (m_bufOverflowBytes.TellPut() || nSamplesRemaining && bFinal)
|
||||
{
|
||||
m_bufOverflowBytes.Put(pUncompressedIn, nSamplesIn * BYTES_PER_SAMPLE);
|
||||
nSamplesToUse = GetNumQueuedEncodingSamples();
|
||||
nSamplesRemaining = nSamplesToUse % nSamplesPerFrame;
|
||||
|
||||
if (bFinal && nSamplesRemaining)
|
||||
{
|
||||
// fill samples of silence at the remaining bytes
|
||||
for (int i = nSamplesPerFrame - nSamplesRemaining; i > 0; i--)
|
||||
{
|
||||
m_bufOverflowBytes.PutShort(0);
|
||||
}
|
||||
|
||||
nSamplesToUse = GetNumQueuedEncodingSamples();
|
||||
nSamplesRemaining = nSamplesToUse % nSamplesPerFrame;
|
||||
}
|
||||
|
||||
psRead = (const int16_t *)m_bufOverflowBytes.Base();
|
||||
Assert(!bFinal || nSamplesRemaining == 0);
|
||||
}
|
||||
|
||||
nSamplesPerFrame = inSampleRate / 50;
|
||||
nSamplesRemaining = nSamplesToUse % nSamplesPerFrame;
|
||||
pWritePosMax = pCompressed + maxCompressedBytes;
|
||||
nSamples = nSamplesToUse - nSamplesRemaining;
|
||||
pWritePos = pCompressed;
|
||||
char *pWritePos = pCompressed;
|
||||
const char *pWritePosMax = &pCompressed[maxCompressedBytes];
|
||||
|
||||
int nSamples = nSamplesToUse - nSamplesRemaining;
|
||||
while (nSamples > 0)
|
||||
{
|
||||
int16 *pWritePayloadSize = (int16 *)pWritePos;
|
||||
pWritePos += sizeof(int16); //leave 2 bytes for the frame size (will be written after encoding)
|
||||
int16_t *pWritePayloadSize = (int16_t *)pWritePos;
|
||||
pWritePos += sizeof(int16_t);
|
||||
|
||||
int originalNBytes = (pWritePosMax - pWritePos > 0xFFFF) ? -1 : (pWritePosMax - pWritePos);
|
||||
nSamplesToEncode = (nSamples < nSamplesPerFrame) ? nSamples : nSamplesPerFrame;
|
||||
m_encControl.maxInternalSampleRate = 24000;
|
||||
m_encControl.useInBandFEC = 0;
|
||||
m_encControl.useDTX = 1;
|
||||
m_encControl.complexity = 2;
|
||||
m_encControl.API_sampleRate = inSampleRate;
|
||||
m_encControl.packetSize = 20 * (inSampleRate / 1000);
|
||||
m_encControl.packetLossPercentage = m_packetLoss_perc;
|
||||
m_encControl.bitRate = 30000;//(m_targetRate_bps >= 0) ? m_targetRate_bps : 0;//clamp(voice_silk_bitrate.GetInt(), 10000, 40000);
|
||||
|
||||
this->m_encControl.useDTX = 0;
|
||||
this->m_encControl.maxInternalSampleRate = 16000;
|
||||
this->m_encControl.useInBandFEC = 0;
|
||||
this->m_encControl.API_sampleRate = inSampleRate;
|
||||
this->m_encControl.complexity = 2;
|
||||
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;
|
||||
int nSamplesToEncode = min(nSamples, nSamplesPerFrame);
|
||||
|
||||
int nBytes = ((pWritePosMax - pWritePos) < 0x7FFF) ? (pWritePosMax - pWritePos) : 0x7FFF;
|
||||
int ret = SKP_Silk_SDK_Encode(m_pEncoder, &m_encControl, psRead, nSamplesToEncode, (unsigned char *)pWritePos, (__int16 *)&nBytes);
|
||||
*pWritePayloadSize = nBytes; // write frame size
|
||||
|
||||
nSamples -= nSamplesToEncode;
|
||||
|
||||
int16 nBytes = originalNBytes;
|
||||
int res = SKP_Silk_SDK_Encode(this->m_pEncoder, &this->m_encControl, psRead, nSamplesToEncode, (unsigned char *)pWritePos, &nBytes);
|
||||
*pWritePayloadSize = nBytes; //write frame size
|
||||
|
||||
pWritePos += nBytes;
|
||||
psRead += nSamplesToEncode;
|
||||
pWritePos += nBytes;
|
||||
}
|
||||
|
||||
m_bufOverflowBytes.Clear();
|
||||
|
||||
if (nSamplesRemaining <= nSamplesIn && nSamplesRemaining) {
|
||||
m_bufOverflowBytes.Put(&pUncompressedIn[2 * (nSamplesIn - nSamplesRemaining)], 2 * nSamplesRemaining);
|
||||
if (nSamplesRemaining && nSamplesRemaining <= nSamplesIn)
|
||||
{
|
||||
m_bufOverflowBytes.Put(pUncompressedIn + ((nSamplesIn - nSamplesRemaining) * sizeof(int16_t)), nSamplesRemaining * BYTES_PER_SAMPLE);
|
||||
}
|
||||
|
||||
if (bFinal)
|
||||
{
|
||||
ResetState();
|
||||
|
||||
if (pWritePosMax > pWritePos + 2) {
|
||||
uint16 *pWriteEndFlag = (uint16*)pWritePos;
|
||||
pWritePos += sizeof(uint16);
|
||||
if (pWritePosMax > pWritePos + 2)
|
||||
{
|
||||
uint16_t *pWriteEndFlag = (uint16_t *)pWritePos;
|
||||
pWritePos += sizeof(uint16_t);
|
||||
*pWriteEndFlag = 0xFFFF;
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ public:
|
||||
|
||||
virtual bool Init(int quality);
|
||||
virtual void Release();
|
||||
virtual bool ResetState();
|
||||
virtual bool ResetState();
|
||||
virtual int Compress(const char *pUncompressedBytes, int nSamples, char *pCompressed, int maxCompressedBytes, bool bFinal);
|
||||
virtual int Decompress(const char *pCompressed, int compressedBytes, char *pUncompressed, int maxUncompressedBytes);
|
||||
|
||||
|
@ -52,7 +52,7 @@ DLL_FUNCTIONS g_DLLFuncTable =
|
||||
NULL, // pfnClientDisconnect
|
||||
NULL, // pfnClientKill
|
||||
NULL, // pfnClientPutInServer
|
||||
NULL, // pfnClientCommand
|
||||
&ClientCommand, // pfnClientCommand
|
||||
NULL, // pfnClientUserInfoChanged
|
||||
NULL, // pfnServerActivate
|
||||
NULL, // pfnServerDeactivate
|
||||
@ -105,14 +105,14 @@ DLL_FUNCTIONS g_DLLFuncTable_Post =
|
||||
NULL, // pfnClientConnect
|
||||
NULL, // pfnClientDisconnect
|
||||
NULL, // pfnClientKill
|
||||
NULL, // pfnClientPutInServer
|
||||
&ClientPutInServer_PostHook, // pfnClientPutInServer
|
||||
NULL, // pfnClientCommand
|
||||
NULL, // pfnClientUserInfoChanged
|
||||
&ServerActivate_PostHook, // pfnServerActivate
|
||||
NULL, // pfnServerDeactivate
|
||||
NULL, // pfnPlayerPreThink
|
||||
NULL, // pfnPlayerPostThink
|
||||
NULL, // pfnStartFrame
|
||||
&StartFrame_Post, // pfnStartFrame
|
||||
NULL, // pfnParmsNewLevel
|
||||
NULL, // pfnParmsChangeLevel
|
||||
NULL, // pfnGetGameDescription
|
||||
|
@ -18,6 +18,9 @@ bool Revoice_Init_Config()
|
||||
const char *pszGameDir = GET_GAME_INFO(PLID, GINFO_GAMEDIR);
|
||||
const char *pszPluginDir = GET_PLUGIN_PATH(PLID);
|
||||
|
||||
printf("> pszGameDir: (%s)\n", pszGameDir);
|
||||
printf("> pszPluginDir: (%s)\n", pszPluginDir);
|
||||
|
||||
char szRelativePath[MAX_PATH];
|
||||
strncpy(szRelativePath, &pszPluginDir[strlen(pszGameDir) + 1], sizeof(szRelativePath) - 1);
|
||||
szRelativePath[sizeof(szRelativePath) - 1] = '\0';
|
||||
@ -94,7 +97,7 @@ void Cmd_REV_Status()
|
||||
for (int i = 0; i < g_RehldsSvs->GetMaxClients(); i++) {
|
||||
auto plr = &g_Players[i];
|
||||
if (plr->IsConnected()) {
|
||||
printf("#%-4i %-32s %-6s %-4i %-2i %-3s", i + 1, UTIL_VarArgs("\"%s\"", plr->GetClient()->GetName()), plr->GetCodecTypeToString(), plr->GetVoiceRate(), plr->GetProtocol(), plr->IsHLTV() ? " (HLTV)" : "");
|
||||
UTIL_ServerPrintf("#%-4i %-32s %-6s %-4i %-2i %-3s", i + 1, UTIL_VarArgs("\"%s\"", plr->GetClient()->GetName()), plr->GetCodecTypeToString(), plr->GetVoiceRate(), plr->GetProtocol(), plr->IsHLTV() ? " (HLTV)" : "");
|
||||
nUsers++;
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ void CvarValue2_PreHook(const edict_t *pEnt, int requestID, const char *cvarName
|
||||
if (lastSeparator)
|
||||
{
|
||||
int buildNumber = atoi(lastSeparator + 1);
|
||||
if (buildNumber > 4554) {
|
||||
if (buildNumber > 4554 || buildNumber == 2017) {
|
||||
plr->SetCodecType(vct_opus);
|
||||
}
|
||||
}
|
||||
@ -75,52 +75,34 @@ void SV_ParseVoiceData_emu(IGameClient *cl)
|
||||
}
|
||||
|
||||
CRevoicePlayer *srcPlayer = GetPlayerByClientPtr(cl);
|
||||
srcPlayer->SetLastVoiceTime(g_RehldsSv->GetTime());
|
||||
|
||||
//FILE *fp = fopen("recorder.snd", "ab");
|
||||
//if (fp)
|
||||
//{
|
||||
// printf(" -> Write chunk: (%d)\n", nDataLength);
|
||||
// fwrite(chReceived, 1, nDataLength, fp);
|
||||
// fclose(fp);
|
||||
//}
|
||||
|
||||
/*srcPlayer->SetLastVoiceTime(g_RehldsSv->GetTime());
|
||||
srcPlayer->IncreaseVoiceRate(nDataLength);
|
||||
|
||||
char transcodedBuf[4096];
|
||||
char compressedBuf[16384];
|
||||
int compressedSize = TranscodeVoice(srcPlayer, chReceived, nDataLength, srcPlayer->GetOpusCodec(), srcPlayer->GetSilkCodec(), compressedBuf, sizeof(compressedBuf));
|
||||
|
||||
char *silkData = nullptr;
|
||||
char *speexData = nullptr;
|
||||
uint32_t computedChecksum = crc32(compressedBuf, compressedSize - 4);
|
||||
uint32 wireChecksum = *(uint32 *)(compressedBuf + compressedSize - 4);
|
||||
|
||||
int silkDataLen = 0;
|
||||
int speexDataLen = 0;
|
||||
|
||||
switch (srcPlayer->GetCodecType())
|
||||
FILE *fp = fopen("recorder.snd", "ab");
|
||||
if (fp)
|
||||
{
|
||||
case vct_silk:
|
||||
{
|
||||
if (nDataLength > MAX_SILK_DATA_LEN || srcPlayer->GetVoiceRate() > MAX_SILK_VOICE_RATE)
|
||||
return;
|
||||
printf(" -> Write chunk: (%d), computedChecksum: (%u), wireChecksum: (%u)\n", compressedSize, computedChecksum, wireChecksum);
|
||||
printf(" -> Write chunk: (%d), computedChecksum: (%u), wireChecksum: (%u)\n", compressedSize, computedChecksum, wireChecksum);
|
||||
fwrite(compressedBuf, 1, compressedSize, fp);
|
||||
fclose(fp);
|
||||
}*/
|
||||
|
||||
silkData = chReceived; silkDataLen = nDataLength;
|
||||
speexData = transcodedBuf;
|
||||
speexDataLen = TranscodeVoice(srcPlayer, silkData, silkDataLen, srcPlayer->GetSilkCodec(), srcPlayer->GetSpeexCodec(), transcodedBuf, sizeof(transcodedBuf));
|
||||
break;
|
||||
}
|
||||
case vct_opus:
|
||||
{
|
||||
if (nDataLength > MAX_OPUS_DATA_LEN || srcPlayer->GetVoiceRate() > MAX_OPUS_VOICE_RATE)
|
||||
return;
|
||||
|
||||
silkData = chReceived; silkDataLen = nDataLength;
|
||||
speexData = transcodedBuf;
|
||||
speexDataLen = TranscodeVoice(srcPlayer, silkData, silkDataLen, srcPlayer->GetOpusCodec(), srcPlayer->GetSpeexCodec(), transcodedBuf, sizeof(transcodedBuf));
|
||||
break;
|
||||
}
|
||||
case vct_speex:
|
||||
{
|
||||
if (nDataLength > MAX_SPEEX_DATA_LEN || srcPlayer->GetVoiceRate() > MAX_SPEEX_VOICE_RATE)
|
||||
return;
|
||||
|
||||
speexData = chReceived; speexDataLen = nDataLength;
|
||||
silkData = transcodedBuf;
|
||||
silkDataLen = TranscodeVoice(srcPlayer, speexData, speexDataLen, srcPlayer->GetSpeexCodec(), srcPlayer->GetSilkCodec(), transcodedBuf, sizeof(transcodedBuf));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
//return;
|
||||
|
||||
int maxclients = g_RehldsSvs->GetMaxClients();
|
||||
for (int i = 0; i < maxclients; i++)
|
||||
@ -128,43 +110,21 @@ void SV_ParseVoiceData_emu(IGameClient *cl)
|
||||
CRevoicePlayer *dstPlayer = &g_Players[i];
|
||||
IGameClient *dstClient = dstPlayer->GetClient();
|
||||
|
||||
if (!((1 << i) & cl->GetVoiceStream(0)) && dstPlayer != srcPlayer)
|
||||
if (!((1 << i) & cl->GetVoiceStream(0)) && dstPlayer != srcPlayer) {
|
||||
continue;
|
||||
|
||||
if (!dstClient->IsActive() && !dstClient->IsConnected() && dstPlayer != srcPlayer)
|
||||
continue;
|
||||
|
||||
char *sendBuf;
|
||||
int nSendLen;
|
||||
switch (dstPlayer->GetCodecType())
|
||||
{
|
||||
case vct_silk:
|
||||
case vct_opus:
|
||||
sendBuf = silkData;
|
||||
nSendLen = silkDataLen;
|
||||
break;
|
||||
case vct_speex:
|
||||
sendBuf = speexData;
|
||||
nSendLen = speexDataLen;
|
||||
break;
|
||||
default:
|
||||
sendBuf = nullptr;
|
||||
nSendLen = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (sendBuf == nullptr || nSendLen == 0)
|
||||
if (!dstClient->IsActive() && !dstClient->IsConnected() && dstPlayer != srcPlayer) {
|
||||
continue;
|
||||
|
||||
if (dstPlayer == srcPlayer && !dstClient->GetLoopback())
|
||||
nSendLen = 0;
|
||||
}
|
||||
|
||||
sizebuf_t *dstDatagram = dstClient->GetDatagram();
|
||||
if (dstDatagram->cursize + nSendLen + 6 < dstDatagram->maxsize) {
|
||||
if (dstDatagram->cursize + nDataLength + 6 < dstDatagram->maxsize)
|
||||
{
|
||||
g_RehldsFuncs->MSG_WriteByte(dstDatagram, svc_voicedata);
|
||||
g_RehldsFuncs->MSG_WriteByte(dstDatagram, cl->GetId());
|
||||
g_RehldsFuncs->MSG_WriteShort(dstDatagram, nSendLen);
|
||||
g_RehldsFuncs->MSG_WriteBuf(dstDatagram, nSendLen, sendBuf);
|
||||
g_RehldsFuncs->MSG_WriteShort(dstDatagram, nDataLength);
|
||||
g_RehldsFuncs->MSG_WriteBuf(dstDatagram, nDataLength, chReceived);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -172,10 +132,10 @@ void SV_ParseVoiceData_emu(IGameClient *cl)
|
||||
void Rehlds_HandleNetCommand(IRehldsHook_HandleNetCommand *chain, IGameClient *cl, int8 opcode)
|
||||
{
|
||||
const int clc_voicedata = 8;
|
||||
if (opcode == clc_voicedata) {
|
||||
SV_ParseVoiceData_emu(cl);
|
||||
return;
|
||||
}
|
||||
//if (opcode == clc_voicedata) {
|
||||
// SV_ParseVoiceData_emu(cl);
|
||||
// return;
|
||||
//}
|
||||
|
||||
chain->callNext(cl, opcode);
|
||||
}
|
||||
@ -188,6 +148,438 @@ qboolean ClientConnect_PreHook(edict_t *pEntity, const char *pszName, const char
|
||||
RETURN_META_VALUE(MRES_IGNORED, TRUE);
|
||||
}
|
||||
|
||||
enum VoiceCodec_e
|
||||
{
|
||||
VC_SPEEX = 0,
|
||||
VC_SILK,
|
||||
VC_MAX
|
||||
};
|
||||
|
||||
struct SpeexContext_t
|
||||
{
|
||||
VoiceCodec_e type;
|
||||
const char *filename;
|
||||
char *data;
|
||||
int nDataBytes;
|
||||
int wBitsPerSample;
|
||||
int frame;
|
||||
bool play;
|
||||
bool load;
|
||||
bool failed;
|
||||
bool send_order;
|
||||
double time;
|
||||
double nextsend;
|
||||
float framerate;
|
||||
int index;
|
||||
int startindex;
|
||||
uint64_t steamid;
|
||||
IVoiceCodec *encoder;
|
||||
};
|
||||
|
||||
int g_tracks_silk = 0;
|
||||
int g_tracks_speex = 0;
|
||||
int g_tracksNumbers[VC_MAX][16] = {0};
|
||||
uint64_t g_ulSteamIdCurrent = 0ULL;
|
||||
|
||||
SpeexContext_t g_SoundLists[] =
|
||||
{
|
||||
{ VC_SPEEX, "kolshik.wav", nullptr, 0, 0, 0, false, false, false, false, 0, 0, 8000, 2, 0, 76561198051972183ULL, nullptr },
|
||||
{ VC_SPEEX, "pchela.wav", nullptr, 0, 0, 0, false, false, false, false, 0, 0, 11025, 3, 0, 76561198051972185ULL, nullptr },
|
||||
{ VC_SILK, "c2a2_ba_launch.wav", nullptr, 0, 0, 0, false, false, false, false, 0, 0, 8000, 7, 0, 76561198051972186ULL, nullptr },
|
||||
{ VC_SILK, "cslig_nuages.wav", nullptr, 0, 0, 0, false, false, false, false, 0, 0, 8000, 7, 0, 76561198051972182ULL, nullptr },
|
||||
{ VC_SILK, "kolshik.wav", nullptr, 0, 0, 0, false, false, false, false, 0, 0, 8000, 4, 0, 76561198051972187ULL, nullptr },
|
||||
{ VC_SILK, "dance.wav", nullptr, 0, 0, 0, false, false, false, false, 0, 0, 8000, 5, 102832, 76561198051972188ULL, nullptr },
|
||||
};
|
||||
|
||||
void ClientCommand(edict_t *pEdict)
|
||||
{
|
||||
const char *argv1 = CMD_ARGV(0);
|
||||
if (_stricmp(argv1, "speexmulti") == 0 || _stricmp(argv1, "silkmulti") == 0)
|
||||
{
|
||||
VoiceCodec_e type = _stricmp(argv1, "speexmulti") == 0 ? VC_SPEEX : VC_SILK;
|
||||
|
||||
if (type == VC_SILK)
|
||||
{
|
||||
g_SoundLists[2].play ^= true;
|
||||
g_SoundLists[3].play ^= true;
|
||||
g_SoundLists[4].play ^= true;
|
||||
g_SoundLists[5].play ^= true;
|
||||
|
||||
if (g_SoundLists[2].play)
|
||||
g_SoundLists[2].time = gpGlobals->time;
|
||||
|
||||
if (g_SoundLists[3].play)
|
||||
g_SoundLists[3].time = gpGlobals->time;
|
||||
|
||||
if (g_SoundLists[4].play)
|
||||
g_SoundLists[4].time = gpGlobals->time;
|
||||
|
||||
if (g_SoundLists[5].play)
|
||||
g_SoundLists[5].time = gpGlobals->time;
|
||||
|
||||
g_SoundLists[2].frame = g_SoundLists[2].startindex;
|
||||
g_SoundLists[3].frame = g_SoundLists[3].startindex;
|
||||
g_SoundLists[4].frame = g_SoundLists[4].startindex;
|
||||
g_SoundLists[5].frame = g_SoundLists[5].startindex;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
g_SoundLists[0].play ^= true;
|
||||
g_SoundLists[1].play ^= true;
|
||||
|
||||
if (g_SoundLists[0].play)
|
||||
{
|
||||
g_SoundLists[0].time = gpGlobals->time;
|
||||
}
|
||||
|
||||
if (g_SoundLists[1].play)
|
||||
{
|
||||
g_SoundLists[1].time = gpGlobals->time;
|
||||
}
|
||||
|
||||
g_SoundLists[0].frame = 0;
|
||||
g_SoundLists[1].frame = 0;
|
||||
*/
|
||||
}
|
||||
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
else if (_stricmp(argv1, "speexplay") == 0 || _stricmp(argv1, "silkplay") == 0)
|
||||
{
|
||||
VoiceCodec_e type = _stricmp(argv1, "speexplay") == 0 ? VC_SPEEX : VC_SILK;
|
||||
|
||||
if (CMD_ARGC() < 2)
|
||||
{
|
||||
int nIndex = 0;
|
||||
|
||||
bool header_once = false;
|
||||
for (auto &list : g_SoundLists)
|
||||
{
|
||||
if (list.type != type)
|
||||
continue;
|
||||
|
||||
if (!header_once)
|
||||
{
|
||||
header_once = true;
|
||||
|
||||
CLIENT_PRINTF(pEdict, print_console, UTIL_VarArgs("\nusage: silkplay [ <tracknumber> ]\n\n"));
|
||||
CLIENT_PRINTF(pEdict, print_console, UTIL_VarArgs("%4s %-32s %-10s %-12s\n", "#", "[name]", "[chunk]", "[framerate]"));
|
||||
}
|
||||
|
||||
CLIENT_PRINTF(pEdict, print_console, UTIL_VarArgs("%4d. %-32s %-10d %-12.2f\n", nIndex++, list.filename, list.nDataBytes, list.framerate));
|
||||
}
|
||||
|
||||
CLIENT_PRINTF(pEdict, print_console, "\n");
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
|
||||
int trackNumber = atoi(CMD_ARGV(1));
|
||||
if (trackNumber < 0 || trackNumber >= (type == VC_SPEEX ? g_tracks_speex : g_tracks_silk))
|
||||
{
|
||||
trackNumber = 0;
|
||||
}
|
||||
|
||||
trackNumber = g_tracksNumbers[type][trackNumber];
|
||||
|
||||
g_SoundLists[trackNumber].play ^= true;
|
||||
|
||||
if (g_SoundLists[trackNumber].play)
|
||||
{
|
||||
g_SoundLists[trackNumber].time = gpGlobals->time;
|
||||
}
|
||||
|
||||
g_SoundLists[trackNumber].frame = g_SoundLists[trackNumber].startindex;
|
||||
g_SoundLists[trackNumber].type = type;
|
||||
|
||||
CLIENT_PRINTF(pEdict, print_console, UTIL_VarArgs(" -> send voice are %s, track: (%s)\n", g_SoundLists[trackNumber].play ? "RUNNING" : "STOPPED", g_SoundLists[trackNumber].filename));
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
unsigned long ReadDWord(FILE *fp)
|
||||
{
|
||||
unsigned long ret;
|
||||
fread(&ret, 4, 1, fp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned short ReadWord(FILE *fp)
|
||||
{
|
||||
unsigned short ret;
|
||||
fread(&ret, 2, 1, fp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ReadWaveFile(const char *pFilename, char *&pData, int &nDataBytes, int &wBitsPerSample, int &nChannels, int &nSamplesPerSec)
|
||||
{
|
||||
FILE *fp = fopen(pFilename, "rb");
|
||||
if(!fp)
|
||||
return false;
|
||||
|
||||
fseek(fp, 22, SEEK_SET);
|
||||
|
||||
nChannels = ReadWord(fp);
|
||||
nSamplesPerSec = ReadDWord(fp);
|
||||
|
||||
fseek(fp, 34, SEEK_SET);
|
||||
wBitsPerSample = ReadWord(fp);
|
||||
|
||||
fseek(fp, 40, SEEK_SET);
|
||||
nDataBytes = ReadDWord(fp);
|
||||
ReadDWord(fp);
|
||||
pData = new char[nDataBytes];
|
||||
if(!pData)
|
||||
{
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
fread(pData, nDataBytes, 1, fp);
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
int Voice_GetSpeexCompressed(SpeexContext_t &snd, char *pchDest, int nCount, bool bFinal)
|
||||
{
|
||||
if (!snd.encoder)
|
||||
{
|
||||
snd.encoder = new VoiceCodec_Frame(new VoiceEncoder_Speex());
|
||||
snd.encoder->Init(SPEEX_VOICE_QUALITY);
|
||||
}
|
||||
|
||||
if (snd.encoder)
|
||||
{
|
||||
int gotten;
|
||||
short tempData[8192];
|
||||
|
||||
// If they want to get the data from a file instead of the mic, use that.
|
||||
if (snd.data)
|
||||
{
|
||||
double curtime = gpGlobals->time;
|
||||
int nShouldGet = (curtime - snd.time) * 8000;
|
||||
gotten = min((signed)sizeof(tempData) / 2, min(nShouldGet, (snd.nDataBytes - snd.frame) / 2));
|
||||
memcpy(tempData, &snd.data[snd.frame], gotten * 2);
|
||||
snd.frame += gotten * 2;
|
||||
snd.time = curtime;
|
||||
|
||||
return snd.encoder->Compress((char *)tempData, gotten, pchDest, nCount, !!bFinal);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char uncompressedBuf[12002];
|
||||
|
||||
int Voice_GetSilkCompressed(SpeexContext_t &snd, char *pchDest, int nCount, bool bFinal)
|
||||
{
|
||||
if (!snd.encoder)
|
||||
{
|
||||
snd.encoder = new CSteamP2PCodec(new VoiceEncoder_Silk());
|
||||
snd.encoder->Init(SILK_VOICE_QUALITY);
|
||||
}
|
||||
|
||||
if (snd.encoder)
|
||||
{
|
||||
int gotten;
|
||||
short tempData[8192];
|
||||
|
||||
// If they want to get the data from a file instead of the mic, use that.
|
||||
if (snd.data)
|
||||
{
|
||||
double curtime = gpGlobals->time;
|
||||
int nShouldGet = (curtime - snd.time) * 8000;
|
||||
gotten = min((signed)sizeof(tempData) / 2, min(nShouldGet, (snd.nDataBytes - snd.frame) / 2));
|
||||
memcpy(tempData, &snd.data[snd.frame], gotten * 2);
|
||||
snd.frame += gotten * 2;
|
||||
snd.time = curtime;
|
||||
|
||||
g_ulSteamIdCurrent = snd.steamid;
|
||||
int res = snd.encoder->Compress((char *)tempData, gotten, pchDest, nCount, !!bFinal);
|
||||
g_ulSteamIdCurrent = 0ULL;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Voice_GetCompressedData(SpeexContext_t &snd, char *pchDest, int nCount, bool bFinal)
|
||||
{
|
||||
switch (snd.type)
|
||||
{
|
||||
case VC_SPEEX:
|
||||
return Voice_GetSpeexCompressed(snd, pchDest, nCount, bFinal);
|
||||
case VC_SILK:
|
||||
return Voice_GetSilkCompressed(snd, pchDest, nCount, bFinal);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void StartFrame_Post()
|
||||
{
|
||||
static bool all_sound_initializes = false;
|
||||
if (!all_sound_initializes)
|
||||
{
|
||||
for (auto &list : g_SoundLists)
|
||||
{
|
||||
if (list.load || list.failed)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int nDataBytes, wBitsPerSample, nChannels, nSamplesPerSec;
|
||||
list.load = ReadWaveFile(list.filename, list.data, nDataBytes, wBitsPerSample, nChannels, nSamplesPerSec);
|
||||
|
||||
list.frame = 0;
|
||||
list.nDataBytes = nDataBytes;
|
||||
list.wBitsPerSample = wBitsPerSample;
|
||||
list.time = gpGlobals->time;
|
||||
|
||||
//if (list.type == VC_SILK)
|
||||
//{
|
||||
// if (wBitsPerSample != 16 || nChannels != 1 || nSamplesPerSec != 24000)
|
||||
// {
|
||||
// printf(" > %s Wave file mismatch was got %d bits, %d channels, "
|
||||
// "%d sample rate was expecting %d bits, %d channels, %d sample rate\n",
|
||||
// list.filename, wBitsPerSample, nChannels, nSamplesPerSec, 16, 1, 24000);
|
||||
//
|
||||
// delete [] list.data;
|
||||
// list.load = false;
|
||||
// list.failed = true;
|
||||
// continue;
|
||||
// }
|
||||
//}
|
||||
|
||||
if (list.load)
|
||||
{
|
||||
g_tracksNumbers[list.type][list.type == VC_SPEEX ? g_tracks_speex++ : g_tracks_silk++] = &list - g_SoundLists;
|
||||
printf(" '%s' trackid: (%d), Load: (%s), chunk: (%d), framerate: (%0.2f), wBitsPerSample: (%d), nDataBytes: (%d), nSamplesPerSec: (%d)\n",
|
||||
list.type == VC_SPEEX ? "SPEEX" : "SILK", g_tracksNumbers[list.type][(list.type == VC_SPEEX ? g_tracks_speex++ : g_tracks_silk) - 1],
|
||||
list.filename, list.nDataBytes, list.framerate, list.wBitsPerSample, nDataBytes, nSamplesPerSec);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
all_sound_initializes = true;
|
||||
for (auto &list : g_SoundLists)
|
||||
{
|
||||
if (!list.load)
|
||||
{
|
||||
all_sound_initializes = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static float fltime = 0.0f;
|
||||
if (fltime > gpGlobals->time)
|
||||
{
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
fltime = gpGlobals->time + 0.02f;// - 0.000125;
|
||||
|
||||
for (int snd = 0; snd < ARRAYSIZE(g_SoundLists); snd++)
|
||||
{
|
||||
if (!g_SoundLists[snd].play)
|
||||
continue;
|
||||
|
||||
char uchVoiceData[4096];
|
||||
bool bFinal = false;
|
||||
int nDataLength = Voice_GetCompressedData(g_SoundLists[snd], uchVoiceData, sizeof(uchVoiceData), bFinal);
|
||||
if (nDataLength <= 0)
|
||||
continue;
|
||||
|
||||
if (g_SoundLists[snd].frame >= g_SoundLists[snd].nDataBytes)// || nDataLength <= 0)
|
||||
{
|
||||
g_SoundLists[snd].play = false;
|
||||
g_SoundLists[snd].frame = 0;
|
||||
|
||||
//printf("> HIT END\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
int maxclients = g_RehldsSvs->GetMaxClients();
|
||||
for (int i = 0; i < maxclients; i++)
|
||||
{
|
||||
CRevoicePlayer *dstPlayer = &g_Players[i];
|
||||
IGameClient *dstClient = dstPlayer->GetClient();
|
||||
|
||||
if (!dstClient->IsActive() && !dstClient->IsConnected()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sizebuf_t *dstDatagram = dstClient->GetDatagram();
|
||||
if (dstDatagram->cursize + nDataLength + 6 < dstDatagram->maxsize)
|
||||
{
|
||||
//CLIENT_PRINTF(dstPlayer->GetClient()->GetEdict(), print_console, UTIL_VarArgs(" -> chunk: %4d / %4d, chunksize: %4d, progress: %3.2f%%\n", g_SoundLists[snd].frame, g_SoundLists[snd].nDataBytes, nDataLength, ((double)g_SoundLists[snd].frame / (double)g_SoundLists[snd].nDataBytes) * 100.0));
|
||||
printf(" -> chunk: %4d / %4d, chunksize: %4d, progress: %3.2f%%\n", g_SoundLists[snd].frame, g_SoundLists[snd].nDataBytes, nDataLength, ((double)g_SoundLists[snd].frame / (double)g_SoundLists[snd].nDataBytes) * 100.0);
|
||||
|
||||
g_RehldsFuncs->MSG_WriteByte(dstDatagram, svc_voicedata);
|
||||
g_RehldsFuncs->MSG_WriteByte(dstDatagram, g_SoundLists[snd].index);
|
||||
g_RehldsFuncs->MSG_WriteShort(dstDatagram, nDataLength);
|
||||
g_RehldsFuncs->MSG_WriteBuf(dstDatagram, nDataLength, uchVoiceData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
static const char *steamids[]
|
||||
{
|
||||
"76561198051972183",
|
||||
"76561198051972184",
|
||||
"76561198051972185",
|
||||
"76561198051972186",
|
||||
"76561198051972187",
|
||||
"76561198051972188",
|
||||
"76561198051972189",
|
||||
"76561198051972190",
|
||||
"76561198051972191",
|
||||
"76561198051972192",
|
||||
"76561198051972193",
|
||||
"76561198051972194",
|
||||
"76561198051972195",
|
||||
"76561198051972196",
|
||||
"76561198051972197",
|
||||
};
|
||||
|
||||
void ClientPutInServer_PostHook(edict_t *pEntity)
|
||||
{
|
||||
IGameClient* client = g_RehldsSvs->GetClient(ENTINDEX(pEntity) - 1);
|
||||
sizebuf_t *buf = client->GetNetChan()->GetMessageBuf();
|
||||
|
||||
unsigned char digest[] =
|
||||
{
|
||||
0xcd, 0xff, 0xcc, 0x70, 0xda, 0x4a, 0x79, 0x1c, 0xea, 0x66, 0xba, 0xaa, 0xad, 0x2b, 0x40, 0x01
|
||||
};
|
||||
|
||||
//memset(digest, 0, sizeof(digest));
|
||||
|
||||
for (int i = 1; i < 8; i++)
|
||||
{
|
||||
char name[64];
|
||||
_snprintf(name, sizeof(name), "play-voice-%i", i);
|
||||
|
||||
char userinfo[256];
|
||||
_snprintf(userinfo, sizeof(userinfo), "\\bottomcolor\\0\\topcolor\\0\\name\\%s\\model\\urban\\*sid\\%s", name, steamids[i]);
|
||||
|
||||
g_RehldsFuncs->MSG_WriteByte(buf, 13); // svc_updateuserinfo
|
||||
g_RehldsFuncs->MSG_WriteByte(buf, i);
|
||||
g_RehldsFuncs->MSG_WriteLong(buf, i - 1);
|
||||
g_RehldsFuncs->MSG_WriteString(buf, userinfo);
|
||||
g_RehldsFuncs->MSG_WriteBuf(buf, sizeof(digest), digest);
|
||||
}
|
||||
|
||||
SET_META_RESULT(MRES_IGNORED);
|
||||
}
|
||||
|
||||
void ServerActivate_PostHook(edict_t *pEdictList, int edictCount, int clientMax)
|
||||
{
|
||||
Revoice_Exec_Config();
|
||||
|
@ -9,5 +9,7 @@ bool Revoice_Main_Init();
|
||||
|
||||
void CvarValue2_PreHook(const edict_t *pEnt, int requestID, const char *cvarName, const char *cvarValue);
|
||||
qboolean ClientConnect_PreHook(edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[128]);
|
||||
void ClientPutInServer_PostHook(edict_t *pEntity);
|
||||
void ServerActivate_PostHook(edict_t *pEdictList, int edictCount, int clientMax);
|
||||
|
||||
void StartFrame_Post();
|
||||
void ClientCommand(edict_t *pEdict);
|
||||
|
494
revoice/src/revoice_main_.cpp
Normal file
494
revoice/src/revoice_main_.cpp
Normal file
@ -0,0 +1,494 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
void SV_DropClient_hook(IRehldsHook_SV_DropClient *chain, IGameClient *cl, bool crash, const char *msg)
|
||||
{
|
||||
CRevoicePlayer *plr = GetPlayerByClientPtr(cl);
|
||||
|
||||
plr->OnDisconnected();
|
||||
|
||||
chain->callNext(cl, crash, msg);
|
||||
}
|
||||
|
||||
void CvarValue2_PreHook(const edict_t *pEnt, int requestID, const char *cvarName, const char *cvarValue)
|
||||
{
|
||||
CRevoicePlayer *plr = GetPlayerByEdict(pEnt);
|
||||
if (plr->GetRequestId() != requestID) {
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
const char *lastSeparator = strrchr(cvarValue, ',');
|
||||
if (lastSeparator)
|
||||
{
|
||||
int buildNumber = atoi(lastSeparator + 1);
|
||||
if (buildNumber > 4554 || buildNumber == 2017) {
|
||||
plr->SetCodecType(vct_opus);
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
int TranscodeVoice(CRevoicePlayer *srcPlayer, 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;
|
||||
}
|
||||
|
||||
int compressedSize = dstCodec->Compress(decodedBuf, numDecodedSamples, dstBuf, dstBufSize, false);
|
||||
if (compressedSize <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
int numDecodedSamples2 = dstCodec->Decompress(dstBuf, compressedSize, decodedBuf, sizeof(decodedBuf));
|
||||
if (numDecodedSamples2 <= 0) {
|
||||
return compressedSize;
|
||||
}
|
||||
|
||||
FILE *rawSndFile = fopen("d:\\revoice_raw.snd", "ab");
|
||||
if (rawSndFile) {
|
||||
fwrite(decodedBuf, 2, numDecodedSamples2, rawSndFile);
|
||||
fclose(rawSndFile);
|
||||
}
|
||||
*/
|
||||
|
||||
return compressedSize;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (g_pcv_sv_voiceenable->value == 0.0f) {
|
||||
return;
|
||||
}
|
||||
|
||||
CRevoicePlayer *srcPlayer = GetPlayerByClientPtr(cl);
|
||||
|
||||
|
||||
|
||||
//FILE *fp = fopen("recorder.snd", "ab");
|
||||
//if (fp)
|
||||
//{
|
||||
// printf(" -> Write chunk: (%d)\n", nDataLength);
|
||||
// fwrite(chReceived, 1, nDataLength, fp);
|
||||
// fclose(fp);
|
||||
//}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*srcPlayer->SetLastVoiceTime(g_RehldsSv->GetTime());
|
||||
srcPlayer->IncreaseVoiceRate(nDataLength);
|
||||
|
||||
char compressedBuf[16384];
|
||||
int compressedSize = TranscodeVoice(srcPlayer, chReceived, nDataLength, srcPlayer->GetOpusCodec(), srcPlayer->GetSilkCodec(), compressedBuf, sizeof(compressedBuf));
|
||||
|
||||
uint32_t computedChecksum = crc32(compressedBuf, compressedSize - 4);
|
||||
uint32 wireChecksum = *(uint32 *)(compressedBuf + compressedSize - 4);
|
||||
|
||||
FILE *fp = fopen("recorder.snd", "ab");
|
||||
if (fp)
|
||||
{
|
||||
printf(" -> Write chunk: (%d), computedChecksum: (%u), wireChecksum: (%u)\n", compressedSize, computedChecksum, wireChecksum);
|
||||
printf(" -> Write chunk: (%d), computedChecksum: (%u), wireChecksum: (%u)\n", compressedSize, computedChecksum, wireChecksum);
|
||||
fwrite(compressedBuf, 1, compressedSize, fp);
|
||||
fclose(fp);
|
||||
}*/
|
||||
|
||||
//return;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int maxclients = g_RehldsSvs->GetMaxClients();
|
||||
for (int i = 0; i < maxclients; i++)
|
||||
{
|
||||
CRevoicePlayer *dstPlayer = &g_Players[i];
|
||||
IGameClient *dstClient = dstPlayer->GetClient();
|
||||
|
||||
if (!((1 << i) & cl->GetVoiceStream(0)) && dstPlayer != srcPlayer) {
|
||||
//printf("-> #0\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!dstClient->IsActive() && !dstClient->IsConnected() && dstPlayer != srcPlayer) {
|
||||
//printf("-> #1\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
sizebuf_t *dstDatagram = dstClient->GetDatagram();
|
||||
if (dstDatagram->cursize + nDataLength + 6 < dstDatagram->maxsize)
|
||||
{
|
||||
//uint32_t computedChecksum = crc32(compressedBuf, compressedSize - 4);
|
||||
//uint32 wireChecksum = *(uint32 *)(compressedBuf + compressedSize - 4);
|
||||
|
||||
//FILE *fp = fopen("silk_chunk.snd", "ab");
|
||||
//if (fp)
|
||||
//{
|
||||
// printf(" -> Write chunk: (%d), computedChecksum: (%u), wireChecksum: (%u)\n", compressedSize, computedChecksum, wireChecksum);
|
||||
// fwrite(compressedBuf, 1, compressedSize, fp);
|
||||
// fclose(fp);
|
||||
//}
|
||||
|
||||
g_RehldsFuncs->MSG_WriteByte(dstDatagram, svc_voicedata);
|
||||
g_RehldsFuncs->MSG_WriteByte(dstDatagram, cl->GetId());
|
||||
g_RehldsFuncs->MSG_WriteShort(dstDatagram, nDataLength);
|
||||
g_RehldsFuncs->MSG_WriteBuf(dstDatagram, nDataLength, chReceived);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Rehlds_HandleNetCommand(IRehldsHook_HandleNetCommand *chain, IGameClient *cl, int8 opcode)
|
||||
{
|
||||
const int clc_voicedata = 8;
|
||||
//if (opcode == clc_voicedata) {
|
||||
// SV_ParseVoiceData_emu(cl);
|
||||
// return;
|
||||
//}
|
||||
|
||||
chain->callNext(cl, opcode);
|
||||
}
|
||||
|
||||
qboolean ClientConnect_PreHook(edict_t *pEntity, const char *pszName, const char *pszAddress, char szRejectReason[128])
|
||||
{
|
||||
CRevoicePlayer *plr = GetPlayerByEdict(pEntity);
|
||||
plr->OnConnected();
|
||||
|
||||
RETURN_META_VALUE(MRES_IGNORED, TRUE);
|
||||
}
|
||||
|
||||
struct SpeexContext_t
|
||||
{
|
||||
const char *filename;
|
||||
char *data;
|
||||
int chunk;
|
||||
int frame;
|
||||
bool play;
|
||||
bool load;
|
||||
bool send_order;
|
||||
double time;
|
||||
double nextsend;
|
||||
float framerate;
|
||||
int index;
|
||||
IVoiceCodec *encoder;
|
||||
};
|
||||
|
||||
int g_NumFullSended = 0;
|
||||
SpeexContext_t g_SoundLists[] =
|
||||
{
|
||||
{ "akol.wav", nullptr, 0, 0, false, false, false, 0, 0, 8000, 4, nullptr },
|
||||
//{ "akol2.wav", nullptr, 0, 0, false, false, false, 0, 0, 8000, 5, nullptr },
|
||||
{ "apchela.wav", nullptr, 0, 0, false, false, false, 0, 0, 11025, 6, nullptr },
|
||||
};
|
||||
|
||||
void ClientCommand(edict_t *pEdict)
|
||||
{
|
||||
const char *argv1 = CMD_ARGV(0);
|
||||
if (_stricmp(argv1, "speexmulti") == 0)
|
||||
{
|
||||
g_SoundLists[0].play ^= true;
|
||||
g_SoundLists[1].play ^= true;
|
||||
|
||||
if (g_SoundLists[0].play)
|
||||
{
|
||||
g_SoundLists[0].time = gpGlobals->time;
|
||||
}
|
||||
|
||||
if (g_SoundLists[1].play)
|
||||
{
|
||||
g_SoundLists[1].time = gpGlobals->time;
|
||||
}
|
||||
|
||||
g_SoundLists[0].frame = 0;
|
||||
g_SoundLists[1].frame = 0;
|
||||
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
else if (_stricmp(argv1, "speexplay") == 0)
|
||||
{
|
||||
if (CMD_ARGC() < 2)
|
||||
{
|
||||
CLIENT_PRINTF(pEdict, print_console, UTIL_VarArgs("\nusage: speexplay [ <tracknumber> ]\n\n"));
|
||||
CLIENT_PRINTF(pEdict, print_console, UTIL_VarArgs("%4s %-32s %-10s %-12s\n", "#", "[name]", "[chunk]", "[framerate]"));
|
||||
|
||||
int nIndex = 0;
|
||||
for (auto &list : g_SoundLists)
|
||||
{
|
||||
CLIENT_PRINTF(pEdict, print_console, UTIL_VarArgs("%4d. %-32s %-10d %-12.2f\n", nIndex++, list.filename, list.chunk, list.framerate));
|
||||
}
|
||||
|
||||
CLIENT_PRINTF(pEdict, print_console, "\n");
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
|
||||
int trackNumber = atoi(CMD_ARGV(1));
|
||||
if (trackNumber < 0 || trackNumber >= ARRAYSIZE(g_SoundLists))
|
||||
{
|
||||
trackNumber = 0;
|
||||
}
|
||||
|
||||
g_SoundLists[trackNumber].play ^= true;
|
||||
|
||||
if (g_SoundLists[trackNumber].play)
|
||||
{
|
||||
g_SoundLists[trackNumber].time = gpGlobals->time;
|
||||
}
|
||||
|
||||
g_SoundLists[trackNumber].frame = 0;
|
||||
|
||||
CLIENT_PRINTF(pEdict, print_console, UTIL_VarArgs(" -> send voice are %s, track: (%s)\n", g_SoundLists[trackNumber].play ? "RUNNING" : "STOPPED", g_SoundLists[trackNumber].filename));
|
||||
RETURN_META(MRES_SUPERCEDE);
|
||||
}
|
||||
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
bool ReadWaveFile(const char *pFilename, char **pData, int &nDataBytes, int &nBitsPerSample, int &nChannels, int &nSamplesPerSec)
|
||||
{
|
||||
FILE *fp = fopen(pFilename, "rb");
|
||||
if (!fp) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int pOutput;
|
||||
fseek(fp, 22, SEEK_SET);
|
||||
fread(&pOutput, sizeof(uint16), 1, fp);
|
||||
nChannels = (uint16)pOutput;
|
||||
|
||||
fread(&pOutput, sizeof(int), 1, fp);
|
||||
nSamplesPerSec = pOutput;
|
||||
|
||||
fseek(fp, 34, SEEK_SET);
|
||||
fread(&pOutput, sizeof(uint16), 1, fp);
|
||||
nBitsPerSample = (uint16)pOutput;
|
||||
|
||||
fseek(fp, 40, SEEK_SET);
|
||||
fread(&pOutput, sizeof(int), 1, fp);
|
||||
nDataBytes = pOutput;
|
||||
|
||||
fread(&pOutput, sizeof(int), 1, fp);
|
||||
|
||||
*pData = new char[ nDataBytes ];
|
||||
|
||||
if (*pData)
|
||||
{
|
||||
fread(*pData, nDataBytes, 1, fp);
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
int Voice_GetCompressedData(SpeexContext_t &snd, char *pchDest, int nCount, bool bFinal)
|
||||
{
|
||||
if (!snd.encoder)
|
||||
{
|
||||
snd.encoder = new VoiceCodec_Frame(new VoiceEncoder_Speex());
|
||||
snd.encoder->Init(SPEEX_VOICE_QUALITY);
|
||||
}
|
||||
|
||||
if (snd.encoder)
|
||||
{
|
||||
int gotten;
|
||||
short tempData[8192];
|
||||
|
||||
// If they want to get the data from a file instead of the mic, use that.
|
||||
if (snd.data)
|
||||
{
|
||||
double curtime = gpGlobals->time;
|
||||
int nShouldGet = (curtime - snd.time) * 8000;
|
||||
gotten = min((signed)sizeof(tempData) / 2, min(nShouldGet, (snd.chunk - snd.frame) / 2));
|
||||
memcpy(tempData, &snd.data[snd.frame], gotten * 2);
|
||||
snd.frame += gotten * 2;
|
||||
snd.time = curtime;
|
||||
|
||||
return snd.encoder->Compress((char *)tempData, gotten, pchDest, nCount, !!bFinal);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#include "counter.h"
|
||||
CCounter g_Timer;
|
||||
|
||||
#include <iostream>
|
||||
#include <chrono>
|
||||
|
||||
void StartFrame_Post()
|
||||
{
|
||||
static bool all_sound_initializes = false;
|
||||
if (!all_sound_initializes)
|
||||
{
|
||||
g_Timer.Init();
|
||||
|
||||
for (auto &list : g_SoundLists)
|
||||
{
|
||||
if (list.load)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
int a, b, c;
|
||||
list.load = ReadWaveFile(list.filename, &list.data, list.chunk, a, b, c);
|
||||
list.frame = 0;
|
||||
list.time = gpGlobals->time;
|
||||
|
||||
if (list.load)
|
||||
{
|
||||
printf(" Load: (%s), chunk: (%d), framerate: (%0.2f)\n", list.filename, list.chunk, list.framerate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
all_sound_initializes = true;
|
||||
for (auto &list : g_SoundLists)
|
||||
{
|
||||
if (!list.load)
|
||||
{
|
||||
all_sound_initializes = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static float fltime = 0.0f;
|
||||
if (fltime > gpGlobals->time)
|
||||
{
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
fltime = gpGlobals->time + 0.02f - 0.000125;
|
||||
|
||||
for (int snd = 0; snd < ARRAYSIZE(g_SoundLists); snd++)
|
||||
{
|
||||
if (!g_SoundLists[snd].play)
|
||||
continue;
|
||||
|
||||
char uchVoiceData[4096];
|
||||
bool bFinal = false;
|
||||
int nDataLength = Voice_GetCompressedData(g_SoundLists[snd], uchVoiceData, sizeof(uchVoiceData), bFinal);
|
||||
|
||||
if (g_SoundLists[snd].frame >= g_SoundLists[snd].chunk)// || nDataLength <= 0)
|
||||
{
|
||||
g_SoundLists[snd].play = false;
|
||||
g_SoundLists[snd].frame = 0;
|
||||
|
||||
//printf("> HIT END\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
int maxclients = g_RehldsSvs->GetMaxClients();
|
||||
for (int i = 0; i < maxclients; i++)
|
||||
{
|
||||
CRevoicePlayer *dstPlayer = &g_Players[i];
|
||||
IGameClient *dstClient = dstPlayer->GetClient();
|
||||
|
||||
if (!dstClient->IsActive() && !dstClient->IsConnected()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sizebuf_t *dstDatagram = dstClient->GetDatagram();
|
||||
if (dstDatagram->cursize + nDataLength + 6 < dstDatagram->maxsize)
|
||||
{
|
||||
//CLIENT_PRINTF(dstPlayer->GetClient()->GetEdict(), print_console, UTIL_VarArgs(" -> chunk: %4d / %4d, chunksize: %4d, progress: %3.2f%%\n", g_SoundLists[snd].frame, g_SoundLists[snd].chunk, nDataLength, ((double)g_SoundLists[snd].frame / (double)g_SoundLists[snd].chunk) * 100.0));
|
||||
printf(" -> chunk: %4d / %4d, chunksize: %4d, progress: %3.2f%%\n", g_SoundLists[snd].frame, g_SoundLists[snd].chunk, nDataLength, ((double)g_SoundLists[snd].frame / (double)g_SoundLists[snd].chunk) * 100.0);
|
||||
|
||||
g_RehldsFuncs->MSG_WriteByte(dstDatagram, svc_voicedata);
|
||||
g_RehldsFuncs->MSG_WriteByte(dstDatagram, g_SoundLists[snd].index);
|
||||
g_RehldsFuncs->MSG_WriteShort(dstDatagram, nDataLength);
|
||||
g_RehldsFuncs->MSG_WriteBuf(dstDatagram, nDataLength, uchVoiceData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_META(MRES_IGNORED);
|
||||
}
|
||||
|
||||
void ServerActivate_PostHook(edict_t *pEdictList, int edictCount, int clientMax)
|
||||
{
|
||||
Revoice_Exec_Config();
|
||||
SET_META_RESULT(MRES_IGNORED);
|
||||
}
|
||||
|
||||
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:
|
||||
case vct_opus:
|
||||
case vct_speex:
|
||||
{
|
||||
g_RehldsFuncs->MSG_WriteByte(sb, svc_voiceinit);
|
||||
g_RehldsFuncs->MSG_WriteString(sb, "voice_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_Load()
|
||||
{
|
||||
if (!Revoice_Utils_Init())
|
||||
return false;
|
||||
|
||||
if (!Revoice_RehldsApi_Init()) {
|
||||
LCPrintf(true, "Failed to locate REHLDS API\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Revoice_ReunionApi_Init())
|
||||
return false;
|
||||
|
||||
Revoice_Init_Cvars();
|
||||
Revoice_Init_Config();
|
||||
Revoice_Init_Players();
|
||||
|
||||
if (!Revoice_Main_Init()) {
|
||||
LCPrintf(true, "Initialization failed\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Revoice_Main_Init()
|
||||
{
|
||||
g_RehldsHookchains->SV_DropClient()->registerHook(&SV_DropClient_hook, HC_PRIORITY_DEFAULT + 1);
|
||||
g_RehldsHookchains->HandleNetCommand()->registerHook(&Rehlds_HandleNetCommand, HC_PRIORITY_DEFAULT + 1);
|
||||
g_RehldsHookchains->SV_WriteVoiceCodec()->registerHook(&SV_WriteVoiceCodec_hooked, HC_PRIORITY_DEFAULT + 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Revoice_Main_DeInit()
|
||||
{
|
||||
g_RehldsHookchains->SV_DropClient()->unregisterHook(&SV_DropClient_hook);
|
||||
g_RehldsHookchains->HandleNetCommand()->unregisterHook(&Rehlds_HandleNetCommand);
|
||||
g_RehldsHookchains->SV_WriteVoiceCodec()->unregisterHook(&SV_WriteVoiceCodec_hooked);
|
||||
|
||||
Revoice_DeInit_Cvars();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user