STEAMVoice Speex

This commit is contained in:
BotoX 2017-08-02 22:50:33 +02:00
commit fed7ab800d
17 changed files with 2338 additions and 0 deletions

406
AMBuildScript Normal file
View File

@ -0,0 +1,406 @@
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
import os, sys
# Simple extensions do not need to modify this file.
class SDK(object):
def __init__(self, sdk, ext, aDef, name, platform, dir):
self.folder = 'hl2sdk-' + dir
self.envvar = sdk
self.ext = ext
self.code = aDef
self.define = name
self.platform = platform
self.name = dir
self.path = None
WinOnly = ['windows']
WinLinux = ['windows', 'linux']
WinLinuxMac = ['windows', 'linux', 'mac']
PossibleSDKs = {
'css': SDK('HL2SDKCSS', '2.css', '6', 'CSS', WinLinuxMac, 'css'),
}
def ResolveEnvPath(env, folder):
if env in os.environ:
path = os.environ[env]
if os.path.isdir(path):
return path
return None
head = os.getcwd()
oldhead = None
while head != None and head != oldhead:
path = os.path.join(head, folder)
if os.path.isdir(path):
return path
oldhead = head
head, tail = os.path.split(head)
return None
def Normalize(path):
return os.path.abspath(os.path.normpath(path))
class ExtensionConfig(object):
def __init__(self):
self.sdks = {}
self.binaries = []
self.extensions = []
self.generated_headers = None
self.mms_root = None
self.sm_root = None
@property
def tag(self):
if builder.options.debug == '1':
return 'Debug'
return 'Release'
def detectSDKs(self):
sdk_list = builder.options.sdks.split(',')
use_all = sdk_list[0] == 'all'
use_present = sdk_list[0] == 'present'
for sdk_name in PossibleSDKs:
sdk = PossibleSDKs[sdk_name]
if builder.target_platform in sdk.platform:
if builder.options.hl2sdk_root:
sdk_path = os.path.join(builder.options.hl2sdk_root, sdk.folder)
else:
sdk_path = ResolveEnvPath(sdk.envvar, sdk.folder)
if sdk_path is None or not os.path.isdir(sdk_path):
if use_all or sdk_name in sdk_list:
raise Exception('Could not find a valid path for {0}'.format(sdk.envvar))
continue
if use_all or use_present or sdk_name in sdk_list:
sdk.path = Normalize(sdk_path)
self.sdks[sdk_name] = sdk
if len(self.sdks) < 1:
raise Exception('At least one SDK must be available.')
if builder.options.sm_path:
self.sm_root = builder.options.sm_path
else:
self.sm_root = ResolveEnvPath('SOURCEMOD18', 'sourcemod-1.8')
if not self.sm_root:
self.sm_root = ResolveEnvPath('SOURCEMOD', 'sourcemod')
if not self.sm_root:
self.sm_root = ResolveEnvPath('SOURCEMOD_DEV', 'sourcemod-central')
if not self.sm_root or not os.path.isdir(self.sm_root):
raise Exception('Could not find a source copy of SourceMod')
self.sm_root = Normalize(self.sm_root)
if builder.options.mms_path:
self.mms_root = builder.options.mms_path
else:
self.mms_root = ResolveEnvPath('MMSOURCE110', 'mmsource-1.10')
if not self.mms_root:
self.mms_root = ResolveEnvPath('MMSOURCE', 'metamod-source')
if not self.mms_root:
self.mms_root = ResolveEnvPath('MMSOURCE_DEV', 'mmsource-central')
if not self.mms_root or not os.path.isdir(self.mms_root):
raise Exception('Could not find a source copy of Metamod:Source')
self.mms_root = Normalize(self.mms_root)
def configure(self):
cxx = builder.DetectCompilers()
if cxx.like('gcc'):
cxx.defines += [
'stricmp=strcasecmp',
'_stricmp=strcasecmp',
'_snprintf=snprintf',
'_vsnprintf=vsnprintf',
'HAVE_STDINT_H',
'GNUC',
]
cxx.cflags += [
'-pipe',
'-fno-strict-aliasing',
'-Wall',
# '-Werror',
'-Wno-unused',
'-Wno-switch',
'-Wno-array-bounds',
'-msse',
'-m32',
]
cxx.cxxflags += [
'-std=c++11',
]
have_gcc = cxx.vendor == 'gcc'
have_clang = cxx.vendor == 'clang'
if have_clang or (have_gcc and cxx.version >= '4'):
cxx.cflags += ['-fvisibility=hidden']
cxx.cxxflags += ['-fvisibility-inlines-hidden']
if have_clang or (have_gcc and cxx.version >= '4.6'):
cxx.cflags += ['-Wno-narrowing']
if (have_gcc and cxx.version >= '4.7') or (have_clang and cxx.version >= '3'):
cxx.cxxflags += ['-Wno-delete-non-virtual-dtor']
if have_gcc and cxx.version >= '4.8':
cxx.cflags += ['-Wno-unused-result']
if have_clang:
cxx.cxxflags += ['-Wno-implicit-exception-spec-mismatch']
if cxx.version >= 'apple-clang-5.1' or cxx.version >= 'clang-3.4':
cxx.cxxflags += ['-Wno-deprecated-register']
else:
cxx.cxxflags += ['-Wno-deprecated']
cxx.cflags += ['-Wno-sometimes-uninitialized']
cxx.linkflags += ['-m32']
cxx.cxxflags += [
'-fno-exceptions',
'-fno-threadsafe-statics',
'-Wno-non-virtual-dtor',
'-Wno-overloaded-virtual',
]
if have_gcc:
cxx.cflags += ['-mfpmath=sse']
elif cxx.vendor == 'msvc':
if builder.options.debug == '1':
cxx.cflags += ['/MTd']
cxx.linkflags += ['/NODEFAULTLIB:libcmt']
else:
cxx.cflags += ['/MT']
cxx.defines += [
'_CRT_SECURE_NO_DEPRECATE',
'_CRT_SECURE_NO_WARNINGS',
'_CRT_NONSTDC_NO_DEPRECATE',
'_ITERATOR_DEBUG_LEVEL=0',
]
cxx.cflags += [
'/W3',
]
cxx.cxxflags += [
'/EHsc',
'/GR-',
'/TP',
]
cxx.linkflags += [
'/MACHINE:X86',
'kernel32.lib',
'user32.lib',
'gdi32.lib',
'winspool.lib',
'comdlg32.lib',
'advapi32.lib',
'shell32.lib',
'ole32.lib',
'oleaut32.lib',
'uuid.lib',
'odbc32.lib',
'odbccp32.lib',
]
# Optimization
if builder.options.opt == '1':
cxx.defines += ['NDEBUG']
if cxx.like('gcc'):
cxx.cflags += ['-O3']
elif cxx.like('msvc'):
cxx.cflags += ['/Ox', '/Zo']
cxx.linkflags += ['/OPT:ICF', '/OPT:REF']
# Debugging
if builder.options.debug == '1':
cxx.defines += ['DEBUG', '_DEBUG']
if cxx.like('msvc'):
cxx.cflags += ['/Od', '/RTC1']
# This needs to be after our optimization flags which could otherwise disable it.
if cxx.vendor == 'msvc':
# Don't omit the frame pointer.
cxx.cflags += ['/Oy-']
# Platform-specifics
if builder.target_platform == 'linux':
cxx.defines += ['_LINUX', 'POSIX']
cxx.linkflags += ['-lm']
if cxx.vendor == 'gcc':
cxx.linkflags += ['-static-libgcc']
elif cxx.vendor == 'clang':
cxx.linkflags += ['-lgcc_eh']
elif builder.target_platform == 'mac':
cxx.defines += ['OSX', '_OSX', 'POSIX']
cxx.cflags += ['-mmacosx-version-min=10.5']
cxx.linkflags += [
'-mmacosx-version-min=10.5',
'-arch', 'i386',
'-lstdc++',
'-stdlib=libstdc++',
]
cxx.cxxflags += ['-stdlib=libstdc++']
elif builder.target_platform == 'windows':
cxx.defines += ['WIN32', '_WINDOWS']
# Finish up.
cxx.includes += [
os.path.join(self.sm_root, 'public'),
]
def ConfigureForHL2(self, binary, sdk):
compiler = binary.compiler
if sdk.name == 'episode1':
mms_path = os.path.join(self.mms_root, 'core-legacy')
else:
mms_path = os.path.join(self.mms_root, 'core')
compiler.cxxincludes += [
os.path.join(mms_path),
os.path.join(mms_path, 'sourcehook'),
]
defines = ['SE_' + PossibleSDKs[i].define + '=' + PossibleSDKs[i].code for i in PossibleSDKs]
compiler.defines += defines
paths = [
['public'],
['public', 'engine'],
['public', 'mathlib'],
['public', 'vstdlib'],
['public', 'tier0'],
['public', 'tier1']
]
if sdk.name == 'episode1' or sdk.name == 'darkm':
paths.append(['public', 'dlls'])
paths.append(['game_shared'])
else:
paths.append(['public', 'game', 'server'])
paths.append(['public', 'toolframework'])
paths.append(['game', 'shared'])
paths.append(['common'])
compiler.defines += ['SOURCE_ENGINE=' + sdk.code]
if sdk.name in ['sdk2013', 'bms'] and compiler.like('gcc'):
# The 2013 SDK already has these in public/tier0/basetypes.h
compiler.defines.remove('stricmp=strcasecmp')
compiler.defines.remove('_stricmp=strcasecmp')
compiler.defines.remove('_snprintf=snprintf')
compiler.defines.remove('_vsnprintf=vsnprintf')
if compiler.like('msvc'):
compiler.defines += ['COMPILER_MSVC', 'COMPILER_MSVC32']
else:
compiler.defines += ['COMPILER_GCC']
# For everything after Swarm, this needs to be defined for entity networking
# to work properly with sendprop value changes.
if sdk.name in ['blade', 'insurgency', 'csgo', 'dota']:
compiler.defines += ['NETWORK_VARS_ENABLED']
if sdk.name in ['css', 'hl2dm', 'dods', 'sdk2013', 'bms', 'tf2', 'l4d', 'nucleardawn', 'l4d2', 'dota']:
if builder.target_platform in ['linux', 'mac']:
compiler.defines += ['NO_HOOK_MALLOC', 'NO_MALLOC_OVERRIDE']
if sdk.name == 'csgo' and builder.target_platform == 'linux':
compiler.linkflags += ['-lstdc++']
for path in paths:
compiler.cxxincludes += [os.path.join(sdk.path, *path)]
if builder.target_platform == 'linux':
if sdk.name == 'episode1':
lib_folder = os.path.join(sdk.path, 'linux_sdk')
elif sdk.name in ['sdk2013', 'bms']:
lib_folder = os.path.join(sdk.path, 'lib', 'public', 'linux32')
else:
lib_folder = os.path.join(sdk.path, 'lib', 'linux')
elif builder.target_platform == 'mac':
if sdk.name in ['sdk2013', 'bms']:
lib_folder = os.path.join(sdk.path, 'lib', 'public', 'osx32')
else:
lib_folder = os.path.join(sdk.path, 'lib', 'mac')
if builder.target_platform in ['linux', 'mac']:
if sdk.name in ['sdk2013', 'bms']:
compiler.postlink += [
compiler.Dep(os.path.join(lib_folder, 'tier1.a')),
compiler.Dep(os.path.join(lib_folder, 'mathlib.a'))
]
else:
compiler.postlink += [
compiler.Dep(os.path.join(lib_folder, 'tier1_i486.a')),
compiler.Dep(os.path.join(lib_folder, 'mathlib_i486.a'))
]
if sdk.name in ['blade', 'insurgency', 'csgo', 'dota']:
compiler.postlink += [compiler.Dep(os.path.join(lib_folder, 'interfaces_i486.a'))]
dynamic_libs = []
if builder.target_platform == 'linux':
if sdk.name in ['css', 'hl2dm', 'dods', 'tf2', 'sdk2013', 'bms', 'nucleardawn', 'l4d2']:
dynamic_libs = ['libtier0_srv.so', 'libvstdlib_srv.so']
elif sdk.name in ['l4d', 'blade', 'insurgency', 'csgo', 'dota']:
dynamic_libs = ['libtier0.so', 'libvstdlib.so']
else:
dynamic_libs = ['tier0_i486.so', 'vstdlib_i486.so']
elif builder.target_platform == 'mac':
compiler.linkflags.append('-liconv')
dynamic_libs = ['libtier0.dylib', 'libvstdlib.dylib']
elif builder.target_platform == 'windows':
libs = ['tier0', 'tier1', 'vstdlib', 'mathlib']
if sdk.name in ['swarm', 'blade', 'insurgency', 'csgo', 'dota']:
libs.append('interfaces')
for lib in libs:
lib_path = os.path.join(sdk.path, 'lib', 'public', lib) + '.lib'
compiler.linkflags.append(compiler.Dep(lib_path))
for library in dynamic_libs:
source_path = os.path.join(lib_folder, library)
output_path = os.path.join(binary.localFolder, library)
def make_linker(source_path, output_path):
def link(context, binary):
cmd_node, (output,) = context.AddSymlink(source_path, output_path)
return output
return link
linker = make_linker(source_path, output_path)
compiler.linkflags[0:0] = [compiler.Dep(library, linker)]
return binary
def ConfigureForExtension(self, context, compiler):
compiler.cxxincludes += [
os.path.join(context.currentSourcePath),
os.path.join(context.currentSourcePath, 'sdk'),
os.path.join(self.sm_root, 'public'),
os.path.join(self.sm_root, 'public', 'extensions'),
os.path.join(self.sm_root, 'sourcepawn', 'include'),
os.path.join(self.sm_root, 'public', 'amtl', 'include'),
]
return compiler
def HL2Project(self, context, name):
project = context.compiler.LibraryProject(name)
self.ConfigureForExtension(context, project.compiler)
return project
def HL2Config(self, project, name, sdk):
binary = project.Configure(name, '{0} - {1}'.format(self.tag, sdk.name))
return self.ConfigureForHL2(binary, sdk)
Extension = ExtensionConfig()
Extension.detectSDKs()
Extension.configure()
# Add additional buildscripts here
BuildScripts = [
'AMBuilder',
]
if builder.backend == 'amb2':
BuildScripts += [
'PackageScript',
]
builder.RunBuildScripts(BuildScripts, { 'Extension': Extension})

27
AMBuilder Normal file
View File

@ -0,0 +1,27 @@
# vim: set sts=2 ts=8 sw=2 tw=99 et ft=python:
import os
if not "SM" in globals():
SM = Extension
projectName = 'Voice'
project = SM.HL2Project(builder, projectName + '.ext')
project.sources += [
'extension.cpp',
'ringbuffer.cpp',
'../../public/smsdk_ext.cpp'
]
for sdk_name in SM.sdks:
sdk = SM.sdks[sdk_name]
binary = SM.HL2Config(project, projectName + '.ext', sdk)
binary.compiler.cxxincludes += [
os.path.join(SM.sm_root, 'public', 'extensions'),
os.path.join(builder.sourcePath, 'silk')
]
binary.compiler.linkflags += [
os.path.join(builder.sourcePath, 'silk', 'libSKP_SILK_SDK.a')
]
SM.extensions += builder.Add(project)

233
Makefile Normal file
View File

@ -0,0 +1,233 @@
# (C)2004-2010 SourceMod Development Team
# Makefile written by David "BAILOPAN" Anderson
###########################################
### EDIT THESE PATHS FOR YOUR OWN SETUP ###
###########################################
SMSDK = ../..
HL2SDK_ORIG = ../../../hl2sdk
HL2SDK_OB = ../../../hl2sdk-ob
HL2SDK_CSS = ../../../hl2sdk-css
HL2SDK_OB_VALVE = ../../../hl2sdk-ob-valve
HL2SDK_L4D = ../../../hl2sdk-l4d
HL2SDK_L4D2 = ../../../hl2sdk-l4d2
HL2SDK_CSGO = ../../../hl2sdk-csgo
MMSOURCE19 = ../../../mmsource-1.9
#####################################
### EDIT BELOW FOR OTHER PROJECTS ###
#####################################
PROJECT = sample
#Uncomment for Metamod: Source enabled extension
#USEMETA = true
OBJECTS = smsdk_ext.cpp extension.cpp
##############################################
### CONFIGURE ANY OTHER FLAGS/OPTIONS HERE ###
##############################################
C_OPT_FLAGS = -DNDEBUG -O3 -funroll-loops -pipe -fno-strict-aliasing
C_DEBUG_FLAGS = -D_DEBUG -DDEBUG -g -ggdb3
C_GCC4_FLAGS = -fvisibility=hidden
CPP_GCC4_FLAGS = -fvisibility-inlines-hidden
CPP = gcc
CPP_OSX = clang
##########################
### SDK CONFIGURATIONS ###
##########################
override ENGSET = false
# Check for valid list of engines
ifneq (,$(filter original orangebox orangeboxvalve css left4dead left4dead2 csgo,$(ENGINE)))
override ENGSET = true
endif
ifeq "$(ENGINE)" "original"
HL2SDK = $(HL2SDK_ORIG)
CFLAGS += -DSOURCE_ENGINE=1
endif
ifeq "$(ENGINE)" "orangebox"
HL2SDK = $(HL2SDK_OB)
CFLAGS += -DSOURCE_ENGINE=3
endif
ifeq "$(ENGINE)" "css"
HL2SDK = $(HL2SDK_CSS)
CFLAGS += -DSOURCE_ENGINE=6
endif
ifeq "$(ENGINE)" "orangeboxvalve"
HL2SDK = $(HL2SDK_OB_VALVE)
CFLAGS += -DSOURCE_ENGINE=7
endif
ifeq "$(ENGINE)" "left4dead"
HL2SDK = $(HL2SDK_L4D)
CFLAGS += -DSOURCE_ENGINE=8
endif
ifeq "$(ENGINE)" "left4dead2"
HL2SDK = $(HL2SDK_L4D2)
CFLAGS += -DSOURCE_ENGINE=9
endif
ifeq "$(ENGINE)" "csgo"
HL2SDK = $(HL2SDK_CSGO)
CFLAGS += -DSOURCE_ENGINE=12
endif
HL2PUB = $(HL2SDK)/public
ifeq "$(ENGINE)" "original"
INCLUDE += -I$(HL2SDK)/public/dlls
METAMOD = $(MMSOURCE19)/core-legacy
else
INCLUDE += -I$(HL2SDK)/public/game/server
METAMOD = $(MMSOURCE19)/core
endif
OS := $(shell uname -s)
ifeq "$(OS)" "Darwin"
LIB_EXT = dylib
HL2LIB = $(HL2SDK)/lib/mac
else
LIB_EXT = so
ifeq "$(ENGINE)" "original"
HL2LIB = $(HL2SDK)/linux_sdk
else
HL2LIB = $(HL2SDK)/lib/linux
endif
endif
# if ENGINE is original or OB
ifneq (,$(filter original orangebox,$(ENGINE)))
LIB_SUFFIX = _i486.$(LIB_EXT)
else
LIB_PREFIX = lib
LIB_SUFFIX = .$(LIB_EXT)
endif
INCLUDE += -I. -I.. -Isdk -I$(SMSDK)/public -I$(SMSDK)/public/sourcepawn
ifeq "$(USEMETA)" "true"
LINK_HL2 = $(HL2LIB)/tier1_i486.a $(LIB_PREFIX)vstdlib$(LIB_SUFFIX) $(LIB_PREFIX)tier0$(LIB_SUFFIX)
ifeq "$(ENGINE)" "csgo"
LINK_HL2 += $(HL2LIB)/interfaces_i486.a
endif
LINK += $(LINK_HL2)
INCLUDE += -I$(HL2PUB) -I$(HL2PUB)/engine -I$(HL2PUB)/tier0 -I$(HL2PUB)/tier1 -I$(METAMOD) \
-I$(METAMOD)/sourcehook
CFLAGS += -DSE_EPISODEONE=1 -DSE_DARKMESSIAH=2 -DSE_ORANGEBOX=3 -DSE_BLOODYGOODTIME=4 -DSE_EYE=5 \
-DSE_CSS=6 -DSE_ORANGEBOXVALVE=7 -DSE_LEFT4DEAD=8 -DSE_LEFT4DEAD2=9 -DSE_ALIENSWARM=10 \
-DSE_PORTAL2=11 -DSE_CSGO=12
endif
LINK += -m32 -lm -ldl
CFLAGS += -DPOSIX -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp \
-D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -DCOMPILER_GCC -Wall -Werror \
-Wno-overloaded-virtual -Wno-switch -Wno-unused -msse -DSOURCEMOD_BUILD -DHAVE_STDINT_H -m32
CPPFLAGS += -Wno-non-virtual-dtor -fno-exceptions -fno-rtti
################################################
### DO NOT EDIT BELOW HERE FOR MOST PROJECTS ###
################################################
BINARY = $(PROJECT).ext.$(LIB_EXT)
ifeq "$(DEBUG)" "true"
BIN_DIR = Debug
CFLAGS += $(C_DEBUG_FLAGS)
else
BIN_DIR = Release
CFLAGS += $(C_OPT_FLAGS)
endif
ifeq "$(USEMETA)" "true"
BIN_DIR := $(BIN_DIR).$(ENGINE)
endif
ifeq "$(OS)" "Darwin"
CPP = $(CPP_OSX)
LIB_EXT = dylib
CFLAGS += -DOSX -D_OSX
LINK += -dynamiclib -lstdc++ -mmacosx-version-min=10.5
else
LIB_EXT = so
CFLAGS += -D_LINUX
LINK += -shared
endif
IS_CLANG := $(shell $(CPP) --version | head -1 | grep clang > /dev/null && echo "1" || echo "0")
ifeq "$(IS_CLANG)" "1"
CPP_MAJOR := $(shell $(CPP) --version | grep clang | sed "s/.*version \([0-9]\)*\.[0-9]*.*/\1/")
CPP_MINOR := $(shell $(CPP) --version | grep clang | sed "s/.*version [0-9]*\.\([0-9]\)*.*/\1/")
else
CPP_MAJOR := $(shell $(CPP) -dumpversion >&1 | cut -b1)
CPP_MINOR := $(shell $(CPP) -dumpversion >&1 | cut -b3)
endif
# If not clang
ifeq "$(IS_CLANG)" "0"
CFLAGS += -mfpmath=sse
endif
# Clang || GCC >= 4
ifeq "$(shell expr $(IS_CLANG) \| $(CPP_MAJOR) \>= 4)" "1"
CFLAGS += $(C_GCC4_FLAGS)
CPPFLAGS += $(CPP_GCC4_FLAGS)
endif
# Clang >= 3 || GCC >= 4.7
ifeq "$(shell expr $(IS_CLANG) \& $(CPP_MAJOR) \>= 3 \| $(CPP_MAJOR) \>= 4 \& $(CPP_MINOR) \>= 7)" "1"
CFLAGS += -Wno-delete-non-virtual-dtor
endif
# OS is Linux and not using clang
ifeq "$(shell expr $(OS) \= Linux \& $(IS_CLANG) \= 0)" "1"
LINK += -static-libgcc
endif
OBJ_BIN := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o)
# This will break if we include other Makefiles, but is fine for now. It allows
# us to make a copy of this file that uses altered paths (ie. Makefile.mine)
# or other changes without mucking up the original.
MAKEFILE_NAME := $(CURDIR)/$(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
$(BIN_DIR)/%.o: %.cpp
$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) -o $@ -c $<
all: check
mkdir -p $(BIN_DIR)
ln -sf ../smsdk_ext.cpp
if [ "$(USEMETA)" = "true" ]; then \
ln -sf $(HL2LIB)/$(LIB_PREFIX)vstdlib$(LIB_SUFFIX); \
ln -sf $(HL2LIB)/$(LIB_PREFIX)tier0$(LIB_SUFFIX); \
fi
$(MAKE) -f $(MAKEFILE_NAME) extension
check:
if [ "$(USEMETA)" = "true" ] && [ "$(ENGSET)" = "false" ]; then \
echo "You must supply one of the following values for ENGINE:"; \
echo "csgo, left4dead2, left4dead, css, orangeboxvalve, orangebox, or original"; \
exit 1; \
fi
extension: check $(OBJ_BIN)
$(CPP) $(INCLUDE) $(OBJ_BIN) $(LINK) -o $(BIN_DIR)/$(BINARY)
debug:
$(MAKE) -f $(MAKEFILE_NAME) all DEBUG=true
default: all
clean: check
rm -rf $(BIN_DIR)/*.o
rm -rf $(BIN_DIR)/$(BINARY)

30
PackageScript Normal file
View File

@ -0,0 +1,30 @@
# vim: set ts=8 sts=2 sw=2 tw=99 et ft=python:
import os
# This is where the files will be output to
# package is the default
builder.SetBuildFolder('package')
# Add any folders you need to this list
folder_list = [
'addons/sourcemod/extensions'
]
# Create the distribution folder hierarchy.
folder_map = {}
for folder in folder_list:
norm_folder = os.path.normpath(folder)
folder_map[folder] = builder.AddFolder(norm_folder)
# Do all straight-up file copies from the source tree.
def CopyFiles(src, dest, files):
if not dest:
dest = src
dest_entry = folder_map[dest]
for source_file in files:
source_path = os.path.join(builder.sourcePath, src, source_file)
builder.AddCopy(source_path, dest_entry)
# Copy binaries.
for cxx_task in Extension.extensions:
builder.AddCopy(cxx_task.binary, folder_map['addons/sourcemod/extensions'])

23
configure.py Executable file
View File

@ -0,0 +1,23 @@
# vim: set sts=2 ts=8 sw=2 tw=99 et:
import sys
from ambuild2 import run
# Simple extensions do not need to modify this file.
builder = run.PrepareBuild(sourcePath = sys.path[0])
builder.options.add_option('--hl2sdk-root', type=str, dest='hl2sdk_root', default=None,
help='Root search folder for HL2SDKs')
builder.options.add_option('--mms-path', type=str, dest='mms_path', default=None,
help='Path to Metamod:Source')
builder.options.add_option('--sm-path', type=str, dest='sm_path', default=None,
help='Path to SourceMod')
builder.options.add_option('--enable-debug', action='store_const', const='1', dest='debug',
help='Enable debugging symbols')
builder.options.add_option('--enable-optimize', action='store_const', const='1', dest='opt',
help='Enable optimization')
builder.options.add_option('-s', '--sdks', default='all', dest='sdks',
help='Build against specified SDKs; valid args are "all", "present", or '
'comma-delimited list of engine names (default: %default)')
builder.Configure()

655
extension.cpp Normal file
View File

@ -0,0 +1,655 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod Sample Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* 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, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
//#define _GNU_SOURCE
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <poll.h>
#include <iclient.h>
#include <iserver.h>
#include <ISDKTools.h>
#include "extension.h"
#define LISTEN_ADDR "127.0.0.1"
//#define LISTEN_ADDR "10.0.0.101"
#define LISTEN_PORT 27020
/**
* @file extension.cpp
* @brief Implement extension code here.
*/
template <typename T> inline T min(T a, T b) { return a<b?a:b; }
/**
* Polynomial: 0x04C11DB7
*/
const unsigned int CRCTable[256] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d};
unsigned int UTIL_CRC32(const void *pdata, size_t data_length)
{
unsigned char *data = (unsigned char *)pdata;
unsigned int crc = 0xFFFFFFFF;
unsigned char c;
for(size_t i = 0; i < data_length; i++, data++)
{
c = (unsigned char)((crc ^ *data) & 0xFF);
crc = CRCTable[c] ^ (crc >> 8);
}
return ~crc;
}
CVoice g_Interface;
SMEXT_LINK(&g_Interface);
ISDKTools *g_pSDKTools = NULL;
SH_DECL_MANUALHOOK0(GetPlayerSlot, 0, 0, 0, int); // IClient::GetPlayerSlot
double getTime()
{
struct timespec tv;
if(clock_gettime(CLOCK_REALTIME, &tv) != 0)
return 0;
return (tv.tv_sec + (tv.tv_nsec / 1000000000.0));
}
void OnGameFrame(bool simulating)
{
g_Interface.OnGameFrame(simulating);
}
CVoice::CVoice()
{
m_ListenSocket = -1;
m_PollFds = 0;
for(int i = 1; i < 1 + MAX_CLIENTS; i++)
m_aPollFds[i].fd = -1;
for(int i = 0; i < MAX_CLIENTS; i++)
m_aClients[i].m_Socket = -1;
m_AvailableTime = 0.0;
m_Silk_EncoderState = NULL;
m_SV_BroadcastVoiceData = NULL;
}
bool CVoice::SDK_OnLoad(char *error, size_t maxlength, bool late)
{
// Setup engine-specific data.
Dl_info info;
void *engineFactory = (void *)g_SMAPI->GetEngineFactory(false);
if(dladdr(engineFactory, &info) == 0)
{
g_SMAPI->Format(error, maxlength, "dladdr(engineFactory) failed.");
return false;
}
void *pEngineSo = dlopen(info.dli_fname, RTLD_NOW);
if(pEngineSo == NULL)
{
g_SMAPI->Format(error, maxlength, "dlopen(%s) failed.", info.dli_fname);
return false;
}
int engineVersion = g_SMAPI->GetSourceEngineBuild();
int offsPlayerSlot = 0;
switch (engineVersion)
{
case SOURCE_ENGINE_CSGO:
#ifdef _WIN32
m_SV_BroadcastVoiceData = (t_SV_BroadcastVoiceData)memutils->FindPattern(pEngineSo, "\x55\x8B\xEC\x81\xEC\xD0\x00\x00\x00\x53\x56\x57", 12);
offsPlayerSlot = 15;
#else
m_SV_BroadcastVoiceData = (t_SV_BroadcastVoiceData)memutils->ResolveSymbol(pEngineSo, "_Z21SV_BroadcastVoiceDataP7IClientiPcx");
offsPlayerSlot = 16;
#endif
break;
case SOURCE_ENGINE_LEFT4DEAD2:
#ifdef _WIN32
m_SV_BroadcastVoiceData = (t_SV_BroadcastVoiceData)memutils->FindPattern(pEngineSo, "\x55\x8B\xEC\x83\xEC\x70\xA1\x2A\x2A\x2A\x2A\x33\xC5\x89\x45\xFC\xA1\x2A\x2A\x2A\x2A\x53\x56", 23);
offsPlayerSlot = 14;
#else
m_SV_BroadcastVoiceData = (t_SV_BroadcastVoiceData)memutils->ResolveSymbol(pEngineSo, "_Z21SV_BroadcastVoiceDataP7IClientiPcx");
offsPlayerSlot = 15;
#endif
break;
case SOURCE_ENGINE_NUCLEARDAWN:
#ifdef _WIN32
m_SV_BroadcastVoiceData = (t_SV_BroadcastVoiceData)memutils->FindPattern(pEngineSo, "\x55\x8B\xEC\xA1\x2A\x2A\x2A\x2A\x83\xEC\x58\x57\x33\xFF", 14);
offsPlayerSlot = 14;
#else
m_SV_BroadcastVoiceData = (t_SV_BroadcastVoiceData)memutils->ResolveSymbol(pEngineSo, "_Z21SV_BroadcastVoiceDataP7IClientiPcx");
offsPlayerSlot = 15;
#endif
break;
case SOURCE_ENGINE_INSURGENCY:
#ifdef _WIN32
m_SV_BroadcastVoiceData = (t_SV_BroadcastVoiceData)memutils->FindPattern(pEngineSo, "\x55\x8B\xEC\x83\xEC\x74\x68\x2A\x2A\x2A\x2A\x8D\x4D\xE4\xE8", 15);
offsPlayerSlot = 14;
#else
m_SV_BroadcastVoiceData = (t_SV_BroadcastVoiceData)memutils->ResolveSymbol(pEngineSo, "_Z21SV_BroadcastVoiceDataP7IClientiPcx");
offsPlayerSlot = 15;
#endif
break;
case SOURCE_ENGINE_TF2:
case SOURCE_ENGINE_CSS:
case SOURCE_ENGINE_HL2DM:
case SOURCE_ENGINE_DODS:
case SOURCE_ENGINE_SDK2013:
#ifdef _WIN32
m_SV_BroadcastVoiceData = (t_SV_BroadcastVoiceData)memutils->FindPattern(pEngineSo, "\x55\x8B\xEC\xA1\x2A\x2A\x2A\x2A\x83\xEC\x50\x83\x78\x30", 14);
offsPlayerSlot = 14;
#else
m_SV_BroadcastVoiceData = (t_SV_BroadcastVoiceData)memutils->ResolveSymbol(pEngineSo, "_Z21SV_BroadcastVoiceDataP7IClientiPcx");
offsPlayerSlot = 15;
#endif
break;
default:
g_SMAPI->Format(error, maxlength, "Unsupported game.");
dlclose(pEngineSo);
return false;
}
dlclose(pEngineSo);
if(!m_SV_BroadcastVoiceData)
{
g_SMAPI->Format(error, maxlength, "SV_BroadcastVoiceData sigscan failed.");
return false;
}
SH_MANUALHOOK_RECONFIGURE(GetPlayerSlot, offsPlayerSlot, 0, 0);
// Init tcp server
m_ListenSocket = socket(AF_INET, SOCK_STREAM, 0);
if(m_ListenSocket < 0)
{
g_SMAPI->Format(error, maxlength, "Failed creating socket.");
SDK_OnUnload();
return false;
}
int yes = 1;
if(setsockopt(m_ListenSocket, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) < 0)
{
g_SMAPI->Format(error, maxlength, "Failed setting SO_REUSEADDR on socket.");
SDK_OnUnload();
return false;
}
sockaddr_in bindAddr;
memset(&bindAddr, 0, sizeof(bindAddr));
bindAddr.sin_family = AF_INET;
inet_aton(LISTEN_ADDR, &bindAddr.sin_addr);
bindAddr.sin_port = htons(LISTEN_PORT);
// Listen on LISTEN_ADDR:LISTEN_PORT
if(bind(m_ListenSocket, (sockaddr *)&bindAddr, sizeof(sockaddr_in)) < 0)
{
g_SMAPI->Format(error, maxlength, "Failed binding to socket (%d '%s').", errno, strerror(errno));
SDK_OnUnload();
return false;
}
if(listen(m_ListenSocket, MAX_CLIENTS) < 0)
{
g_SMAPI->Format(error, maxlength, "Failed listening on socket.");
SDK_OnUnload();
return false;
}
m_aPollFds[0].fd = m_ListenSocket;
m_aPollFds[0].events = POLLIN;
m_PollFds++;
// Encoder settings
m_EncoderSettings.InputSampleRate_kHz = 48; // 8, 12, 16, 24, 32, 44.1, 48
m_EncoderSettings.OutputSampleRate_kHz = 16; // 8, 12, 16, 24
m_EncoderSettings.TargetBitRate_Kbps = 100; // 6 - 40
m_EncoderSettings.PacketSize_ms = 20; // 20, 40, 60, 80, 100
m_EncoderSettings.FrameSize_ms = 20; //
m_EncoderSettings.PacketLoss_perc = 0; // 0 - 100
m_EncoderSettings.Complexity = 2; // 0 - 2
m_EncoderSettings.InBandFEC = 0; // 0, 1
m_EncoderSettings.DTX = 0; // 0, 1
// Init SILK encoder
int encoderSize;
SKP_Silk_SDK_Get_Encoder_Size(&encoderSize);
m_Silk_EncoderState = malloc(encoderSize);
if(!m_Silk_EncoderState)
{
g_SMAPI->Format(error, maxlength, "Failed to malloc %d bytes for silk encoder.", encoderSize);
SDK_OnUnload();
return false;
}
int retEnc = SKP_Silk_SDK_InitEncoder(m_Silk_EncoderState, &m_Silk_EncoderControl);
if(retEnc != SKP_SILK_NO_ERROR)
{
g_SMAPI->Format(error, maxlength, "Silk encoder initialization failed with: %d", retEnc);
SDK_OnUnload();
return false;
}
m_Silk_EncoderControl.API_sampleRate = m_EncoderSettings.InputSampleRate_kHz * 1000;
m_Silk_EncoderControl.maxInternalSampleRate = m_EncoderSettings.OutputSampleRate_kHz * 1000;
m_Silk_EncoderControl.bitRate = m_EncoderSettings.TargetBitRate_Kbps * 1000;
m_Silk_EncoderControl.packetSize = m_EncoderSettings.PacketSize_ms * m_EncoderSettings.InputSampleRate_kHz;
m_Silk_EncoderControl.packetLossPercentage = m_EncoderSettings.PacketLoss_perc;
m_Silk_EncoderControl.complexity = m_EncoderSettings.Complexity;
m_Silk_EncoderControl.useInBandFEC = m_EncoderSettings.InBandFEC;
m_Silk_EncoderControl.useDTX = m_EncoderSettings.DTX;
smutils->AddGameFrameHook(::OnGameFrame);
return true;
}
void CVoice::SDK_OnAllLoaded()
{
SM_GET_LATE_IFACE(SDKTOOLS, g_pSDKTools);
if(g_pSDKTools == NULL)
smutils->LogError(myself, "SDKTools interface not found");
}
void CVoice::SDK_OnUnload()
{
smutils->RemoveGameFrameHook(::OnGameFrame);
if(m_ListenSocket != -1)
{
close(m_ListenSocket);
m_ListenSocket = -1;
}
for(int Client = 0; Client < MAX_CLIENTS; Client++)
{
if(m_aClients[Client].m_Socket != -1)
{
close(m_aClients[Client].m_Socket);
m_aClients[Client].m_Socket = -1;
}
}
if(m_Silk_EncoderState)
{
free(m_Silk_EncoderState);
m_Silk_EncoderState = NULL;
}
}
void CVoice::OnGameFrame(bool simulating)
{
HandleNetwork();
HandleVoiceData();
}
void CVoice::HandleNetwork()
{
if(m_ListenSocket == -1)
return;
int PollRes = poll(m_aPollFds, m_PollFds, 0);
if(PollRes <= 0)
return;
// Accept new clients
if(m_aPollFds[0].revents & POLLIN)
{
// Find slot
int Client;
for(Client = 0; Client < MAX_CLIENTS; Client++)
{
if(m_aClients[Client].m_Socket == -1)
break;
}
// no free slot
if(Client != MAX_CLIENTS)
{
sockaddr_in addr;
size_t size = sizeof(sockaddr_in);
int Socket = accept(m_ListenSocket, (sockaddr *)&addr, &size);
m_aClients[Client].m_Socket = Socket;
m_aClients[Client].m_BufferWriteIndex = 0;
m_aClients[Client].m_LastLength = 0;
m_aClients[Client].m_LastValidData = 0.0;
m_aClients[Client].m_New = true;
m_aPollFds[m_PollFds].fd = Socket;
m_aPollFds[m_PollFds].events = POLLIN | POLLHUP;
m_aPollFds[m_PollFds].revents = 0;
m_PollFds++;
smutils->LogMessage(myself, "Client %d connected!\n", Client);
}
}
bool CompressPollFds = false;
for(int PollFds = 1; PollFds < m_PollFds; PollFds++)
{
int Client = -1;
for(Client = 0; Client < MAX_CLIENTS; Client++)
{
if(m_aClients[Client].m_Socket == m_aPollFds[PollFds].fd)
break;
}
if(Client == -1)
continue;
CClient *pClient = &m_aClients[Client];
// Connection shutdown prematurely ^C
// Make sure to set SO_LINGER l_onoff = 1, l_linger = 0
if(m_aPollFds[PollFds].revents & POLLHUP)
{
close(pClient->m_Socket);
pClient->m_Socket = -1;
m_aPollFds[PollFds].fd = -1;
CompressPollFds = true;
smutils->LogMessage(myself, "Client %d disconnected!(2)\n", Client);
continue;
}
// Data available?
if(!(m_aPollFds[PollFds].revents & POLLIN))
continue;
size_t BytesAvailable;
if(ioctl(pClient->m_Socket, FIONREAD, &BytesAvailable) == -1)
continue;
if(pClient->m_New)
{
pClient->m_BufferWriteIndex = m_Buffer.GetReadIndex();
pClient->m_New = false;
}
m_Buffer.SetWriteIndex(pClient->m_BufferWriteIndex);
// Don't recv() when we can't fit data into the ringbuffer
unsigned char aBuf[32768];
if(min(BytesAvailable, sizeof(aBuf)) > m_Buffer.CurrentFree() * sizeof(int16_t))
continue;
ssize_t Bytes = recv(pClient->m_Socket, aBuf, sizeof(aBuf), 0);
if(Bytes <= 0)
{
close(pClient->m_Socket);
pClient->m_Socket = -1;
m_aPollFds[PollFds].fd = -1;
CompressPollFds = true;
smutils->LogMessage(myself, "Client %d disconnected!(1)\n", Client);
continue;
}
// Got data!
OnDataReceived(pClient, (int16_t *)aBuf, Bytes / sizeof(int16_t));
pClient->m_LastLength = m_Buffer.CurrentLength();
pClient->m_BufferWriteIndex = m_Buffer.GetWriteIndex();
}
if(CompressPollFds)
{
for(int PollFds = 1; PollFds < m_PollFds; PollFds++)
{
if(m_aPollFds[PollFds].fd != -1)
continue;
for(int PollFds_ = PollFds; PollFds_ < 1 + MAX_CLIENTS; PollFds_++)
m_aPollFds[PollFds_].fd = m_aPollFds[PollFds_ + 1].fd;
PollFds--;
m_PollFds--;
}
}
}
void CVoice::OnDataReceived(CClient *pClient, int16_t *pData, size_t Samples)
{
// Check for empty input
ssize_t DataStartsAt = -1;
for(size_t i = 0; i < Samples; i++)
{
if(pData[i] == 0)
continue;
DataStartsAt = i;
break;
}
// Discard empty data if last vaild data was more than a second ago.
if(pClient->m_LastValidData + 1.0 < getTime())
{
// All empty
if(DataStartsAt == -1)
return;
// Data starts here
pData += DataStartsAt;
Samples -= DataStartsAt;
}
if(!m_Buffer.Push(pData, Samples))
{
smutils->LogError(myself, "Buffer push failed!!! Samples: %u, Free: %u\n", Samples, m_Buffer.CurrentFree());
return;
}
pClient->m_LastValidData = getTime();
}
struct SteamVoiceHeader
{
uint32_t iSteamAccountID : 32;
uint32_t iSteamCommunity : 32;
uint32_t nPayload1 : 8;
uint32_t iSampleRate : 16;
uint32_t nPayload2 : 8;
uint32_t iDataLength : 16;
};
void CVoice::HandleVoiceData()
{
int SamplesPerFrame = m_EncoderSettings.FrameSize_ms * m_EncoderSettings.InputSampleRate_kHz;
int FramesAvailable = m_Buffer.TotalLength() / SamplesPerFrame;
float TimeAvailable = (float)m_Buffer.TotalLength() / (m_EncoderSettings.InputSampleRate_kHz * 1000.0);
if(!FramesAvailable)
return;
// Before starting playback we want at least 100ms in the buffer
if(m_AvailableTime < getTime() && TimeAvailable < 0.1)
return;
// let the clients have no more than 500ms
if(m_AvailableTime > getTime() + 0.5)
return;
// 5 = max frames per packet
FramesAvailable = min(FramesAvailable, 5);
// 0 = SourceTV
IClient *pClient = g_pSDKTools->GetIServer()->GetClient(0);
if(!pClient)
return;
SteamVoiceHeader Header;
size_t HeaderSize = 14;
Header.iSteamAccountID = 1; // Steam Account ID
Header.iSteamCommunity = 0x01100001; // Steam Community ID part: 0x01100001 << 32
Header.nPayload1 = 11; // nPayLoad | Type 11 = Samplerate
Header.iSampleRate = m_EncoderSettings.OutputSampleRate_kHz * 1000; // Samplerate
Header.nPayload2 = 4; // nPayLoad | Type 4 = Silk Frames
Header.iDataLength = 0; // Silk Frames total length
// Header + Frames + CRC32
unsigned char aFinal[HeaderSize + 8192 + sizeof(uint32_t)];
size_t FinalSize = HeaderSize;
for(int Frame = 0; Frame < FramesAvailable; Frame++)
{
// Get data into buffer from ringbuffer.
int16_t aBuffer[SamplesPerFrame];
size_t OldReadIdx = m_Buffer.m_ReadIndex;
size_t OldCurLength = m_Buffer.CurrentLength();
size_t OldTotalLength = m_Buffer.TotalLength();
if(!m_Buffer.Pop(aBuffer, SamplesPerFrame))
{
smutils->LogError(myself, "Buffer pop failed!!! Samples: %u, Length: %u\n", SamplesPerFrame, m_Buffer.TotalLength());
return;
}
// Frame Size
int16_t *pFrameSize = (int16_t *)(&aFinal[FinalSize]);
FinalSize += sizeof(int16_t);
Header.iDataLength += sizeof(int16_t);
*pFrameSize = sizeof(aFinal) - HeaderSize - sizeof(uint32_t) - FinalSize;
// Encode it!
int Ret = SKP_Silk_SDK_Encode(m_Silk_EncoderState, &m_Silk_EncoderControl, aBuffer,
SamplesPerFrame, &aFinal[FinalSize], pFrameSize);
if(Ret)
{
smutils->LogError(myself, "SKP_Silk_SDK_Encode returned %d\n", Ret);
return;
}
FinalSize += *pFrameSize;
Header.iDataLength += *pFrameSize;
// Check for buffer underruns
for(int Client = 0; Client < MAX_CLIENTS; Client++)
{
CClient *pClient = &m_aClients[Client];
if(pClient->m_Socket == -1 || pClient->m_New == true)
continue;
m_Buffer.SetWriteIndex(pClient->m_BufferWriteIndex);
if(m_Buffer.CurrentLength() > pClient->m_LastLength)
{
pClient->m_BufferWriteIndex = m_Buffer.GetReadIndex();
m_Buffer.SetWriteIndex(pClient->m_BufferWriteIndex);
pClient->m_LastLength = m_Buffer.CurrentLength();
}
}
}
// Header
memcpy(aFinal, &Header, HeaderSize);
// CRC32
*(uint32_t *)(&aFinal[FinalSize]) = UTIL_CRC32(aFinal, FinalSize);
FinalSize += sizeof(uint32_t);
SV_BroadcastVoiceData(pClient, FinalSize, aFinal);
if(m_AvailableTime < getTime())
m_AvailableTime = getTime();
m_AvailableTime += (double)FramesAvailable * ((double)m_EncoderSettings.FrameSize_ms / 1000.0);
}
void CVoice::SV_BroadcastVoiceData(IClient *pClient, int nBytes, unsigned char *pData)
{
m_SV_BroadcastVoiceData(pClient, nBytes, pData, 0);
}

177
extension.h Normal file
View File

@ -0,0 +1,177 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod Sample Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* 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, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#ifndef _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
#define _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_
#include "smsdk_ext.h"
#include <SKP_Silk_SDK_API.h>
#include "ringbuffer.h"
/**
* @file extension.h
* @brief Sample extension code header.
*/
#define MAX_CLIENTS 16
#ifdef _WIN32
typedef __int64 int64;
#else
typedef long long int64;
#endif
class IClient;
typedef void (*t_SV_BroadcastVoiceData)(IClient *, int, unsigned char *, int64);
/**
* @brief Sample implementation of the SDK Extension.
* Note: Uncomment one of the pre-defined virtual functions in order to use it.
*/
class CVoice : public SDKExtension
{
public:
/**
* @brief This is called after the initial loading sequence has been processed.
*
* @param error Error message buffer.
* @param maxlength Size of error message buffer.
* @param late Whether or not the module was loaded after map load.
* @return True to succeed loading, false to fail.
*/
virtual bool SDK_OnLoad(char *error, size_t maxlength, bool late);
/**
* @brief This is called right before the extension is unloaded.
*/
virtual void SDK_OnUnload();
/**
* @brief This is called once all known extensions have been loaded.
* Note: It is is a good idea to add natives here, if any are provided.
*/
virtual void SDK_OnAllLoaded();
/**
* @brief Called when the pause state is changed.
*/
//virtual void SDK_OnPauseChange(bool paused);
/**
* @brief this is called when Core wants to know if your extension is working.
*
* @param error Error message buffer.
* @param maxlength Size of error message buffer.
* @return True if working, false otherwise.
*/
//virtual bool QueryRunning(char *error, size_t maxlength);
public:
#if defined SMEXT_CONF_METAMOD
/**
* @brief Called when Metamod is attached, before the extension version is called.
*
* @param error Error buffer.
* @param maxlength Maximum size of error buffer.
* @param late Whether or not Metamod considers this a late load.
* @return True to succeed, false to fail.
*/
//virtual bool SDK_OnMetamodLoad(ISmmAPI *ismm, char *error, size_t maxlength, bool late);
/**
* @brief Called when Metamod is detaching, after the extension version is called.
* NOTE: By default this is blocked unless sent from SourceMod.
*
* @param error Error buffer.
* @param maxlength Maximum size of error buffer.
* @return True to succeed, false to fail.
*/
//virtual bool SDK_OnMetamodUnload(char *error, size_t maxlength);
/**
* @brief Called when Metamod's pause state is changing.
* NOTE: By default this is blocked unless sent from SourceMod.
*
* @param paused Pause state being set.
* @param error Error buffer.
* @param maxlength Maximum size of error buffer.
* @return True to succeed, false to fail.
*/
//virtual bool SDK_OnMetamodPauseChange(bool paused, char *error, size_t maxlength);
#endif
public:
CVoice();
void OnGameFrame(bool simulating);
private:
int m_ListenSocket;
struct CClient
{
int m_Socket;
size_t m_BufferWriteIndex;
size_t m_LastLength;
double m_LastValidData;
bool m_New;
} m_aClients[MAX_CLIENTS];
struct pollfd m_aPollFds[1 + MAX_CLIENTS];
int m_PollFds;
CRingBuffer m_Buffer;
double m_AvailableTime;
struct CEncoderSettings
{
SKP_int InputSampleRate_kHz;
SKP_int OutputSampleRate_kHz;
SKP_int TargetBitRate_Kbps;
SKP_int PacketSize_ms;
SKP_int FrameSize_ms;
SKP_int PacketLoss_perc;
SKP_int Complexity;
SKP_int InBandFEC;
SKP_int DTX;
} m_EncoderSettings;
void *m_Silk_EncoderState;
SKP_SILK_SDK_EncControlStruct m_Silk_EncoderControl;
t_SV_BroadcastVoiceData m_SV_BroadcastVoiceData;
void HandleNetwork();
void OnDataReceived(CClient *pClient, int16_t *pData, size_t Samples);
void HandleVoiceData();
void SV_BroadcastVoiceData(IClient *pClient, int nBytes, unsigned char *pData);
};
#endif // _INCLUDE_SOURCEMOD_EXTENSION_PROPER_H_

164
ringbuffer.cpp Normal file
View File

@ -0,0 +1,164 @@
#include <string.h>
#include <stdio.h>
#include "ringbuffer.h"
#undef NDEBUG
#include <assert.h>
template <typename T> inline T min(T a, T b) { return a<b?a:b; }
CRingBuffer::CRingBuffer() : m_BufferSize(sizeof(m_aBuffer) / sizeof(*m_aBuffer))
{
m_ReadIndex = 0;
m_WriteIndex = 0;
m_Length = 0;
}
bool CRingBuffer::Pop(int16_t *pBuffer, size_t Samples)
{
if(Samples > TotalLength())
return false;
if(m_ReadIndex + Samples > m_BufferSize)
{
size_t TowardsEnd = m_BufferSize - m_ReadIndex;
memcpy(pBuffer, &m_aBuffer[m_ReadIndex], TowardsEnd * sizeof(*m_aBuffer));
m_ReadIndex = 0;
size_t Left = Samples - TowardsEnd;
memcpy(&pBuffer[TowardsEnd], m_aBuffer, Left * sizeof(*m_aBuffer));
m_ReadIndex = Left;
}
else
{
memcpy(pBuffer, &m_aBuffer[m_ReadIndex], Samples * sizeof(*m_aBuffer));
m_ReadIndex += Samples;
}
if(m_ReadIndex == m_BufferSize)
m_ReadIndex = 0;
m_Length -= Samples;
return true;
}
void CRingBuffer::Mix(int16_t *pData, size_t Samples)
{
assert(!(m_WriteIndex + Samples > m_BufferSize));
int16_t *pBuffer = &m_aBuffer[m_WriteIndex];
while(Samples--)
{
int32_t Sample = *pBuffer;
Sample += *pData;
if(Sample > INT16_MAX)
*pBuffer = INT16_MAX;
else if(Sample < INT16_MIN)
*pBuffer = INT16_MIN;
else
*pBuffer = Sample;
pBuffer++;
pData++;
}
}
bool CRingBuffer::Push(int16_t *pData, size_t Samples)
{
if(Samples > CurrentFree())
return false;
// Mix with data in front of us
if(CurrentLength() < TotalLength())
{
//
size_t ToMix = min(Samples, TotalLength() - CurrentLength());
if(m_WriteIndex + ToMix > m_BufferSize)
{
size_t TowardsEnd = m_BufferSize - m_WriteIndex;
Mix(pData, TowardsEnd);
m_WriteIndex = 0;
size_t Left = ToMix - TowardsEnd;
Mix(&pData[TowardsEnd], Left);
m_WriteIndex = Left;
}
else
{
Mix(pData, ToMix);
m_WriteIndex += ToMix;
}
if(m_WriteIndex == m_BufferSize)
m_WriteIndex = 0;
pData += ToMix;
Samples -= ToMix;
}
//
if(!Samples)
return true;
if(m_WriteIndex + Samples > m_BufferSize)
{
size_t TowardsEnd = m_BufferSize - m_WriteIndex;
memcpy(&m_aBuffer[m_WriteIndex], pData, TowardsEnd * sizeof(*m_aBuffer));
m_WriteIndex = 0;
size_t Left = Samples - TowardsEnd;
memcpy(m_aBuffer, &pData[TowardsEnd], Left * sizeof(*m_aBuffer));
m_WriteIndex = Left;
}
else
{
memcpy(&m_aBuffer[m_WriteIndex], pData, Samples * sizeof(*m_aBuffer));
m_WriteIndex += Samples;
}
if(m_WriteIndex == m_BufferSize)
m_WriteIndex = 0;
m_Length += Samples;
return true;
}
size_t CRingBuffer::TotalLength()
{
return m_Length;
}
size_t CRingBuffer::TotalFree()
{
return m_BufferSize - m_Length - 1;
}
size_t CRingBuffer::CurrentLength()
{
return ((ssize_t)m_WriteIndex - (ssize_t)m_ReadIndex) % m_BufferSize;
}
size_t CRingBuffer::CurrentFree()
{
size_t BufferFree = ((ssize_t)m_ReadIndex - (ssize_t)m_WriteIndex) % m_BufferSize;
return (BufferFree ? BufferFree : m_BufferSize) - 1;
}
size_t CRingBuffer::GetReadIndex()
{
return m_ReadIndex;
}
size_t CRingBuffer::GetWriteIndex()
{
return m_WriteIndex;
}
void CRingBuffer::SetWriteIndex(size_t WriteIndex)
{
m_WriteIndex = WriteIndex;
}

35
ringbuffer.h Normal file
View File

@ -0,0 +1,35 @@
#ifndef RINGBUFFER_H
#define RINGBUFFER_H
#include <stdint.h>
#include <stdlib.h>
class CRingBuffer
{
public:
const size_t m_BufferSize;
CRingBuffer();
bool Pop(int16_t *pData, size_t Samples);
bool Push(int16_t *pData, size_t BufLen);
size_t TotalLength();
size_t TotalFree();
size_t CurrentLength();
size_t CurrentFree();
size_t GetReadIndex();
size_t GetWriteIndex();
void SetWriteIndex(size_t WriteIndex);
public:
void Mix(int16_t *pData, size_t Samples);
size_t m_ReadIndex;
size_t m_WriteIndex;
size_t m_Length;
int16_t m_aBuffer[32768];
};
#endif // RINGBUFFER_H

Binary file not shown.

152
silk/SKP_Silk_SDK_API.h Normal file
View File

@ -0,0 +1,152 @@
/***********************************************************************
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
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
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
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,
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
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#ifndef SKP_SILK_SDK_API_H
#define SKP_SILK_SDK_API_H
#include "SKP_Silk_control.h"
#include "SKP_Silk_typedef.h"
#include "SKP_Silk_errors.h"
#ifdef __cplusplus
extern "C"
{
#endif
#define SILK_MAX_FRAMES_PER_PACKET 5
/* Struct for TOC (Table of Contents) */
typedef struct {
SKP_int framesInPacket; /* Number of 20 ms frames in packet */
SKP_int fs_kHz; /* Sampling frequency in packet */
SKP_int inbandLBRR; /* Does packet contain LBRR information */
SKP_int corrupt; /* Packet is corrupt */
SKP_int vadFlags[ SILK_MAX_FRAMES_PER_PACKET ]; /* VAD flag for each frame in packet */
SKP_int sigtypeFlags[ SILK_MAX_FRAMES_PER_PACKET ]; /* Signal type for each frame in packet */
} SKP_Silk_TOC_struct;
/****************************************/
/* Encoder functions */
/****************************************/
/***********************************************/
/* Get size in bytes of the Silk encoder state */
/***********************************************/
SKP_int SKP_Silk_SDK_Get_Encoder_Size(
SKP_int32 *encSizeBytes /* O: Number of bytes in SILK encoder state */
);
/*************************/
/* Init or reset encoder */
/*************************/
SKP_int SKP_Silk_SDK_InitEncoder(
void *encState, /* I/O: State */
SKP_SILK_SDK_EncControlStruct *encStatus /* O: Encoder Status */
);
/***************************************/
/* Read control structure from encoder */
/***************************************/
SKP_int SKP_Silk_SDK_QueryEncoder(
const void *encState, /* I: State */
SKP_SILK_SDK_EncControlStruct *encStatus /* O: Encoder Status */
);
/**************************/
/* Encode frame with Silk */
/**************************/
SKP_int SKP_Silk_SDK_Encode(
void *encState, /* I/O: State */
const SKP_SILK_SDK_EncControlStruct *encControl, /* I: Control status */
const SKP_int16 *samplesIn, /* I: Speech sample input vector */
SKP_int nSamplesIn, /* I: Number of samples in input vector */
SKP_uint8 *outData, /* O: Encoded output vector */
SKP_int16 *nBytesOut /* I/O: Number of bytes in outData (input: Max bytes) */
);
/****************************************/
/* Decoder functions */
/****************************************/
/***********************************************/
/* Get size in bytes of the Silk decoder state */
/***********************************************/
SKP_int SKP_Silk_SDK_Get_Decoder_Size(
SKP_int32 *decSizeBytes /* O: Number of bytes in SILK decoder state */
);
/*************************/
/* Init or Reset decoder */
/*************************/
SKP_int SKP_Silk_SDK_InitDecoder(
void *decState /* I/O: State */
);
/******************/
/* Decode a frame */
/******************/
SKP_int SKP_Silk_SDK_Decode(
void* decState, /* I/O: State */
SKP_SILK_SDK_DecControlStruct* decControl, /* I/O: Control Structure */
SKP_int lostFlag, /* I: 0: no loss, 1 loss */
const SKP_uint8 *inData, /* I: Encoded input vector */
const SKP_int nBytesIn, /* I: Number of input bytes */
SKP_int16 *samplesOut, /* O: Decoded output speech vector */
SKP_int16 *nSamplesOut /* I/O: Number of samples (vector/decoded) */
);
/***************************************************************/
/* Find Low Bit Rate Redundancy (LBRR) information in a packet */
/***************************************************************/
void SKP_Silk_SDK_search_for_LBRR(
const SKP_uint8 *inData, /* I: Encoded input vector */
const SKP_int nBytesIn, /* I: Number of input Bytes */
SKP_int lost_offset, /* I: Offset from lost packet */
SKP_uint8 *LBRRData, /* O: LBRR payload */
SKP_int16 *nLBRRBytes /* O: Number of LBRR Bytes */
);
/**************************************/
/* Get table of contents for a packet */
/**************************************/
void SKP_Silk_SDK_get_TOC(
const SKP_uint8 *inData, /* I: Encoded input vector */
const SKP_int nBytesIn, /* I: Number of input bytes */
SKP_Silk_TOC_struct *Silk_TOC /* O: Table of contents */
);
/**************************/
/* Get the version number */
/**************************/
/* Return a pointer to string specifying the version */
const char *SKP_Silk_SDK_get_version();
#ifdef __cplusplus
}
#endif
#endif

91
silk/SKP_Silk_control.h Normal file
View File

@ -0,0 +1,91 @@
/***********************************************************************
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
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
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
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,
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
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#ifndef SKP_SILK_CONTROL_H
#define SKP_SILK_CONTROL_H
#include "SKP_Silk_typedef.h"
#ifdef __cplusplus
extern "C"
{
#endif
/***********************************************/
/* Structure for controlling encoder operation */
/***********************************************/
typedef struct {
/* I: Input signal sampling rate in Hertz; 8000/12000/16000/24000 */
SKP_int32 API_sampleRate;
/* I: Maximum internal sampling rate in Hertz; 8000/12000/16000/24000 */
SKP_int32 maxInternalSampleRate;
/* I: Number of samples per packet; must be equivalent of 20, 40, 60, 80 or 100 ms */
SKP_int packetSize;
/* I: Bitrate during active speech in bits/second; internally limited */
SKP_int32 bitRate;
/* I: Uplink packet loss in percent (0-100) */
SKP_int packetLossPercentage;
/* I: Complexity mode; 0 is lowest; 1 is medium and 2 is highest complexity */
SKP_int complexity;
/* I: Flag to enable in-band Forward Error Correction (FEC); 0/1 */
SKP_int useInBandFEC;
/* I: Flag to enable discontinuous transmission (DTX); 0/1 */
SKP_int useDTX;
} SKP_SILK_SDK_EncControlStruct;
/**************************************************************************/
/* Structure for controlling decoder operation and reading decoder status */
/**************************************************************************/
typedef struct {
/* I: Output signal sampling rate in Hertz; 8000/12000/16000/24000 */
SKP_int32 API_sampleRate;
/* O: Number of samples per frame */
SKP_int frameSize;
/* O: Frames per packet 1, 2, 3, 4, 5 */
SKP_int framesPerPacket;
/* O: Flag to indicate that the decoder has remaining payloads internally */
SKP_int moreInternalDecoderFrames;
/* O: Distance between main payload and redundant payload in packets */
SKP_int inBandFECOffset;
} SKP_SILK_SDK_DecControlStruct;
#ifdef __cplusplus
}
#endif
#endif

89
silk/SKP_Silk_errors.h Normal file
View File

@ -0,0 +1,89 @@
/***********************************************************************
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
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
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
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,
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
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#ifndef SKP_SILK_ERRORS_H
#define SKP_SILK_ERRORS_H
#ifdef __cplusplus
extern "C"
{
#endif
/******************/
/* Error messages */
/******************/
#define SKP_SILK_NO_ERROR 0
/**************************/
/* Encoder error messages */
/**************************/
/* Input length is not a multiplum of 10 ms, or length is longer than the packet length */
#define SKP_SILK_ENC_INPUT_INVALID_NO_OF_SAMPLES -1
/* Sampling frequency not 8000, 12000, 16000 or 24000 Hertz */
#define SKP_SILK_ENC_FS_NOT_SUPPORTED -2
/* Packet size not 20, 40, 60, 80 or 100 ms */
#define SKP_SILK_ENC_PACKET_SIZE_NOT_SUPPORTED -3
/* Allocated payload buffer too short */
#define SKP_SILK_ENC_PAYLOAD_BUF_TOO_SHORT -4
/* Loss rate not between 0 and 100 percent */
#define SKP_SILK_ENC_INVALID_LOSS_RATE -5
/* Complexity setting not valid, use 0, 1 or 2 */
#define SKP_SILK_ENC_INVALID_COMPLEXITY_SETTING -6
/* Inband FEC setting not valid, use 0 or 1 */
#define SKP_SILK_ENC_INVALID_INBAND_FEC_SETTING -7
/* DTX setting not valid, use 0 or 1 */
#define SKP_SILK_ENC_INVALID_DTX_SETTING -8
/* Internal encoder error */
#define SKP_SILK_ENC_INTERNAL_ERROR -9
/**************************/
/* Decoder error messages */
/**************************/
/* Output sampling frequency lower than internal decoded sampling frequency */
#define SKP_SILK_DEC_INVALID_SAMPLING_FREQUENCY -10
/* Payload size exceeded the maximum allowed 1024 bytes */
#define SKP_SILK_DEC_PAYLOAD_TOO_LARGE -11
/* Payload has bit errors */
#define SKP_SILK_DEC_PAYLOAD_ERROR -12
#ifdef __cplusplus
}
#endif
#endif

107
silk/SKP_Silk_typedef.h Normal file
View File

@ -0,0 +1,107 @@
/***********************************************************************
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
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
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
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,
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
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
***********************************************************************/
#ifndef _SKP_SILK_API_TYPDEF_H_
#define _SKP_SILK_API_TYPDEF_H_
#ifndef SKP_USE_DOUBLE_PRECISION_FLOATS
#define SKP_USE_DOUBLE_PRECISION_FLOATS 0
#endif
#include <float.h>
#if defined( __GNUC__ )
#include <stdint.h>
#endif
#define SKP_int int /* used for counters etc; at least 16 bits */
#ifdef __GNUC__
# define SKP_int64 int64_t
#else
# define SKP_int64 long long
#endif
#define SKP_int32 int
#define SKP_int16 short
#define SKP_int8 signed char
#define SKP_uint unsigned int /* used for counters etc; at least 16 bits */
#ifdef __GNUC__
# define SKP_uint64 uint64_t
#else
# define SKP_uint64 unsigned long long
#endif
#define SKP_uint32 unsigned int
#define SKP_uint16 unsigned short
#define SKP_uint8 unsigned char
#define SKP_int_ptr_size intptr_t
#if SKP_USE_DOUBLE_PRECISION_FLOATS
# define SKP_float double
# define SKP_float_MAX DBL_MAX
#else
# define SKP_float float
# define SKP_float_MAX FLT_MAX
#endif
#define SKP_INLINE static __inline
#ifdef _WIN32
# define SKP_STR_CASEINSENSITIVE_COMPARE(x, y) _stricmp(x, y)
#else
# define SKP_STR_CASEINSENSITIVE_COMPARE(x, y) strcasecmp(x, y)
#endif
#define SKP_int64_MAX ((SKP_int64)0x7FFFFFFFFFFFFFFFLL) /* 2^63 - 1 */
#define SKP_int64_MIN ((SKP_int64)0x8000000000000000LL) /* -2^63 */
#define SKP_int32_MAX 0x7FFFFFFF /* 2^31 - 1 = 2147483647*/
#define SKP_int32_MIN ((SKP_int32)0x80000000) /* -2^31 = -2147483648*/
#define SKP_int16_MAX 0x7FFF /* 2^15 - 1 = 32767*/
#define SKP_int16_MIN ((SKP_int16)0x8000) /* -2^15 = -32768*/
#define SKP_int8_MAX 0x7F /* 2^7 - 1 = 127*/
#define SKP_int8_MIN ((SKP_int8)0x80) /* -2^7 = -128*/
#define SKP_uint32_MAX 0xFFFFFFFF /* 2^32 - 1 = 4294967295 */
#define SKP_uint32_MIN 0x00000000
#define SKP_uint16_MAX 0xFFFF /* 2^16 - 1 = 65535 */
#define SKP_uint16_MIN 0x0000
#define SKP_uint8_MAX 0xFF /* 2^8 - 1 = 255 */
#define SKP_uint8_MIN 0x00
#define SKP_TRUE 1
#define SKP_FALSE 0
/* assertions */
#if (defined _WIN32 && !defined _WINCE && !defined(__GNUC__) && !defined(NO_ASSERTS))
# ifndef SKP_assert
# include <crtdbg.h> /* ASSERTE() */
# define SKP_assert(COND) _ASSERTE(COND)
# endif
#else
# define SKP_assert(COND)
#endif
#endif

BIN
silk/libSKP_SILK_SDK.a Normal file

Binary file not shown.

81
smsdk_config.h Normal file
View File

@ -0,0 +1,81 @@
/**
* vim: set ts=4 :
* =============================================================================
* SourceMod Sample Extension
* Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
* =============================================================================
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, version 3.0, as published by the
* Free Software Foundation.
*
* 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, see <http://www.gnu.org/licenses/>.
*
* As a special exception, AlliedModders LLC gives you permission to link the
* code of this program (as well as its derivative works) to "Half-Life 2," the
* "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
* by the Valve Corporation. You must obey the GNU General Public License in
* all respects for all other code used. Additionally, AlliedModders LLC grants
* this exception to all derivative works. AlliedModders LLC defines further
* exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
* or <http://www.sourcemod.net/license.php>.
*
* Version: $Id$
*/
#ifndef _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_
#define _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_
/**
* @file smsdk_config.h
* @brief Contains macros for configuring basic extension information.
*/
/* Basic information exposed publicly */
#define SMEXT_CONF_NAME "Voice"
#define SMEXT_CONF_DESCRIPTION "Inject voice data over existing clients"
#define SMEXT_CONF_VERSION "1.0"
#define SMEXT_CONF_AUTHOR "BotoX"
#define SMEXT_CONF_URL ""
#define SMEXT_CONF_LOGTAG "VOICE"
#define SMEXT_CONF_LICENSE "GPL"
#define SMEXT_CONF_DATESTRING __DATE__
/**
* @brief Exposes plugin's main interface.
*/
#define SMEXT_LINK(name) SDKExtension *g_pExtensionIface = name;
/**
* @brief Sets whether or not this plugin required Metamod.
* NOTE: Uncomment to enable, comment to disable.
*/
#define SMEXT_CONF_METAMOD
/** Enable interfaces you want to use here by uncommenting lines */
//#define SMEXT_ENABLE_FORWARDSYS
//#define SMEXT_ENABLE_HANDLESYS
//#define SMEXT_ENABLE_PLAYERHELPERS
//#define SMEXT_ENABLE_DBMANAGER
#define SMEXT_ENABLE_GAMECONF
#define SMEXT_ENABLE_MEMUTILS
#define SMEXT_ENABLE_GAMEHELPERS
//#define SMEXT_ENABLE_TIMERSYS
//#define SMEXT_ENABLE_THREADER
//#define SMEXT_ENABLE_LIBSYS
//#define SMEXT_ENABLE_MENUS
//#define SMEXT_ENABLE_ADTFACTORY
//#define SMEXT_ENABLE_PLUGINSYS
//#define SMEXT_ENABLE_ADMINSYS
//#define SMEXT_ENABLE_TEXTPARSERS
//#define SMEXT_ENABLE_USERMSGS
//#define SMEXT_ENABLE_TRANSLATOR
//#define SMEXT_ENABLE_ROOTCONSOLEMENU
#endif // _INCLUDE_SOURCEMOD_EXTENSION_CONFIG_H_

68
voice_packet.bt.txt Normal file
View File

@ -0,0 +1,68 @@
//--------------------------------------
//--- 010 Editor v6.0.3 Binary Template
//
// File:
// Author:
// Revision:
// Purpose:
//--------------------------------------
// CClientAudio::DecompressVoice
local int64 crcLength = FileSize() - sizeof(uint32);
uint64 steamId;
FSeek(crcLength);
uint32 crc;
local int64 crc_calc = Checksum(CHECKSUM_CRC32, 0, crcLength);
if (crc != crc_calc) {
Warning("CRC mismatch!");
return;
}
// CVoiceDecoder::ProcessVoicePayload
FSeek(sizeof(uint64));
while (FTell() < crcLength) {
char payloadType;
switch (payloadType) {
default:
Warning("Unhandled payload!");
return;
case 11: // Sample Rate
short sampleRate;
break;
case 10: // Unknown / Unused
char unk1;
char unk2;
break;
case 1: // Unknown Codec???
case 2: // Speex Data (Unsupported)
case 3: // Uncompressed Data
case 4: // SILK Data
short dataLength;
char data[dataLength];
break;
case 0: // Silence
short numSamples;
break;
}
}
// CVoiceDecoder::AddIncomingData
FSeek(startof(data));
// VoiceEncoder_SILK::Decompress
// chunkLength == -1 means ResetState
while ((FTell() - startof(data)) < dataLength) {
struct Chunk {
short chunkLength;
if (chunkLength != -1) {
char chunk[chunkLength];
}
} chunk;
}