mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-10-27 05:34:17 +00:00
Merge remote-tracking branch 'fsorig/master'
Conflicts: src/mod/endpoints/mod_sofia/mod_sofia.c src/mod/endpoints/mod_sofia/sofia_glue.c
This commit is contained in:
commit
b004bcfc6d
407 files changed
+25813
-41133
No files matched your search
+342
-585
File diff suppressed because it is too large.
Load diff
+4
-4
@@ -3,11 +3,11 @@ INCS=-I$(PWD)/src/include
|
||||
LIBEDIT_DIR=../../libs/libedit
|
||||
DEBUG=-g -ggdb
|
||||
BASE_FLAGS=$(INCS) -DHAVE_EDITLINE $(DEBUG) -I$(LIBEDIT_DIR)/src/ -fPIC
|
||||
PICKY=-O2 -ffast-math -Wall -Werror -Wunused-variable -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes
|
||||
PICKY=-O2
|
||||
CFLAGS=$(BASE_FLAGS) $(PICKY)
|
||||
CXXFLAGS=$(BASE_FLAGS) -Wall -Werror -Wno-unused-variable
|
||||
CXXFLAGS=$(BASE_FLAGS)
|
||||
MYLIB=libesl.a
|
||||
LIBS=-lncurses -lpthread -lesl -lm
|
||||
LIBS=-lncurses -lesl -lpthread -lm
|
||||
LDFLAGS=-L.
|
||||
OBJS=src/esl.o src/esl_event.o src/esl_threadmutex.o src/esl_config.o src/esl_json.o src/esl_buffer.o
|
||||
SRC=src/esl.c src/esl_json.c src/esl_event.c src/esl_threadmutex.c src/esl_config.c src/esl_oop.cpp src/esl_json.c src/esl_buffer.c
|
||||
@@ -32,7 +32,7 @@ testclient: $(MYLIB) testclient.c
|
||||
$(CC) $(CC_CFLAGS) $(CFLAGS) testclient.c -o testclient $(LDFLAGS) $(LIBS)
|
||||
|
||||
fs_cli: $(MYLIB) fs_cli.c
|
||||
$(CC) $(CC_CFLAGS) $(CFLAGS) fs_cli.c -o fs_cli $(LDFLAGS) -L$(LIBEDIT_DIR)/src/.libs $(LIBS) -ledit
|
||||
$(CC) $(CC_CFLAGS) $(CFLAGS) fs_cli.c -o fs_cli $(LDFLAGS) -L$(LIBEDIT_DIR)/src/.libs -ledit $(LIBS)
|
||||
|
||||
%.o: %.c $(HEADERS)
|
||||
$(CC) $(CC_CFLAGS) $(CFLAGS) -c $< -o $@
|
||||
|
||||
+513
-519
File diff suppressed because it is too large.
Load diff
@@ -904,6 +904,31 @@ SWIGEXPORT jlong JNICALL Java_org_freeswitch_esl_eslJNI_ESLconnection_1sendEvent
|
||||
}
|
||||
|
||||
|
||||
SWIGEXPORT jint JNICALL Java_org_freeswitch_esl_eslJNI_ESLconnection_1sendMSG(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_, jlong jarg2, jobject jarg2_, jstring jarg3) {
|
||||
jint jresult = 0 ;
|
||||
ESLconnection *arg1 = (ESLconnection *) 0 ;
|
||||
ESLevent *arg2 = (ESLevent *) 0 ;
|
||||
char *arg3 = (char *) NULL ;
|
||||
int result;
|
||||
|
||||
(void)jenv;
|
||||
(void)jcls;
|
||||
(void)jarg1_;
|
||||
(void)jarg2_;
|
||||
arg1 = *(ESLconnection **)&jarg1;
|
||||
arg2 = *(ESLevent **)&jarg2;
|
||||
arg3 = 0;
|
||||
if (jarg3) {
|
||||
arg3 = (char *)jenv->GetStringUTFChars(jarg3, 0);
|
||||
if (!arg3) return 0;
|
||||
}
|
||||
result = (int)(arg1)->sendMSG(arg2,(char const *)arg3);
|
||||
jresult = (jint)result;
|
||||
if (arg3) jenv->ReleaseStringUTFChars(jarg3, (const char *)arg3);
|
||||
return jresult;
|
||||
}
|
||||
|
||||
|
||||
SWIGEXPORT jlong JNICALL Java_org_freeswitch_esl_eslJNI_ESLconnection_1recvEvent(JNIEnv *jenv, jclass jcls, jlong jarg1, jobject jarg1_) {
|
||||
jlong jresult = 0 ;
|
||||
ESLconnection *arg1 = (ESLconnection *) 0 ;
|
||||
|
||||
@@ -82,6 +82,10 @@ public class ESLconnection {
|
||||
return (cPtr == 0) ? null : new ESLevent(cPtr, true);
|
||||
}
|
||||
|
||||
public int sendMSG(ESLevent send_me, String uuid) {
|
||||
return eslJNI.ESLconnection_sendMSG(swigCPtr, this, ESLevent.getCPtr(send_me), send_me, uuid);
|
||||
}
|
||||
|
||||
public ESLevent recvEvent() {
|
||||
long cPtr = eslJNI.ESLconnection_recvEvent(swigCPtr, this);
|
||||
return (cPtr == 0) ? null : new ESLevent(cPtr, true);
|
||||
|
||||
@@ -43,6 +43,7 @@ class eslJNI {
|
||||
public final static native long ESLconnection_api(long jarg1, ESLconnection jarg1_, String jarg2, String jarg3);
|
||||
public final static native long ESLconnection_bgapi(long jarg1, ESLconnection jarg1_, String jarg2, String jarg3, String jarg4);
|
||||
public final static native long ESLconnection_sendEvent(long jarg1, ESLconnection jarg1_, long jarg2, ESLevent jarg2_);
|
||||
public final static native int ESLconnection_sendMSG(long jarg1, ESLconnection jarg1_, long jarg2, ESLevent jarg2_, String jarg3);
|
||||
public final static native long ESLconnection_recvEvent(long jarg1, ESLconnection jarg1_);
|
||||
public final static native long ESLconnection_recvEventTimed(long jarg1, ESLconnection jarg1_, int jarg2);
|
||||
public final static native long ESLconnection_filter(long jarg1, ESLconnection jarg1_, String jarg2, String jarg3);
|
||||
|
||||
@@ -2632,6 +2632,43 @@ fail:
|
||||
}
|
||||
|
||||
|
||||
static int _wrap_ESLconnection_sendMSG(lua_State* L) {
|
||||
int SWIG_arg = -1;
|
||||
ESLconnection *arg1 = (ESLconnection *) 0 ;
|
||||
ESLevent *arg2 = (ESLevent *) 0 ;
|
||||
char *arg3 = (char *) NULL ;
|
||||
int result;
|
||||
|
||||
SWIG_check_num_args("sendMSG",2,3)
|
||||
if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("sendMSG",1,"ESLconnection *");
|
||||
if(!SWIG_isptrtype(L,2)) SWIG_fail_arg("sendMSG",2,"ESLevent *");
|
||||
if(lua_gettop(L)>=3 && !lua_isstring(L,3)) SWIG_fail_arg("sendMSG",3,"char const *");
|
||||
|
||||
if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_ESLconnection,0))){
|
||||
SWIG_fail_ptr("ESLconnection_sendMSG",1,SWIGTYPE_p_ESLconnection);
|
||||
}
|
||||
|
||||
|
||||
if (!SWIG_IsOK(SWIG_ConvertPtr(L,2,(void**)&arg2,SWIGTYPE_p_ESLevent,0))){
|
||||
SWIG_fail_ptr("ESLconnection_sendMSG",2,SWIGTYPE_p_ESLevent);
|
||||
}
|
||||
|
||||
if(lua_gettop(L)>=3){
|
||||
arg3 = (char *)lua_tostring(L, 3);
|
||||
}
|
||||
result = (int)(arg1)->sendMSG(arg2,(char const *)arg3);
|
||||
SWIG_arg=0;
|
||||
lua_pushnumber(L, (lua_Number) result); SWIG_arg++;
|
||||
return SWIG_arg;
|
||||
|
||||
if(0) SWIG_fail;
|
||||
|
||||
fail:
|
||||
lua_error(L);
|
||||
return SWIG_arg;
|
||||
}
|
||||
|
||||
|
||||
static int _wrap_ESLconnection_recvEvent(lua_State* L) {
|
||||
int SWIG_arg = -1;
|
||||
ESLconnection *arg1 = (ESLconnection *) 0 ;
|
||||
@@ -2917,6 +2954,7 @@ static swig_lua_method swig_ESLconnection_methods[] = {
|
||||
{"api", _wrap_ESLconnection_api},
|
||||
{"bgapi", _wrap_ESLconnection_bgapi},
|
||||
{"sendEvent", _wrap_ESLconnection_sendEvent},
|
||||
{"sendMSG", _wrap_ESLconnection_sendMSG},
|
||||
{"recvEvent", _wrap_ESLconnection_recvEvent},
|
||||
{"recvEventTimed", _wrap_ESLconnection_recvEventTimed},
|
||||
{"filter", _wrap_ESLconnection_filter},
|
||||
|
||||
@@ -286,6 +286,9 @@ class ESLPINVOKE {
|
||||
[DllImport("ESL", EntryPoint="CSharp_ESLconnection_SendEvent")]
|
||||
public static extern IntPtr ESLconnection_SendEvent(HandleRef jarg1, HandleRef jarg2);
|
||||
|
||||
[DllImport("ESL", EntryPoint="CSharp_ESLconnection_sendMSG")]
|
||||
public static extern int ESLconnection_sendMSG(HandleRef jarg1, HandleRef jarg2, string jarg3);
|
||||
|
||||
[DllImport("ESL", EntryPoint="CSharp_ESLconnection_RecvEvent")]
|
||||
public static extern IntPtr ESLconnection_RecvEvent(HandleRef jarg1);
|
||||
|
||||
|
||||
@@ -92,6 +92,11 @@ public class ESLconnection : IDisposable {
|
||||
return ret;
|
||||
}
|
||||
|
||||
public int sendMSG(ESLevent send_me, string uuid) {
|
||||
int ret = ESLPINVOKE.ESLconnection_sendMSG(swigCPtr, ESLevent.getCPtr(send_me), uuid);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public ESLevent RecvEvent() {
|
||||
IntPtr cPtr = ESLPINVOKE.ESLconnection_RecvEvent(swigCPtr);
|
||||
ESLevent ret = (cPtr == IntPtr.Zero) ? null : new ESLevent(cPtr, true);
|
||||
|
||||
@@ -743,6 +743,22 @@ SWIGEXPORT void * SWIGSTDCALL CSharp_ESLconnection_SendEvent(void * jarg1, void
|
||||
}
|
||||
|
||||
|
||||
SWIGEXPORT int SWIGSTDCALL CSharp_ESLconnection_sendMSG(void * jarg1, void * jarg2, char * jarg3) {
|
||||
int jresult ;
|
||||
ESLconnection *arg1 = (ESLconnection *) 0 ;
|
||||
ESLevent *arg2 = (ESLevent *) 0 ;
|
||||
char *arg3 = (char *) NULL ;
|
||||
int result;
|
||||
|
||||
arg1 = (ESLconnection *)jarg1;
|
||||
arg2 = (ESLevent *)jarg2;
|
||||
arg3 = (char *)jarg3;
|
||||
result = (int)(arg1)->sendMSG(arg2,(char const *)arg3);
|
||||
jresult = result;
|
||||
return jresult;
|
||||
}
|
||||
|
||||
|
||||
SWIGEXPORT void * SWIGSTDCALL CSharp_ESLconnection_RecvEvent(void * jarg1) {
|
||||
void * jresult ;
|
||||
ESLconnection *arg1 = (ESLconnection *) 0 ;
|
||||
|
||||
@@ -138,6 +138,7 @@ sub DESTROY {
|
||||
*api = *ESLc::ESLconnection_api;
|
||||
*bgapi = *ESLc::ESLconnection_bgapi;
|
||||
*sendEvent = *ESLc::ESLconnection_sendEvent;
|
||||
*sendMSG = *ESLc::ESLconnection_sendMSG;
|
||||
*recvEvent = *ESLc::ESLconnection_recvEvent;
|
||||
*recvEventTimed = *ESLc::ESLconnection_recvEventTimed;
|
||||
*filter = *ESLc::ESLconnection_filter;
|
||||
|
||||
@@ -3282,6 +3282,57 @@ XS(_wrap_ESLconnection_sendEvent) {
|
||||
}
|
||||
|
||||
|
||||
XS(_wrap_ESLconnection_sendMSG) {
|
||||
{
|
||||
ESLconnection *arg1 = (ESLconnection *) 0 ;
|
||||
ESLevent *arg2 = (ESLevent *) 0 ;
|
||||
char *arg3 = (char *) NULL ;
|
||||
int result;
|
||||
void *argp1 = 0 ;
|
||||
int res1 = 0 ;
|
||||
void *argp2 = 0 ;
|
||||
int res2 = 0 ;
|
||||
int res3 ;
|
||||
char *buf3 = 0 ;
|
||||
int alloc3 = 0 ;
|
||||
int argvi = 0;
|
||||
dXSARGS;
|
||||
|
||||
if ((items < 2) || (items > 3)) {
|
||||
SWIG_croak("Usage: ESLconnection_sendMSG(self,send_me,uuid);");
|
||||
}
|
||||
res1 = SWIG_ConvertPtr(ST(0), &argp1,SWIGTYPE_p_ESLconnection, 0 | 0 );
|
||||
if (!SWIG_IsOK(res1)) {
|
||||
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ESLconnection_sendMSG" "', argument " "1"" of type '" "ESLconnection *""'");
|
||||
}
|
||||
arg1 = reinterpret_cast< ESLconnection * >(argp1);
|
||||
res2 = SWIG_ConvertPtr(ST(1), &argp2,SWIGTYPE_p_ESLevent, 0 | 0 );
|
||||
if (!SWIG_IsOK(res2)) {
|
||||
SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ESLconnection_sendMSG" "', argument " "2"" of type '" "ESLevent *""'");
|
||||
}
|
||||
arg2 = reinterpret_cast< ESLevent * >(argp2);
|
||||
if (items > 2) {
|
||||
res3 = SWIG_AsCharPtrAndSize(ST(2), &buf3, NULL, &alloc3);
|
||||
if (!SWIG_IsOK(res3)) {
|
||||
SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "ESLconnection_sendMSG" "', argument " "3"" of type '" "char const *""'");
|
||||
}
|
||||
arg3 = reinterpret_cast< char * >(buf3);
|
||||
}
|
||||
result = (int)(arg1)->sendMSG(arg2,(char const *)arg3);
|
||||
ST(argvi) = SWIG_From_int SWIG_PERL_CALL_ARGS_1(static_cast< int >(result)); argvi++ ;
|
||||
|
||||
|
||||
if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
|
||||
XSRETURN(argvi);
|
||||
fail:
|
||||
|
||||
|
||||
if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
|
||||
SWIG_croak_null();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
XS(_wrap_ESLconnection_recvEvent) {
|
||||
{
|
||||
ESLconnection *arg1 = (ESLconnection *) 0 ;
|
||||
@@ -3785,6 +3836,7 @@ static swig_command_info swig_commands[] = {
|
||||
{"ESLc::ESLconnection_api", _wrap_ESLconnection_api},
|
||||
{"ESLc::ESLconnection_bgapi", _wrap_ESLconnection_bgapi},
|
||||
{"ESLc::ESLconnection_sendEvent", _wrap_ESLconnection_sendEvent},
|
||||
{"ESLc::ESLconnection_sendMSG", _wrap_ESLconnection_sendMSG},
|
||||
{"ESLc::ESLconnection_recvEvent", _wrap_ESLconnection_recvEvent},
|
||||
{"ESLc::ESLconnection_recvEventTimed", _wrap_ESLconnection_recvEventTimed},
|
||||
{"ESLc::ESLconnection_filter", _wrap_ESLconnection_filter},
|
||||
|
||||
@@ -174,6 +174,14 @@ class ESLconnection {
|
||||
return is_resource($r) ? new ESLevent($r) : $r;
|
||||
}
|
||||
|
||||
function sendMSG($send_me,$uuid=null) {
|
||||
switch (func_num_args()) {
|
||||
case 1: $r=ESLconnection_sendMSG($this->_cPtr,$send_me); break;
|
||||
default: $r=ESLconnection_sendMSG($this->_cPtr,$send_me,$uuid);
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
|
||||
function recvEvent() {
|
||||
$r=ESLconnection_recvEvent($this->_cPtr);
|
||||
return is_resource($r) ? new ESLevent($r) : $r;
|
||||
|
||||
@@ -2244,6 +2244,48 @@ fail:
|
||||
}
|
||||
|
||||
|
||||
ZEND_NAMED_FUNCTION(_wrap_ESLconnection_sendMSG) {
|
||||
ESLconnection *arg1 = (ESLconnection *) 0 ;
|
||||
ESLevent *arg2 = (ESLevent *) 0 ;
|
||||
char *arg3 = (char *) NULL ;
|
||||
int result;
|
||||
zval **args[3];
|
||||
int arg_count;
|
||||
|
||||
SWIG_ResetError();
|
||||
arg_count = ZEND_NUM_ARGS();
|
||||
if(arg_count<2 || arg_count>3 ||
|
||||
zend_get_parameters_array_ex(arg_count,args)!=SUCCESS)
|
||||
WRONG_PARAM_COUNT;
|
||||
|
||||
{
|
||||
if(SWIG_ConvertPtr(*args[0], (void **) &arg1, SWIGTYPE_p_ESLconnection, 0) < 0) {
|
||||
SWIG_PHP_Error(E_ERROR, "Type error in argument 1 of ESLconnection_sendMSG. Expected SWIGTYPE_p_ESLconnection");
|
||||
}
|
||||
}
|
||||
if(!arg1) SWIG_PHP_Error(E_ERROR, "this pointer is NULL");
|
||||
{
|
||||
if(SWIG_ConvertPtr(*args[1], (void **) &arg2, SWIGTYPE_p_ESLevent, 0) < 0) {
|
||||
SWIG_PHP_Error(E_ERROR, "Type error in argument 2 of ESLconnection_sendMSG. Expected SWIGTYPE_p_ESLevent");
|
||||
}
|
||||
}
|
||||
if(arg_count > 2) {
|
||||
/*@SWIG:/usr/local/share/swig/1.3.35/php4/utils.i,26,CONVERT_STRING_IN@*/
|
||||
convert_to_string_ex(args[2]);
|
||||
arg3 = (char *) Z_STRVAL_PP(args[2]);
|
||||
/*@SWIG@*/;
|
||||
|
||||
}
|
||||
result = (int)(arg1)->sendMSG(arg2,(char const *)arg3);
|
||||
{
|
||||
ZVAL_LONG(return_value,result);
|
||||
}
|
||||
return;
|
||||
fail:
|
||||
zend_error(SWIG_ErrorCode(),SWIG_ErrorMsg());
|
||||
}
|
||||
|
||||
|
||||
ZEND_NAMED_FUNCTION(_wrap_ESLconnection_recvEvent) {
|
||||
ESLconnection *arg1 = (ESLconnection *) 0 ;
|
||||
ESLevent *result = 0 ;
|
||||
@@ -2651,6 +2693,7 @@ static zend_function_entry ESL_functions[] = {
|
||||
SWIG_ZEND_NAMED_FE(eslconnection_api,_wrap_ESLconnection_api,NULL)
|
||||
SWIG_ZEND_NAMED_FE(eslconnection_bgapi,_wrap_ESLconnection_bgapi,NULL)
|
||||
SWIG_ZEND_NAMED_FE(eslconnection_sendevent,_wrap_ESLconnection_sendEvent,NULL)
|
||||
SWIG_ZEND_NAMED_FE(eslconnection_sendmsg,_wrap_ESLconnection_sendMSG,NULL)
|
||||
SWIG_ZEND_NAMED_FE(eslconnection_recvevent,_wrap_ESLconnection_recvEvent,NULL)
|
||||
SWIG_ZEND_NAMED_FE(eslconnection_recveventtimed,_wrap_ESLconnection_recvEventTimed,NULL)
|
||||
SWIG_ZEND_NAMED_FE(eslconnection_filter,_wrap_ESLconnection_filter,NULL)
|
||||
|
||||
@@ -60,6 +60,7 @@ ZEND_NAMED_FUNCTION(_wrap_ESLconnection_sendRecv);
|
||||
ZEND_NAMED_FUNCTION(_wrap_ESLconnection_api);
|
||||
ZEND_NAMED_FUNCTION(_wrap_ESLconnection_bgapi);
|
||||
ZEND_NAMED_FUNCTION(_wrap_ESLconnection_sendEvent);
|
||||
ZEND_NAMED_FUNCTION(_wrap_ESLconnection_sendMSG);
|
||||
ZEND_NAMED_FUNCTION(_wrap_ESLconnection_recvEvent);
|
||||
ZEND_NAMED_FUNCTION(_wrap_ESLconnection_recvEventTimed);
|
||||
ZEND_NAMED_FUNCTION(_wrap_ESLconnection_filter);
|
||||
|
||||
@@ -87,6 +87,7 @@ class ESLconnection:
|
||||
def api(*args): return apply(_ESL.ESLconnection_api, args)
|
||||
def bgapi(*args): return apply(_ESL.ESLconnection_bgapi, args)
|
||||
def sendEvent(*args): return apply(_ESL.ESLconnection_sendEvent, args)
|
||||
def sendMSG(*args): return apply(_ESL.ESLconnection_sendMSG, args)
|
||||
def recvEvent(*args): return apply(_ESL.ESLconnection_recvEvent, args)
|
||||
def recvEventTimed(*args): return apply(_ESL.ESLconnection_recvEventTimed, args)
|
||||
def filter(*args): return apply(_ESL.ESLconnection_filter, args)
|
||||
|
||||
@@ -4370,6 +4370,58 @@ fail:
|
||||
}
|
||||
|
||||
|
||||
SWIGINTERN PyObject *_wrap_ESLconnection_sendMSG(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
|
||||
PyObject *resultobj = 0;
|
||||
ESLconnection *arg1 = (ESLconnection *) 0 ;
|
||||
ESLevent *arg2 = (ESLevent *) 0 ;
|
||||
char *arg3 = (char *) NULL ;
|
||||
int result;
|
||||
void *argp1 = 0 ;
|
||||
int res1 = 0 ;
|
||||
void *argp2 = 0 ;
|
||||
int res2 = 0 ;
|
||||
int res3 ;
|
||||
char *buf3 = 0 ;
|
||||
int alloc3 = 0 ;
|
||||
PyObject * obj0 = 0 ;
|
||||
PyObject * obj1 = 0 ;
|
||||
PyObject * obj2 = 0 ;
|
||||
|
||||
SWIG_PYTHON_THREAD_BEGIN_BLOCK;
|
||||
if (!PyArg_ParseTuple(args,(char *)"OO|O:ESLconnection_sendMSG",&obj0,&obj1,&obj2)) SWIG_fail;
|
||||
res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ESLconnection, 0 | 0 );
|
||||
if (!SWIG_IsOK(res1)) {
|
||||
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ESLconnection_sendMSG" "', argument " "1"" of type '" "ESLconnection *""'");
|
||||
}
|
||||
arg1 = reinterpret_cast< ESLconnection * >(argp1);
|
||||
res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_ESLevent, 0 | 0 );
|
||||
if (!SWIG_IsOK(res2)) {
|
||||
SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ESLconnection_sendMSG" "', argument " "2"" of type '" "ESLevent *""'");
|
||||
}
|
||||
arg2 = reinterpret_cast< ESLevent * >(argp2);
|
||||
if (obj2) {
|
||||
res3 = SWIG_AsCharPtrAndSize(obj2, &buf3, NULL, &alloc3);
|
||||
if (!SWIG_IsOK(res3)) {
|
||||
SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "ESLconnection_sendMSG" "', argument " "3"" of type '" "char const *""'");
|
||||
}
|
||||
arg3 = reinterpret_cast< char * >(buf3);
|
||||
}
|
||||
{
|
||||
SWIG_PYTHON_THREAD_BEGIN_ALLOW;
|
||||
result = (int)(arg1)->sendMSG(arg2,(char const *)arg3);
|
||||
SWIG_PYTHON_THREAD_END_ALLOW;
|
||||
}
|
||||
resultobj = SWIG_From_int(static_cast< int >(result));
|
||||
if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
|
||||
SWIG_PYTHON_THREAD_END_BLOCK;
|
||||
return resultobj;
|
||||
fail:
|
||||
if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
|
||||
SWIG_PYTHON_THREAD_END_BLOCK;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
SWIGINTERN PyObject *_wrap_ESLconnection_recvEvent(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
|
||||
PyObject *resultobj = 0;
|
||||
ESLconnection *arg1 = (ESLconnection *) 0 ;
|
||||
@@ -4859,6 +4911,7 @@ static PyMethodDef SwigMethods[] = {
|
||||
{ (char *)"ESLconnection_api", _wrap_ESLconnection_api, METH_VARARGS, NULL},
|
||||
{ (char *)"ESLconnection_bgapi", _wrap_ESLconnection_bgapi, METH_VARARGS, NULL},
|
||||
{ (char *)"ESLconnection_sendEvent", _wrap_ESLconnection_sendEvent, METH_VARARGS, NULL},
|
||||
{ (char *)"ESLconnection_sendMSG", _wrap_ESLconnection_sendMSG, METH_VARARGS, NULL},
|
||||
{ (char *)"ESLconnection_recvEvent", _wrap_ESLconnection_recvEvent, METH_VARARGS, NULL},
|
||||
{ (char *)"ESLconnection_recvEventTimed", _wrap_ESLconnection_recvEventTimed, METH_VARARGS, NULL},
|
||||
{ (char *)"ESLconnection_filter", _wrap_ESLconnection_filter, METH_VARARGS, NULL},
|
||||
|
||||
@@ -3245,6 +3245,51 @@ fail:
|
||||
}
|
||||
|
||||
|
||||
SWIGINTERN VALUE
|
||||
_wrap_ESLconnection_sendMSG(int argc, VALUE *argv, VALUE self) {
|
||||
ESLconnection *arg1 = (ESLconnection *) 0 ;
|
||||
ESLevent *arg2 = (ESLevent *) 0 ;
|
||||
char *arg3 = (char *) NULL ;
|
||||
int result;
|
||||
void *argp1 = 0 ;
|
||||
int res1 = 0 ;
|
||||
void *argp2 = 0 ;
|
||||
int res2 = 0 ;
|
||||
int res3 ;
|
||||
char *buf3 = 0 ;
|
||||
int alloc3 = 0 ;
|
||||
VALUE vresult = Qnil;
|
||||
|
||||
if ((argc < 1) || (argc > 2)) {
|
||||
rb_raise(rb_eArgError, "wrong # of arguments(%d for 1)",argc); SWIG_fail;
|
||||
}
|
||||
res1 = SWIG_ConvertPtr(self, &argp1,SWIGTYPE_p_ESLconnection, 0 | 0 );
|
||||
if (!SWIG_IsOK(res1)) {
|
||||
SWIG_exception_fail(SWIG_ArgError(res1), Ruby_Format_TypeError( "", "ESLconnection *","sendMSG", 1, self ));
|
||||
}
|
||||
arg1 = reinterpret_cast< ESLconnection * >(argp1);
|
||||
res2 = SWIG_ConvertPtr(argv[0], &argp2,SWIGTYPE_p_ESLevent, 0 | 0 );
|
||||
if (!SWIG_IsOK(res2)) {
|
||||
SWIG_exception_fail(SWIG_ArgError(res2), Ruby_Format_TypeError( "", "ESLevent *","sendMSG", 2, argv[0] ));
|
||||
}
|
||||
arg2 = reinterpret_cast< ESLevent * >(argp2);
|
||||
if (argc > 1) {
|
||||
res3 = SWIG_AsCharPtrAndSize(argv[1], &buf3, NULL, &alloc3);
|
||||
if (!SWIG_IsOK(res3)) {
|
||||
SWIG_exception_fail(SWIG_ArgError(res3), Ruby_Format_TypeError( "", "char const *","sendMSG", 3, argv[1] ));
|
||||
}
|
||||
arg3 = reinterpret_cast< char * >(buf3);
|
||||
}
|
||||
result = (int)(arg1)->sendMSG(arg2,(char const *)arg3);
|
||||
vresult = SWIG_From_int(static_cast< int >(result));
|
||||
if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
|
||||
return vresult;
|
||||
fail:
|
||||
if (alloc3 == SWIG_NEWOBJ) delete[] buf3;
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
|
||||
SWIGINTERN VALUE
|
||||
_wrap_ESLconnection_recvEvent(int argc, VALUE *argv, VALUE self) {
|
||||
ESLconnection *arg1 = (ESLconnection *) 0 ;
|
||||
@@ -3958,6 +4003,7 @@ SWIGEXPORT void Init_ESL(void) {
|
||||
rb_define_method(cESLconnection.klass, "api", VALUEFUNC(_wrap_ESLconnection_api), -1);
|
||||
rb_define_method(cESLconnection.klass, "bgapi", VALUEFUNC(_wrap_ESLconnection_bgapi), -1);
|
||||
rb_define_method(cESLconnection.klass, "sendEvent", VALUEFUNC(_wrap_ESLconnection_sendEvent), -1);
|
||||
rb_define_method(cESLconnection.klass, "sendMSG", VALUEFUNC(_wrap_ESLconnection_sendMSG), -1);
|
||||
rb_define_method(cESLconnection.klass, "recvEvent", VALUEFUNC(_wrap_ESLconnection_recvEvent), -1);
|
||||
rb_define_method(cESLconnection.klass, "recvEventTimed", VALUEFUNC(_wrap_ESLconnection_recvEventTimed), -1);
|
||||
rb_define_method(cESLconnection.klass, "filter", VALUEFUNC(_wrap_ESLconnection_filter), -1);
|
||||
|
||||
@@ -534,6 +534,39 @@ ESL_DECLARE(esl_status_t) esl_execute(esl_handle_t *handle, const char *app, con
|
||||
}
|
||||
|
||||
|
||||
ESL_DECLARE(esl_status_t) esl_sendmsg(esl_handle_t *handle, esl_event_t *event, const char *uuid)
|
||||
{
|
||||
char cmd_buf[128] = "sendmsg\n";
|
||||
char *txt;
|
||||
|
||||
if (!handle || !handle->connected || handle->sock == ESL_SOCK_INVALID) {
|
||||
return ESL_FAIL;
|
||||
}
|
||||
|
||||
if (uuid) {
|
||||
snprintf(cmd_buf, sizeof(cmd_buf), "sendmsg %s\n", uuid);
|
||||
}
|
||||
|
||||
esl_event_serialize(event, &txt, ESL_FALSE);
|
||||
esl_log(ESL_LOG_DEBUG, "%s%s\n", cmd_buf, txt);
|
||||
|
||||
if (send(handle->sock, cmd_buf, strlen(cmd_buf), 0) <= 0) goto fail;
|
||||
if (send(handle->sock, txt, strlen(txt), 0) <= 0) goto fail;
|
||||
|
||||
free(txt);
|
||||
|
||||
return esl_recv(handle);
|
||||
|
||||
fail:
|
||||
|
||||
handle->connected = 0;
|
||||
|
||||
free(txt);
|
||||
|
||||
return ESL_FAIL;
|
||||
}
|
||||
|
||||
|
||||
ESL_DECLARE(esl_status_t) esl_filter(esl_handle_t *handle, const char *header, const char *value)
|
||||
{
|
||||
char send_buf[1024] = "";
|
||||
|
||||
@@ -270,8 +270,9 @@ ESL_DECLARE(char *) esl_event_get_header_idx(esl_event_t *event, const char *hea
|
||||
}
|
||||
|
||||
return hp->value;
|
||||
|
||||
}
|
||||
} else if (!strcmp(header_name, "_body")) {
|
||||
return event->body;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -414,6 +415,10 @@ static esl_status_t esl_event_base_add_header(esl_event_t *event, esl_stack_t st
|
||||
int index = 0;
|
||||
char *real_header_name = NULL;
|
||||
|
||||
if (!strcmp(header_name, "_body")) {
|
||||
esl_event_set_body(event, data);
|
||||
}
|
||||
|
||||
if ((index_ptr = strchr(header_name, '['))) {
|
||||
index_ptr++;
|
||||
index = atoi(index_ptr);
|
||||
@@ -604,6 +609,17 @@ ESL_DECLARE(esl_status_t) esl_event_add_header_string(esl_event_t *event, esl_st
|
||||
return ESL_FAIL;
|
||||
}
|
||||
|
||||
ESL_DECLARE(esl_status_t) esl_event_set_body(esl_event_t *event, const char *body)
|
||||
{
|
||||
esl_safe_free(event->body);
|
||||
|
||||
if (body) {
|
||||
event->body = DUP(body);
|
||||
}
|
||||
|
||||
return ESL_SUCCESS;
|
||||
}
|
||||
|
||||
ESL_DECLARE(esl_status_t) esl_event_add_body(esl_event_t *event, const char *fmt, ...)
|
||||
{
|
||||
int ret = 0;
|
||||
@@ -791,7 +807,7 @@ ESL_DECLARE(esl_status_t) esl_event_serialize(esl_event_t *event, char **str, es
|
||||
if (encode) {
|
||||
esl_url_encode(hp->value, encode_buf, encode_len);
|
||||
} else {
|
||||
esl_snprintf(encode_buf, encode_len, "[%s]", hp->value);
|
||||
esl_snprintf(encode_buf, encode_len, "%s", hp->value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -205,6 +205,15 @@ ESLevent *ESLconnection::sendEvent(ESLevent *send_me)
|
||||
return new ESLevent("server_disconnected");
|
||||
}
|
||||
|
||||
int ESLconnection::sendMSG(ESLevent *send_me, const char *uuid)
|
||||
{
|
||||
if (esl_sendmsg(&handle, send_me->event, uuid) == ESL_SUCCESS) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
ESLevent *ESLconnection::recvEvent()
|
||||
{
|
||||
if (esl_recv_event(&handle, 1, NULL) == ESL_SUCCESS) {
|
||||
|
||||
@@ -61,12 +61,22 @@ typedef enum {
|
||||
|
||||
#ifdef WIN32
|
||||
#define ESL_SEQ_FWHITE FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY
|
||||
#define ESL_SEQ_BWHITE FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
|
||||
#define ESL_SEQ_FRED FOREGROUND_RED | FOREGROUND_INTENSITY
|
||||
#define ESL_SEQ_FMAGEN FOREGROUND_BLUE | FOREGROUND_RED
|
||||
#define ESL_SEQ_FCYAN FOREGROUND_GREEN | FOREGROUND_BLUE
|
||||
#define ESL_SEQ_FGREEN FOREGROUND_GREEN
|
||||
#define ESL_SEQ_BRED FOREGROUND_RED
|
||||
#define ESL_SEQ_FMAGEN FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_INTENSITY
|
||||
#define ESL_SEQ_BMAGEN FOREGROUND_BLUE | FOREGROUND_RED
|
||||
#define ESL_SEQ_FCYAN FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY
|
||||
#define ESL_SEQ_BCYAN FOREGROUND_GREEN | FOREGROUND_BLUE
|
||||
#define ESL_SEQ_FGREEN FOREGROUND_GREEN | FOREGROUND_INTENSITY
|
||||
#define ESL_SEQ_BGREEN FOREGROUND_GREEN
|
||||
#define ESL_SEQ_FYELLOW FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY
|
||||
#define ESL_SEQ_BYELLOW FOREGROUND_RED | FOREGROUND_GREEN
|
||||
#define ESL_SEQ_DEFAULT_COLOR ESL_SEQ_FWHITE
|
||||
#define ESL_SEQ_FBLUE FOREGROUND_BLUE | FOREGROUND_INTENSITY
|
||||
#define ESL_SEQ_BBLUE FOREGROUND_BLUE
|
||||
#define ESL_SEQ_FBLACK 0 | FOREGROUND_INTENSITY
|
||||
#define ESL_SEQ_BBLACK 0
|
||||
#else
|
||||
#define ESL_SEQ_ESC "\033["
|
||||
/* Ansi Control character suffixes */
|
||||
@@ -397,6 +407,14 @@ ESL_DECLARE(esl_status_t) esl_execute(esl_handle_t *handle, const char *app, con
|
||||
*/
|
||||
ESL_DECLARE(esl_status_t) esl_sendevent(esl_handle_t *handle, esl_event_t *event);
|
||||
|
||||
/*!
|
||||
\brief Send an event as a message to be parsed
|
||||
\param handle Handle to which the event should be sent
|
||||
\param event Event to be sent
|
||||
\param uuid a specific uuid if not the default
|
||||
*/
|
||||
ESL_DECLARE(esl_status_t) esl_sendmsg(esl_handle_t *handle, esl_event_t *event, const char *uuid);
|
||||
|
||||
/*!
|
||||
\brief Connect a handle to a host/port with a specific password. This will also authenticate against the server
|
||||
\param handle Handle to connect
|
||||
|
||||
@@ -298,6 +298,7 @@ ESL_DECLARE(esl_status_t) esl_event_create_json(esl_event_t **event, const char
|
||||
\note the body parameter can be shadowed by the esl_event_reserve_subclass_detailed function
|
||||
*/
|
||||
ESL_DECLARE(esl_status_t) esl_event_add_body(esl_event_t *event, const char *fmt, ...);
|
||||
ESL_DECLARE(esl_status_t) esl_event_set_body(esl_event_t *event, const char *body);
|
||||
|
||||
/*!
|
||||
\brief Create a new event assuming it will not be custom event and therefore hiding the unused parameters
|
||||
|
||||
@@ -86,6 +86,7 @@ class ESLconnection {
|
||||
ESLevent *api(const char *cmd, const char *arg = NULL);
|
||||
ESLevent *bgapi(const char *cmd, const char *arg = NULL, const char *job_uuid = NULL);
|
||||
ESLevent *sendEvent(ESLevent *send_me);
|
||||
int sendMSG(ESLevent *send_me, const char *uuid = NULL);
|
||||
ESLevent *recvEvent();
|
||||
ESLevent *recvEventTimed(int ms);
|
||||
ESLevent *filter(const char *header, const char *value);
|
||||
|
||||
@@ -248,6 +248,14 @@ ftmod_r2_la_LDFLAGS = -shared -module -avoid-version -lopenr2
|
||||
ftmod_r2_la_LIBADD = libfreetdm.la
|
||||
endif
|
||||
|
||||
if HAVE_MISDN
|
||||
mod_LTLIBRARIES += ftmod_misdn.la
|
||||
ftmod_misdn_la_SOURCES = $(SRC)/ftmod/ftmod_misdn/ftmod_misdn.c
|
||||
ftmod_misdn_la_CFLAGS = $(FTDM_CFLAGS) $(AM_CFLAGS) $(MISDN_CFLAGS)
|
||||
ftmod_misdn_la_LDFLAGS = -shared -module -avoid-version
|
||||
ftmod_misdn_la_LIBADD = libfreetdm.la
|
||||
endif
|
||||
|
||||
dox doxygen:
|
||||
doxygen $(FT_SRCDIR)/docs/Doxygen.conf
|
||||
|
||||
|
||||
@@ -75,6 +75,11 @@ with the signaling protocols that you can run on top of your I/O interfaces.
|
||||
<param name="polarity-delay" value="600"/>
|
||||
-->
|
||||
|
||||
<!-- Retrieve caller id on polarity reverse -->
|
||||
<!--
|
||||
<param name="polarity-callerid" value="true"/>
|
||||
-->
|
||||
|
||||
<!-- regex to stop dialing when it matches -->
|
||||
<!--<param name="dial-regex" value="5555"/>-->
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
; This file is used to generate telephony tones by FreeTDM
|
||||
|
||||
[us]
|
||||
generate-dial => v=-7;%(1000,0,350,440)
|
||||
detect-dial => 350,440
|
||||
@@ -47,19 +45,98 @@ detect-fail1 => 913.8
|
||||
detect-fail2 => 1370.6
|
||||
detect-fail3 => 1776.7
|
||||
|
||||
|
||||
[ru]
|
||||
generate-dial => v=-7;%(1000,425)
|
||||
detect-dial => 0
|
||||
|
||||
generate-ring => v=-7;%(800,5000,425,0)
|
||||
detect-ring => 425,0
|
||||
|
||||
generate-busy => v=-7;%(350,350,425,0)
|
||||
detect-busy => 425,0
|
||||
|
||||
generate-attn => v=0;%(100,100,1400,2060,2450,2600)
|
||||
detect-attn => 1400,2060,2450,2600
|
||||
|
||||
generate-callwaiting-sas => v=0;%(300,0,440)
|
||||
detect-callwaiting-sas => 440,480
|
||||
|
||||
generate-callwaiting-cas => v=0;%(80,0,2750,2130)
|
||||
detect-callwaiting-cas => 2750,2130
|
||||
|
||||
detect-fail1 => 913.8
|
||||
detect-fail2 => 1370.6
|
||||
detect-fail3 => 1776.7
|
||||
|
||||
|
||||
[in]
|
||||
generate-dial => v=-7;%(1000,0,375,425)
|
||||
detect-dial => 375,425
|
||||
|
||||
generate-ring => v=-7;%(2000,4000,440,480)
|
||||
detect-ring => 440,480
|
||||
|
||||
generate-busy => v=-7;%(500,500,480,620)
|
||||
detect-busy => 480,620
|
||||
|
||||
generate-attn => v=0;%(100,100,1400,2060,2450,2600)
|
||||
detect-attn => 1400,2060,2450,2600
|
||||
|
||||
generate-callwaiting-sas => v=0;%(300,0,440)
|
||||
detect-callwaiting-sas => 440
|
||||
|
||||
generate-callwaiting-cas => v=0;%(80,0,2750,2130)
|
||||
detect-callwaiting-cas => 2750,2130
|
||||
|
||||
detect-fail1 => 913.8
|
||||
detect-fail2 => 1370.6
|
||||
detect-fail3 => 776.7
|
||||
|
||||
|
||||
[th]
|
||||
generate-dial => v=-7;%(1000,0,400,400)
|
||||
detect-dial => 400,400
|
||||
|
||||
generate-ring => v=-7;%(2000,4000,400,400)
|
||||
detect-ring => 400,400
|
||||
|
||||
generate-busy => v=-7;%(500,500,480,620)
|
||||
detect-busy => 480,620
|
||||
|
||||
generate-attn => v=0;%(100,100,1400,2060,2450,2600)
|
||||
detect-attn => 1400,2060,2450,2600
|
||||
|
||||
generate-callwaiting-sas => v=0;%(300,0,440)
|
||||
detect-callwaiting-sas => 440
|
||||
|
||||
generate-callwaiting-cas => v=0;%(80,0,2750,2130)
|
||||
detect-callwaiting-cas => 2750,2130
|
||||
|
||||
detect-fail1 => 913.8
|
||||
detect-fail2 => 1370.6
|
||||
detect-fail3 => 1776.7
|
||||
|
||||
|
||||
[au]
|
||||
generate-dial => v=-7;%(1000,0,413,438)
|
||||
detect-dial => 413,438
|
||||
|
||||
generate-ring => v=-7;%(400,200,413,438);%(400,2000,413,438)
|
||||
detect-ring => 413,438
|
||||
|
||||
generate-busy => v=-7;%(375,375,425)
|
||||
detect-busy => 425
|
||||
|
||||
generate-attn => v=0;%(100,100,1400,2060,2450,2600)
|
||||
detect-attn => 1400,2060,2450,2600
|
||||
|
||||
generate-callwaiting-sas => v=0;%(300,0,440)
|
||||
detect-callwaiting-sas => 440
|
||||
|
||||
generate-callwaiting-cas => v=0;%(80,0,2750,2130)
|
||||
detect-callwaiting-cas => 2750,2130
|
||||
|
||||
detect-fail1 => 913.8
|
||||
detect-fail2 => 1370.6
|
||||
detect-fail3 => 776.7
|
||||
@@ -54,6 +54,9 @@ fi
|
||||
|
||||
AC_SUBST([confdir])
|
||||
|
||||
DEFAULT_INCLUDES="-I. -I./src/include -I$(srcdir)"
|
||||
AC_SUBST([DEFAULT_INCLUDES])
|
||||
|
||||
# Where to install the modules
|
||||
AC_ARG_WITH([modinstdir],
|
||||
[AS_HELP_STRING([--with-modinstdir=DIR], [Install modules into this location (default: ${prefix}/mod)])],
|
||||
@@ -364,6 +367,42 @@ then
|
||||
fi
|
||||
AM_CONDITIONAL([HAVE_LIBISDN], [test "${HAVE_LIBISDN}" = "yes"])
|
||||
|
||||
|
||||
##
|
||||
# mISDN dependencies
|
||||
#
|
||||
HAVE_MISDN="no"
|
||||
AC_ARG_WITH([misdn],
|
||||
[AS_HELP_STRING([--with-misdn], [Install ftmod_misdn (mISDN I/O plugin)])],
|
||||
[case "${withval}" in
|
||||
no|yes) with_misdn="${withval}" ;;
|
||||
*) AC_MSG_ERROR([Invalid value \"${with_misdn}\" for --with-misdn option]) ;;
|
||||
esac],
|
||||
[with_misdn="auto"]
|
||||
)
|
||||
AS_IF([test "${with_misdn}" != "no"],
|
||||
[AC_MSG_RESULT([${as_nl}<<>> ftmod_misdn (Linux mISDN I/O plugin)])
|
||||
AC_CHECK_FUNCS([timerfd_create],,
|
||||
[AS_IF([test "${with_misdn}" = "yes"],
|
||||
[AC_MSG_ERROR([no timerfd support in libc])],
|
||||
[AC_MSG_NOTICE([no timerfd support in libc])]
|
||||
)]
|
||||
)
|
||||
AC_CHECK_HEADER([mISDN/mISDNif.h],,
|
||||
[AS_IF([test "${with_misdn}" = "yes"],
|
||||
[AC_MSG_ERROR([mISDN/mISDNif.h not found])],
|
||||
[AC_MSG_NOTICE([mISDN/mISDNif.h not found])]
|
||||
)],
|
||||
[#include <sys/socket.h>]
|
||||
)
|
||||
AS_IF([test "${ac_cv_func_timerfd_create}" = "yes" -a "${ac_cv_header_mISDN_mISDNif_h}" = "yes"],
|
||||
[HAVE_MISDN="yes"],
|
||||
[AC_MSG_NOTICE([Some required dependencies are missing, module disabled])]
|
||||
)]
|
||||
)
|
||||
AM_CONDITIONAL([HAVE_MISDN], [test "${HAVE_MISDN}" = "yes"])
|
||||
|
||||
|
||||
AC_MSG_RESULT([${as_nl}<<>> Creating output files])
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
@@ -389,6 +428,7 @@ AC_MSG_RESULT([
|
||||
ftmod_pritap....................... ${HAVE_PRITAP}
|
||||
I/O:
|
||||
ftmod_wanpipe...................... ${HAVE_LIBSANGOMA}
|
||||
ftmod_misdn........................ ${HAVE_MISDN}
|
||||
|
||||
===============================================================================
|
||||
])
|
||||
@@ -0,0 +1,76 @@
|
||||
== This is an email sent to stkn responding to his post http://stkn.techmage.de/archives/200 ==
|
||||
|
||||
1. FreeTDM open channels immediately.
|
||||
|
||||
Yes, this seems to come from the early days of OpenZAP where probably the analog modules were implemented first and was dragged incorrectly to ISDN.
|
||||
The open API also sets the flag in use so others cannot use it. We should decouple this open and reserve operations. Does not seem very hard to do,
|
||||
I'll take a look at it on my way back to Toronto this week or earlier if possible, I'll create a git branch for it and send you the url for peer review.
|
||||
Feel free to do the opposite if you are in a hurry.
|
||||
|
||||
2. FreeTDM does not completely close the channel on hangup.
|
||||
|
||||
As long as the signaling module calls ftdm_channel_close() the fio->close API will be called where the IO module is responsible
|
||||
for turning off ec or any other operations to leave the channel unused/idle (not really closed). There was indeed a bug where ftdm_zt module
|
||||
was not properly closing the channel, if that is what you mean, then it means that was already fixed by you with your audio mode turn off patch.
|
||||
|
||||
Now, a more lengthy response ...
|
||||
|
||||
When we, Sangoma, took over openzap and renamed it to freetdm, it was not just a name change, many API cleanups were done so API users cannot access
|
||||
|
||||
the internal data structures and cannot explicitly move between channel states. Also, some order on the state transitions has been put into place.
|
||||
|
||||
We've tried to keep backwards compatibility though, so old modules may not follow all of the conventions. Some unwritten conventions are:
|
||||
|
||||
1. Signaling modules are responsible for calling ftdm_channel_close() when done with the channel. In fact, signaling modules should not
|
||||
call ftdm_channel_done unless they really know what they're doing. ftdm_channel_close will call ftdm_channel_done anyways.
|
||||
|
||||
2. When remote end hangs up a call, signaling module should go to TERMINATING state and send SIGEVENT_STOP to the user. The signaling stack
|
||||
should not acknowledge the hangup until the user implicitly moves us to HANGUP (via ftdm_channel_call_hangup()). There is a core timer
|
||||
that will ensure we move from TERMINATING to HANGUP if the user does not moves us fast enough (arbitrarely 3000ms), although that is considered
|
||||
a bug in the user application (at some point we saw that in FreeSWITCH) and we complain loudly when that happens.
|
||||
|
||||
3. Signaling modules should leave the channel with NO pending states once they unlock it. This means, whenever you have a message to process
|
||||
you must lock the channel, check its current state (the user may have already changed the state to something else), process any pending
|
||||
state set by the user, then process your message and if required move the channel to a new state and process that state before releasing the lock.
|
||||
There is a chance of a deadlock due to the callbacks we use to notify users of messages if we call those callbacks with the channel lock held and
|
||||
that is why new signaling modules should use the FTDM_SPAN_USE_SIGNALS_QUEUE to defer the notification to the user when the ftdm_channel_t is not
|
||||
locked calling ftdm_span_trigger_signals() at the end of their processing loop which delivers the callback notifications to users.
|
||||
|
||||
Having said that, there is a major architectural change coming, probably early 2011, and I'd like to have your input.
|
||||
|
||||
== Decoupling calls from IO channels ==
|
||||
|
||||
We've also found that the concept of a channel and a call are unnecesarily coupled together in FreeTDM. I've never asked Anthony the reasoning
|
||||
for this, but it seems the API was meant to be used with, or without calls. That is, a user should be able to just 'open' a channel and start
|
||||
reading and writing raw data without ever launching one of the provided signaling stacks on top, may be just because the user is using their
|
||||
own signaling stack and just needs freetdm/openzap as an I/O API. In fact, signaling modules work like this (but there are defects there).
|
||||
The problem is, as you have noticed, the way ftdm_channel_open_xx APIs has been implemented is abusing this concept.
|
||||
|
||||
Problems with current implementation.
|
||||
|
||||
1. Exclusive channel is the only way we can request channels to the ISDN network. There is no room to change the channel later on easily.
|
||||
2. Multi-rate calls cannot be done. We need to associate multiple B-channels to a single call.
|
||||
3. Low-bit-rate calls (not sure what is the proper name for them) where a single B-channel can feed media to multiple calls with a low bit-rate
|
||||
codec (I know of at least one request from a big company for this to support some Q.SIG stuff for Eurocontrol).
|
||||
|
||||
|
||||
What do we need?
|
||||
|
||||
I think there should be only one open() API that wraps calls around fio->open(), the other current open_xx functions that do hunting, should
|
||||
be eliminated and some extra arguments provided to ftdm_channel_call_place to provide information about the channel where we would like to
|
||||
place the call or group hunting information and the API would return immediately providing a ftdm_call_t reference pointer that can be used
|
||||
to further track the status of that call, or in the case where a channel exclusivity was requested and we know for a fact is not available,
|
||||
just return failure. At that point there is no I/O channel involved yet. Eventually after the signaling stack hunts the channel and
|
||||
negotiaties its availability with the network, an I/O channel can be attached to that call, or even attach multiple channels (for the case
|
||||
of multi rate calls?).
|
||||
|
||||
This involves heavy changes. The state machine should be moved out of the ftdm_channel_t structure along with probably some other members
|
||||
and stuffed into a new ftdm_call_t structure. Signaling modules would have to be updated to run their state machines with this call
|
||||
structure and then at some point attach IO channels to the call. There would be 2 type of read/write APIs, one low level ftdm_channel_read
|
||||
which receives an ftdm_channel_t as parameter and an ftdm_call_read() which receives an ftdm_call_t as parameter, for the case of multi-rate
|
||||
calls or low-bit-rate multiplexed calls in the same B-channel this API would return just the media corresponding to that call already
|
||||
demultiplexed or concatenated, or whatever needs to be done with the media from the multiple low-level IO channels.
|
||||
|
||||
This is fairly disruptive, but I believe should be done sooner or later.
|
||||
|
||||
|
||||
@@ -34,6 +34,15 @@
|
||||
#include <switch.h>
|
||||
#include "freetdm.h"
|
||||
|
||||
//#define CUDATEL_DEBUG
|
||||
#ifdef CUDATEL_DEBUG
|
||||
#ifndef _BSD_SOURCE
|
||||
#define _BSD_SOURCE
|
||||
#endif
|
||||
#include <execinfo.h>
|
||||
#include <syscall.h>
|
||||
#endif
|
||||
|
||||
#ifndef __FUNCTION__
|
||||
#define __FUNCTION__ __SWITCH_FUNC__
|
||||
#endif
|
||||
@@ -495,7 +504,14 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session)
|
||||
switch_channel_t *channel = NULL;
|
||||
private_t *tech_pvt = NULL;
|
||||
ftdm_chan_type_t chantype;
|
||||
const char *name = NULL;
|
||||
int span_id = 0;
|
||||
int chan_id = 0;
|
||||
int t = 0;
|
||||
uint32_t tokencnt;
|
||||
char *uuid = NULL;
|
||||
const char *token = NULL;
|
||||
uint8_t uuid_found = 0;
|
||||
|
||||
channel = switch_core_session_get_channel(session);
|
||||
assert(channel != NULL);
|
||||
@@ -503,13 +519,64 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session)
|
||||
tech_pvt = switch_core_session_get_private(session);
|
||||
assert(tech_pvt != NULL);
|
||||
|
||||
/* ignore any further I/O requests, we're hanging up already! */
|
||||
switch_clear_flag_locked(tech_pvt, TFLAG_IO);
|
||||
|
||||
name = switch_channel_get_name(channel);
|
||||
|
||||
span_id = tech_pvt->ftdmchan ? ftdm_channel_get_span_id(tech_pvt->ftdmchan) : 0;
|
||||
chan_id = tech_pvt->ftdmchan ? ftdm_channel_get_id(tech_pvt->ftdmchan) : 0;
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%d:%d] %s CHANNEL HANGUP ENTER\n", span_id, chan_id, name);
|
||||
|
||||
/* First verify this call has a device attached */
|
||||
if (!tech_pvt->ftdmchan) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s does not have any ftdmchan attached\n", name);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now verify the device is still attached to this call :-)
|
||||
* Sometimes the FS core takes too long (more than 3 seconds) in calling
|
||||
* channel_on_hangup() and the FreeTDM core decides to take the brute
|
||||
* force approach and hangup and detach themselves from the call. Later
|
||||
* when FS finally comes around, we might end up hanging up the device
|
||||
* attached to another call, this verification avoids that. */
|
||||
uuid = switch_core_session_get_uuid(session);
|
||||
tokencnt = ftdm_channel_get_token_count(tech_pvt->ftdmchan);
|
||||
for (t = 0; t < tokencnt; t++) {
|
||||
token = ftdm_channel_get_token(tech_pvt->ftdmchan, t);
|
||||
if (!zstr(token) && !strcasecmp(uuid, token)) {
|
||||
uuid_found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!uuid_found) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Device [%d:%d] is no longer attached to %s. Nothing to do.\n", span_id, chan_id, name);
|
||||
goto end;
|
||||
}
|
||||
|
||||
#ifdef CUDATEL_DEBUG
|
||||
{
|
||||
pid_t tid = 0;
|
||||
size_t size = 0;
|
||||
char **symbols = NULL;
|
||||
void *stacktrace[50];
|
||||
int si = 0;
|
||||
size = backtrace(stacktrace, ftdm_array_len(stacktrace));
|
||||
symbols = backtrace_symbols(stacktrace, size);
|
||||
tid = syscall(SYS_gettid);
|
||||
for (si = 0; si < size; si++) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%d:%d][tid:%d] %s -> %s\n",
|
||||
span_id, chan_id, tid, name, symbols[si]);
|
||||
}
|
||||
free(symbols);
|
||||
}
|
||||
#endif
|
||||
|
||||
ftdm_channel_clear_token(tech_pvt->ftdmchan, switch_core_session_get_uuid(session));
|
||||
|
||||
chantype = ftdm_channel_get_type(tech_pvt->ftdmchan);
|
||||
chantype = ftdm_channel_get_type(tech_pvt->ftdmchan);
|
||||
switch (chantype) {
|
||||
case FTDM_CHAN_TYPE_FXO:
|
||||
case FTDM_CHAN_TYPE_EM:
|
||||
@@ -520,7 +587,6 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session)
|
||||
case FTDM_CHAN_TYPE_FXS:
|
||||
{
|
||||
if (!ftdm_channel_call_check_busy(tech_pvt->ftdmchan) && !ftdm_channel_call_check_done(tech_pvt->ftdmchan)) {
|
||||
tokencnt = ftdm_channel_get_token_count(tech_pvt->ftdmchan);
|
||||
if (tokencnt) {
|
||||
cycle_foreground(tech_pvt->ftdmchan, 0, NULL);
|
||||
} else {
|
||||
@@ -548,9 +614,6 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session)
|
||||
|
||||
end:
|
||||
|
||||
switch_clear_flag_locked(tech_pvt, TFLAG_IO);
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "%s CHANNEL HANGUP\n", switch_channel_get_name(channel));
|
||||
switch_mutex_lock(globals.mutex);
|
||||
globals.calls--;
|
||||
if (globals.calls < 0) {
|
||||
@@ -558,6 +621,7 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session)
|
||||
}
|
||||
switch_mutex_unlock(globals.mutex);
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "[%d:%d] %s CHANNEL HANGUP EXIT\n", span_id, chan_id, name);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -629,6 +693,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
|
||||
int total_to;
|
||||
int chunk, do_break = 0;
|
||||
uint32_t span_id, chan_id;
|
||||
const char *name = NULL;
|
||||
|
||||
channel = switch_core_session_get_channel(session);
|
||||
assert(channel != NULL);
|
||||
@@ -636,17 +701,18 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
|
||||
tech_pvt = switch_core_session_get_private(session);
|
||||
assert(tech_pvt != NULL);
|
||||
|
||||
if (switch_test_flag(tech_pvt, TFLAG_DEAD)) {
|
||||
ftdm_log(FTDM_LOG_DEBUG, "TFLAG_DEAD is set\n");
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
name = switch_channel_get_name(channel);
|
||||
if (!tech_pvt->ftdmchan) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "no ftdmchan set in channel %s!\n", name);
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
span_id = ftdm_channel_get_span_id(tech_pvt->ftdmchan);
|
||||
chan_id = ftdm_channel_get_id(tech_pvt->ftdmchan);
|
||||
if (switch_test_flag(tech_pvt, TFLAG_DEAD)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TFLAG_DEAD is set in channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
/* Digium Cards sometimes timeout several times in a row here.
|
||||
Yes, we support digium cards, ain't we nice.......
|
||||
@@ -678,7 +744,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
|
||||
}
|
||||
|
||||
if (!switch_test_flag(tech_pvt, TFLAG_IO)) {
|
||||
ftdm_log(FTDM_LOG_DEBUG, "TFLAG_IO is not set\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TFLAG_IO is not set in channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -686,7 +752,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
|
||||
status = ftdm_channel_wait(tech_pvt->ftdmchan, &wflags, chunk);
|
||||
|
||||
if (status == FTDM_FAIL) {
|
||||
ftdm_log(FTDM_LOG_ERROR, "Failed to wait for I/O\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to read from channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -694,7 +760,7 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
|
||||
if (!switch_test_flag(tech_pvt, TFLAG_HOLD)) {
|
||||
total_to -= chunk;
|
||||
if (total_to <= 0) {
|
||||
ftdm_log(FTDM_LOG_WARNING, "Too many timeouts while waiting for I/O\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Too many timeouts while waiting I/O in channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
@@ -707,9 +773,9 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
|
||||
|
||||
len = tech_pvt->read_frame.buflen;
|
||||
if (ftdm_channel_read(tech_pvt->ftdmchan, tech_pvt->read_frame.data, &len) != FTDM_SUCCESS) {
|
||||
ftdm_log(FTDM_LOG_WARNING, "failed to read from device %d:%d\n", span_id, chan_id);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to read from channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
if (++tech_pvt->read_error > FTDM_MAX_READ_WRITE_ERRORS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "too many I/O read errors on device %d:%d!\n", span_id, chan_id);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "too many I/O read errors on channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
@@ -725,23 +791,23 @@ static switch_status_t channel_read_frame(switch_core_session_t *session, switch
|
||||
}
|
||||
|
||||
while (ftdm_channel_dequeue_dtmf(tech_pvt->ftdmchan, dtmf, sizeof(dtmf))) {
|
||||
switch_dtmf_t _dtmf = { 0, SWITCH_DEFAULT_DTMF_DURATION };
|
||||
switch_dtmf_t _dtmf = { 0, switch_core_default_dtmf_duration(0) };
|
||||
char *p;
|
||||
for (p = dtmf; p && *p; p++) {
|
||||
if (is_dtmf(*p)) {
|
||||
_dtmf.digit = *p;
|
||||
ftdm_log(FTDM_LOG_DEBUG, "Queuing DTMF [%c] in channel %s\n", *p, switch_channel_get_name(channel));
|
||||
ftdm_log(FTDM_LOG_DEBUG, "Queuing DTMF [%c] in channel %s device %d:%d\n", *p, name, span_id, chan_id);
|
||||
switch_channel_queue_dtmf(channel, &_dtmf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
||||
fail:
|
||||
fail:
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "clearing IO in channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
switch_clear_flag_locked(tech_pvt, TFLAG_IO);
|
||||
return SWITCH_STATUS_GENERR;
|
||||
|
||||
|
||||
}
|
||||
|
||||
static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
|
||||
@@ -750,8 +816,9 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
|
||||
private_t *tech_pvt = NULL;
|
||||
ftdm_size_t len;
|
||||
unsigned char data[SWITCH_RECOMMENDED_BUFFER_SIZE] = {0};
|
||||
const char *name = "(none)";
|
||||
ftdm_wait_flag_t wflags = FTDM_WRITE;
|
||||
uint32_t span_id, chan_id;
|
||||
uint32_t span_id = 0, chan_id = 0;
|
||||
|
||||
channel = switch_core_session_get_channel(session);
|
||||
assert(channel != NULL);
|
||||
@@ -759,7 +826,17 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
|
||||
tech_pvt = switch_core_session_get_private(session);
|
||||
assert(tech_pvt != NULL);
|
||||
|
||||
name = switch_channel_get_name(channel);
|
||||
if (!tech_pvt->ftdmchan) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "no ftdmchan set in channel %s!\n", name);
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
span_id = ftdm_channel_get_span_id(tech_pvt->ftdmchan);
|
||||
chan_id = ftdm_channel_get_id(tech_pvt->ftdmchan);
|
||||
|
||||
if (switch_test_flag(tech_pvt, TFLAG_DEAD)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TFLAG_DEAD is set in channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
@@ -768,17 +845,10 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
|
||||
}
|
||||
|
||||
if (!switch_test_flag(tech_pvt, TFLAG_IO)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TFLAG_IO is not set in channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!tech_pvt->ftdmchan) {
|
||||
return SWITCH_STATUS_FALSE;
|
||||
}
|
||||
|
||||
span_id = ftdm_channel_get_span_id(tech_pvt->ftdmchan);
|
||||
chan_id = ftdm_channel_get_id(tech_pvt->ftdmchan);
|
||||
|
||||
|
||||
if (switch_test_flag(frame, SFF_CNG)) {
|
||||
frame->data = data;
|
||||
frame->buflen = sizeof(data);
|
||||
@@ -793,16 +863,16 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
|
||||
ftdm_channel_wait(tech_pvt->ftdmchan, &wflags, ftdm_channel_get_io_interval(tech_pvt->ftdmchan) * 10);
|
||||
|
||||
if (!(wflags & FTDM_WRITE)) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Dropping frame! (write not ready)\n");
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Dropping frame! (write note ready) in channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
len = frame->datalen;
|
||||
if (ftdm_channel_write(tech_pvt->ftdmchan, frame->data, frame->buflen, &len) != FTDM_SUCCESS) {
|
||||
ftdm_log(FTDM_LOG_WARNING, "failed to write to device %d:%d\n", span_id, chan_id);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Failed to write to channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
if (++tech_pvt->write_error > FTDM_MAX_READ_WRITE_ERRORS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG,
|
||||
SWITCH_LOG_ERROR, "too many I/O write errors on device %d:%d!\n", span_id, chan_id);
|
||||
SWITCH_LOG_ERROR, "Too many I/O write errors on channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
@@ -812,7 +882,7 @@ static switch_status_t channel_write_frame(switch_core_session_t *session, switc
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
|
||||
fail:
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Error writing to channel %s device %d:%d!\n", name, span_id, chan_id);
|
||||
switch_clear_flag_locked(tech_pvt, TFLAG_IO);
|
||||
return SWITCH_STATUS_GENERR;
|
||||
|
||||
@@ -2374,7 +2444,6 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal)
|
||||
switch_set_flag_locked(tech_pvt, TFLAG_DEAD);
|
||||
channel = switch_core_session_get_channel(session);
|
||||
switch_channel_hangup(channel, caller_data->hangup_cause);
|
||||
ftdm_channel_clear_token(sigmsg->channel, switch_core_session_get_uuid(session));
|
||||
switch_core_session_rwunlock(session);
|
||||
}
|
||||
}
|
||||
@@ -3025,6 +3094,7 @@ static switch_status_t load_config(void)
|
||||
const char *enable_callerid = "true";
|
||||
const char *answer_polarity = "false";
|
||||
const char *hangup_polarity = "false";
|
||||
const char *polarity_callerid = "false";
|
||||
int polarity_delay = 600;
|
||||
int callwaiting = 1;
|
||||
int dialtone_timeout = 5000;
|
||||
@@ -3106,6 +3176,8 @@ static switch_status_t load_config(void)
|
||||
hangup_polarity = val;
|
||||
} else if (!strcasecmp(var, "polarity-delay")) {
|
||||
polarity_delay = atoi(val);
|
||||
} else if (!strcasecmp(var, "polarity-callerid")) {
|
||||
polarity_callerid = val;
|
||||
} else if (!strcasecmp(var, "fail-dial-regex")) {
|
||||
fail_dial_regex = val;
|
||||
} else if (!strcasecmp(var, "hold-music")) {
|
||||
@@ -3168,6 +3240,7 @@ static switch_status_t load_config(void)
|
||||
"enable_callerid", enable_callerid,
|
||||
"answer_polarity_reverse", answer_polarity,
|
||||
"hangup_polarity_reverse", hangup_polarity,
|
||||
"polarity_callerid", polarity_callerid,
|
||||
"polarity_delay", &polarity_delay,
|
||||
"callwaiting", &callwaiting,
|
||||
"wait_dialtone_timeout", &dialtone_timeout,
|
||||
@@ -3794,16 +3867,151 @@ void dump_chan_xml(ftdm_span_t *span, uint32_t chan_id, switch_stream_handle_t *
|
||||
switch_channel_cause2str(caller_data->hangup_cause));
|
||||
}
|
||||
|
||||
typedef struct ftdm_cli_entry ftdm_cli_entry_t;
|
||||
typedef switch_status_t (*ftdm_cli_function_t)(ftdm_cli_entry_t *cli, const char *cmd, switch_core_session_t *session,
|
||||
switch_stream_handle_t *stream, int argc, char *argv[]);
|
||||
#define FTDM_CLI_DECLARE(name) static switch_status_t name(ftdm_cli_entry_t *cli, const char *cmd, \
|
||||
switch_core_session_t *session, switch_stream_handle_t *stream, \
|
||||
int argc, char *argv[])
|
||||
static void print_usage(switch_stream_handle_t *stream, ftdm_cli_entry_t *cli);
|
||||
|
||||
static switch_status_t ftdm_cmd_voice_detect(const char *cmd, switch_core_session_t *session,
|
||||
switch_stream_handle_t *stream, int argc, char *argv[])
|
||||
|
||||
typedef struct cmd_ioread_data {
|
||||
int num_times;
|
||||
uint32_t interval;
|
||||
ftdm_span_t *span;
|
||||
ftdm_channel_t *fchan;
|
||||
switch_memory_pool_t *pool;
|
||||
int already_open;
|
||||
} cmd_ioread_data_t;
|
||||
|
||||
static void *SWITCH_THREAD_FUNC ioread_thread(switch_thread_t *thread, void *obj)
|
||||
{
|
||||
stream->write_function(stream, "IMPLEMENT ME!\n");
|
||||
ftdm_wait_flag_t wflags = FTDM_READ;
|
||||
ftdm_status_t status = FTDM_FAIL;
|
||||
unsigned char iobuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
|
||||
cmd_ioread_data_t *data = obj;
|
||||
int span_id = ftdm_span_get_id(data->span);
|
||||
int chan_id = ftdm_channel_get_id(data->fchan);
|
||||
ftdm_size_t len = ftdm_channel_get_io_packet_len(data->fchan);
|
||||
ftdm_size_t origlen = len;
|
||||
unsigned int pbuf[5];
|
||||
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
|
||||
"Started ioread thread (times = %d, interval = %ums, len = %"FTDM_SIZE_FMT", span = %d, chan = %d\n",
|
||||
data->num_times, data->interval, len, span_id, chan_id);
|
||||
|
||||
while (ftdm_running() && data->num_times > 0) {
|
||||
data->num_times--;
|
||||
|
||||
wflags = FTDM_READ;
|
||||
|
||||
status = ftdm_channel_wait(data->fchan, &wflags, (data->interval * 10));
|
||||
|
||||
if (status == FTDM_FAIL) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to wait for IO in device %d:%d!\n", span_id, chan_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (status == FTDM_TIMEOUT) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Timed out while waiting I/O in device %d:%d!\n", span_id, chan_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
len = origlen;
|
||||
if (ftdm_channel_read(data->fchan, iobuf, &len) != FTDM_SUCCESS) {
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Failed to read from device %d:%d!\n", span_id, chan_id);
|
||||
continue;
|
||||
}
|
||||
pbuf[0] = iobuf[0];
|
||||
pbuf[1] = iobuf[1];
|
||||
pbuf[2] = iobuf[2];
|
||||
pbuf[3] = iobuf[3];
|
||||
pbuf[4] = iobuf[4];
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Read 0x%1X 0x%1X 0x%1X 0x%1X 0x%1X\n",
|
||||
pbuf[0], pbuf[1], pbuf[2], pbuf[3], pbuf[4]);
|
||||
}
|
||||
|
||||
if (!data->already_open) {
|
||||
ftdm_channel_close(&data->fchan);
|
||||
}
|
||||
|
||||
switch_core_destroy_memory_pool(&data->pool);
|
||||
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
|
||||
"Done ioread thread (times = %d, interval = %ums, len = %"FTDM_SIZE_FMT", span = %d, chan = %d\n",
|
||||
data->num_times, data->interval, origlen, span_id, chan_id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FTDM_CLI_DECLARE(ftdm_cmd_ioread)
|
||||
{
|
||||
char *span_name = NULL;
|
||||
int channo = 0;
|
||||
ftdm_status_t status = FTDM_SUCCESS;
|
||||
switch_threadattr_t *attr = NULL;
|
||||
switch_thread_t *thread = NULL;
|
||||
|
||||
cmd_ioread_data_t *thdata;
|
||||
cmd_ioread_data_t data;
|
||||
|
||||
memset(&data, 0, sizeof(data));
|
||||
data.num_times = 1;
|
||||
|
||||
if (argc < 3) {
|
||||
print_usage(stream, cli);
|
||||
goto end;
|
||||
}
|
||||
|
||||
span_name = argv[1];
|
||||
|
||||
ftdm_span_find_by_name(span_name, &data.span);
|
||||
if (!data.span) {
|
||||
stream->write_function(stream, "-ERR span %s not found\n", span_name);
|
||||
goto end;
|
||||
}
|
||||
|
||||
channo = atoi(argv[2]);
|
||||
|
||||
status = ftdm_channel_open(ftdm_span_get_id(data.span), channo, &data.fchan);
|
||||
if (!data.fchan || (status != FTDM_SUCCESS && status != FTDM_EBUSY)) {
|
||||
stream->write_function(stream, "-ERR Failed to open channel %d in span %s\n", channo, span_name);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (status == FTDM_EBUSY) {
|
||||
data.already_open = 1;
|
||||
}
|
||||
|
||||
if (argc > 3) {
|
||||
data.num_times = atoi(argv[3]);
|
||||
if (data.num_times < 1) {
|
||||
data.num_times = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc > 4) {
|
||||
data.interval = atoi(argv[4]);
|
||||
}
|
||||
|
||||
if (data.interval <= 0 || data.interval > 10000) {
|
||||
data.interval = ftdm_channel_get_io_interval(data.fchan);
|
||||
}
|
||||
|
||||
switch_core_new_memory_pool(&data.pool);
|
||||
|
||||
thdata = switch_core_alloc(data.pool, sizeof(data));
|
||||
memcpy(thdata, &data, sizeof(*thdata));
|
||||
|
||||
switch_threadattr_create(&attr, data.pool);
|
||||
switch_threadattr_detach_set(attr, 1);
|
||||
switch_threadattr_stacksize_set(attr, SWITCH_THREAD_STACKSIZE);
|
||||
switch_thread_create(&thread, attr, ioread_thread, thdata, data.pool);
|
||||
|
||||
end:
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t ftdm_cmd_list(const char *cmd, switch_core_session_t *session,
|
||||
switch_stream_handle_t *stream, int argc, char *argv[])
|
||||
FTDM_CLI_DECLARE(ftdm_cmd_list)
|
||||
{
|
||||
int j;
|
||||
for (j = 0 ; j < FTDM_MAX_SPANS_INTERFACE; j++) {
|
||||
@@ -3880,19 +4088,20 @@ static switch_status_t ftdm_cmd_list(const char *cmd, switch_core_session_t *ses
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t ftdm_cmd_start_stop(const char *cmd, switch_core_session_t *session,
|
||||
switch_stream_handle_t *stream, int argc, char *argv[])
|
||||
FTDM_CLI_DECLARE(ftdm_cmd_start_stop)
|
||||
{
|
||||
char *span_name = argv[1];
|
||||
ftdm_span_t *span = NULL;
|
||||
ftdm_status_t status;
|
||||
|
||||
if (span_name) {
|
||||
ftdm_span_find_by_name(span_name, &span);
|
||||
if (argc < 2) {
|
||||
print_usage(stream, cli);
|
||||
goto end;
|
||||
}
|
||||
|
||||
ftdm_span_find_by_name(span_name, &span);
|
||||
if (!span) {
|
||||
stream->write_function(stream, "-ERR no span\n");
|
||||
stream->write_function(stream, "-ERR span %s not found\n", span_name);
|
||||
goto end;
|
||||
}
|
||||
|
||||
@@ -3907,34 +4116,36 @@ end:
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t ftdm_cmd_reset(const char *cmd, switch_core_session_t *session,
|
||||
switch_stream_handle_t *stream, int argc, char *argv[])
|
||||
FTDM_CLI_DECLARE(ftdm_cmd_reset)
|
||||
{
|
||||
uint32_t chan_id = 0;
|
||||
uint32_t ccount = 0;
|
||||
ftdm_channel_t *chan;
|
||||
ftdm_span_t *span = NULL;
|
||||
|
||||
if (argc < 2) {
|
||||
stream->write_function(stream, "-ERR Usage: ftdm reset <span_id> [<chan_id>]\n");
|
||||
print_usage(stream, cli);
|
||||
goto end;
|
||||
}
|
||||
|
||||
ftdm_span_find_by_name(argv[1], &span);
|
||||
if (!span) {
|
||||
stream->write_function(stream, "-ERR invalid span\n");
|
||||
stream->write_function(stream, "-ERR span %s not found\n", argv[1]);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (argc > 2) {
|
||||
chan_id = atoi(argv[2]);
|
||||
if (chan_id > ftdm_span_get_chan_count(span)) {
|
||||
stream->write_function(stream, "-ERR invalid chan\n");
|
||||
stream->write_function(stream, "-ERR invalid channel %d\n", chan_id);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (chan_id) {
|
||||
chan = ftdm_span_get_channel(span, chan_id);
|
||||
if (!chan) {
|
||||
stream->write_function(stream, "-ERR Could not find chan\n");
|
||||
stream->write_function(stream, "-ERR Could not find channel %d\n", chan_id);
|
||||
goto end;
|
||||
}
|
||||
stream->write_function(stream, "Resetting channel %s:%s\n", argv[1], argv[2]);
|
||||
@@ -3954,8 +4165,7 @@ end:
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t ftdm_cmd_dump(const char *cmd, switch_core_session_t *session,
|
||||
switch_stream_handle_t *stream, int argc, char *argv[])
|
||||
FTDM_CLI_DECLARE(ftdm_cmd_dump)
|
||||
{
|
||||
ftdm_iterator_t *chaniter = NULL;
|
||||
ftdm_iterator_t *curr = NULL;
|
||||
@@ -3964,12 +4174,11 @@ static switch_status_t ftdm_cmd_dump(const char *cmd, switch_core_session_t *ses
|
||||
char *as = NULL;
|
||||
|
||||
if (argc < 2) {
|
||||
stream->write_function(stream, "-ERR Usage: ftdm dump <span_id> [<chan_id>]\n");
|
||||
print_usage(stream, cli);
|
||||
goto end;
|
||||
}
|
||||
|
||||
ftdm_span_find_by_name(argv[1], &span);
|
||||
|
||||
if (argc > 2) {
|
||||
if (argv[3] && !strcasecmp(argv[2], "as")) {
|
||||
as = argv[3];
|
||||
@@ -4032,28 +4241,29 @@ end:
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t ftdm_cmd_sigstatus(const char *cmd, switch_core_session_t *session,
|
||||
switch_stream_handle_t *stream, int argc, char *argv[])
|
||||
FTDM_CLI_DECLARE(ftdm_cmd_sigstatus)
|
||||
{
|
||||
ftdm_span_t *span = NULL;
|
||||
ftdm_signaling_status_t sigstatus;
|
||||
|
||||
if (argc < 3) {
|
||||
stream->write_function(stream, "-ERR Usage: ftdm sigstatus get|set [<span_id>] [<chan_id>] [<sigstatus>]\n");
|
||||
print_usage(stream, cli);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!strcasecmp(argv[1], "get") && argc < 3) {
|
||||
stream->write_function(stream, "-ERR sigstatus get usage: get <span_id>\n");
|
||||
print_usage(stream, cli);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!strcasecmp(argv[1], "set") && argc != 5) {
|
||||
stream->write_function(stream, "-ERR sigstatus set usage: set <span_id> <chan_id>|all <sigstatus>\n");
|
||||
print_usage(stream, cli);
|
||||
goto end;
|
||||
}
|
||||
|
||||
ftdm_span_find_by_name(argv[2], &span);
|
||||
if (!span) {
|
||||
stream->write_function(stream, "-ERR invalid span\n");
|
||||
stream->write_function(stream, "-ERR invalid span %s\n", argv[2]);
|
||||
goto end;
|
||||
}
|
||||
|
||||
@@ -4062,21 +4272,21 @@ static switch_status_t ftdm_cmd_sigstatus(const char *cmd, switch_core_session_t
|
||||
uint32_t chan_id = atol(argv[3]);
|
||||
ftdm_channel_t *fchan = ftdm_span_get_channel(span, chan_id);
|
||||
if (!fchan) {
|
||||
stream->write_function(stream, "-ERR failed to get channel id '%d'\n", chan_id);
|
||||
stream->write_function(stream, "-ERR invalid channel id '%d'\n", chan_id);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if ((FTDM_SUCCESS == ftdm_channel_get_sig_status(fchan, &sigstatus))) {
|
||||
stream->write_function(stream, "channel %d signaling status: %s\n", chan_id, ftdm_signaling_status2str(sigstatus));
|
||||
stream->write_function(stream, "Channel %d signaling status: %s\n", chan_id, ftdm_signaling_status2str(sigstatus));
|
||||
} else {
|
||||
stream->write_function(stream, "-ERR failed to get channel sigstatus\n");
|
||||
stream->write_function(stream, "-ERR failed to get channel signaling status\n");
|
||||
}
|
||||
goto end;
|
||||
} else {
|
||||
if ((FTDM_SUCCESS == ftdm_span_get_sig_status(span, &sigstatus))) {
|
||||
stream->write_function(stream, "signaling_status: %s\n", ftdm_signaling_status2str(sigstatus));
|
||||
} else {
|
||||
stream->write_function(stream, "-ERR failed to read span status: %s\n", ftdm_span_get_last_error(span));
|
||||
stream->write_function(stream, "-ERR failed to read span signaling status: %s\n", ftdm_span_get_last_error(span));
|
||||
}
|
||||
}
|
||||
goto end;
|
||||
@@ -4114,8 +4324,7 @@ end:
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t ftdm_cmd_trace(const char *cmd, switch_core_session_t *session,
|
||||
switch_stream_handle_t *stream, int argc, char *argv[])
|
||||
FTDM_CLI_DECLARE(ftdm_cmd_trace)
|
||||
{
|
||||
char tracepath[255];
|
||||
unsigned i = 0;
|
||||
@@ -4125,19 +4334,19 @@ static switch_status_t ftdm_cmd_trace(const char *cmd, switch_core_session_t *se
|
||||
ftdm_span_t *span = NULL;
|
||||
ftdm_channel_t *chan = NULL;
|
||||
if (argc < 3) {
|
||||
stream->write_function(stream, "-ERR Usage: ftdm trace <path> <span_id> [<chan_id>]\n");
|
||||
print_usage(stream, cli);
|
||||
goto end;
|
||||
}
|
||||
ftdm_span_find_by_name(argv[2], &span);
|
||||
if (!span) {
|
||||
stream->write_function(stream, "-ERR invalid span\n");
|
||||
stream->write_function(stream, "-ERR failed to find span %s\n", argv[2]);
|
||||
goto end;
|
||||
}
|
||||
chan_count = ftdm_span_get_chan_count(span);
|
||||
if (argc > 3) {
|
||||
chan_id = atoi(argv[3]);
|
||||
if (chan_id > chan_count) {
|
||||
stream->write_function(stream, "-ERR invalid chan\n");
|
||||
stream->write_function(stream, "-ERR invalid channel\n");
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
@@ -4162,31 +4371,33 @@ end:
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t ftdm_cmd_notrace(const char *cmd, switch_core_session_t *session,
|
||||
switch_stream_handle_t *stream, int argc, char *argv[])
|
||||
FTDM_CLI_DECLARE(ftdm_cmd_notrace)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint32_t chan_id = 0;
|
||||
uint32_t chan_count = 0;
|
||||
ftdm_channel_t *fchan = NULL;
|
||||
ftdm_span_t *span = NULL;
|
||||
|
||||
if (argc < 2) {
|
||||
stream->write_function(stream, "-ERR Usage: ftdm notrace <span_id> [<chan_id>]\n");
|
||||
print_usage(stream, cli);
|
||||
goto end;
|
||||
}
|
||||
ftdm_span_find_by_name(argv[1], &span);
|
||||
if (!span) {
|
||||
stream->write_function(stream, "-ERR invalid span\n");
|
||||
stream->write_function(stream, "-ERR failed to find span %s\n", argv[1]);
|
||||
goto end;
|
||||
}
|
||||
|
||||
chan_count = ftdm_span_get_chan_count(span);
|
||||
if (argc > 2) {
|
||||
chan_id = atoi(argv[2]);
|
||||
if (chan_id > chan_count) {
|
||||
stream->write_function(stream, "-ERR invalid chan\n");
|
||||
stream->write_function(stream, "-ERR invalid channel\n");
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (chan_id) {
|
||||
fchan = ftdm_span_get_channel(span, chan_id);
|
||||
ftdm_channel_command(fchan, FTDM_COMMAND_TRACE_END_ALL, NULL);
|
||||
@@ -4197,12 +4408,12 @@ static switch_status_t ftdm_cmd_notrace(const char *cmd, switch_core_session_t *
|
||||
}
|
||||
}
|
||||
stream->write_function(stream, "+OK trace disabled\n");
|
||||
|
||||
end:
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t ftdm_cmd_gains(const char *cmd, switch_core_session_t *session,
|
||||
switch_stream_handle_t *stream, int argc, char *argv[])
|
||||
FTDM_CLI_DECLARE(ftdm_cmd_gains)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
float txgain = 0.0;
|
||||
@@ -4212,18 +4423,19 @@ static switch_status_t ftdm_cmd_gains(const char *cmd, switch_core_session_t *se
|
||||
ftdm_channel_t *chan;
|
||||
ftdm_span_t *span = NULL;
|
||||
if (argc < 4) {
|
||||
stream->write_function(stream, "-ERR Usage: ftdm gains <rxgain> <txgain> <span_id> [<chan_id>]\n");
|
||||
print_usage(stream, cli);
|
||||
goto end;
|
||||
}
|
||||
ftdm_span_find_by_name(argv[3], &span);
|
||||
if (!span) {
|
||||
stream->write_function(stream, "-ERR invalid span\n");
|
||||
stream->write_function(stream, "-ERR failed to find span %s\n", argv[3]);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (argc > 4) {
|
||||
chan_id = atoi(argv[4]);
|
||||
if (chan_id > ftdm_span_get_chan_count(span)) {
|
||||
stream->write_function(stream, "-ERR invalid chan\n");
|
||||
stream->write_function(stream, "-ERR invalid channel\n");
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
@@ -4251,8 +4463,7 @@ end:
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t ftdm_cmd_dtmf(const char *cmd, switch_core_session_t *session,
|
||||
switch_stream_handle_t *stream, int argc, char *argv[])
|
||||
FTDM_CLI_DECLARE(ftdm_cmd_dtmf)
|
||||
{
|
||||
unsigned i = 0;
|
||||
uint32_t chan_id = 0;
|
||||
@@ -4260,8 +4471,9 @@ static switch_status_t ftdm_cmd_dtmf(const char *cmd, switch_core_session_t *ses
|
||||
ftdm_span_t *span = NULL;
|
||||
ftdm_command_t fcmd = FTDM_COMMAND_ENABLE_DTMF_DETECT;
|
||||
ftdm_channel_t *fchan;
|
||||
|
||||
if (argc < 3) {
|
||||
stream->write_function(stream, "-ERR Usage: dtmf on|off <span_id> [<chan_id>]\n");
|
||||
print_usage(stream, cli);
|
||||
goto end;
|
||||
}
|
||||
|
||||
@@ -4273,14 +4485,15 @@ static switch_status_t ftdm_cmd_dtmf(const char *cmd, switch_core_session_t *ses
|
||||
|
||||
ftdm_span_find_by_name(argv[2], &span);
|
||||
if (!span) {
|
||||
stream->write_function(stream, "-ERR invalid span\n");
|
||||
stream->write_function(stream, "-ERR failed to find span %s\n", argv[2]);
|
||||
goto end;
|
||||
}
|
||||
|
||||
schan_count = ftdm_span_get_chan_count(span);
|
||||
if (argc > 3) {
|
||||
chan_id = atoi(argv[3]);
|
||||
if (chan_id > schan_count) {
|
||||
stream->write_function(stream, "-ERR invalid chan\n");
|
||||
stream->write_function(stream, "-ERR invalid channel\n");
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
@@ -4300,8 +4513,7 @@ end:
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static switch_status_t ftdm_cmd_queuesize(const char *cmd, switch_core_session_t *session,
|
||||
switch_stream_handle_t *stream, int argc, char *argv[])
|
||||
FTDM_CLI_DECLARE(ftdm_cmd_queuesize)
|
||||
{
|
||||
unsigned int i = 0;
|
||||
uint32_t rxsize = 10;
|
||||
@@ -4311,21 +4523,24 @@ static switch_status_t ftdm_cmd_queuesize(const char *cmd, switch_core_session_t
|
||||
ftdm_channel_t *chan;
|
||||
ftdm_span_t *span = NULL;
|
||||
if (argc < 4) {
|
||||
stream->write_function(stream, "-ERR Usage: ftdm queuesize <rxsize> <txsize> <span_id> [<chan_id>]\n");
|
||||
print_usage(stream, cli);
|
||||
goto end;
|
||||
}
|
||||
|
||||
ftdm_span_find_by_name(argv[3], &span);
|
||||
if (!span) {
|
||||
stream->write_function(stream, "-ERR invalid span\n");
|
||||
stream->write_function(stream, "-ERR failed to find span %s\n", argv[3]);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (argc > 4) {
|
||||
chan_id = atoi(argv[4]);
|
||||
if (chan_id > ftdm_span_get_chan_count(span)) {
|
||||
stream->write_function(stream, "-ERR invalid chan\n");
|
||||
stream->write_function(stream, "-ERR invalid channel\n");
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
i = sscanf(argv[1], "%u", &rxsize);
|
||||
i += sscanf(argv[2], "%u", &txsize);
|
||||
if (i != 2) {
|
||||
@@ -4379,8 +4594,7 @@ static void exec_io_command(const char *cmd, switch_stream_handle_t *stream, ftd
|
||||
}
|
||||
}
|
||||
|
||||
static switch_status_t ftdm_cmd_iostats(const char *cmd, switch_core_session_t *session,
|
||||
switch_stream_handle_t *stream, int argc, char *argv[])
|
||||
FTDM_CLI_DECLARE(ftdm_cmd_iostats)
|
||||
{
|
||||
uint32_t chan_id = 0;
|
||||
ftdm_channel_t *chan;
|
||||
@@ -4389,20 +4603,20 @@ static switch_status_t ftdm_cmd_iostats(const char *cmd, switch_core_session_t *
|
||||
ftdm_span_t *span = NULL;
|
||||
|
||||
if (argc < 3) {
|
||||
stream->write_function(stream, "-ERR Usage: ftdm iostats enable|disable|flush|print <span_id> [<chan_id>]\n");
|
||||
print_usage(stream, cli);
|
||||
goto end;
|
||||
}
|
||||
|
||||
ftdm_span_find_by_name(argv[2], &span);
|
||||
if (!span) {
|
||||
stream->write_function(stream, "-ERR invalid span\n");
|
||||
stream->write_function(stream, "-ERR failed to find span %s\n", argv[2]);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (argc > 3) {
|
||||
chan_id = atoi(argv[3]);
|
||||
if (chan_id > ftdm_span_get_chan_count(span)) {
|
||||
stream->write_function(stream, "-ERR invalid chan\n");
|
||||
stream->write_function(stream, "-ERR invalid channel\n");
|
||||
goto end;
|
||||
}
|
||||
chan = ftdm_span_get_channel(span, chan_id);
|
||||
@@ -4420,14 +4634,12 @@ end:
|
||||
return SWITCH_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
typedef switch_status_t (*ftdm_cli_function_t)(const char *cmd, switch_core_session_t *session,
|
||||
switch_stream_handle_t *stream, int argc, char *argv[]);
|
||||
typedef struct ftdm_cli_entry {
|
||||
struct ftdm_cli_entry {
|
||||
const char *name;
|
||||
const char *args;
|
||||
const char *complete;
|
||||
ftdm_cli_function_t execute;
|
||||
} ftdm_cli_entry_t;
|
||||
};
|
||||
|
||||
static ftdm_cli_entry_t ftdm_cli_options[] =
|
||||
{
|
||||
@@ -4443,7 +4655,7 @@ static ftdm_cli_entry_t ftdm_cli_options[] =
|
||||
{ "dtmf", "on|off <span_id|span_name> [<chan_id>]", "::[on:off", ftdm_cmd_dtmf },
|
||||
{ "queuesize", "<rxsize> <txsize> <span_id|span_name> [<chan_id>]", "", ftdm_cmd_queuesize },
|
||||
{ "iostats", "enable|disable|flush|print <span_id|span_name> <chan_id>", "::[enable:disable:flush:print", ftdm_cmd_iostats },
|
||||
{ "voice_detect", "[on|off] <span_id|span_name> [<chan_id>]", "::[on:off", ftdm_cmd_voice_detect },
|
||||
{ "ioread", "<span_id|span_name> <chan_id> [num_times] [interval]", "", ftdm_cmd_ioread },
|
||||
|
||||
/* Fake handlers as they are handled within freetdm library,
|
||||
* we should provide a way inside freetdm to query for completions from signaling modules */
|
||||
@@ -4452,6 +4664,11 @@ static ftdm_cli_entry_t ftdm_cli_options[] =
|
||||
{ "core calls", "", "", NULL },
|
||||
};
|
||||
|
||||
static void print_usage(switch_stream_handle_t *stream, ftdm_cli_entry_t *cli)
|
||||
{
|
||||
stream->write_function(stream, "-ERR Usage: ftdm %s %s\n", cli->name, cli->args);
|
||||
}
|
||||
|
||||
static void print_full_usage(switch_stream_handle_t *stream)
|
||||
{
|
||||
int i = 0;
|
||||
@@ -4484,7 +4701,7 @@ SWITCH_STANDARD_API(ft_function)
|
||||
for (i = 0 ; i < ftdm_array_len(ftdm_cli_options); i++) {
|
||||
entry = &ftdm_cli_options[i];
|
||||
if (!strcasecmp(argv[0], entry->name) && entry->execute) {
|
||||
entry->execute(cmd, session, stream, argc, argv);
|
||||
entry->execute(entry, cmd, session, stream, argc, argv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ int main(int argc, char *argv[])
|
||||
int fd, b;
|
||||
short sln[512] = {0};
|
||||
teletone_dtmf_detect_state_t dtmf_detect = {0};
|
||||
char digit_str[128] = "";
|
||||
teletone_hit_type_t hit;
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "Arg Error!\n");
|
||||
@@ -21,10 +21,31 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
while((b = read(fd, sln, 320)) > 0) {
|
||||
char digit_char;
|
||||
unsigned int dur;
|
||||
|
||||
teletone_dtmf_detect(&dtmf_detect, sln, b / 2);
|
||||
teletone_dtmf_get(&dtmf_detect, digit_str, sizeof(digit_str));
|
||||
if (*digit_str) {
|
||||
printf("digit: %s\n", digit_str);
|
||||
if ((hit = teletone_dtmf_get(&dtmf_detect, &digit_char, &dur))) {
|
||||
const char *hs = NULL;
|
||||
|
||||
|
||||
switch(hit) {
|
||||
case TT_HIT_BEGIN:
|
||||
hs = "begin";
|
||||
break;
|
||||
|
||||
case TT_HIT_MIDDLE:
|
||||
hs = "middle";
|
||||
break;
|
||||
|
||||
case TT_HIT_END:
|
||||
hs = "end";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
printf("%s digit: %c\n", hs, digit_char);
|
||||
}
|
||||
}
|
||||
close(fd);
|
||||
|
||||
+28
-15
@@ -649,9 +649,6 @@ static ftdm_status_t ftdm_span_destroy(ftdm_span_t *span)
|
||||
if (span->fio->span_destroy(span) != FTDM_SUCCESS) {
|
||||
status = FTDM_FAIL;
|
||||
}
|
||||
ftdm_safe_free(span->type);
|
||||
ftdm_safe_free(span->name);
|
||||
ftdm_safe_free(span->dtmf_hangup);
|
||||
}
|
||||
|
||||
/* destroy final basic resources of the span data structure */
|
||||
@@ -1858,7 +1855,14 @@ static ftdm_status_t _ftdm_channel_open(uint32_t span_id, uint32_t chan_id, ftdm
|
||||
goto done;
|
||||
}
|
||||
|
||||
ftdm_mutex_lock(check->mutex);
|
||||
ftdm_channel_lock(check);
|
||||
|
||||
if (ftdm_test_flag(check, FTDM_CHANNEL_OPEN)) {
|
||||
/* let them know is already open, but return the channel anyway */
|
||||
status = FTDM_EBUSY;
|
||||
*ftdmchan = check;
|
||||
goto unlockchan;
|
||||
}
|
||||
|
||||
/* The following if's and gotos replace a big if (this || this || this || this) else { nothing; } */
|
||||
|
||||
@@ -1905,7 +1909,7 @@ openchan:
|
||||
goto done;
|
||||
|
||||
unlockchan:
|
||||
ftdm_mutex_unlock(check->mutex);
|
||||
ftdm_channel_unlock(check);
|
||||
|
||||
done:
|
||||
ftdm_mutex_unlock(globals.mutex);
|
||||
@@ -3855,7 +3859,6 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_process_media(ftdm_channel_t *ftdmchan, v
|
||||
uint8_t sln_buf[1024] = {0};
|
||||
int16_t *sln;
|
||||
ftdm_size_t slen = 0;
|
||||
char digit_str[80] = "";
|
||||
|
||||
if (ftdmchan->effective_codec == FTDM_CODEC_SLIN) {
|
||||
sln = data;
|
||||
@@ -3956,13 +3959,18 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_process_media(ftdm_channel_t *ftdmchan, v
|
||||
}
|
||||
|
||||
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_DTMF_DETECT) && !ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_DTMF_DETECT)) {
|
||||
teletone_dtmf_detect(&ftdmchan->dtmf_detect, sln, (int)slen);
|
||||
teletone_dtmf_get(&ftdmchan->dtmf_detect, digit_str, sizeof(digit_str));
|
||||
teletone_hit_type_t hit;
|
||||
char digit_char;
|
||||
uint32_t dur;
|
||||
|
||||
if(*digit_str) {
|
||||
if (ftdmchan->state == FTDM_CHANNEL_STATE_CALLWAITING && (*digit_str == 'D' || *digit_str == 'A')) {
|
||||
if ((hit = teletone_dtmf_detect(&ftdmchan->dtmf_detect, sln, (int)slen)) == TT_HIT_END) {
|
||||
teletone_dtmf_get(&ftdmchan->dtmf_detect, &digit_char, &dur);
|
||||
|
||||
if (ftdmchan->state == FTDM_CHANNEL_STATE_CALLWAITING && (digit_char == 'D' || digit_char == 'A')) {
|
||||
ftdmchan->detected_tones[FTDM_TONEMAP_CALLWAITING_ACK]++;
|
||||
} else {
|
||||
char digit_str[2] = { digit_char, 0};
|
||||
|
||||
if (!ftdmchan->span->sig_dtmf || (ftdmchan->span->sig_dtmf(ftdmchan, (const char*)digit_str) != FTDM_BREAK)) {
|
||||
ftdm_channel_queue_dtmf(ftdmchan, digit_str);
|
||||
}
|
||||
@@ -4568,7 +4576,7 @@ FT_DECLARE(ftdm_status_t) ftdm_configure_span_channels(ftdm_span_t *span, const
|
||||
*configured = 0;
|
||||
*configured = span->fio->configure_span(span, str, chan_config->type, chan_config->name, chan_config->number);
|
||||
if (!*configured) {
|
||||
ftdm_log(FTDM_LOG_ERROR, "%d:Failed to configure span", span->span_id);
|
||||
ftdm_log(FTDM_LOG_ERROR, "%d:Failed to configure span\n", span->span_id);
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
|
||||
@@ -5468,10 +5476,6 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
|
||||
if (sigmsg->channel) {
|
||||
fchan = sigmsg->channel;
|
||||
ftdm_channel_lock(fchan);
|
||||
sigmsg->chan_id = fchan->chan_id;
|
||||
sigmsg->span_id = fchan->span_id;
|
||||
sigmsg->call_id = fchan->caller_data.call_id;
|
||||
sigmsg->call_priv = fchan->caller_data.priv;
|
||||
}
|
||||
|
||||
/* some core things to do on special events */
|
||||
@@ -5561,6 +5565,14 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
|
||||
|
||||
}
|
||||
|
||||
if (fchan) {
|
||||
/* set members of the sigmsg that must be present for all events */
|
||||
sigmsg->chan_id = fchan->chan_id;
|
||||
sigmsg->span_id = fchan->span_id;
|
||||
sigmsg->call_id = fchan->caller_data.call_id;
|
||||
sigmsg->call_priv = fchan->caller_data.priv;
|
||||
}
|
||||
|
||||
/* if the signaling module uses a queue for signaling notifications, then enqueue it */
|
||||
if (ftdm_test_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE)) {
|
||||
ftdm_span_queue_signal(span, sigmsg);
|
||||
@@ -5774,6 +5786,7 @@ FT_DECLARE(ftdm_status_t) ftdm_global_destroy(void)
|
||||
}
|
||||
|
||||
hashtable_remove(globals.span_hash, (void *)cur_span->name);
|
||||
ftdm_safe_free(cur_span->dtmf_hangup);
|
||||
ftdm_safe_free(cur_span->type);
|
||||
ftdm_safe_free(cur_span->name);
|
||||
ftdm_safe_free(cur_span);
|
||||
|
||||
@@ -39,7 +39,8 @@ typedef enum {
|
||||
FTDM_ANALOG_RUNNING = (1 << 0),
|
||||
FTDM_ANALOG_CALLERID = (1 << 1),
|
||||
FTDM_ANALOG_ANSWER_POLARITY_REVERSE = (1 << 2),
|
||||
FTDM_ANALOG_HANGUP_POLARITY_REVERSE = (1 << 3)
|
||||
FTDM_ANALOG_HANGUP_POLARITY_REVERSE = (1 << 3),
|
||||
FTDM_ANALOG_POLARITY_CALLERID = (1 << 4)
|
||||
} ftdm_analog_flag_t;
|
||||
|
||||
#define FTDM_MAX_HOTLINE_STR 20
|
||||
|
||||
@@ -275,6 +275,15 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_configure_span)
|
||||
break;
|
||||
}
|
||||
hotline = val;
|
||||
} else if (!strcasecmp(var, "polarity_callerid")) {
|
||||
if (!(val = va_arg(ap, char *))) {
|
||||
break;
|
||||
}
|
||||
if (ftdm_true(val)) {
|
||||
flags |= FTDM_ANALOG_POLARITY_CALLERID;
|
||||
} else {
|
||||
flags &= ~FTDM_ANALOG_POLARITY_CALLERID;
|
||||
}
|
||||
} else {
|
||||
ftdm_log(FTDM_LOG_ERROR, "Unknown parameter %s in span %s\n", var, span->name);
|
||||
}
|
||||
@@ -1130,8 +1139,18 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
|
||||
break;
|
||||
}
|
||||
if (event->channel->state == FTDM_CHANNEL_STATE_DOWN) {
|
||||
ftdm_log_chan_msg(event->channel, FTDM_LOG_DEBUG,
|
||||
"Ignoring polarity reversal because this channel is down\n");
|
||||
if (ftdm_test_flag(analog_data, FTDM_ANALOG_CALLERID)
|
||||
&& ftdm_test_flag(analog_data, FTDM_ANALOG_POLARITY_CALLERID)) {
|
||||
ftdm_log_chan_msg(event->channel, FTDM_LOG_DEBUG, "Polarity reversal detected while down, getting caller id now\n");
|
||||
ftdm_set_state(event->channel, FTDM_CHANNEL_STATE_GET_CALLERID);
|
||||
event->channel->ring_count = 1;
|
||||
ftdm_mutex_unlock(event->channel->mutex);
|
||||
locked = 0;
|
||||
ftdm_thread_create_detached(ftdm_analog_channel_run, event->channel);
|
||||
} else {
|
||||
ftdm_log_chan_msg(event->channel, FTDM_LOG_DEBUG,
|
||||
"Ignoring polarity reversal because this channel is down\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* we have a good channel, set the polarity flag and let the channel thread deal with it */
|
||||
|
||||
@@ -204,6 +204,32 @@ static int parse_debug(const char *in, uint32_t *flags)
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Parses a change status string to flags
|
||||
* \param in change status string to parse for
|
||||
* \return Flags
|
||||
*/
|
||||
static int parse_change_status(const char *in)
|
||||
{
|
||||
int flags = 0;
|
||||
if (!in) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strstr(in, "in_service") || strstr(in, "in")) {
|
||||
flags = SERVICE_CHANGE_STATUS_INSERVICE;
|
||||
}
|
||||
if (strstr(in, "maintenance") || strstr(in, "maint")) {
|
||||
flags = SERVICE_CHANGE_STATUS_MAINTENANCE;
|
||||
}
|
||||
if (strstr(in, "out_of_service") || strstr(in, "out")) {
|
||||
flags = SERVICE_CHANGE_STATUS_OUTOFSERVICE;
|
||||
}
|
||||
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
static int print_debug(uint32_t flags, char *tmp, const int size)
|
||||
{
|
||||
int offset = 0;
|
||||
@@ -240,6 +266,9 @@ static ftdm_io_interface_t ftdm_libpri_interface;
|
||||
static const char *ftdm_libpri_usage =
|
||||
"Usage:\n"
|
||||
"libpri kill <span>\n"
|
||||
"libpri reset <span>\n"
|
||||
"libpri restart <span> <channel/all>\n"
|
||||
"libpri maintenance <span> <channel/all> <in/maint/out>\n"
|
||||
"libpri debug <span> [all|none|flag,...flagN]\n"
|
||||
"\n"
|
||||
"Possible debug flags:\n"
|
||||
@@ -339,8 +368,78 @@ static FIO_API_FUNCTION(ftdm_libpri_api)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if (!strcasecmp(argv[0], "reset")) {
|
||||
ftdm_span_t *span = NULL;
|
||||
if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS) {
|
||||
ftdm_libpri_data_t *isdn_data = span->signal_data;
|
||||
if (span->start != ftdm_libpri_start) {
|
||||
stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__);
|
||||
goto done;
|
||||
}
|
||||
|
||||
pri_restart(isdn_data->spri.pri);
|
||||
stream->write_function(stream, "%s: +OK reset.\n", __FILE__);
|
||||
goto done;
|
||||
} else {
|
||||
stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if (!strcasecmp(argv[0], "restart") && argc == 3) {
|
||||
ftdm_span_t *span = NULL;
|
||||
if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS) {
|
||||
ftdm_libpri_data_t *isdn_data = span->signal_data;
|
||||
if (span->start != ftdm_libpri_start) {
|
||||
stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__);
|
||||
goto done;
|
||||
}
|
||||
if (!strcasecmp(argv[2], "all")) {
|
||||
int j;
|
||||
for(j = 1; j <= span->chan_count; j++) {
|
||||
pri_reset(isdn_data->spri.pri, j);
|
||||
ftdm_sleep(50);
|
||||
}
|
||||
} else {
|
||||
pri_reset(isdn_data->spri.pri, atoi(argv[2]));
|
||||
}
|
||||
stream->write_function(stream, "%s: +OK restart set.\n", __FILE__);
|
||||
goto done;
|
||||
} else {
|
||||
stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if (!strcasecmp(argv[0], "maintenance") && argc > 3) {
|
||||
ftdm_span_t *span = NULL;
|
||||
if (ftdm_span_find_by_name(argv[1], &span) == FTDM_SUCCESS) {
|
||||
ftdm_libpri_data_t *isdn_data = span->signal_data;
|
||||
if (span->start != ftdm_libpri_start) {
|
||||
stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__);
|
||||
goto done;
|
||||
}
|
||||
if (!isdn_data->service_message_support) {
|
||||
stream->write_function(stream, "%s: -ERR service message support is disabled\n", __FILE__);
|
||||
goto done;
|
||||
}
|
||||
if (!strcasecmp(argv[2], "all")) {
|
||||
int j;
|
||||
for(j = 1; j <= span->chan_count; j++) {
|
||||
pri_maintenance_service(isdn_data->spri.pri, atoi(argv[1]), j, parse_change_status(argv[3]));
|
||||
ftdm_sleep(50);
|
||||
}
|
||||
} else {
|
||||
pri_maintenance_service(isdn_data->spri.pri, atoi(argv[1]), atoi(argv[2]), parse_change_status(argv[3]));
|
||||
}
|
||||
stream->write_function(stream, "%s: +OK change status set.\n", __FILE__);
|
||||
goto done;
|
||||
} else {
|
||||
stream->write_function(stream, "%s: -ERR invalid span.\n", __FILE__);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
stream->write_function(stream, "%s: -ERR invalid command.\n", __FILE__);
|
||||
|
||||
done:
|
||||
@@ -1780,6 +1879,10 @@ static void *ftdm_libpri_run(ftdm_thread_t *me, void *obj)
|
||||
pri_facility_enable(isdn_data->spri.pri);
|
||||
}
|
||||
#endif
|
||||
/* Support the different switch of service status */
|
||||
if (isdn_data->service_message_support) {
|
||||
pri_set_service_message_support(isdn_data->spri.pri, 1 /* True */);
|
||||
}
|
||||
|
||||
if (res == 0) {
|
||||
LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_ANY, on_anything);
|
||||
@@ -1835,6 +1938,14 @@ static void *ftdm_libpri_run(ftdm_thread_t *me, void *obj)
|
||||
ftdm_sleep(5000);
|
||||
}
|
||||
out:
|
||||
/* close d-channel, if set */
|
||||
if (isdn_data->dchan) {
|
||||
if (ftdm_channel_close(&isdn_data->dchan) != FTDM_SUCCESS) {
|
||||
ftdm_log(FTDM_LOG_ERROR, "Failed to close D-Channel %d:%d\n",
|
||||
ftdm_channel_get_span_id(isdn_data->dchan), ftdm_channel_get_id(isdn_data->dchan));
|
||||
}
|
||||
}
|
||||
|
||||
ftdm_log(FTDM_LOG_DEBUG, "PRI thread ended on span %d\n", ftdm_span_get_id(span));
|
||||
|
||||
ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD);
|
||||
@@ -2159,6 +2270,11 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_libpri_configure_span)
|
||||
isdn_data->debug_mask = 0;
|
||||
}
|
||||
}
|
||||
else if (!strcasecmp(var, "service_message_support")) {
|
||||
if (ftdm_true(val)) {
|
||||
isdn_data->service_message_support = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ftdm_log(FTDM_LOG_ERROR, "Unknown parameter '%s', aborting configuration\n", var);
|
||||
snprintf(span->last_error, sizeof(span->last_error), "Unknown parameter [%s]", var);
|
||||
|
||||
@@ -31,6 +31,11 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
SERVICE_CHANGE_STATUS_INSERVICE = 0,
|
||||
SERVICE_CHANGE_STATUS_MAINTENANCE = 1,
|
||||
SERVICE_CHANGE_STATUS_OUTOFSERVICE = 2
|
||||
} service_change_status_t;
|
||||
|
||||
#ifndef FTMOD_LIBPRI_H
|
||||
#define FTMOD_LIBPRI_H
|
||||
@@ -69,6 +74,7 @@ struct ftdm_libpri_data {
|
||||
int overlap; /*!< Overlap dial flags */
|
||||
unsigned int layer1;
|
||||
unsigned int ton;
|
||||
unsigned int service_message_support;
|
||||
|
||||
lpwrap_pri_t spri;
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -69,6 +69,8 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
|
||||
set_calling_subaddr(ftdmchan, &conEvnt.cgPtySad);
|
||||
set_redir_num(ftdmchan, &conEvnt.redirNmb);
|
||||
set_calling_name(ftdmchan, &conEvnt);
|
||||
|
||||
/* set_facility_ie will overwrite Calling Name for NI-2 if user specifies custom Facility IE */
|
||||
set_facility_ie(ftdmchan, &conEvnt.facilityStr);
|
||||
set_prog_ind_ie(ftdmchan, &conEvnt.progInd, prog_ind);
|
||||
|
||||
|
||||
@@ -719,12 +719,19 @@ ftdm_status_t set_calling_name(ftdm_channel_t *ftdmchan, ConEvnt *conEvnt)
|
||||
} else {
|
||||
switch (signal_data->switchtype) {
|
||||
case SNGISDN_SWITCH_NI2:
|
||||
/* TODO: Need to send the caller ID as a facility IE */
|
||||
|
||||
#ifdef SNGISDN_SUPPORT_CALLING_NAME_IN_FACILITY
|
||||
{
|
||||
if (signal_data->signalling == SNGISDN_SIGNALING_NET) {
|
||||
sng_isdn_encode_facility_caller_name(caller_data->cid_name, conEvnt->facilityStr.facilityStr.val, &conEvnt->facilityStr.facilityStr.len);
|
||||
conEvnt->facilityStr.eh.pres = PRSNT_NODEF;
|
||||
conEvnt->facilityStr.facilityStr.pres = PRSNT_NODEF;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case SNGISDN_SWITCH_EUROISDN:
|
||||
if (signal_data->signalling != SNGISDN_SIGNALING_NET) {
|
||||
break;
|
||||
break;
|
||||
}
|
||||
/* follow through */
|
||||
case SNGISDN_SWITCH_5ESS:
|
||||
|
||||
@@ -39,6 +39,11 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef WP_DEBUG_IO
|
||||
#define _BSD_SOURCE
|
||||
#include <syscall.h>
|
||||
#endif
|
||||
|
||||
#ifdef __sun
|
||||
#include <unistd.h>
|
||||
#include <stropts.h>
|
||||
@@ -99,6 +104,17 @@ static struct {
|
||||
uint32_t ring_off_ms;
|
||||
} wp_globals;
|
||||
|
||||
typedef struct {
|
||||
sangoma_wait_obj_t *waitobj;
|
||||
#ifdef WP_DEBUG_IO
|
||||
/* record the last reader threads */
|
||||
pid_t readers[10];
|
||||
int rindex;
|
||||
ftdm_time_t last_read;
|
||||
#endif
|
||||
} wp_channel_t;
|
||||
#define WP_GET_WAITABLE(fchan) ((wp_channel_t *)((fchan)->io_data))->waitobj
|
||||
|
||||
/* a bunch of this stuff should go into the wanpipe_tdm_api_iface.h */
|
||||
|
||||
FIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event);
|
||||
@@ -123,7 +139,7 @@ static __inline__ int tdmv_api_wait_socket(ftdm_channel_t *ftdmchan, int timeout
|
||||
int err;
|
||||
uint32_t inflags = *flags;
|
||||
uint32_t outflags = 0;
|
||||
sangoma_wait_obj_t *sangoma_wait_obj = ftdmchan->io_data;
|
||||
sangoma_wait_obj_t *sangoma_wait_obj = WP_GET_WAITABLE(ftdmchan);
|
||||
|
||||
if (timeout == -1) {
|
||||
timeout = SANGOMA_WAIT_INFINITE;
|
||||
@@ -254,9 +270,13 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start
|
||||
}
|
||||
|
||||
if (ftdm_span_add_channel(span, sockfd, type, &chan) == FTDM_SUCCESS) {
|
||||
wp_channel_t *wpchan = NULL;
|
||||
wanpipe_tdm_api_t tdm_api;
|
||||
memset(&tdm_api, 0, sizeof(tdm_api));
|
||||
#ifdef LIBSANGOMA_VERSION
|
||||
wpchan = ftdm_calloc(1, sizeof(*wpchan));
|
||||
ftdm_assert(wpchan != NULL, "wpchan alloc failed\n");
|
||||
chan->io_data = wpchan;
|
||||
/* we need SANGOMA_DEVICE_WAIT_OBJ_SIG and not SANGOMA_DEVICE_WAIT_OBJ alone because we need to call
|
||||
* sangoma_wait_obj_sig to wake up any I/O waiters when closing the channel (typically on ftdm shutdown)
|
||||
* this adds an extra pair of file descriptors to the waitable object
|
||||
@@ -266,7 +286,7 @@ static unsigned wp_open_range(ftdm_span_t *span, unsigned spanno, unsigned start
|
||||
ftdm_log(FTDM_LOG_ERROR, "failure create waitable object for s%dc%d\n", spanno, x);
|
||||
continue;
|
||||
}
|
||||
chan->io_data = sangoma_wait_obj;
|
||||
WP_GET_WAITABLE(chan) = sangoma_wait_obj;
|
||||
#endif
|
||||
|
||||
chan->physical_span_id = spanno;
|
||||
@@ -580,9 +600,16 @@ static FIO_OPEN_FUNCTION(wanpipe_open)
|
||||
static FIO_CLOSE_FUNCTION(wanpipe_close)
|
||||
{
|
||||
#ifdef LIBSANGOMA_VERSION
|
||||
sangoma_wait_obj_t *waitobj = ftdmchan->io_data;
|
||||
sangoma_wait_obj_t *waitobj = WP_GET_WAITABLE(ftdmchan);
|
||||
/* kick any I/O waiters */
|
||||
sangoma_wait_obj_signal(waitobj);
|
||||
#ifdef WP_DEBUG_IO
|
||||
{
|
||||
wp_channel_t *wchan = ftdmchan->io_data;
|
||||
memset(wchan->readers, 0, sizeof(wchan->readers));
|
||||
wchan->rindex = 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
@@ -950,10 +977,44 @@ static void wanpipe_read_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_rx_hdr_t *rx
|
||||
static FIO_READ_FUNCTION(wanpipe_read)
|
||||
{
|
||||
int rx_len = 0;
|
||||
int rq_len = (int)*datalen;
|
||||
wp_tdm_api_rx_hdr_t hdrframe;
|
||||
|
||||
memset(&hdrframe, 0, sizeof(hdrframe));
|
||||
#ifdef WP_DEBUG_IO
|
||||
wp_channel_t *wchan = ftdmchan->io_data;
|
||||
ftdm_time_t time_diff = 0;
|
||||
pid_t previous_thread = 1;
|
||||
pid_t current_thread = 0;
|
||||
int previous_thread_index = 0;
|
||||
|
||||
previous_thread_index = wchan->rindex == 0 ? (ftdm_array_len(wchan->readers) - 1) : wchan->rindex - 1;
|
||||
previous_thread = wchan->readers[previous_thread_index];
|
||||
current_thread = syscall(SYS_gettid);
|
||||
if (current_thread && current_thread != wchan->readers[wchan->rindex]) {
|
||||
if (!wchan->readers[wchan->rindex]) {
|
||||
wchan->readers[wchan->rindex] = current_thread;
|
||||
/* first read */
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Initial reader thread is %d\n", current_thread);
|
||||
previous_thread = current_thread;
|
||||
} else {
|
||||
previous_thread = wchan->readers[wchan->rindex];
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Changed reader thread from %d to %d (rindex = %d)\n",
|
||||
previous_thread, current_thread, wchan->rindex);
|
||||
if (wchan->rindex == (ftdm_array_len(wchan->readers) - 1)) {
|
||||
wchan->rindex = 0;
|
||||
} else {
|
||||
wchan->rindex++;
|
||||
}
|
||||
wchan->readers[wchan->rindex] = current_thread;
|
||||
}
|
||||
}
|
||||
ftdm_time_t curr = ftdm_current_time_in_ms();
|
||||
if (wchan->last_read) {
|
||||
time_diff = curr - wchan->last_read;
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(&hdrframe, 0, sizeof(hdrframe));
|
||||
rx_len = sangoma_readmsg_tdm(ftdmchan->sockfd, &hdrframe, (int)sizeof(hdrframe), data, (int)*datalen, 0);
|
||||
*datalen = rx_len;
|
||||
|
||||
@@ -963,14 +1024,20 @@ static FIO_READ_FUNCTION(wanpipe_read)
|
||||
}
|
||||
|
||||
if (rx_len < 0) {
|
||||
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", strerror(errno));
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Failed to read from sangoma device: %s (%d)\n", strerror(errno), rx_len);
|
||||
#ifdef WP_DEBUG_IO
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Failed to read %d bytes from sangoma device: %s (%d) "
|
||||
"(read time diff = %llums, prev thread = %d, curr thread = %d)\n", rq_len, strerror(errno), rx_len,
|
||||
time_diff, previous_thread, current_thread);
|
||||
#else
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Failed to read %d bytes from sangoma device: %s (%d)\n", rq_len, strerror(errno), rx_len);
|
||||
#endif
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
|
||||
if (ftdm_channel_test_feature(ftdmchan, FTDM_CHANNEL_FEATURE_IO_STATS)) {
|
||||
wanpipe_read_stats(ftdmchan, &hdrframe);
|
||||
}
|
||||
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1116,7 +1183,7 @@ FIO_SPAN_POLL_EVENT_FUNCTION(wanpipe_poll_event)
|
||||
if (!ftdmchan->io_data) {
|
||||
continue; /* should never happen but happens when shutting down */
|
||||
}
|
||||
pfds[j] = ftdmchan->io_data;
|
||||
pfds[j] = WP_GET_WAITABLE(ftdmchan);
|
||||
inflags[j] = chan_events;
|
||||
#else
|
||||
memset(&pfds[j], 0, sizeof(pfds[j]));
|
||||
@@ -1578,10 +1645,10 @@ static FIO_CHANNEL_DESTROY_FUNCTION(wanpipe_channel_destroy)
|
||||
{
|
||||
#ifdef LIBSANGOMA_VERSION
|
||||
if (ftdmchan->io_data) {
|
||||
sangoma_wait_obj_t *sangoma_wait_obj;
|
||||
sangoma_wait_obj = ftdmchan->io_data;
|
||||
ftdmchan->io_data = NULL;
|
||||
sangoma_wait_obj_t *sangoma_wait_obj = WP_GET_WAITABLE(ftdmchan);
|
||||
sangoma_wait_obj_delete(&sangoma_wait_obj);
|
||||
ftdm_safe_free(ftdmchan->io_data);
|
||||
ftdmchan->io_data = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1612,7 +1679,8 @@ static FIO_CHANNEL_DESTROY_FUNCTION(wanpipe_channel_destroy)
|
||||
*/
|
||||
static FIO_IO_LOAD_FUNCTION(wanpipe_init)
|
||||
{
|
||||
assert(fio != NULL);
|
||||
ftdm_assert(fio != NULL, "fio should not be null\n");
|
||||
|
||||
memset(&wanpipe_interface, 0, sizeof(wanpipe_interface));
|
||||
|
||||
wp_globals.codec_ms = 20;
|
||||
|
||||
@@ -29,6 +29,12 @@
|
||||
* 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.
|
||||
*
|
||||
* Contributors:
|
||||
*
|
||||
* Moises Silva <moy@sangoma.com>
|
||||
* W McRoberts <fs@whmcr.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "private/ftdm_core.h"
|
||||
@@ -94,6 +100,7 @@ struct ioctl_codes {
|
||||
ioctlcmd ECHOTRAIN;
|
||||
ioctlcmd SETTXBITS;
|
||||
ioctlcmd GETRXBITS;
|
||||
ioctlcmd SETPOLARITY;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -169,7 +176,8 @@ static struct ioctl_codes dahdi_ioctl_codes = {
|
||||
.GETCONFMUTE = DAHDI_GETCONFMUTE,
|
||||
.ECHOTRAIN = DAHDI_ECHOTRAIN,
|
||||
.SETTXBITS = DAHDI_SETTXBITS,
|
||||
.GETRXBITS = DAHDI_GETRXBITS
|
||||
.GETRXBITS = DAHDI_GETRXBITS,
|
||||
.SETPOLARITY = DAHDI_SETPOLARITY
|
||||
};
|
||||
|
||||
#define ZT_INVALID_SOCKET -1
|
||||
@@ -826,6 +834,15 @@ static FIO_COMMAND_FUNCTION(zt_command)
|
||||
err = ioctl(ftdmchan->sockfd, codes.FLUSH, &flushmode);
|
||||
}
|
||||
break;
|
||||
case FTDM_COMMAND_SET_POLARITY:
|
||||
{
|
||||
ftdm_polarity_t polarity = FTDM_COMMAND_OBJ_INT;
|
||||
err = ioctl(ftdmchan->sockfd, codes.SETPOLARITY, polarity);
|
||||
if (!err) {
|
||||
ftdmchan->polarity = polarity;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FTDM_COMMAND_FLUSH_RX_BUFFERS:
|
||||
{
|
||||
int flushmode = ZT_FLUSH_READ;
|
||||
@@ -1088,6 +1105,12 @@ static __inline__ ftdm_status_t zt_channel_process_event(ftdm_channel_t *fchan,
|
||||
*event_id = FTDM_OOB_NOOP; /* What else could we do? */
|
||||
}
|
||||
break;
|
||||
case ZT_EVENT_POLARITY:
|
||||
{
|
||||
ftdm_log_chan_msg(fchan, FTDM_LOG_ERROR, "Got polarity reverse (ZT_EVENT_POLARITY)\n");
|
||||
*event_id = FTDM_OOB_POLARITY_REVERSE;
|
||||
}
|
||||
break;
|
||||
case ZT_EVENT_NONE:
|
||||
{
|
||||
ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "No event\n");
|
||||
|
||||
@@ -29,6 +29,12 @@
|
||||
* 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.
|
||||
*
|
||||
* Contributors:
|
||||
*
|
||||
* Moises Silva <moy@sangoma.com>
|
||||
* W McRoberts <fs@whmcr.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef FTDM_ZT_H
|
||||
@@ -349,6 +355,7 @@ ZT_ABIT = 8
|
||||
#define DAHDI_SETTXBITS _IOW (DAHDI_CODE, 43, int)
|
||||
#define DAHDI_GETRXBITS _IOR (DAHDI_CODE, 43, int)
|
||||
|
||||
#define DAHDI_SETPOLARITY _IOW (DAHDI_CODE, 92, int) /* Polarity setting for FXO lines */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -926,20 +926,20 @@ typedef enum {
|
||||
/*! \brief IO statistics */
|
||||
typedef struct {
|
||||
struct {
|
||||
uint64_t packets;
|
||||
uint32_t errors;
|
||||
uint16_t flags;
|
||||
uint8_t queue_size; /*!< max queue size configured */
|
||||
uint8_t queue_len; /*!< Current number of elements in queue */
|
||||
uint64_t packets;
|
||||
} rx;
|
||||
|
||||
struct {
|
||||
uint64_t idle_packets;
|
||||
uint64_t packets;
|
||||
uint32_t errors;
|
||||
uint16_t flags;
|
||||
uint8_t idle_packets;
|
||||
uint8_t queue_size; /*!< max queue size configured */
|
||||
uint8_t queue_len; /*!< Current number of elements in queue */
|
||||
uint64_t packets;
|
||||
} tx;
|
||||
} ftdm_channel_iostats_t;
|
||||
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mftilla Public License Version
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mftilla.org/MPL/
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
@@ -33,8 +33,8 @@
|
||||
* Exception:
|
||||
* The author hereby grants the use of this source code under the
|
||||
* following license if and only if the source code is distributed
|
||||
* as part of the freetdm library. Any use or distribution of this
|
||||
* source code outside the scope of the freetdm library will nullify the
|
||||
* as part of the OpenZAP or FreeTDM library. Any use or distribution of this
|
||||
* source code outside the scope of the OpenZAP or FreeTDM library will nullify the
|
||||
* following license and reinact the MPL 1.1 as stated above.
|
||||
*
|
||||
* Copyright (c) 2007, Anthony Minessale II
|
||||
|
||||
@@ -2,13 +2,60 @@
|
||||
* libteletone
|
||||
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is tone_detect.c - General telephony tone detection, and specific detection of DTMF.
|
||||
*
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Stephen Underwood <steveu@coppice.org>
|
||||
* Portions created by the Initial Developer are Copyright (C)
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* The the original interface designed by Steve Underwood was preserved to retain
|
||||
*the optimizations when considering DTMF tones though the names were changed in the interest
|
||||
* of namespace.
|
||||
*
|
||||
* Much less efficient expansion interface was added to allow for the detection of
|
||||
* a single arbitrary tone combination which may also exceed 2 simultaneous tones.
|
||||
* (controlled by compile time constant TELETONE_MAX_TONES)
|
||||
*
|
||||
* Copyright (C) 2006 Anthony Minessale II <anthm@freeswitch.org>
|
||||
*
|
||||
*
|
||||
* libteletone_detect.c Tone Detection Code
|
||||
*
|
||||
*
|
||||
*********************************************************************************
|
||||
*
|
||||
* Derived from tone_detect.h - General telephony tone detection, and specific
|
||||
* detection of DTMF.
|
||||
*
|
||||
* Copyright (C) 2001 Steve Underwood <steveu@coppice.org>
|
||||
*
|
||||
* Despite my general liking of the GPL, I place this code in the
|
||||
* public domain for the benefit of all mankind - even the slimy
|
||||
* ones who might try to proprietize my work and use it to my
|
||||
* detriment.
|
||||
*
|
||||
*
|
||||
* Exception:
|
||||
* The author hereby grants the use of this source code under the
|
||||
* following license if and only if the source code is distributed
|
||||
* as part of the freetdm library. Any use or distribution of this
|
||||
* source code outside the scope of the freetdm library will nullify the
|
||||
* as part of the OpenZAP or FreeTDM library. Any use or distribution of this
|
||||
* source code outside the scope of the OpenZAP or FreeTDM library will nullify the
|
||||
* following license and reinact the MPL 1.1 as stated above.
|
||||
*
|
||||
* Copyright (c) 2007, Anthony Minessale II
|
||||
@@ -41,20 +88,6 @@
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************************
|
||||
*
|
||||
* Derived from tone_detect.h - General telephony tone detection, and specific
|
||||
* detection of DTMF.
|
||||
*
|
||||
* Copyright (C) 2001 Steve Underwood <steveu@coppice.org>
|
||||
*
|
||||
* Despite my general liking of the GPL, I place this code in the
|
||||
* public domain for the benefit of all mankind - even the slimy
|
||||
* ones who might try to proprietize my work and use it to my
|
||||
* detriment.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LIBTELETONE_DETECT_H
|
||||
@@ -101,6 +134,14 @@ extern "C" {
|
||||
#define BLOCK_LEN 102
|
||||
#define M_TWO_PI 2.0*M_PI
|
||||
|
||||
typedef enum {
|
||||
TT_HIT_NONE = 0,
|
||||
TT_HIT_BEGIN = 1,
|
||||
TT_HIT_MIDDLE = 2,
|
||||
TT_HIT_END = 3
|
||||
} teletone_hit_type_t;
|
||||
|
||||
|
||||
/*! \brief A continer for the elements of a Goertzel Algorithm (The names are from his formula) */
|
||||
typedef struct {
|
||||
float v2;
|
||||
@@ -114,16 +155,19 @@ extern "C" {
|
||||
int hit2;
|
||||
int hit3;
|
||||
int hit4;
|
||||
int mhit;
|
||||
int dur;
|
||||
int zc;
|
||||
|
||||
|
||||
teletone_goertzel_state_t row_out[GRID_FACTOR];
|
||||
teletone_goertzel_state_t col_out[GRID_FACTOR];
|
||||
teletone_goertzel_state_t row_out2nd[GRID_FACTOR];
|
||||
teletone_goertzel_state_t col_out2nd[GRID_FACTOR];
|
||||
float energy;
|
||||
float lenergy;
|
||||
|
||||
int current_sample;
|
||||
char digits[TELETONE_MAX_DTMF_DIGITS + 1];
|
||||
char digit;
|
||||
int current_digits;
|
||||
int detected_digits;
|
||||
int lost_digits;
|
||||
@@ -196,7 +240,7 @@ TELETONE_API(void) teletone_dtmf_detect_init (teletone_dtmf_detect_state_t *dtmf
|
||||
\param samples the number of samples present in sample_buffer
|
||||
\return true when DTMF was detected or false when it is not
|
||||
*/
|
||||
TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state,
|
||||
TELETONE_API(teletone_hit_type_t) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state,
|
||||
int16_t sample_buffer[],
|
||||
int samples);
|
||||
/*!
|
||||
@@ -206,9 +250,7 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec
|
||||
\param max the maximum length of buf
|
||||
\return the number of characters written to buf
|
||||
*/
|
||||
TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state,
|
||||
char *buf,
|
||||
int max);
|
||||
TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, char *buf, unsigned int *dur);
|
||||
|
||||
/*!
|
||||
\brief Step through the Goertzel Algorithm for each sample in a buffer
|
||||
|
||||
@@ -2,6 +2,41 @@
|
||||
* libteletone
|
||||
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libteletone
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Anthony Minessale II <anthm@freeswitch.org>
|
||||
* Portions created by the Initial Developer are Copyright (C)
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Anthony Minessale II <anthm@freeswitch.org>
|
||||
*
|
||||
*
|
||||
* libteletone.h -- Tone Generator
|
||||
*
|
||||
*
|
||||
*
|
||||
* Exception:
|
||||
* The author hereby grants the use of this source code under the
|
||||
* following license if and only if the source code is distributed
|
||||
* as part of the OpenZAP or FreeTDM library. Any use or distribution of this
|
||||
* source code outside the scope of the OpenZAP or FreeTDM library will nullify the
|
||||
* following license and reinact the MPL 1.1 as stated above.
|
||||
*
|
||||
* Copyright (c) 2007, Anthony Minessale II
|
||||
* All rights reserved.
|
||||
*
|
||||
|
||||
@@ -2,14 +2,62 @@
|
||||
* libteletone
|
||||
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is tone_detect.c - General telephony tone detection, and specific detection of DTMF.
|
||||
*
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Stephen Underwood <steveu@coppice.org>
|
||||
* Portions created by the Initial Developer are Copyright (C)
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* The the original interface designed by Steve Underwood was preserved to retain
|
||||
*the optimizations when considering DTMF tones though the names were changed in the interest
|
||||
* of namespace.
|
||||
*
|
||||
* Much less efficient expansion interface was added to allow for the detection of
|
||||
* a single arbitrary tone combination which may also exceed 2 simultaneous tones.
|
||||
* (controlled by compile time constant TELETONE_MAX_TONES)
|
||||
*
|
||||
* Copyright (C) 2006 Anthony Minessale II <anthm@freeswitch.org>
|
||||
*
|
||||
*
|
||||
* libteletone_detect.c Tone Detection Code
|
||||
*
|
||||
*
|
||||
*********************************************************************************
|
||||
*
|
||||
* Derived from tone_detect.c - General telephony tone detection, and specific
|
||||
* detection of DTMF.
|
||||
*
|
||||
* Copyright (C) 2001 Steve Underwood <steveu@coppice.org>
|
||||
*
|
||||
* Despite my general liking of the GPL, I place this code in the
|
||||
* public domain for the benefit of all mankind - even the slimy
|
||||
* ones who might try to proprietize my work and use it to my
|
||||
* detriment.
|
||||
*
|
||||
*
|
||||
* Exception:
|
||||
* The author hereby grants the use of this source code under the
|
||||
* following license if and only if the source code is distributed
|
||||
* as part of the OpenZAP or FreeTDM library. Any use or distribution of this
|
||||
* source code outside the scope of the OpenZAP or FreeTDM library will nullify the
|
||||
* following license and reinact the MPL 1.1 as stated above.
|
||||
*
|
||||
* Copyright (c) 2007, Anthony Minessale II
|
||||
* All rights reserved.
|
||||
*
|
||||
@@ -40,21 +88,6 @@
|
||||
* 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.
|
||||
*
|
||||
*********************************************************************************
|
||||
*
|
||||
* Derived from tone_detect.c - General telephony tone detection, and specific
|
||||
* detection of DTMF.
|
||||
*
|
||||
* Copyright (C) 2001 Steve Underwood <steveu@coppice.org>
|
||||
*
|
||||
* Despite my general liking of the GPL, I place this code in the
|
||||
* public domain for the benefit of all mankind - even the slimy
|
||||
* ones who might try to proprietize my work and use it to my
|
||||
* detriment.
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include <libteletone_detect.h>
|
||||
@@ -67,7 +100,8 @@
|
||||
#include <time.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
#define LOW_ENG 10000000
|
||||
#define ZC 2
|
||||
static teletone_detection_descriptor_t dtmf_detect_row[GRID_FACTOR];
|
||||
static teletone_detection_descriptor_t dtmf_detect_col[GRID_FACTOR];
|
||||
static teletone_detection_descriptor_t dtmf_detect_row_2nd[GRID_FACTOR];
|
||||
@@ -132,8 +166,8 @@ TELETONE_API(void) teletone_dtmf_detect_init (teletone_dtmf_detect_state_t *dtmf
|
||||
dtmf_detect_state->current_sample = 0;
|
||||
dtmf_detect_state->detected_digits = 0;
|
||||
dtmf_detect_state->lost_digits = 0;
|
||||
dtmf_detect_state->digits[0] = '\0';
|
||||
dtmf_detect_state->mhit = 0;
|
||||
dtmf_detect_state->digit = 0;
|
||||
dtmf_detect_state->dur = 0;
|
||||
}
|
||||
|
||||
TELETONE_API(void) teletone_multi_tone_init(teletone_multi_tone_t *mt, teletone_tone_map_t *map)
|
||||
@@ -266,7 +300,7 @@ TELETONE_API(int) teletone_multi_tone_detect (teletone_multi_tone_t *mt,
|
||||
}
|
||||
|
||||
|
||||
TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state,
|
||||
TELETONE_API(teletone_hit_type_t) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state,
|
||||
int16_t sample_buffer[],
|
||||
int samples)
|
||||
{
|
||||
@@ -281,6 +315,7 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec
|
||||
int best_col;
|
||||
char hit;
|
||||
int limit;
|
||||
teletone_hit_type_t r = 0;
|
||||
|
||||
hit = 0;
|
||||
for (sample = 0; sample < samples; sample = limit) {
|
||||
@@ -317,6 +352,32 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec
|
||||
|
||||
}
|
||||
|
||||
if (dtmf_detect_state->zc > 0) {
|
||||
if (dtmf_detect_state->energy < LOW_ENG && dtmf_detect_state->lenergy < LOW_ENG) {
|
||||
if (!--dtmf_detect_state->zc) {
|
||||
/* Reinitialise the detector for the next block */
|
||||
dtmf_detect_state->hit1 = dtmf_detect_state->hit2 = 0;
|
||||
for (i = 0; i < GRID_FACTOR; i++) {
|
||||
goertzel_init (&dtmf_detect_state->row_out[i], &dtmf_detect_row[i]);
|
||||
goertzel_init (&dtmf_detect_state->col_out[i], &dtmf_detect_col[i]);
|
||||
goertzel_init (&dtmf_detect_state->row_out2nd[i], &dtmf_detect_row_2nd[i]);
|
||||
goertzel_init (&dtmf_detect_state->col_out2nd[i], &dtmf_detect_col_2nd[i]);
|
||||
}
|
||||
dtmf_detect_state->dur -= samples;
|
||||
return TT_HIT_END;
|
||||
}
|
||||
}
|
||||
|
||||
dtmf_detect_state->dur += samples;
|
||||
dtmf_detect_state->lenergy = dtmf_detect_state->energy;
|
||||
dtmf_detect_state->energy = 0.0;
|
||||
dtmf_detect_state->current_sample = 0;
|
||||
return TT_HIT_MIDDLE;
|
||||
} else if (dtmf_detect_state->digit) {
|
||||
return TT_HIT_END;
|
||||
}
|
||||
|
||||
|
||||
dtmf_detect_state->current_sample += (limit - sample);
|
||||
if (dtmf_detect_state->current_sample < BLOCK_LEN) {
|
||||
continue;
|
||||
@@ -361,58 +422,55 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec
|
||||
back to back differing digits. More importantly, it
|
||||
can work with nasty phones that give a very wobbly start
|
||||
to a digit. */
|
||||
if (hit == dtmf_detect_state->hit3 && dtmf_detect_state->hit3 != dtmf_detect_state->hit2) {
|
||||
dtmf_detect_state->mhit = hit;
|
||||
if (! r && hit == dtmf_detect_state->hit3 && dtmf_detect_state->hit3 != dtmf_detect_state->hit2) {
|
||||
dtmf_detect_state->digit_hits[(best_row << 2) + best_col]++;
|
||||
dtmf_detect_state->detected_digits++;
|
||||
if (dtmf_detect_state->current_digits < TELETONE_MAX_DTMF_DIGITS) {
|
||||
dtmf_detect_state->digits[dtmf_detect_state->current_digits++] = hit;
|
||||
dtmf_detect_state->digits[dtmf_detect_state->current_digits] = '\0';
|
||||
dtmf_detect_state->digit = hit;
|
||||
} else {
|
||||
dtmf_detect_state->lost_digits++;
|
||||
}
|
||||
else
|
||||
{
|
||||
dtmf_detect_state->lost_digits++;
|
||||
}
|
||||
|
||||
if (!dtmf_detect_state->zc) {
|
||||
dtmf_detect_state->zc = ZC;
|
||||
dtmf_detect_state->dur = 0;
|
||||
r = TT_HIT_BEGIN;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dtmf_detect_state->hit1 = dtmf_detect_state->hit2;
|
||||
dtmf_detect_state->hit2 = dtmf_detect_state->hit3;
|
||||
dtmf_detect_state->hit3 = hit;
|
||||
/* Reinitialise the detector for the next block */
|
||||
for (i = 0; i < GRID_FACTOR; i++) {
|
||||
goertzel_init (&dtmf_detect_state->row_out[i], &dtmf_detect_row[i]);
|
||||
goertzel_init (&dtmf_detect_state->col_out[i], &dtmf_detect_col[i]);
|
||||
goertzel_init (&dtmf_detect_state->row_out2nd[i], &dtmf_detect_row_2nd[i]);
|
||||
goertzel_init (&dtmf_detect_state->col_out2nd[i], &dtmf_detect_col_2nd[i]);
|
||||
}
|
||||
|
||||
dtmf_detect_state->energy = 0.0;
|
||||
dtmf_detect_state->current_sample = 0;
|
||||
|
||||
}
|
||||
if ((!dtmf_detect_state->mhit) || (dtmf_detect_state->mhit != hit)) {
|
||||
dtmf_detect_state->mhit = 0;
|
||||
return(0);
|
||||
}
|
||||
return (hit);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state,
|
||||
char *buf,
|
||||
int max)
|
||||
TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, char *buf, unsigned int *dur)
|
||||
{
|
||||
teletone_assert(dtmf_detect_state->current_digits <= TELETONE_MAX_DTMF_DIGITS);
|
||||
if (!dtmf_detect_state->digit) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (max > dtmf_detect_state->current_digits) {
|
||||
max = dtmf_detect_state->current_digits;
|
||||
*buf = dtmf_detect_state->digit;
|
||||
|
||||
*dur = dtmf_detect_state->dur;
|
||||
|
||||
if (!dtmf_detect_state->zc) {
|
||||
dtmf_detect_state->dur = 0;
|
||||
dtmf_detect_state->digit = 0;
|
||||
}
|
||||
if (max > 0) {
|
||||
memcpy (buf, dtmf_detect_state->digits, max);
|
||||
memmove (dtmf_detect_state->digits, dtmf_detect_state->digits + max, dtmf_detect_state->current_digits - max);
|
||||
dtmf_detect_state->current_digits -= max;
|
||||
}
|
||||
buf[max] = '\0';
|
||||
return max;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* For Emacs:
|
||||
|
||||
@@ -1,5 +1,41 @@
|
||||
/*
|
||||
* libteletone_generate.c -- Tone Generator
|
||||
* libteletone
|
||||
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
|
||||
*
|
||||
* Version: MPL 1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is libteletone
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Anthony Minessale II <anthm@freeswitch.org>
|
||||
* Portions created by the Initial Developer are Copyright (C)
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Anthony Minessale II <anthm@freeswitch.org>
|
||||
*
|
||||
*
|
||||
* libteletone.c -- Tone Generator
|
||||
*
|
||||
*
|
||||
*
|
||||
* Exception:
|
||||
* The author hereby grants the use of this source code under the
|
||||
* following license if and only if the source code is distributed
|
||||
* as part of the OpenZAP or FreeTDM library. Any use or distribution of this
|
||||
* source code outside the scope of the OpenZAP or FreeTDM library will nullify the
|
||||
* following license and reinact the MPL 1.1 as stated above.
|
||||
*
|
||||
* Copyright (c) 2007, Anthony Minessale II
|
||||
* All rights reserved.
|
||||
@@ -34,7 +70,6 @@
|
||||
*/
|
||||
|
||||
#include <libteletone.h>
|
||||
#include "private/ftdm_core.h"
|
||||
|
||||
#define SMAX 32767
|
||||
#define SMIN -32768
|
||||
@@ -111,7 +146,7 @@ TELETONE_API(int) teletone_init_session(teletone_generation_session_t *ts, int b
|
||||
ts->decay_step = 0;
|
||||
ts->decay_factor = 1;
|
||||
if (buflen) {
|
||||
if ((ts->buffer = ftdm_calloc(buflen, sizeof(teletone_audio_t))) == 0) {
|
||||
if ((ts->buffer = calloc(buflen, sizeof(teletone_audio_t))) == 0) {
|
||||
return -1;
|
||||
}
|
||||
ts->datalen = buflen;
|
||||
@@ -142,7 +177,7 @@ TELETONE_API(int) teletone_init_session(teletone_generation_session_t *ts, int b
|
||||
TELETONE_API(int) teletone_destroy_session(teletone_generation_session_t *ts)
|
||||
{
|
||||
if (ts->buffer) {
|
||||
ftdm_safe_free(ts->buffer);
|
||||
free(ts->buffer);
|
||||
ts->buffer = NULL;
|
||||
ts->samples = 0;
|
||||
}
|
||||
@@ -270,6 +305,19 @@ TELETONE_API(int) teletone_mux_tones(teletone_generation_session_t *ts, teletone
|
||||
return ts->samples / ts->channels;
|
||||
}
|
||||
|
||||
/* don't ask */
|
||||
static char *my_strdup (const char *s)
|
||||
{
|
||||
size_t len = strlen (s) + 1;
|
||||
void *new = malloc (len);
|
||||
|
||||
if (new == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (char *) memcpy (new, s, len);
|
||||
}
|
||||
|
||||
TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cmd)
|
||||
{
|
||||
char *data = NULL, *cur = NULL, *end = NULL;
|
||||
@@ -280,7 +328,7 @@ TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cm
|
||||
}
|
||||
|
||||
do {
|
||||
if (!(data = ftdm_strdup(cmd))) {
|
||||
if (!(data = my_strdup(cmd))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -363,6 +411,9 @@ TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cm
|
||||
*e++ = '\0';
|
||||
}
|
||||
do {
|
||||
if (!p) {
|
||||
break;
|
||||
}
|
||||
if ((next = strchr(p, ',')) != 0) {
|
||||
*next++ = '\0';
|
||||
}
|
||||
@@ -427,7 +478,7 @@ TELETONE_API(int) teletone_run(teletone_generation_session_t *ts, const char *cm
|
||||
}
|
||||
}
|
||||
bottom:
|
||||
ftdm_safe_free(data);
|
||||
free(data);
|
||||
data = NULL;
|
||||
if (ts->LOOPS > 0) {
|
||||
ts->LOOPS--;
|
||||
|
||||
Vendored
-1407
File diff suppressed because it is too large.
Load diff
Vendored
-1504
File diff suppressed because it is too large.
Load diff
Vendored
-17354
File diff suppressed because it is too large.
Load diff
Vendored
+1
-6
@@ -673,12 +673,7 @@ CFLAGS
|
||||
LDFLAGS
|
||||
LIBS
|
||||
CPPFLAGS
|
||||
CPP
|
||||
CPPFLAGS
|
||||
CC
|
||||
LDFLAGS
|
||||
LIBS
|
||||
CPPFLAGS'
|
||||
CPP'
|
||||
|
||||
|
||||
# Initialize some variables set by options.
|
||||
|
||||
@@ -467,4 +467,10 @@ size_t strlcpy(char *dst, const char *src, size_t siz);
|
||||
#ifndef HAVE_STRTOUL
|
||||
#define strtoul (unsigned long)strtol
|
||||
#endif
|
||||
#ifdef HAVE_B64_PTON
|
||||
#define ldns_b64_pton b64_pton
|
||||
#endif
|
||||
#ifdef HAVE_B64_NTOP
|
||||
#define ldns_b64_ntop b64_ntop
|
||||
#endif
|
||||
|
||||
-9687
File diff suppressed because it is too large.
Load diff
@@ -33,8 +33,8 @@
|
||||
* Exception:
|
||||
* The author hereby grants the use of this source code under the
|
||||
* following license if and only if the source code is distributed
|
||||
* as part of the openzap library. Any use or distribution of this
|
||||
* source code outside the scope of the openzap library will nullify the
|
||||
* as part of the OpenZAP or FreeTDM library. Any use or distribution of this
|
||||
* source code outside the scope of the OpenZAP or FreeTDM library will nullify the
|
||||
* following license and reinact the MPL 1.1 as stated above.
|
||||
*
|
||||
* Copyright (c) 2007, Anthony Minessale II
|
||||
|
||||
@@ -54,8 +54,8 @@
|
||||
* Exception:
|
||||
* The author hereby grants the use of this source code under the
|
||||
* following license if and only if the source code is distributed
|
||||
* as part of the openzap library. Any use or distribution of this
|
||||
* source code outside the scope of the openzap library will nullify the
|
||||
* as part of the OpenZAP or FreeTDM library. Any use or distribution of this
|
||||
* source code outside the scope of the OpenZAP or FreeTDM library will nullify the
|
||||
* following license and reinact the MPL 1.1 as stated above.
|
||||
*
|
||||
* Copyright (c) 2007, Anthony Minessale II
|
||||
@@ -100,7 +100,8 @@
|
||||
#include <time.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
#define LOW_ENG 10000000
|
||||
#define ZC 2
|
||||
static teletone_detection_descriptor_t dtmf_detect_row[GRID_FACTOR];
|
||||
static teletone_detection_descriptor_t dtmf_detect_col[GRID_FACTOR];
|
||||
static teletone_detection_descriptor_t dtmf_detect_row_2nd[GRID_FACTOR];
|
||||
@@ -165,8 +166,8 @@ TELETONE_API(void) teletone_dtmf_detect_init (teletone_dtmf_detect_state_t *dtmf
|
||||
dtmf_detect_state->current_sample = 0;
|
||||
dtmf_detect_state->detected_digits = 0;
|
||||
dtmf_detect_state->lost_digits = 0;
|
||||
dtmf_detect_state->digits[0] = '\0';
|
||||
dtmf_detect_state->mhit = 0;
|
||||
dtmf_detect_state->digit = 0;
|
||||
dtmf_detect_state->dur = 0;
|
||||
}
|
||||
|
||||
TELETONE_API(void) teletone_multi_tone_init(teletone_multi_tone_t *mt, teletone_tone_map_t *map)
|
||||
@@ -299,7 +300,7 @@ TELETONE_API(int) teletone_multi_tone_detect (teletone_multi_tone_t *mt,
|
||||
}
|
||||
|
||||
|
||||
TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state,
|
||||
TELETONE_API(teletone_hit_type_t) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state,
|
||||
int16_t sample_buffer[],
|
||||
int samples)
|
||||
{
|
||||
@@ -314,6 +315,7 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec
|
||||
int best_col;
|
||||
char hit;
|
||||
int limit;
|
||||
teletone_hit_type_t r = 0;
|
||||
|
||||
hit = 0;
|
||||
for (sample = 0; sample < samples; sample = limit) {
|
||||
@@ -350,6 +352,32 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec
|
||||
|
||||
}
|
||||
|
||||
if (dtmf_detect_state->zc > 0) {
|
||||
if (dtmf_detect_state->energy < LOW_ENG && dtmf_detect_state->lenergy < LOW_ENG) {
|
||||
if (!--dtmf_detect_state->zc) {
|
||||
/* Reinitialise the detector for the next block */
|
||||
dtmf_detect_state->hit1 = dtmf_detect_state->hit2 = 0;
|
||||
for (i = 0; i < GRID_FACTOR; i++) {
|
||||
goertzel_init (&dtmf_detect_state->row_out[i], &dtmf_detect_row[i]);
|
||||
goertzel_init (&dtmf_detect_state->col_out[i], &dtmf_detect_col[i]);
|
||||
goertzel_init (&dtmf_detect_state->row_out2nd[i], &dtmf_detect_row_2nd[i]);
|
||||
goertzel_init (&dtmf_detect_state->col_out2nd[i], &dtmf_detect_col_2nd[i]);
|
||||
}
|
||||
dtmf_detect_state->dur -= samples;
|
||||
return TT_HIT_END;
|
||||
}
|
||||
}
|
||||
|
||||
dtmf_detect_state->dur += samples;
|
||||
dtmf_detect_state->lenergy = dtmf_detect_state->energy;
|
||||
dtmf_detect_state->energy = 0.0;
|
||||
dtmf_detect_state->current_sample = 0;
|
||||
return TT_HIT_MIDDLE;
|
||||
} else if (dtmf_detect_state->digit) {
|
||||
return TT_HIT_END;
|
||||
}
|
||||
|
||||
|
||||
dtmf_detect_state->current_sample += (limit - sample);
|
||||
if (dtmf_detect_state->current_sample < BLOCK_LEN) {
|
||||
continue;
|
||||
@@ -394,58 +422,55 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec
|
||||
back to back differing digits. More importantly, it
|
||||
can work with nasty phones that give a very wobbly start
|
||||
to a digit. */
|
||||
if (hit == dtmf_detect_state->hit3 && dtmf_detect_state->hit3 != dtmf_detect_state->hit2) {
|
||||
dtmf_detect_state->mhit = hit;
|
||||
if (! r && hit == dtmf_detect_state->hit3 && dtmf_detect_state->hit3 != dtmf_detect_state->hit2) {
|
||||
dtmf_detect_state->digit_hits[(best_row << 2) + best_col]++;
|
||||
dtmf_detect_state->detected_digits++;
|
||||
if (dtmf_detect_state->current_digits < TELETONE_MAX_DTMF_DIGITS) {
|
||||
dtmf_detect_state->digits[dtmf_detect_state->current_digits++] = hit;
|
||||
dtmf_detect_state->digits[dtmf_detect_state->current_digits] = '\0';
|
||||
dtmf_detect_state->digit = hit;
|
||||
} else {
|
||||
dtmf_detect_state->lost_digits++;
|
||||
}
|
||||
else
|
||||
{
|
||||
dtmf_detect_state->lost_digits++;
|
||||
}
|
||||
|
||||
if (!dtmf_detect_state->zc) {
|
||||
dtmf_detect_state->zc = ZC;
|
||||
dtmf_detect_state->dur = 0;
|
||||
r = TT_HIT_BEGIN;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dtmf_detect_state->hit1 = dtmf_detect_state->hit2;
|
||||
dtmf_detect_state->hit2 = dtmf_detect_state->hit3;
|
||||
dtmf_detect_state->hit3 = hit;
|
||||
/* Reinitialise the detector for the next block */
|
||||
for (i = 0; i < GRID_FACTOR; i++) {
|
||||
goertzel_init (&dtmf_detect_state->row_out[i], &dtmf_detect_row[i]);
|
||||
goertzel_init (&dtmf_detect_state->col_out[i], &dtmf_detect_col[i]);
|
||||
goertzel_init (&dtmf_detect_state->row_out2nd[i], &dtmf_detect_row_2nd[i]);
|
||||
goertzel_init (&dtmf_detect_state->col_out2nd[i], &dtmf_detect_col_2nd[i]);
|
||||
}
|
||||
|
||||
dtmf_detect_state->energy = 0.0;
|
||||
dtmf_detect_state->current_sample = 0;
|
||||
|
||||
}
|
||||
if ((!dtmf_detect_state->mhit) || (dtmf_detect_state->mhit != hit)) {
|
||||
dtmf_detect_state->mhit = 0;
|
||||
return(0);
|
||||
}
|
||||
return (hit);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state,
|
||||
char *buf,
|
||||
int max)
|
||||
TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, char *buf, unsigned int *dur)
|
||||
{
|
||||
teletone_assert(dtmf_detect_state->current_digits <= TELETONE_MAX_DTMF_DIGITS);
|
||||
if (!dtmf_detect_state->digit) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (max > dtmf_detect_state->current_digits) {
|
||||
max = dtmf_detect_state->current_digits;
|
||||
*buf = dtmf_detect_state->digit;
|
||||
|
||||
*dur = dtmf_detect_state->dur;
|
||||
|
||||
if (!dtmf_detect_state->zc) {
|
||||
dtmf_detect_state->dur = 0;
|
||||
dtmf_detect_state->digit = 0;
|
||||
}
|
||||
if (max > 0) {
|
||||
memcpy (buf, dtmf_detect_state->digits, max);
|
||||
memmove (dtmf_detect_state->digits, dtmf_detect_state->digits + max, dtmf_detect_state->current_digits - max);
|
||||
dtmf_detect_state->current_digits -= max;
|
||||
}
|
||||
buf[max] = '\0';
|
||||
return max;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* For Emacs:
|
||||
|
||||
@@ -54,8 +54,8 @@
|
||||
* Exception:
|
||||
* The author hereby grants the use of this source code under the
|
||||
* following license if and only if the source code is distributed
|
||||
* as part of the openzap library. Any use or distribution of this
|
||||
* source code outside the scope of the openzap library will nullify the
|
||||
* as part of the OpenZAP or FreeTDM library. Any use or distribution of this
|
||||
* source code outside the scope of the OpenZAP or FreeTDM library will nullify the
|
||||
* following license and reinact the MPL 1.1 as stated above.
|
||||
*
|
||||
* Copyright (c) 2007, Anthony Minessale II
|
||||
@@ -134,6 +134,14 @@ extern "C" {
|
||||
#define BLOCK_LEN 102
|
||||
#define M_TWO_PI 2.0*M_PI
|
||||
|
||||
typedef enum {
|
||||
TT_HIT_NONE = 0,
|
||||
TT_HIT_BEGIN = 1,
|
||||
TT_HIT_MIDDLE = 2,
|
||||
TT_HIT_END = 3
|
||||
} teletone_hit_type_t;
|
||||
|
||||
|
||||
/*! \brief A continer for the elements of a Goertzel Algorithm (The names are from his formula) */
|
||||
typedef struct {
|
||||
float v2;
|
||||
@@ -147,16 +155,19 @@ extern "C" {
|
||||
int hit2;
|
||||
int hit3;
|
||||
int hit4;
|
||||
int mhit;
|
||||
int dur;
|
||||
int zc;
|
||||
|
||||
|
||||
teletone_goertzel_state_t row_out[GRID_FACTOR];
|
||||
teletone_goertzel_state_t col_out[GRID_FACTOR];
|
||||
teletone_goertzel_state_t row_out2nd[GRID_FACTOR];
|
||||
teletone_goertzel_state_t col_out2nd[GRID_FACTOR];
|
||||
float energy;
|
||||
float lenergy;
|
||||
|
||||
int current_sample;
|
||||
char digits[TELETONE_MAX_DTMF_DIGITS + 1];
|
||||
char digit;
|
||||
int current_digits;
|
||||
int detected_digits;
|
||||
int lost_digits;
|
||||
@@ -229,7 +240,7 @@ TELETONE_API(void) teletone_dtmf_detect_init (teletone_dtmf_detect_state_t *dtmf
|
||||
\param samples the number of samples present in sample_buffer
|
||||
\return true when DTMF was detected or false when it is not
|
||||
*/
|
||||
TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state,
|
||||
TELETONE_API(teletone_hit_type_t) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detect_state,
|
||||
int16_t sample_buffer[],
|
||||
int samples);
|
||||
/*!
|
||||
@@ -239,9 +250,7 @@ TELETONE_API(int) teletone_dtmf_detect (teletone_dtmf_detect_state_t *dtmf_detec
|
||||
\param max the maximum length of buf
|
||||
\return the number of characters written to buf
|
||||
*/
|
||||
TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state,
|
||||
char *buf,
|
||||
int max);
|
||||
TELETONE_API(int) teletone_dtmf_get (teletone_dtmf_detect_state_t *dtmf_detect_state, char *buf, unsigned int *dur);
|
||||
|
||||
/*!
|
||||
\brief Step through the Goertzel Algorithm for each sample in a buffer
|
||||
|
||||
@@ -33,8 +33,8 @@
|
||||
* Exception:
|
||||
* The author hereby grants the use of this source code under the
|
||||
* following license if and only if the source code is distributed
|
||||
* as part of the openzap library. Any use or distribution of this
|
||||
* source code outside the scope of the openzap library will nullify the
|
||||
* as part of the OpenZAP or FreeTDM library. Any use or distribution of this
|
||||
* source code outside the scope of the OpenZAP or FreeTDM library will nullify the
|
||||
* following license and reinact the MPL 1.1 as stated above.
|
||||
*
|
||||
* Copyright (c) 2007, Anthony Minessale II
|
||||
|
||||
@@ -33,8 +33,8 @@
|
||||
* Exception:
|
||||
* The author hereby grants the use of this source code under the
|
||||
* following license if and only if the source code is distributed
|
||||
* as part of the openzap library. Any use or distribution of this
|
||||
* source code outside the scope of the openzap library will nullify the
|
||||
* as part of the OpenZAP or FreeTDM library. Any use or distribution of this
|
||||
* source code outside the scope of the OpenZAP or FreeTDM library will nullify the
|
||||
* following license and reinact the MPL 1.1 as stated above.
|
||||
*
|
||||
* Copyright (c) 2007, Anthony Minessale II
|
||||
|
||||
@@ -107,7 +107,10 @@ case "$host" in
|
||||
;;
|
||||
esac
|
||||
|
||||
DEFAULT_INCLUDES="-I. -I./src/include -I$(srcdir)"
|
||||
|
||||
AC_SUBST(SOLINK)
|
||||
AC_SUBST(DEFAULT_INCLUDES)
|
||||
AC_SUBST(DYNAMIC_LIB_EXTEN)
|
||||
|
||||
AC_CHECK_LIB([dl], [dlopen])
|
||||
|
||||
+37
-41
@@ -1,5 +1,4 @@
|
||||
|
||||
AM_CFLAGS = -Isrc -Iinterface -fPIC -Wall -O3
|
||||
AM_CFLAGS = -Isrc -Iinterface -fPIC -O3
|
||||
AUTOMAKE_OPTS = gnu
|
||||
NAME = libSKP_SILK_SDK
|
||||
AM_CPPFLAGS = $(AM_CFLAGS)
|
||||
@@ -15,34 +14,32 @@ test/SignalCompare.vcproj
|
||||
|
||||
lib_LTLIBRARIES = libSKP_SILK_SDK.la
|
||||
libSKP_SILK_SDK_la_SOURCES = src/SKP_Silk_A2NLSF.c \
|
||||
src/SKP_Silk_allpass_int.c \
|
||||
src/SKP_Silk_ana_filt_bank_1.c \
|
||||
src/SKP_Silk_apply_sine_window.c \
|
||||
src/SKP_Silk_apply_sine_window_new.c \
|
||||
src/SKP_Silk_array_maxabs.c \
|
||||
src/SKP_Silk_autocorr.c \
|
||||
src/SKP_Silk_biquad_alt.c \
|
||||
src/SKP_Silk_biquad.c \
|
||||
src/SKP_Silk_biquad_alt.c \
|
||||
src/SKP_Silk_burg_modified.c \
|
||||
src/SKP_Silk_bwexpander_32.c \
|
||||
src/SKP_Silk_bwexpander.c \
|
||||
src/SKP_Silk_bwexpander_32.c \
|
||||
src/SKP_Silk_CNG.c \
|
||||
src/SKP_Silk_code_signs.c \
|
||||
src/SKP_Silk_control_audio_bandwidth.c \
|
||||
src/SKP_Silk_control_codec_FIX.c \
|
||||
src/SKP_Silk_corrMatrix_FIX.c \
|
||||
src/SKP_Silk_create_init_destroy.c \
|
||||
src/SKP_Silk_dec_API.c \
|
||||
src/SKP_Silk_decode_core.c \
|
||||
src/SKP_Silk_decode_frame.c \
|
||||
src/SKP_Silk_decode_indices_v4.c \
|
||||
src/SKP_Silk_decode_parameters.c \
|
||||
src/SKP_Silk_decode_parameters_v4.c \
|
||||
src/SKP_Silk_decode_pitch.c \
|
||||
src/SKP_Silk_decode_pulses.c \
|
||||
src/SKP_Silk_decoder_set_fs.c \
|
||||
src/SKP_Silk_detect_SWB_input.c \
|
||||
src/SKP_Silk_enc_API.c \
|
||||
src/SKP_Silk_encode_frame_FIX.c \
|
||||
src/SKP_Silk_encode_parameters.c \
|
||||
src/SKP_Silk_encode_parameters_v4.c \
|
||||
src/SKP_Silk_encode_pulses.c \
|
||||
src/SKP_Silk_find_LPC_FIX.c \
|
||||
src/SKP_Silk_find_LTP_FIX.c \
|
||||
@@ -56,78 +53,75 @@ src/SKP_Silk_interpolate.c \
|
||||
src/SKP_Silk_k2a.c \
|
||||
src/SKP_Silk_k2a_Q16.c \
|
||||
src/SKP_Silk_LBRR_reset.c \
|
||||
src/SKP_Silk_lin2log.c \
|
||||
src/SKP_Silk_log2lin.c \
|
||||
src/SKP_Silk_lowpass_int.c \
|
||||
src/SKP_Silk_lowpass_short.c \
|
||||
src/SKP_Silk_LPC_inv_pred_gain.c \
|
||||
src/SKP_Silk_LPC_stabilize.c \
|
||||
src/SKP_Silk_LPC_synthesis_filter.c \
|
||||
src/SKP_Silk_LPC_synthesis_order16.c \
|
||||
src/SKP_Silk_LP_variable_cutoff.c \
|
||||
src/SKP_Silk_LSF_cos_table.c \
|
||||
src/SKP_Silk_LTP_analysis_filter_FIX.c \
|
||||
src/SKP_Silk_LTP_scale_ctrl_FIX.c \
|
||||
src/SKP_Silk_lin2log.c \
|
||||
src/SKP_Silk_log2lin.c \
|
||||
src/SKP_Silk_MA.c \
|
||||
src/SKP_Silk_NLSF2A.c \
|
||||
src/SKP_Silk_NLSF2A_stable.c \
|
||||
src/SKP_Silk_NLSF_MSVQ_decode.c \
|
||||
src/SKP_Silk_NLSF_MSVQ_encode_FIX.c \
|
||||
src/SKP_Silk_NLSF_stabilize.c \
|
||||
src/SKP_Silk_NLSF_VQ_rate_distortion_FIX.c \
|
||||
src/SKP_Silk_NLSF_VQ_sum_error_FIX.c \
|
||||
src/SKP_Silk_NLSF_VQ_weights_laroia.c \
|
||||
src/SKP_Silk_noise_shape_analysis_FIX.c \
|
||||
src/SKP_Silk_NLSF_stabilize.c \
|
||||
src/SKP_Silk_NSQ.c \
|
||||
src/SKP_Silk_NSQ_del_dec.c \
|
||||
src/SKP_Silk_noise_shape_analysis_FIX.c \
|
||||
src/SKP_Silk_PLC.c \
|
||||
src/SKP_Silk_pitch_analysis_core.c \
|
||||
src/SKP_Silk_pitch_est_tables.c \
|
||||
src/SKP_Silk_PLC.c \
|
||||
src/SKP_Silk_prefilter_FIX.c \
|
||||
src/SKP_Silk_process_gains_FIX.c \
|
||||
src/SKP_Silk_process_NLSFs_FIX.c \
|
||||
src/SKP_Silk_pulses_to_bytes.c \
|
||||
src/SKP_Silk_process_gains_FIX.c \
|
||||
src/SKP_Silk_quant_LTP_gains_FIX.c \
|
||||
src/SKP_Silk_range_coder.c \
|
||||
src/SKP_Silk_regularize_correlations_FIX.c \
|
||||
src/SKP_Silk_resample_1_2.c \
|
||||
src/SKP_Silk_resample_1_2_coarse.c \
|
||||
src/SKP_Silk_resample_1_2_coarsest.c \
|
||||
src/SKP_Silk_resample_1_3.c \
|
||||
src/SKP_Silk_resample_2_1_coarse.c \
|
||||
src/SKP_Silk_resample_2_3.c \
|
||||
src/SKP_Silk_resample_2_3_coarse.c \
|
||||
src/SKP_Silk_resample_2_3_coarsest.c \
|
||||
src/SKP_Silk_resample_2_3_rom.c \
|
||||
src/SKP_Silk_resample_3_1.c \
|
||||
src/SKP_Silk_resample_3_2.c \
|
||||
src/SKP_Silk_resample_3_2_rom.c \
|
||||
src/SKP_Silk_resample_3_4.c \
|
||||
src/SKP_Silk_resample_4_3.c \
|
||||
src/SKP_Silk_resampler.c \
|
||||
src/SKP_Silk_resampler_down2.c \
|
||||
src/SKP_Silk_resampler_down2_3.c \
|
||||
src/SKP_Silk_resampler_down3.c \
|
||||
src/SKP_Silk_resampler_private_AR2.c \
|
||||
src/SKP_Silk_resampler_private_ARMA4.c \
|
||||
src/SKP_Silk_resampler_private_IIR_FIR.c \
|
||||
src/SKP_Silk_resampler_private_copy.c \
|
||||
src/SKP_Silk_resampler_private_down4.c \
|
||||
src/SKP_Silk_resampler_private_down_FIR.c \
|
||||
src/SKP_Silk_resampler_private_up2_HQ.c \
|
||||
src/SKP_Silk_resampler_private_up4.c \
|
||||
src/SKP_Silk_resampler_rom.c \
|
||||
src/SKP_Silk_resampler_up2.c \
|
||||
src/SKP_Silk_residual_energy16_FIX.c \
|
||||
src/SKP_Silk_residual_energy_FIX.c \
|
||||
src/SKP_Silk_scale_copy_vector16.c \
|
||||
src/SKP_Silk_scale_vector.c \
|
||||
src/SKP_Silk_schur64.c \
|
||||
src/SKP_Silk_schur.c \
|
||||
src/SKP_Silk_schur64.c \
|
||||
src/SKP_Silk_shell_coder.c \
|
||||
src/SKP_Silk_sigm_Q15.c \
|
||||
src/SKP_Silk_solve_LS_FIX.c \
|
||||
src/SKP_Silk_sort.c \
|
||||
src/SKP_Silk_sum_sqr_shift.c \
|
||||
src/SKP_Silk_tables_gain.c \
|
||||
src/SKP_Silk_tables_LTP.c \
|
||||
src/SKP_Silk_tables_NLSF_CB0_10.c \
|
||||
src/SKP_Silk_tables_NLSF_CB0_16.c \
|
||||
src/SKP_Silk_tables_NLSF_CB1_10.c \
|
||||
src/SKP_Silk_tables_NLSF_CB1_16.c \
|
||||
src/SKP_Silk_tables_gain.c \
|
||||
src/SKP_Silk_tables_other.c \
|
||||
src/SKP_Silk_tables_pitch_lag.c \
|
||||
src/SKP_Silk_tables_pulses_per_block.c \
|
||||
src/SKP_Silk_tables_sign.c \
|
||||
src/SKP_Silk_tables_type_offset.c \
|
||||
src/SKP_Silk_VAD.c \
|
||||
src/SKP_Silk_VQ_nearest_neighbor_FIX.c
|
||||
src/SKP_Silk_VQ_nearest_neighbor_FIX.c \
|
||||
src/SKP_Silk_warped_autocorrelation_FIX.c
|
||||
|
||||
|
||||
libSKP_SILK_SDK_la_CFLAGS = $(AM_CFLAGS)
|
||||
@@ -135,24 +129,26 @@ libSKP_SILK_SDK_la_LDFLAGS = $(LIBS)
|
||||
|
||||
library_includedir = $(prefix)/include/silk
|
||||
library_include_HEADERS = src/SKP_Silk_common_pitch_est_defines.h \
|
||||
src/SKP_Silk_define_FIX.h \
|
||||
src/SKP_Silk_define.h \
|
||||
src/SKP_Silk_Inlines.h \
|
||||
src/SKP_Silk_macros.h \
|
||||
src/SKP_Silk_main_FIX.h \
|
||||
src/SKP_Silk_main.h \
|
||||
src/SKP_Silk_perceptual_parameters_FIX.h \
|
||||
src/SKP_Silk_main_FIX.h \
|
||||
src/SKP_Silk_pitch_est_defines.h \
|
||||
src/SKP_Silk_PLC.h \
|
||||
src/SKP_Silk_resample_rom.h \
|
||||
src/SKP_Silk_resampler_private.h \
|
||||
src/SKP_Silk_resampler_rom.h \
|
||||
src/SKP_Silk_resampler_structs.h \
|
||||
src/SKP_Silk_SigProc_FIX.h \
|
||||
src/SKP_Silk_structs_FIX.h \
|
||||
src/SKP_Silk_setup_complexity.h \
|
||||
src/SKP_Silk_structs.h \
|
||||
src/SKP_Silk_structs_FIX.h \
|
||||
src/SKP_Silk_tables.h \
|
||||
src/SKP_Silk_tables_NLSF_CB0_10.h \
|
||||
src/SKP_Silk_tables_NLSF_CB0_16.h \
|
||||
src/SKP_Silk_tables_NLSF_CB1_10.h \
|
||||
src/SKP_Silk_tables_NLSF_CB1_16.h \
|
||||
src/SKP_Silk_tuning_parameters.h \
|
||||
interface/SKP_Silk_control.h \
|
||||
interface/SKP_Silk_errors.h \
|
||||
interface/SKP_Silk_SDK_API.h \
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ([2.59])
|
||||
AC_INIT(libSKP_SILK_SDK, 1.0.2, brian@freeswitch.org, libSKP_SILK_SDK)
|
||||
AM_INIT_AUTOMAKE(libSKP_SILK_SDK,1.0.2)
|
||||
AC_INIT(libSKP_SILK_SDK, 1.0.8, brian@freeswitch.org, libSKP_SILK_SDK)
|
||||
AM_INIT_AUTOMAKE(libSKP_SILK_SDK,1.0.8)
|
||||
|
||||
# Checks for programs.
|
||||
AC_PROG_CC
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
@@ -39,7 +39,7 @@ extern "C"
|
||||
|
||||
#define SILK_MAX_FRAMES_PER_PACKET 5
|
||||
|
||||
/* Struct for TOC (Table Of Contents) */
|
||||
/* 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 */
|
||||
@@ -85,7 +85,7 @@ SKP_int SKP_Silk_SDK_Encode(
|
||||
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) */
|
||||
SKP_int16 *nBytesOut /* I/O: Number of bytes in outData (input: Max bytes) */
|
||||
);
|
||||
|
||||
/****************************************/
|
||||
@@ -114,7 +114,7 @@ SKP_int SKP_Silk_SDK_Decode(
|
||||
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 */
|
||||
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) */
|
||||
);
|
||||
@@ -123,22 +123,20 @@ SKP_int SKP_Silk_SDK_Decode(
|
||||
/* Find Low Bit Rate Redundancy (LBRR) information in a packet */
|
||||
/***************************************************************/
|
||||
void SKP_Silk_SDK_search_for_LBRR(
|
||||
void *decState, /* I: Decoder state, to select bitstream version only */
|
||||
const SKP_uint8 *inData, /* I: Encoded input vector */
|
||||
const SKP_int16 nBytesIn, /* I: Number of input Bytes */
|
||||
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 type of content for a packet */
|
||||
/************************************/
|
||||
/**************************************/
|
||||
/* Get table of contents for a packet */
|
||||
/**************************************/
|
||||
void SKP_Silk_SDK_get_TOC(
|
||||
void *decState, /* I: Decoder state, to select bitstream version only */
|
||||
const SKP_uint8 *inData, /* I: Encoded input vector */
|
||||
const SKP_int16 nBytesIn, /* I: Number of input bytes */
|
||||
SKP_Silk_TOC_struct *Silk_TOC /* O: Type of content */
|
||||
const SKP_int nBytesIn, /* I: Number of input bytes */
|
||||
SKP_Silk_TOC_struct *Silk_TOC /* O: Table of contents */
|
||||
);
|
||||
|
||||
/**************************/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
@@ -39,8 +39,11 @@ extern "C"
|
||||
/* Structure for controlling encoder operation */
|
||||
/***********************************************/
|
||||
typedef struct {
|
||||
/* I: Sampling rate in Hertz; 8000/12000/16000/24000 */
|
||||
SKP_int32 sampleRate;
|
||||
/* 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;
|
||||
@@ -48,7 +51,7 @@ typedef struct {
|
||||
/* I: Bitrate during active speech in bits/second; internally limited */
|
||||
SKP_int32 bitRate;
|
||||
|
||||
/* I: Uplink Packet loss in pct (0...100) */
|
||||
/* 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 */
|
||||
@@ -57,7 +60,7 @@ typedef struct {
|
||||
/* I: Flag to enable in-band Forward Error Correction (FEC); 0/1 */
|
||||
SKP_int useInBandFEC;
|
||||
|
||||
/* I: Flag to enable Discontinous Transmission; 0/1 */
|
||||
/* I: Flag to enable discontinuous transmission (DTX); 0/1 */
|
||||
SKP_int useDTX;
|
||||
} SKP_SILK_SDK_EncControlStruct;
|
||||
|
||||
@@ -65,8 +68,8 @@ typedef struct {
|
||||
/* Structure for controlling decoder operation and reading decoder status */
|
||||
/**************************************************************************/
|
||||
typedef struct {
|
||||
/* I: Sampling rate in Hertz; 8000/12000/16000/24000 */
|
||||
SKP_int32 sampleRate;
|
||||
/* I: Output signal sampling rate in Hertz; 8000/12000/16000/24000 */
|
||||
SKP_int32 API_sampleRate;
|
||||
|
||||
/* O: Number of samples per frame */
|
||||
SKP_int frameSize;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
@@ -36,48 +36,45 @@ extern "C"
|
||||
/******************/
|
||||
/* Error messages */
|
||||
/******************/
|
||||
#define SKP_SILK_NO_ERROR 0
|
||||
#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
|
||||
/* 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
|
||||
/* 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
|
||||
#define SKP_SILK_ENC_PACKET_SIZE_NOT_SUPPORTED -3
|
||||
|
||||
/* Allocated payload buffer too short */
|
||||
#define SKP_SILK_ENC_PAYLOAD_BUF_TOO_SHORT -4
|
||||
#define SKP_SILK_ENC_PAYLOAD_BUF_TOO_SHORT -4
|
||||
|
||||
/* Loss rate not between 0 and 100 percent */
|
||||
#define SKP_SILK_ENC_WRONG_LOSS_RATE -5
|
||||
#define SKP_SILK_ENC_INVALID_LOSS_RATE -5
|
||||
|
||||
/* Complexity setting not valid, use 0, 1 or 2 */
|
||||
#define SKP_SILK_ENC_WRONG_COMPLEXITY_SETTING -6
|
||||
#define SKP_SILK_ENC_INVALID_COMPLEXITY_SETTING -6
|
||||
|
||||
/* Inband FEC setting not valid, use 0 or 1 */
|
||||
#define SKP_SILK_ENC_WRONG_INBAND_FEC_SETTING -7
|
||||
#define SKP_SILK_ENC_INVALID_INBAND_FEC_SETTING -7
|
||||
|
||||
/* DTX setting not valid, use 0 or 1 */
|
||||
#define SKP_SILK_ENC_WRONG_DTX_SETTING -8
|
||||
#define SKP_SILK_ENC_INVALID_DTX_SETTING -8
|
||||
|
||||
/* Internal encoder error */
|
||||
#define SKP_SILK_ENC_INTERNAL_ERROR -9
|
||||
#define SKP_SILK_ENC_INTERNAL_ERROR -9
|
||||
|
||||
/**************************/
|
||||
/* Decoder error messages */
|
||||
/**************************/
|
||||
|
||||
/* Output sampling frequency lower than internal
|
||||
decoded sampling frequency */
|
||||
#define SKP_SILK_DEC_WRONG_SAMPLING_FREQUENCY -10
|
||||
/* 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
|
||||
@@ -85,7 +82,6 @@ extern "C"
|
||||
/* Payload has bit errors */
|
||||
#define SKP_SILK_DEC_PAYLOAD_ERROR -12
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
|
||||
+23
-7
@@ -1,14 +1,14 @@
|
||||
************************************************************************
|
||||
Fixed Point SILK SDK 1.0.2 beta source code package
|
||||
Fixed Point SILK SDK 1.0.8 beta source code package
|
||||
Copyright 2010 (c), Skype Limited
|
||||
https://developer.skype.com/silk/
|
||||
************************************************************************
|
||||
|
||||
Date: 09/03/2010 (Format: DD/MM/YYYY)
|
||||
Date: 15/06/2011 (Format: DD/MM/YYYY)
|
||||
|
||||
I. Description
|
||||
|
||||
This package contains files for compiling and testing the fixed
|
||||
This package contains files for compilation and evaluation of the fixed
|
||||
point SILK SDK library. The following is included in this package:
|
||||
|
||||
o Source code for the fixed point SILK SDK library
|
||||
@@ -51,22 +51,38 @@ III. How to use the Makefile
|
||||
|
||||
make clean all
|
||||
|
||||
6. How to use the comparison tool:
|
||||
|
||||
6. How to build for big endian CPU's
|
||||
|
||||
Make clean all ADDED_DEFINES+=_SYSTEM_IS_BIG_ENDIAN
|
||||
To be able to use the test vectors with big endian CPU's the test programs
|
||||
need to be compiled in a different way. Note that the 16 bit input and output
|
||||
from the test programs will have the upper and lower bytes swapped with this setting.
|
||||
|
||||
7. How to use the comparison tool:
|
||||
|
||||
See 'How to use the test vectors.txt' in the test_vectors folder.
|
||||
|
||||
IV. History
|
||||
|
||||
Version 1.0.8 - Improved noise shaping, various other improvements, and various bugfixes. Added a MIPS version
|
||||
Version 1.0.7 - Updated with bugfixes for LBRR and pitch estimator. SignalCompare updated
|
||||
Version 1.0.6 - Updated with bugfixes for ARM builds
|
||||
Version 1.0.5 - Updated with bugfixes for ARM builds
|
||||
Version 1.0.4 - Updated with various bugfixes and improvements, including some API changes
|
||||
Added support for big endian platforms
|
||||
Added resampler support for additional API sample rates
|
||||
Version 1.0.3 - Updated with various bugfixes and improvements
|
||||
Version 1.0.2 - Updated with various bugfixes and improvements
|
||||
Version 1.0.1 - First beta source code release
|
||||
|
||||
V. Compatibility
|
||||
|
||||
This package has been tested under the following platforms:
|
||||
This package has been tested on the following platforms:
|
||||
|
||||
Windows XP Home and Professional
|
||||
Windows Vista, 32-bit version
|
||||
Mac OS X Version 10.5.8
|
||||
Mac OSX intel
|
||||
Mac OSX ppc
|
||||
Ubuntu Linux 9.10, 64-bit version
|
||||
|
||||
VI. Known Issues
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
@@ -33,10 +33,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "SKP_Silk_SigProc_FIX.h"
|
||||
|
||||
/* Number of binary divisions, when not in low complexity mode */
|
||||
#define BIN_DIV_STEPS_A2NLSF_FIX 2 /* must be no higher than 16 - log2( LSF_COS_TAB_SZ_FIX ) */
|
||||
/* Number of binary divisions */
|
||||
#define BIN_DIV_STEPS_A2NLSF_FIX 3 /* must be no higher than 16 - log2( LSF_COS_TAB_SZ_FIX ) */
|
||||
#define QPoly 16
|
||||
#define MAX_ITERATIONS_A2NLSF_FIX 50
|
||||
#define MAX_ITERATIONS_A2NLSF_FIX 30
|
||||
|
||||
/* Flag for using 2x as many cosine sampling points, reduces the risk of missing a root */
|
||||
#define OVERSAMPLE_COSINE_TABLE 0
|
||||
@@ -57,12 +57,11 @@ SKP_INLINE void SKP_Silk_A2NLSF_trans_poly(
|
||||
p[ k - 2 ] -= SKP_LSHIFT( p[ k ], 1 );
|
||||
}
|
||||
}
|
||||
|
||||
/* Helper function for A2NLSF(..) */
|
||||
/* Polynomial evaluation */
|
||||
SKP_INLINE SKP_int32 SKP_Silk_A2NLSF_eval_poly( /* return the polynomial evaluation, in QPoly */
|
||||
SKP_int32 *p, /* I Polynomial, QPoly */
|
||||
const SKP_int32 x, /* I Evaluation point, Q12 */
|
||||
const SKP_int32 x, /* I Evaluation point, Q12 */
|
||||
const SKP_int dd /* I Order */
|
||||
)
|
||||
{
|
||||
@@ -79,9 +78,9 @@ SKP_INLINE SKP_int32 SKP_Silk_A2NLSF_eval_poly( /* return the polynomial eval
|
||||
|
||||
SKP_INLINE void SKP_Silk_A2NLSF_init(
|
||||
const SKP_int32 *a_Q16,
|
||||
SKP_int32 *P,
|
||||
SKP_int32 *Q,
|
||||
const SKP_int dd
|
||||
SKP_int32 *P,
|
||||
SKP_int32 *Q,
|
||||
const SKP_int dd
|
||||
)
|
||||
{
|
||||
SKP_int k;
|
||||
@@ -127,8 +126,8 @@ void SKP_Silk_A2NLSF(
|
||||
SKP_int32 xlo, xhi, xmid;
|
||||
SKP_int32 ylo, yhi, ymid;
|
||||
SKP_int32 nom, den;
|
||||
SKP_int32 P[ SigProc_MAX_ORDER_LPC / 2 + 1 ];
|
||||
SKP_int32 Q[ SigProc_MAX_ORDER_LPC / 2 + 1 ];
|
||||
SKP_int32 P[ SKP_Silk_MAX_ORDER_LPC / 2 + 1 ];
|
||||
SKP_int32 Q[ SKP_Silk_MAX_ORDER_LPC / 2 + 1 ];
|
||||
SKP_int32 *PQ[ 2 ];
|
||||
SKP_int32 *p;
|
||||
|
||||
@@ -258,7 +257,7 @@ void SKP_Silk_A2NLSF(
|
||||
}
|
||||
|
||||
/* Error: Apply progressively more bandwidth expansion and run again */
|
||||
SKP_Silk_bwexpander_32( a_Q16, d, 65536 - SKP_SMULBB( 66, i ) ); // 66_Q16 = 0.001
|
||||
SKP_Silk_bwexpander_32( a_Q16, d, 65536 - SKP_SMULBB( 10 + i, i ) ); // 10_Q16 = 0.00015
|
||||
|
||||
SKP_Silk_A2NLSF_init( a_Q16, P, Q, dd );
|
||||
p = P; /* Pointer to polynomial */
|
||||
@@ -269,9 +268,9 @@ void SKP_Silk_A2NLSF(
|
||||
NLSF[ 0 ] = 0;
|
||||
p = Q; /* Pointer to polynomial */
|
||||
ylo = SKP_Silk_A2NLSF_eval_poly( p, xlo, dd );
|
||||
root_ix = 1; /* Index of current root */
|
||||
root_ix = 1; /* Index of current root */
|
||||
} else {
|
||||
root_ix = 0; /* Index of current root */
|
||||
root_ix = 0; /* Index of current root */
|
||||
}
|
||||
k = 1; /* Reset loop counter */
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
@@ -25,7 +25,7 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#include "SKP_Silk_main_FIX.h"
|
||||
#include "SKP_Silk_main.h"
|
||||
|
||||
/* Generates excitation for CNG LPC synthesis */
|
||||
SKP_INLINE void SKP_Silk_CNG_exc(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
@@ -26,6 +26,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
***********************************************************************/
|
||||
|
||||
#include "SKP_Silk_main_FIX.h"
|
||||
#include "SKP_Silk_tuning_parameters.h"
|
||||
|
||||
#if HIGH_PASS_INPUT
|
||||
|
||||
@@ -57,7 +58,7 @@ void SKP_Silk_HP_variable_cutoff_FIX(
|
||||
quality_Q15 = psEncCtrl->input_quality_bands_Q15[ 0 ];
|
||||
pitch_freq_log_Q7 = SKP_SUB32( pitch_freq_log_Q7, SKP_SMULWB( SKP_SMULWB( SKP_LSHIFT( quality_Q15, 2 ), quality_Q15 ),
|
||||
pitch_freq_log_Q7 - SKP_LOG2_VARIABLE_HP_MIN_FREQ_Q7 ) );
|
||||
pitch_freq_log_Q7 = SKP_ADD32( pitch_freq_log_Q7, SKP_RSHIFT( 19661 - quality_Q15, 9 ) ); // 19661_Q15 = 0.6_Q0
|
||||
pitch_freq_log_Q7 = SKP_ADD32( pitch_freq_log_Q7, SKP_RSHIFT( SKP_FIX_CONST( 0.6, 15 ) - quality_Q15, 9 ) );
|
||||
|
||||
//delta_freq = pitch_freq_log - psEnc->variable_HP_smth1;
|
||||
delta_freq_Q7 = pitch_freq_log_Q7 - SKP_RSHIFT( psEnc->variable_HP_smth1_Q15, 8 );
|
||||
@@ -67,21 +68,22 @@ void SKP_Silk_HP_variable_cutoff_FIX(
|
||||
}
|
||||
|
||||
/* limit delta, to reduce impact of outliers */
|
||||
delta_freq_Q7 = SKP_LIMIT( delta_freq_Q7, -VARIABLE_HP_MAX_DELTA_FREQ_Q7, VARIABLE_HP_MAX_DELTA_FREQ_Q7 );
|
||||
delta_freq_Q7 = SKP_LIMIT_32( delta_freq_Q7, -SKP_FIX_CONST( VARIABLE_HP_MAX_DELTA_FREQ, 7 ), SKP_FIX_CONST( VARIABLE_HP_MAX_DELTA_FREQ, 7 ) );
|
||||
|
||||
/* update smoother */
|
||||
psEnc->variable_HP_smth1_Q15 = SKP_SMLAWB( psEnc->variable_HP_smth1_Q15,
|
||||
SKP_MUL( SKP_LSHIFT( psEnc->speech_activity_Q8, 1 ), delta_freq_Q7 ), VARIABLE_HP_SMTH_COEF1_Q16 );
|
||||
SKP_MUL( SKP_LSHIFT( psEnc->speech_activity_Q8, 1 ), delta_freq_Q7 ), SKP_FIX_CONST( VARIABLE_HP_SMTH_COEF1, 16 ) );
|
||||
}
|
||||
/* second smoother */
|
||||
psEnc->variable_HP_smth2_Q15 = SKP_SMLAWB( psEnc->variable_HP_smth2_Q15,
|
||||
psEnc->variable_HP_smth1_Q15 - psEnc->variable_HP_smth2_Q15, VARIABLE_HP_SMTH_COEF2_Q16 );
|
||||
psEnc->variable_HP_smth1_Q15 - psEnc->variable_HP_smth2_Q15, SKP_FIX_CONST( VARIABLE_HP_SMTH_COEF2, 16 ) );
|
||||
|
||||
/* convert from log scale to Hertz */
|
||||
psEncCtrl->pitch_freq_low_Hz = SKP_Silk_log2lin( SKP_RSHIFT( psEnc->variable_HP_smth2_Q15, 8 ) ); //pow( 2.0, psEnc->variable_HP_smth2 );
|
||||
psEncCtrl->pitch_freq_low_Hz = SKP_Silk_log2lin( SKP_RSHIFT( psEnc->variable_HP_smth2_Q15, 8 ) );
|
||||
|
||||
/* limit frequency range */
|
||||
psEncCtrl->pitch_freq_low_Hz = SKP_LIMIT( psEncCtrl->pitch_freq_low_Hz, VARIABLE_HP_MIN_FREQ_Q0, VARIABLE_HP_MAX_FREQ_Q0 );
|
||||
psEncCtrl->pitch_freq_low_Hz = SKP_LIMIT_32( psEncCtrl->pitch_freq_low_Hz,
|
||||
SKP_FIX_CONST( VARIABLE_HP_MIN_FREQ, 0 ), SKP_FIX_CONST( VARIABLE_HP_MAX_FREQ, 0 ) );
|
||||
|
||||
/********************************/
|
||||
/* Compute Filter Coefficients */
|
||||
@@ -94,7 +96,7 @@ void SKP_Silk_HP_variable_cutoff_FIX(
|
||||
SKP_assert( Fc_Q19 >= 3704 );
|
||||
SKP_assert( Fc_Q19 <= 27787 );
|
||||
|
||||
r_Q28 = ( 1 << 28 ) - SKP_MUL( 471, Fc_Q19 ); // 471_Q9 = 0.92_Q0, range: 255347779 to 266690872, 27-28 bits
|
||||
r_Q28 = SKP_FIX_CONST( 1.0, 28 ) - SKP_MUL( SKP_FIX_CONST( 0.92, 9 ), Fc_Q19 );
|
||||
SKP_assert( r_Q28 >= 255347779 );
|
||||
SKP_assert( r_Q28 <= 266690872 );
|
||||
|
||||
@@ -106,7 +108,7 @@ void SKP_Silk_HP_variable_cutoff_FIX(
|
||||
|
||||
// -r * ( 2 - Fc * Fc );
|
||||
r_Q22 = SKP_RSHIFT( r_Q28, 6 );
|
||||
A_Q28[ 0 ] = SKP_SMULWW( r_Q22, SKP_SMULWW( Fc_Q19, Fc_Q19 ) - ( 2 << 22 ) );
|
||||
A_Q28[ 0 ] = SKP_SMULWW( r_Q22, SKP_SMULWW( Fc_Q19, Fc_Q19 ) - SKP_FIX_CONST( 2.0, 22 ) );
|
||||
A_Q28[ 1 ] = SKP_SMULWW( r_Q22, r_Q22 );
|
||||
|
||||
/********************************/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
@@ -57,20 +57,15 @@ SKP_INLINE void SKP_Silk_CLZ_FRAC(SKP_int32 in, /* I: input */
|
||||
SKP_int32 *lz, /* O: number of leading zeros */
|
||||
SKP_int32 *frac_Q7) /* O: the 7 bits right after the leading one */
|
||||
{
|
||||
SKP_int32 leadingZeros;
|
||||
SKP_int32 lzeros = SKP_Silk_CLZ32(in);
|
||||
|
||||
leadingZeros = SKP_Silk_CLZ32(in);
|
||||
*lz = leadingZeros;
|
||||
if( leadingZeros < 24 ) {
|
||||
*frac_Q7 = SKP_RSHIFT(in, 24 - leadingZeros) & 0x7F;
|
||||
} else {
|
||||
*frac_Q7 = SKP_LSHIFT(in, leadingZeros - 24) & 0x7F;
|
||||
}
|
||||
* lz = lzeros;
|
||||
* frac_Q7 = SKP_ROR32(in, 24 - lzeros) & 0x7f;
|
||||
}
|
||||
|
||||
/* Approximation of square root */
|
||||
/* Accuracy: < +/- 10% for output values > 15 */
|
||||
/* < +/- 2.5% for output values > 120 */
|
||||
/* Accuracy: < +/- 10% for output values > 15 */
|
||||
/* < +/- 2.5% for output values > 120 */
|
||||
SKP_INLINE SKP_int32 SKP_Silk_SQRT_APPROX(SKP_int32 x)
|
||||
{
|
||||
SKP_int32 y, lz, frac_Q7;
|
||||
@@ -125,9 +120,9 @@ SKP_INLINE SKP_int32 SKP_Silk_norm32(SKP_int32 a) {
|
||||
|
||||
/* Divide two int32 values and return result as int32 in a given Q-domain */
|
||||
SKP_INLINE SKP_int32 SKP_DIV32_varQ( /* O returns a good approximation of "(a32 << Qres) / b32" */
|
||||
const SKP_int32 a32, /* I numerator (Q0) */
|
||||
const SKP_int32 b32, /* I denominator (Q0) */
|
||||
const SKP_int Qres /* I Q-domain of result (>= 0) */
|
||||
const SKP_int32 a32, /* I numerator (Q0) */
|
||||
const SKP_int32 b32, /* I denominator (Q0) */
|
||||
const SKP_int Qres /* I Q-domain of result (>= 0) */
|
||||
)
|
||||
{
|
||||
SKP_int a_headrm, b_headrm, lshift;
|
||||
@@ -170,14 +165,15 @@ SKP_INLINE SKP_int32 SKP_DIV32_varQ( /* O returns a good approximation of
|
||||
|
||||
/* Invert int32 value and return result as int32 in a given Q-domain */
|
||||
SKP_INLINE SKP_int32 SKP_INVERSE32_varQ( /* O returns a good approximation of "(1 << Qres) / b32" */
|
||||
const SKP_int32 b32, /* I denominator (Q0) */
|
||||
const SKP_int Qres /* I Q-domain of result (> 0) */
|
||||
const SKP_int32 b32, /* I denominator (Q0) */
|
||||
const SKP_int Qres /* I Q-domain of result (> 0) */
|
||||
)
|
||||
{
|
||||
SKP_int b_headrm, lshift;
|
||||
SKP_int32 b32_inv, b32_nrm, err_Q32, result;
|
||||
|
||||
SKP_assert( b32 != 0 );
|
||||
SKP_assert( b32 != SKP_int32_MIN ); /* SKP_int32_MIN is not handled by SKP_abs */
|
||||
SKP_assert( Qres > 0 );
|
||||
|
||||
/* Compute number of bits head room and normalize input */
|
||||
@@ -277,4 +273,4 @@ SKP_INLINE SKP_int32 SKP_Silk_COS_APPROX_Q24( /* O returns approximate
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //_SKP_SILK_FIX_INLINES_H_
|
||||
#endif /*_SKP_SILK_FIX_INLINES_H_*/
|
||||
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
@@ -31,30 +31,27 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* Compute inverse of LPC prediction gain, and *
|
||||
* test if LPC coefficients are stable (all poles within unit circle) *
|
||||
* *
|
||||
* Copyright 2008 (c), Skype Limited *
|
||||
* Copyright 2008 (c), Skype Limited *
|
||||
* */
|
||||
#include "SKP_Silk_SigProc_FIX.h"
|
||||
|
||||
#define QA 16
|
||||
#define A_LIMIT 65520
|
||||
#define A_LIMIT SKP_FIX_CONST( 0.99975, QA )
|
||||
|
||||
/* Compute inverse of LPC prediction gain, and */
|
||||
/* test if LPC coefficients are stable (all poles within unit circle) */
|
||||
SKP_int SKP_Silk_LPC_inverse_pred_gain( /* O: Returns 1 if unstable, otherwise 0 */
|
||||
static SKP_int LPC_inverse_pred_gain_QA( /* O: Returns 1 if unstable, otherwise 0 */
|
||||
SKP_int32 *invGain_Q30, /* O: Inverse prediction gain, Q30 energy domain */
|
||||
const SKP_int16 *A_Q12, /* I: Prediction coefficients, Q12 [order] */
|
||||
SKP_int32 A_QA[ 2 ][ SKP_Silk_MAX_ORDER_LPC ],
|
||||
/* I: Prediction coefficients */
|
||||
const SKP_int order /* I: Prediction order */
|
||||
)
|
||||
{
|
||||
SKP_int k, n, headrm;
|
||||
SKP_int32 rc_Q31, rc_mult1_Q30, rc_mult2_Q16;
|
||||
SKP_int32 Atmp_QA[ 2 ][ SigProc_MAX_ORDER_LPC ], tmp_QA;
|
||||
SKP_int32 rc_Q31, rc_mult1_Q30, rc_mult2_Q16, tmp_QA;
|
||||
SKP_int32 *Aold_QA, *Anew_QA;
|
||||
|
||||
Anew_QA = Atmp_QA[ order & 1 ];
|
||||
/* Increase Q domain of the AR coefficients */
|
||||
for( k = 0; k < order; k++ ) {
|
||||
Anew_QA[ k ] = SKP_LSHIFT( (SKP_int32)A_Q12[ k ], QA - 12 );
|
||||
}
|
||||
Anew_QA = A_QA[ order & 1 ];
|
||||
|
||||
*invGain_Q30 = ( 1 << 30 );
|
||||
for( k = order - 1; k > 0; k-- ) {
|
||||
@@ -82,7 +79,7 @@ SKP_int SKP_Silk_LPC_inverse_pred_gain( /* O: Returns 1 if unstable, oth
|
||||
|
||||
/* Swap pointers */
|
||||
Aold_QA = Anew_QA;
|
||||
Anew_QA = Atmp_QA[ k & 1 ];
|
||||
Anew_QA = A_QA[ k & 1 ];
|
||||
|
||||
/* Update AR coefficient */
|
||||
headrm = SKP_Silk_CLZ32( rc_mult2_Q16 ) - 1;
|
||||
@@ -112,78 +109,45 @@ SKP_int SKP_Silk_LPC_inverse_pred_gain( /* O: Returns 1 if unstable, oth
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* For input in Q13 domain */
|
||||
SKP_int SKP_Silk_LPC_inverse_pred_gain_Q13( /* O: Returns 1 if unstable, otherwise 0 */
|
||||
/* For input in Q12 domain */
|
||||
SKP_int SKP_Silk_LPC_inverse_pred_gain( /* O: Returns 1 if unstable, otherwise 0 */
|
||||
SKP_int32 *invGain_Q30, /* O: Inverse prediction gain, Q30 energy domain */
|
||||
const SKP_int16 *A_Q13, /* I: Prediction coefficients, Q13 [order] */
|
||||
const SKP_int16 *A_Q12, /* I: Prediction coefficients, Q12 [order] */
|
||||
const SKP_int order /* I: Prediction order */
|
||||
)
|
||||
{
|
||||
SKP_int k, n, headrm;
|
||||
SKP_int32 rc_Q31, rc_mult1_Q30, rc_mult2_Q16;
|
||||
SKP_int32 Atmp_QA[ 2 ][ SigProc_MAX_ORDER_LPC ], tmp_QA;
|
||||
SKP_int32 *Aold_QA, *Anew_QA;
|
||||
SKP_int k;
|
||||
SKP_int32 Atmp_QA[ 2 ][ SKP_Silk_MAX_ORDER_LPC ];
|
||||
SKP_int32 *Anew_QA;
|
||||
|
||||
Anew_QA = Atmp_QA[ order & 1 ];
|
||||
|
||||
/* Increase Q domain of the AR coefficients */
|
||||
for( k = 0; k < order; k++ ) {
|
||||
Anew_QA[ k ] = SKP_LSHIFT( (SKP_int32)A_Q13[ k ], QA - 13 );
|
||||
Anew_QA[ k ] = SKP_LSHIFT( (SKP_int32)A_Q12[ k ], QA - 12 );
|
||||
}
|
||||
|
||||
*invGain_Q30 = ( 1 << 30 );
|
||||
for( k = order - 1; k > 0; k-- ) {
|
||||
/* Check for stability */
|
||||
if( ( Anew_QA[ k ] > A_LIMIT ) || ( Anew_QA[ k ] < -A_LIMIT ) ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Set RC equal to negated AR coef */
|
||||
rc_Q31 = -SKP_LSHIFT( Anew_QA[ k ], 31 - QA );
|
||||
|
||||
/* rc_mult1_Q30 range: [ 1 : 2^30-1 ] */
|
||||
rc_mult1_Q30 = ( SKP_int32_MAX >> 1 ) - SKP_SMMUL( rc_Q31, rc_Q31 );
|
||||
SKP_assert( rc_mult1_Q30 > ( 1 << 15 ) ); /* reduce A_LIMIT if fails */
|
||||
SKP_assert( rc_mult1_Q30 < ( 1 << 30 ) );
|
||||
|
||||
/* rc_mult2_Q16 range: [ 2^16 : SKP_int32_MAX ] */
|
||||
rc_mult2_Q16 = SKP_INVERSE32_varQ( rc_mult1_Q30, 46 ); /* 16 = 46 - 30 */
|
||||
|
||||
/* Update inverse gain */
|
||||
/* invGain_Q30 range: [ 0 : 2^30 ] */
|
||||
*invGain_Q30 = SKP_LSHIFT( SKP_SMMUL( *invGain_Q30, rc_mult1_Q30 ), 2 );
|
||||
SKP_assert( *invGain_Q30 >= 0 );
|
||||
SKP_assert( *invGain_Q30 <= 1<<30 );
|
||||
|
||||
/* Swap pointers */
|
||||
Aold_QA = Anew_QA;
|
||||
Anew_QA = Atmp_QA[ k & 1 ];
|
||||
|
||||
/* Update AR coefficient */
|
||||
headrm = SKP_Silk_CLZ32( rc_mult2_Q16 ) - 1;
|
||||
rc_mult2_Q16 = SKP_LSHIFT( rc_mult2_Q16, headrm ); /* Q: 16 + headrm */
|
||||
for( n = 0; n < k; n++ ) {
|
||||
tmp_QA = Aold_QA[ n ] - SKP_LSHIFT( SKP_SMMUL( Aold_QA[ k - n - 1 ], rc_Q31 ), 1 );
|
||||
Anew_QA[ n ] = SKP_LSHIFT( SKP_SMMUL( tmp_QA, rc_mult2_Q16 ), 16 - headrm );
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for stability */
|
||||
if( ( Anew_QA[ 0 ] > A_LIMIT ) || ( Anew_QA[ 0 ] < -A_LIMIT ) ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Set RC equal to negated AR coef */
|
||||
rc_Q31 = -SKP_LSHIFT( Anew_QA[ 0 ], 31 - QA );
|
||||
|
||||
/* Range: [ 1 : 2^30 ] */
|
||||
rc_mult1_Q30 = ( SKP_int32_MAX >> 1 ) - SKP_SMMUL( rc_Q31, rc_Q31 );
|
||||
|
||||
/* Update inverse gain */
|
||||
/* Range: [ 0 : 2^30 ] */
|
||||
*invGain_Q30 = SKP_LSHIFT( SKP_SMMUL( *invGain_Q30, rc_mult1_Q30 ), 2 );
|
||||
SKP_assert( *invGain_Q30 >= 0 );
|
||||
SKP_assert( *invGain_Q30 <= 1<<30 );
|
||||
|
||||
return 0;
|
||||
return LPC_inverse_pred_gain_QA( invGain_Q30, Atmp_QA, order );
|
||||
}
|
||||
|
||||
/* For input in Q24 domain */
|
||||
SKP_int SKP_Silk_LPC_inverse_pred_gain_Q24( /* O: Returns 1 if unstable, otherwise 0 */
|
||||
SKP_int32 *invGain_Q30, /* O: Inverse prediction gain, Q30 energy domain */
|
||||
const SKP_int32 *A_Q24, /* I: Prediction coefficients, Q24 [order] */
|
||||
const SKP_int order /* I: Prediction order */
|
||||
)
|
||||
{
|
||||
SKP_int k;
|
||||
SKP_int32 Atmp_QA[ 2 ][ SKP_Silk_MAX_ORDER_LPC ];
|
||||
SKP_int32 *Anew_QA;
|
||||
|
||||
Anew_QA = Atmp_QA[ order & 1 ];
|
||||
|
||||
/* Increase Q domain of the AR coefficients */
|
||||
for( k = 0; k < order; k++ ) {
|
||||
Anew_QA[ k ] = SKP_RSHIFT_ROUND( A_Q24[ k ], 24 - QA );
|
||||
}
|
||||
|
||||
return LPC_inverse_pred_gain_QA( invGain_Q30, Atmp_QA, order );
|
||||
}
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, 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.
|
||||
***********************************************************************/
|
||||
|
||||
#include "SKP_Silk_typedef.h"
|
||||
#include "SKP_Silk_SigProc_FIX.h"
|
||||
|
||||
#define LPC_STABILIZE_LPC_MAX_ABS_VALUE_Q16 ( ( (SKP_int32)SKP_int16_MAX ) << 4 )
|
||||
|
||||
/* LPC stabilizer, for a single input data vector */
|
||||
void SKP_Silk_LPC_stabilize(
|
||||
SKP_int16 *a_Q12, /* O stabilized LPC vector [L] */
|
||||
SKP_int32 *a_Q16, /* I LPC vector [L] */
|
||||
const SKP_int32 bwe_Q16, /* I Bandwidth expansion factor */
|
||||
const SKP_int L /* I Number of LPC parameters in the input vector */
|
||||
)
|
||||
{
|
||||
SKP_int32 maxabs, absval, sc_Q16;
|
||||
SKP_int i, idx = 0;
|
||||
SKP_int32 invGain_Q30;
|
||||
|
||||
SKP_Silk_bwexpander_32( a_Q16, L, bwe_Q16 );
|
||||
|
||||
/***************************/
|
||||
/* Limit range of the LPCs */
|
||||
/***************************/
|
||||
/* Limit the maximum absolute value of the prediction coefficients */
|
||||
while( SKP_TRUE ) {
|
||||
/* Find maximum absolute value and its index */
|
||||
maxabs = SKP_int32_MIN;
|
||||
for( i = 0; i < L; i++ ) {
|
||||
absval = SKP_abs( a_Q16[ i ] );
|
||||
if( absval > maxabs ) {
|
||||
maxabs = absval;
|
||||
idx = i;
|
||||
}
|
||||
}
|
||||
|
||||
if( maxabs >= LPC_STABILIZE_LPC_MAX_ABS_VALUE_Q16 ) {
|
||||
/* Reduce magnitude of prediction coefficients */
|
||||
sc_Q16 = SKP_DIV32( SKP_int32_MAX, SKP_RSHIFT( maxabs, 4 ) );
|
||||
sc_Q16 = 65536 - sc_Q16;
|
||||
sc_Q16 = SKP_DIV32( sc_Q16, idx + 1 );
|
||||
sc_Q16 = 65536 - sc_Q16;
|
||||
sc_Q16 = SKP_LSHIFT( SKP_SMULWB( sc_Q16, 32604 ), 1 ); // 0.995 in Q16
|
||||
SKP_Silk_bwexpander_32( a_Q16, L, sc_Q16 );
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert to 16 bit Q12 */
|
||||
for( i = 0; i < L; i++ ) {
|
||||
a_Q12[ i ] = (SKP_int16)SKP_RSHIFT_ROUND( a_Q16[ i ], 4 );
|
||||
}
|
||||
|
||||
/**********************/
|
||||
/* Ensure stable LPCs */
|
||||
/**********************/
|
||||
while( SKP_Silk_LPC_inverse_pred_gain( &invGain_Q30, a_Q12, L ) == 1 ) {
|
||||
SKP_Silk_bwexpander( a_Q12, L, 65339 ); // 0.997 in Q16
|
||||
}
|
||||
}
|
||||
|
||||
void SKP_Silk_LPC_fit(
|
||||
SKP_int16 *a_QQ, /* O Stabilized LPC vector, Q(24-rshift) [L] */
|
||||
SKP_int32 *a_Q24, /* I LPC vector [L] */
|
||||
const SKP_int QQ, /* I Q domain of output LPC vector */
|
||||
const SKP_int L /* I Number of LPC parameters in the input vector */
|
||||
)
|
||||
{
|
||||
SKP_int i, rshift, idx = 0;
|
||||
SKP_int32 maxabs, absval, sc_Q16;
|
||||
|
||||
rshift = 24 - QQ;
|
||||
|
||||
/***************************/
|
||||
/* Limit range of the LPCs */
|
||||
/***************************/
|
||||
/* Limit the maximum absolute value of the prediction coefficients */
|
||||
while( SKP_TRUE ) {
|
||||
/* Find maximum absolute value and its index */
|
||||
maxabs = SKP_int32_MIN;
|
||||
for( i = 0; i < L; i++ ) {
|
||||
absval = SKP_abs( a_Q24[ i ] );
|
||||
if( absval > maxabs ) {
|
||||
maxabs = absval;
|
||||
idx = i;
|
||||
}
|
||||
}
|
||||
|
||||
maxabs = SKP_RSHIFT( maxabs, rshift );
|
||||
if( maxabs >= SKP_int16_MAX ) {
|
||||
/* Reduce magnitude of prediction coefficients */
|
||||
sc_Q16 = 65470 - SKP_DIV32( SKP_MUL( 65470 >> 2, maxabs - SKP_int16_MAX ),
|
||||
SKP_RSHIFT32( SKP_MUL( maxabs, idx + 1), 2 ) );
|
||||
SKP_Silk_bwexpander_32( a_Q24, L, sc_Q16 );
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert to 16 bit Q(24-rshift) */
|
||||
SKP_assert( rshift > 0 );
|
||||
SKP_assert( rshift < 31 );
|
||||
for( i = 0; i < L; i++ ) {
|
||||
a_QQ[ i ] = (SKP_int16)SKP_RSHIFT_ROUND( a_Q24[ i ], rshift );
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
@@ -45,54 +45,40 @@ void SKP_Silk_LPC_synthesis_filter(
|
||||
)
|
||||
{
|
||||
SKP_int k, j, idx, Order_half = SKP_RSHIFT( Order, 1 );
|
||||
SKP_int32 SA, SB, Atmp, A_align_Q12[SigProc_MAX_ORDER_LPC >> 1], out32_Q10, out32;
|
||||
SKP_int32 SA, SB, out32_Q10, out32;
|
||||
|
||||
/* Order must be even */
|
||||
SKP_assert( 2*Order_half == Order );
|
||||
|
||||
/* combine two A_Q12 values and ensure 32-bit alignment */
|
||||
for( k = 0; k < Order_half; k++ ) {
|
||||
idx = SKP_SMULBB( 2, k );
|
||||
A_align_Q12[k] = (((SKP_int32)A_Q12[idx]) & 0x0000ffff) | SKP_LSHIFT( (SKP_int32)A_Q12[idx+1], 16 );
|
||||
}
|
||||
SKP_assert( 2 * Order_half == Order );
|
||||
|
||||
/* S[] values are in Q14 */
|
||||
for( k = 0; k < len; k++ ) {
|
||||
SA = S[Order-1];
|
||||
SA = S[ Order - 1 ];
|
||||
out32_Q10 = 0;
|
||||
for( j=0;j<(Order_half-1); j++ ) {
|
||||
for( j = 0; j < ( Order_half - 1 ); j++ ) {
|
||||
idx = SKP_SMULBB( 2, j ) + 1;
|
||||
/* multiply-add two prediction coefficients for each loop */
|
||||
/* NOTE: the code below loads two int16 values in an int32, and multiplies each using the */
|
||||
/* SMLAWB and SMLAWT instructions. On a big-endian CPU the two int16 variables would be */
|
||||
/* loaded in reverse order and the code will give the wrong result. In that case swapping */
|
||||
/* the SMLAWB and SMLAWT instructions should solve the problem. */
|
||||
Atmp = A_align_Q12[j];
|
||||
SB = S[Order - 1 - idx];
|
||||
S[Order - 1 - idx] = SA;
|
||||
out32_Q10 = SKP_SMLAWB( out32_Q10, SA, Atmp );
|
||||
out32_Q10 = SKP_SMLAWT( out32_Q10, SB, Atmp );
|
||||
SA = S[Order - 2 - idx];
|
||||
S[Order - 2 - idx] = SB;
|
||||
SB = S[ Order - 1 - idx ];
|
||||
S[ Order - 1 - idx ] = SA;
|
||||
out32_Q10 = SKP_SMLAWB( out32_Q10, SA, A_Q12[ ( j << 1 ) ] );
|
||||
out32_Q10 = SKP_SMLAWB( out32_Q10, SB, A_Q12[ ( j << 1 ) + 1 ] );
|
||||
SA = S[ Order - 2 - idx ];
|
||||
S[ Order - 2 - idx ] = SB;
|
||||
}
|
||||
|
||||
/* unrolled loop: epilog */
|
||||
Atmp = A_align_Q12[Order_half-1];
|
||||
SB = S[0];
|
||||
S[0] = SA;
|
||||
out32_Q10 = SKP_SMLAWB( out32_Q10, SA, Atmp );
|
||||
out32_Q10 = SKP_SMLAWT( out32_Q10, SB, Atmp );
|
||||
|
||||
SB = S[ 0 ];
|
||||
S[ 0 ] = SA;
|
||||
out32_Q10 = SKP_SMLAWB( out32_Q10, SA, A_Q12[ Order - 2 ] );
|
||||
out32_Q10 = SKP_SMLAWB( out32_Q10, SB, A_Q12[ Order - 1 ] );
|
||||
/* apply gain to excitation signal and add to prediction */
|
||||
out32_Q10 = SKP_ADD_SAT32( out32_Q10, SKP_SMULWB( Gain_Q26, in[k] ) );
|
||||
out32_Q10 = SKP_ADD_SAT32( out32_Q10, SKP_SMULWB( Gain_Q26, in[ k ] ) );
|
||||
|
||||
/* scale to Q0 */
|
||||
out32 = SKP_RSHIFT_ROUND( out32_Q10, 10 );
|
||||
|
||||
/* saturate output */
|
||||
out[k] = (SKP_int16)SKP_SAT16( out32 );
|
||||
out[ k ] = ( SKP_int16 )SKP_SAT16( out32 );
|
||||
|
||||
/* move result into delay line */
|
||||
S[Order - 1] = SKP_LSHIFT_SAT32( out32_Q10, 4 );
|
||||
S[ Order - 1 ] = SKP_LSHIFT_SAT32( out32_Q10, 4 );
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
@@ -43,98 +43,79 @@ void SKP_Silk_LPC_synthesis_order16(const SKP_int16 *in, /* I: excita
|
||||
)
|
||||
{
|
||||
SKP_int k;
|
||||
SKP_int32 SA, SB, Atmp, A_align_Q12[8], out32_Q10, out32;
|
||||
|
||||
/* combine two A_Q12 values and ensure 32-bit alignment */
|
||||
for( k = 0; k < 8; k++ ) {
|
||||
A_align_Q12[k] = (((SKP_int32)A_Q12[ 2*k ]) & 0x0000ffff) | SKP_LSHIFT( (SKP_int32)A_Q12[ 2*k + 1 ], 16 );
|
||||
}
|
||||
|
||||
/* S[] values are in Q14 */
|
||||
/* NOTE: the code below loads two int16 values in an int32, and multiplies each using the */
|
||||
/* SMLAWB and SMLAWT instructions. On a big-endian CPU the two int16 variables would be */
|
||||
/* loaded in reverse order and the code will give the wrong result. In that case swapping */
|
||||
/* the SMLAWB and SMLAWT instructions should solve the problem. */
|
||||
SKP_int32 SA, SB, out32_Q10, out32;
|
||||
for( k = 0; k < len; k++ ) {
|
||||
/* unrolled loop: prolog */
|
||||
/* multiply-add two prediction coefficients per iteration */
|
||||
SA = S[15];
|
||||
Atmp = A_align_Q12[0];
|
||||
SB = S[14];
|
||||
S[14] = SA;
|
||||
out32_Q10 = SKP_SMULWB( SA, Atmp );
|
||||
out32_Q10 = SKP_SMLAWT_ovflw( out32_Q10, SB, Atmp );
|
||||
SA = S[13];
|
||||
S[13] = SB;
|
||||
SA = S[ 15 ];
|
||||
SB = S[ 14 ];
|
||||
S[ 14 ] = SA;
|
||||
out32_Q10 = SKP_SMULWB( SA, A_Q12[ 0 ] );
|
||||
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SB, A_Q12[ 1 ] );
|
||||
SA = S[ 13 ];
|
||||
S[ 13 ] = SB;
|
||||
|
||||
/* unrolled loop: main loop */
|
||||
Atmp = A_align_Q12[1];
|
||||
SB = S[12];
|
||||
S[12] = SA;
|
||||
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SA, Atmp );
|
||||
out32_Q10 = SKP_SMLAWT_ovflw( out32_Q10, SB, Atmp );
|
||||
SA = S[11];
|
||||
S[11] = SB;
|
||||
SB = S[ 12 ];
|
||||
S[ 12 ] = SA;
|
||||
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SA, A_Q12[ 2 ] );
|
||||
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SB, A_Q12[ 3 ] );
|
||||
SA = S[ 11 ];
|
||||
S[ 11 ] = SB;
|
||||
|
||||
Atmp = A_align_Q12[2];
|
||||
SB = S[10];
|
||||
S[10] = SA;
|
||||
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SA, Atmp );
|
||||
out32_Q10 = SKP_SMLAWT_ovflw( out32_Q10, SB, Atmp );
|
||||
SA = S[9];
|
||||
S[9] = SB;
|
||||
SB = S[ 10 ];
|
||||
S[ 10 ] = SA;
|
||||
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SA, A_Q12[ 4 ] );
|
||||
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SB, A_Q12[ 5 ] );
|
||||
SA = S[ 9 ];
|
||||
S[ 9 ] = SB;
|
||||
|
||||
Atmp = A_align_Q12[3];
|
||||
SB = S[8];
|
||||
S[8] = SA;
|
||||
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SA, Atmp );
|
||||
out32_Q10 = SKP_SMLAWT_ovflw( out32_Q10, SB, Atmp );
|
||||
SA = S[7];
|
||||
S[7] = SB;
|
||||
SB = S[ 8 ];
|
||||
S[ 8 ] = SA;
|
||||
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SA, A_Q12[ 6 ] );
|
||||
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SB, A_Q12[ 7 ] );
|
||||
SA = S[ 7 ];
|
||||
S[ 7 ] = SB;
|
||||
|
||||
Atmp = A_align_Q12[4];
|
||||
SB = S[6];
|
||||
S[6] = SA;
|
||||
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SA, Atmp );
|
||||
out32_Q10 = SKP_SMLAWT_ovflw( out32_Q10, SB, Atmp );
|
||||
SA = S[5];
|
||||
S[5] = SB;
|
||||
SB = S[ 6 ];
|
||||
S[ 6 ] = SA;
|
||||
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SA, A_Q12[ 8 ] );
|
||||
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SB, A_Q12[ 9 ] );
|
||||
SA = S[ 5 ];
|
||||
S[ 5 ] = SB;
|
||||
|
||||
Atmp = A_align_Q12[5];
|
||||
SB = S[4];
|
||||
S[4] = SA;
|
||||
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SA, Atmp );
|
||||
out32_Q10 = SKP_SMLAWT_ovflw( out32_Q10, SB, Atmp );
|
||||
SA = S[3];
|
||||
S[3] = SB;
|
||||
SB = S[ 4 ];
|
||||
S[ 4 ] = SA;
|
||||
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SA, A_Q12[ 10 ] );
|
||||
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SB, A_Q12[ 11 ] );
|
||||
SA = S[ 3 ];
|
||||
S[ 3 ] = SB;
|
||||
|
||||
Atmp = A_align_Q12[6];
|
||||
SB = S[2];
|
||||
S[2] = SA;
|
||||
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SA, Atmp );
|
||||
out32_Q10 = SKP_SMLAWT_ovflw( out32_Q10, SB, Atmp );
|
||||
SA = S[1];
|
||||
S[1] = SB;
|
||||
SB = S[ 2 ];
|
||||
S[ 2 ] = SA;
|
||||
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SA, A_Q12[ 12 ] );
|
||||
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SB, A_Q12[ 13 ] );
|
||||
SA = S[ 1 ];
|
||||
S[ 1 ] = SB;
|
||||
|
||||
/* unrolled loop: epilog */
|
||||
Atmp = A_align_Q12[7];
|
||||
SB = S[0];
|
||||
S[0] = SA;
|
||||
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SA, Atmp );
|
||||
out32_Q10 = SKP_SMLAWT_ovflw( out32_Q10, SB, Atmp );
|
||||
SB = S[ 0 ];
|
||||
S[ 0 ] = SA;
|
||||
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SA, A_Q12[ 14 ] );
|
||||
out32_Q10 = SKP_SMLAWB_ovflw( out32_Q10, SB, A_Q12[ 15 ] );
|
||||
|
||||
/* unrolled loop: end */
|
||||
/* apply gain to excitation signal and add to prediction */
|
||||
out32_Q10 = SKP_ADD_SAT32( out32_Q10, SKP_SMULWB( Gain_Q26, in[k] ) );
|
||||
out32_Q10 = SKP_ADD_SAT32( out32_Q10, SKP_SMULWB( Gain_Q26, in[ k ] ) );
|
||||
|
||||
/* scale to Q0 */
|
||||
out32 = SKP_RSHIFT_ROUND( out32_Q10, 10 );
|
||||
|
||||
/* saturate output */
|
||||
out[k] = (SKP_int16)SKP_SAT16( out32 );
|
||||
out[ k ] = ( SKP_int16 )SKP_SAT16( out32 );
|
||||
|
||||
/* move result into delay line */
|
||||
S[15] = SKP_LSHIFT_SAT32( out32_Q10, 4 );
|
||||
S[ 15 ] = SKP_LSHIFT_SAT32( out32_Q10, 4 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
@@ -119,8 +119,8 @@ void SKP_Silk_LP_variable_cutoff(
|
||||
const SKP_int frame_length /* I Frame length */
|
||||
)
|
||||
{
|
||||
SKP_int32 B_Q28[ TRANSITION_NB ], A_Q28[ TRANSITION_NA ];
|
||||
SKP_int fac_Q16 = 0, ind = 0;
|
||||
SKP_int32 B_Q28[ TRANSITION_NB ], A_Q28[ TRANSITION_NA ], fac_Q16 = 0;
|
||||
SKP_int ind = 0;
|
||||
|
||||
SKP_assert( psLP->transition_frame_no >= 0 );
|
||||
SKP_assert( ( ( ( psLP->transition_frame_no <= TRANSITION_FRAMES_DOWN ) && ( psLP->mode == 0 ) ) ||
|
||||
@@ -148,11 +148,13 @@ void SKP_Silk_LP_variable_cutoff(
|
||||
/* Increment transition frame number for next frame */
|
||||
psLP->transition_frame_no++;
|
||||
|
||||
} else if( psLP->transition_frame_no == TRANSITION_FRAMES_DOWN ) {
|
||||
} else {
|
||||
SKP_assert( psLP->transition_frame_no == TRANSITION_FRAMES_DOWN );
|
||||
/* End of transition phase */
|
||||
SKP_Silk_LP_interpolate_filter_taps( B_Q28, A_Q28, TRANSITION_INT_NUM - 1, 0 );
|
||||
}
|
||||
} else if( psLP->mode == 1 ) {
|
||||
} else {
|
||||
SKP_assert( psLP->mode == 1 );
|
||||
if( psLP->transition_frame_no < TRANSITION_FRAMES_UP ) {
|
||||
/* Calculate index and interpolation factor for interpolation */
|
||||
#if( TRANSITION_INT_STEPS_UP == 64 )
|
||||
@@ -172,7 +174,8 @@ void SKP_Silk_LP_variable_cutoff(
|
||||
/* Increment transition frame number for next frame */
|
||||
psLP->transition_frame_no++;
|
||||
|
||||
} else if( psLP->transition_frame_no == TRANSITION_FRAMES_UP ) {
|
||||
} else {
|
||||
SKP_assert( psLP->transition_frame_no == TRANSITION_FRAMES_UP );
|
||||
/* End of transition phase */
|
||||
SKP_Silk_LP_interpolate_filter_taps( B_Q28, A_Q28, 0, 0 );
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
@@ -32,8 +32,7 @@ void SKP_Silk_LTP_analysis_filter_FIX(
|
||||
const SKP_int16 *x, /* I: Pointer to input signal with at least max( pitchL ) preceeding samples */
|
||||
const SKP_int16 LTPCoef_Q14[ LTP_ORDER * NB_SUBFR ],/* I: LTP_ORDER LTP coefficients for each NB_SUBFR subframe */
|
||||
const SKP_int pitchL[ NB_SUBFR ], /* I: Pitch lag, one for each subframe */
|
||||
const SKP_int32 invGains_Qxx[ NB_SUBFR ], /* I: Inverse quantization gains, one for each subframe */
|
||||
const SKP_int Qxx, /* I: Inverse quantization gains Q domain */
|
||||
const SKP_int32 invGains_Q16[ NB_SUBFR ], /* I: Inverse quantization gains, one for each subframe */
|
||||
const SKP_int subfr_length, /* I: Length of each subframe */
|
||||
const SKP_int pre_length /* I: Length of the preceeding samples starting at &x[0] for each subframe */
|
||||
)
|
||||
@@ -61,18 +60,14 @@ void SKP_Silk_LTP_analysis_filter_FIX(
|
||||
LTP_est = SKP_SMULBB( x_lag_ptr[ LTP_ORDER / 2 ], Btmp_Q14[ 0 ] );
|
||||
for( j = 1; j < LTP_ORDER; j++ ) {
|
||||
LTP_est = SKP_SMLABB_ovflw( LTP_est, x_lag_ptr[ LTP_ORDER / 2 - j ], Btmp_Q14[ j ] );
|
||||
}
|
||||
}
|
||||
LTP_est = SKP_RSHIFT_ROUND( LTP_est, 14 ); // round and -> Q0
|
||||
|
||||
/* Subtract long-term prediction */
|
||||
LTP_res_ptr[ i ] = ( SKP_int16 )SKP_SAT16( ( SKP_int32 )x_ptr[ i ] - LTP_est );
|
||||
|
||||
/* Scale residual */
|
||||
if( Qxx == 16 ) {
|
||||
LTP_res_ptr[ i ] = SKP_SMULWB( invGains_Qxx[ k ], LTP_res_ptr[ i ] );
|
||||
} else {
|
||||
LTP_res_ptr[ i ] = ( SKP_int16 )SKP_CHECK_FIT16( SKP_RSHIFT64( SKP_SMULL( invGains_Qxx[ k ], LTP_res_ptr[ i ] ), Qxx ) );
|
||||
}
|
||||
LTP_res_ptr[ i ] = SKP_SMULWB( invGains_Q16[ k ], LTP_res_ptr[ i ] );
|
||||
|
||||
x_lag_ptr++;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
@@ -52,7 +52,7 @@ void SKP_Silk_LTP_scale_ctrl_FIX(
|
||||
|
||||
/* combine input and filtered input */
|
||||
g_out_Q5 = SKP_RSHIFT_ROUND( SKP_RSHIFT( psEncCtrl->LTPredCodGain_Q7, 1 ) + SKP_RSHIFT( psEnc->HPLTPredCodGain_Q7, 1 ), 3 );
|
||||
g_limit_Q15 = SKP_Silk_sigm_Q15( g_out_Q5 - ( 3 << 5 ) ); /* mulitplid with 0.5 */
|
||||
g_limit_Q15 = SKP_Silk_sigm_Q15( g_out_Q5 - ( 3 << 5 ) );
|
||||
|
||||
/* Default is minimum scaling */
|
||||
psEncCtrl->sCmn.LTP_scaleIndex = 0;
|
||||
|
||||
+18
-135
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
@@ -35,33 +35,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* */
|
||||
#include "SKP_Silk_SigProc_FIX.h"
|
||||
|
||||
/* Variable order MA filter */
|
||||
void SKP_Silk_MA(
|
||||
const SKP_int16 *in, /* I: input signal */
|
||||
const SKP_int16 *B, /* I: MA coefficients, Q13 [order+1] */
|
||||
SKP_int32 *S, /* I/O: state vector [order] */
|
||||
SKP_int16 *out, /* O: output signal */
|
||||
const SKP_int32 len, /* I: signal length */
|
||||
const SKP_int32 order /* I: filter order */
|
||||
)
|
||||
{
|
||||
SKP_int k, d, in16;
|
||||
SKP_int32 out32;
|
||||
|
||||
for( k = 0; k < len; k++ ) {
|
||||
in16 = in[ k ];
|
||||
out32 = SKP_SMLABB( S[ 0 ], in16, B[ 0 ] );
|
||||
out32 = SKP_RSHIFT_ROUND( out32, 13 );
|
||||
|
||||
for( d = 1; d < order; d++ ) {
|
||||
S[ d - 1 ] = SKP_SMLABB( S[ d ], in16, B[ d ] );
|
||||
}
|
||||
S[ order - 1 ] = SKP_SMULBB( in16, B[ order ] );
|
||||
|
||||
/* Limit */
|
||||
out[ k ] = (SKP_int16)SKP_SAT16( out32 );
|
||||
}
|
||||
}
|
||||
/* Variable order MA prediction error filter */
|
||||
void SKP_Silk_MA_Prediction(
|
||||
const SKP_int16 *in, /* I: Input signal */
|
||||
@@ -74,105 +47,23 @@ void SKP_Silk_MA_Prediction(
|
||||
{
|
||||
SKP_int k, d, in16;
|
||||
SKP_int32 out32;
|
||||
SKP_int32 B32;
|
||||
|
||||
if( ( order & 1 ) == 0 && (SKP_int32)( (SKP_int_ptr_size)B & 3 ) == 0 ) {
|
||||
/* Even order and 4-byte aligned coefficient array */
|
||||
|
||||
/* NOTE: the code below loads two int16 values in an int32, and multiplies each using the */
|
||||
/* SMLABB and SMLABT instructions. On a big-endian CPU the two int16 variables would be */
|
||||
/* loaded in reverse order and the code will give the wrong result. In that case swapping */
|
||||
/* the SMLABB and SMLABT instructions should solve the problem. */
|
||||
for( k = 0; k < len; k++ ) {
|
||||
in16 = in[ k ];
|
||||
out32 = SKP_LSHIFT( in16, 12 ) - S[ 0 ];
|
||||
out32 = SKP_RSHIFT_ROUND( out32, 12 );
|
||||
|
||||
for( d = 0; d < order - 2; d += 2 ) {
|
||||
B32 = *( (SKP_int32*)&B[ d ] ); /* read two coefficients at once */
|
||||
S[ d ] = SKP_SMLABB_ovflw( S[ d + 1 ], in16, B32 );
|
||||
S[ d + 1 ] = SKP_SMLABT_ovflw( S[ d + 2 ], in16, B32 );
|
||||
}
|
||||
B32 = *( (SKP_int32*)&B[ d ] ); /* read two coefficients at once */
|
||||
S[ order - 2 ] = SKP_SMLABB_ovflw( S[ order - 1 ], in16, B32 );
|
||||
S[ order - 1 ] = SKP_SMULBT( in16, B32 );
|
||||
|
||||
/* Limit */
|
||||
out[ k ] = (SKP_int16)SKP_SAT16( out32 );
|
||||
}
|
||||
} else {
|
||||
/* Odd order or not 4-byte aligned coefficient array */
|
||||
for( k = 0; k < len; k++ ) {
|
||||
in16 = in[ k ];
|
||||
out32 = SKP_LSHIFT( in16, 12 ) - S[ 0 ];
|
||||
out32 = SKP_RSHIFT_ROUND( out32, 12 );
|
||||
|
||||
for( d = 0; d < order - 1; d++ ) {
|
||||
S[ d ] = SKP_SMLABB_ovflw( S[ d + 1 ], in16, B[ d ] );
|
||||
}
|
||||
S[ order - 1 ] = SKP_SMULBB( in16, B[ order - 1 ] );
|
||||
|
||||
/* Limit */
|
||||
out[ k ] = (SKP_int16)SKP_SAT16( out32 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SKP_Silk_MA_Prediction_Q13(
|
||||
const SKP_int16 *in, /* I: input signal */
|
||||
const SKP_int16 *B, /* I: MA prediction coefficients, Q13 [order] */
|
||||
SKP_int32 *S, /* I/O: state vector [order] */
|
||||
SKP_int16 *out, /* O: output signal */
|
||||
SKP_int32 len, /* I: signal length */
|
||||
SKP_int32 order /* I: filter order */
|
||||
)
|
||||
{
|
||||
SKP_int k, d, in16;
|
||||
SKP_int32 out32, B32;
|
||||
|
||||
if( ( order & 1 ) == 0 && (SKP_int32)( (SKP_int_ptr_size)B & 3 ) == 0 ) {
|
||||
/* Even order and 4-byte aligned coefficient array */
|
||||
for( k = 0; k < len; k++ ) {
|
||||
in16 = in[ k ];
|
||||
out32 = SKP_LSHIFT( in16, 12 ) - S[ 0 ];
|
||||
out32 = SKP_RSHIFT_ROUND( out32, 12 );
|
||||
|
||||
/* NOTE: the code below loads two int16 values in an int32, and multiplies each using the */
|
||||
/* SMLABB and SMLABT instructions. On a big-endian CPU the two int16 variables would be */
|
||||
/* loaded in reverse order and the code will give the wrong result. In that case swapping */
|
||||
/* the SMLABB and SMLABT instructions should solve the problem. */
|
||||
for( k = 0; k < len; k++ ) {
|
||||
in16 = in[ k ];
|
||||
out32 = SKP_LSHIFT( in16, 13 ) - S[ 0 ];
|
||||
out32 = SKP_RSHIFT_ROUND( out32, 13 );
|
||||
|
||||
for( d = 0; d < order - 2; d += 2 ) {
|
||||
B32 = *( (SKP_int32*)&B[ d ] ); /* read two coefficients at once */
|
||||
S[ d ] = SKP_SMLABB( S[ d + 1 ], in16, B32 );
|
||||
S[ d + 1 ] = SKP_SMLABT( S[ d + 2 ], in16, B32 );
|
||||
}
|
||||
B32 = *( (SKP_int32*)&B[ d ] ); /* read two coefficients at once */
|
||||
S[ order - 2 ] = SKP_SMLABB( S[ order - 1 ], in16, B32 );
|
||||
S[ order - 1 ] = SKP_SMULBT( in16, B32 );
|
||||
|
||||
/* Limit */
|
||||
out[ k ] = (SKP_int16)SKP_SAT16( out32 );
|
||||
for( d = 0; d < order - 1; d++ ) {
|
||||
S[ d ] = SKP_SMLABB_ovflw( S[ d + 1 ], in16, B[ d ] );
|
||||
}
|
||||
} else {
|
||||
/* Odd order or not 4-byte aligned coefficient array */
|
||||
for( k = 0; k < len; k++ ) {
|
||||
in16 = in[ k ];
|
||||
out32 = SKP_LSHIFT( in16, 13 ) - S[ 0 ];
|
||||
out32 = SKP_RSHIFT_ROUND( out32, 13 );
|
||||
|
||||
for( d = 0; d < order - 1; d++ ) {
|
||||
S[ d ] = SKP_SMLABB( S[ d + 1 ], in16, B[ d ] );
|
||||
}
|
||||
S[ order - 1 ] = SKP_SMULBB( in16, B[ order - 1 ] );
|
||||
S[ order - 1 ] = SKP_SMULBB( in16, B[ order - 1 ] );
|
||||
|
||||
/* Limit */
|
||||
out[ k ] = (SKP_int16)SKP_SAT16( out32 );
|
||||
}
|
||||
/* Limit */
|
||||
out[ k ] = (SKP_int16)SKP_SAT16( out32 );
|
||||
}
|
||||
}
|
||||
/* Variable order MA prediction error filter. */
|
||||
/* Inverse filter of SKP_Silk_LPC_synthesis_filter */
|
||||
|
||||
|
||||
void SKP_Silk_LPC_analysis_filter(
|
||||
const SKP_int16 *in, /* I: Input signal */
|
||||
const SKP_int16 *B, /* I: MA prediction coefficients, Q12 [order] */
|
||||
@@ -183,17 +74,11 @@ void SKP_Silk_LPC_analysis_filter(
|
||||
)
|
||||
{
|
||||
SKP_int k, j, idx, Order_half = SKP_RSHIFT( Order, 1 );
|
||||
SKP_int32 Btmp, B_align_Q12[ SigProc_MAX_ORDER_LPC >> 1 ], out32_Q12, out32;
|
||||
SKP_int32 out32_Q12, out32;
|
||||
SKP_int16 SA, SB;
|
||||
/* Order must be even */
|
||||
SKP_assert( 2 * Order_half == Order );
|
||||
|
||||
/* Combine two A_Q12 values and ensure 32-bit alignment */
|
||||
for( k = 0; k < Order_half; k++ ) {
|
||||
idx = SKP_SMULBB( 2, k );
|
||||
B_align_Q12[ k ] = ( ( (SKP_int32)B[ idx ] ) & 0x0000ffff ) | SKP_LSHIFT( (SKP_int32)B[ idx + 1 ], 16 );
|
||||
}
|
||||
|
||||
/* S[] values are in Q0 */
|
||||
for( k = 0; k < len; k++ ) {
|
||||
SA = S[ 0 ];
|
||||
@@ -201,21 +86,19 @@ void SKP_Silk_LPC_analysis_filter(
|
||||
for( j = 0; j < ( Order_half - 1 ); j++ ) {
|
||||
idx = SKP_SMULBB( 2, j ) + 1;
|
||||
/* Multiply-add two prediction coefficients for each loop */
|
||||
Btmp = B_align_Q12[ j ];
|
||||
SB = S[ idx ];
|
||||
S[ idx ] = SA;
|
||||
out32_Q12 = SKP_SMLABB( out32_Q12, SA, Btmp );
|
||||
out32_Q12 = SKP_SMLABT( out32_Q12, SB, Btmp );
|
||||
out32_Q12 = SKP_SMLABB( out32_Q12, SA, B[ idx - 1 ] );
|
||||
out32_Q12 = SKP_SMLABB( out32_Q12, SB, B[ idx ] );
|
||||
SA = S[ idx + 1 ];
|
||||
S[ idx + 1 ] = SB;
|
||||
}
|
||||
|
||||
/* Unrolled loop: epilog */
|
||||
Btmp = B_align_Q12[ Order_half - 1 ];
|
||||
SB = S[ Order - 1 ];
|
||||
S[ Order - 1 ] = SA;
|
||||
out32_Q12 = SKP_SMLABB( out32_Q12, SA, Btmp );
|
||||
out32_Q12 = SKP_SMLABT( out32_Q12, SB, Btmp );
|
||||
out32_Q12 = SKP_SMLABB( out32_Q12, SA, B[ Order - 2 ] );
|
||||
out32_Q12 = SKP_SMLABB( out32_Q12, SB, B[ Order - 1 ] );
|
||||
|
||||
/* Subtract prediction */
|
||||
out32_Q12 = SKP_SUB_SAT32( SKP_LSHIFT( (SKP_int32)in[ k ], 12 ), out32_Q12 );
|
||||
@@ -224,7 +107,7 @@ void SKP_Silk_LPC_analysis_filter(
|
||||
out32 = SKP_RSHIFT_ROUND( out32_Q12, 12 );
|
||||
|
||||
/* Saturate output */
|
||||
out[ k ] = (SKP_int16)SKP_SAT16( out32 );
|
||||
out[ k ] = ( SKP_int16 )SKP_SAT16( out32 );
|
||||
|
||||
/* Move input line */
|
||||
S[ 0 ] = in[ k ];
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
@@ -63,13 +63,13 @@ void SKP_Silk_NLSF2A(
|
||||
)
|
||||
{
|
||||
SKP_int k, i, dd;
|
||||
SKP_int32 cos_LSF_Q20[SigProc_MAX_ORDER_LPC];
|
||||
SKP_int32 P[SigProc_MAX_ORDER_LPC/2+1], Q[SigProc_MAX_ORDER_LPC/2+1];
|
||||
SKP_int32 cos_LSF_Q20[SKP_Silk_MAX_ORDER_LPC];
|
||||
SKP_int32 P[SKP_Silk_MAX_ORDER_LPC/2+1], Q[SKP_Silk_MAX_ORDER_LPC/2+1];
|
||||
SKP_int32 Ptmp, Qtmp;
|
||||
SKP_int32 f_int;
|
||||
SKP_int32 f_frac;
|
||||
SKP_int32 cos_val, delta;
|
||||
SKP_int32 a_int32[SigProc_MAX_ORDER_LPC];
|
||||
SKP_int32 a_int32[SKP_Silk_MAX_ORDER_LPC];
|
||||
SKP_int32 maxabs, absval, idx=0, sc_Q16;
|
||||
|
||||
SKP_assert(LSF_COS_TAB_SZ_FIX == 128);
|
||||
@@ -127,6 +127,7 @@ void SKP_Silk_NLSF2A(
|
||||
|
||||
if( maxabs > SKP_int16_MAX ) {
|
||||
/* Reduce magnitude of prediction coefficients */
|
||||
maxabs = SKP_min( maxabs, 98369 ); // ( SKP_int32_MAX / ( 65470 >> 2 ) ) + SKP_int16_MAX = 98369
|
||||
sc_Q16 = 65470 - SKP_DIV32( SKP_MUL( 65470 >> 2, maxabs - SKP_int16_MAX ),
|
||||
SKP_RSHIFT32( SKP_MUL( maxabs, idx + 1), 2 ) );
|
||||
SKP_Silk_bwexpander_32( a_int32, d, sc_Q16 );
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
@@ -42,7 +42,7 @@ void SKP_Silk_NLSF2A_stable(
|
||||
/* Ensure stable LPCs */
|
||||
for( i = 0; i < MAX_LPC_STABILIZE_ITERATIONS; i++ ) {
|
||||
if( SKP_Silk_LPC_inverse_pred_gain( &invGain_Q30, pAR_Q12, LPC_order ) == 1 ) {
|
||||
SKP_Silk_bwexpander( pAR_Q12, LPC_order, 65536 - SKP_SMULBB( 66, i ) ); /* 66_Q16 = 0.001 */
|
||||
SKP_Silk_bwexpander( pAR_Q12, LPC_order, 65536 - SKP_SMULBB( 10 + i, i ) ); /* 10_Q16 = 0.00015 */
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
@@ -50,6 +50,7 @@ void SKP_Silk_NLSF2A_stable(
|
||||
|
||||
/* Reached the last iteration */
|
||||
if( i == MAX_LPC_STABILIZE_ITERATIONS ) {
|
||||
SKP_assert( 0 );
|
||||
for( i = 0; i < LPC_order; i++ ) {
|
||||
pAR_Q12[ i ] = 0;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
@@ -43,9 +43,8 @@ void SKP_Silk_NLSF_MSVQ_encode_FIX(
|
||||
const SKP_int deactivate_fluc_red /* I Deactivate fluctuation reduction */
|
||||
)
|
||||
{
|
||||
SKP_int i, s, k, cur_survivors = 0, prev_survivors, input_index, cb_index, bestIndex;
|
||||
SKP_int i, s, k, cur_survivors = 0, prev_survivors, min_survivors, input_index, cb_index, bestIndex;
|
||||
SKP_int32 rateDistThreshold_Q18;
|
||||
SKP_int pNLSF_in_Q15[ MAX_LPC_ORDER ];
|
||||
#if( NLSF_MSVQ_FLUCTUATION_REDUCTION == 1 )
|
||||
SKP_int32 se_Q15, wsse_Q20, bestRateDist_Q20;
|
||||
#endif
|
||||
@@ -75,14 +74,15 @@ void SKP_Silk_NLSF_MSVQ_encode_FIX(
|
||||
const SKP_int16 *pCB_element;
|
||||
const SKP_Silk_NLSF_CBS *pCurrentCBStage;
|
||||
|
||||
#ifdef USE_UNQUANTIZED_LSFS
|
||||
SKP_int NLSF_orig[ MAX_LPC_ORDER ];
|
||||
SKP_memcpy( NLSF_orig, pNLSF_Q15, LPC_order * sizeof( SKP_int ) );
|
||||
#endif
|
||||
|
||||
SKP_assert( NLSF_MSVQ_Survivors <= MAX_NLSF_MSVQ_SURVIVORS );
|
||||
SKP_assert( ( LOW_COMPLEXITY_ONLY == 0 ) || ( NLSF_MSVQ_Survivors <= MAX_NLSF_MSVQ_SURVIVORS_LC_MODE ) );
|
||||
|
||||
|
||||
|
||||
/* Copy the input vector */
|
||||
SKP_memcpy( pNLSF_in_Q15, pNLSF_Q15, LPC_order * sizeof( SKP_int ) );
|
||||
|
||||
/****************************************************/
|
||||
/* Tree search for the multi-stage vector quantizer */
|
||||
/****************************************************/
|
||||
@@ -98,6 +98,9 @@ void SKP_Silk_NLSF_MSVQ_encode_FIX(
|
||||
/* Set first stage values */
|
||||
prev_survivors = 1;
|
||||
|
||||
/* Minimum number of survivors */
|
||||
min_survivors = NLSF_MSVQ_Survivors / 2;
|
||||
|
||||
/* Loop over all stages */
|
||||
for( s = 0; s < psNLSF_CB->nStages; s++ ) {
|
||||
|
||||
@@ -124,9 +127,10 @@ void SKP_Silk_NLSF_MSVQ_encode_FIX(
|
||||
prev_survivors * pCurrentCBStage->nVectors, cur_survivors );
|
||||
|
||||
/* Discard survivors with rate-distortion values too far above the best one */
|
||||
if( pRateDist_Q18[ 0 ] < SKP_int32_MAX / NLSF_MSVQ_SURV_MAX_REL_RD ) {
|
||||
rateDistThreshold_Q18 = SKP_MUL( NLSF_MSVQ_SURV_MAX_REL_RD, pRateDist_Q18[ 0 ] );
|
||||
while( pRateDist_Q18[ cur_survivors - 1 ] > rateDistThreshold_Q18 && cur_survivors > 1 ) {
|
||||
if( pRateDist_Q18[ 0 ] < SKP_int32_MAX / MAX_NLSF_MSVQ_SURVIVORS ) {
|
||||
rateDistThreshold_Q18 = SKP_SMLAWB( pRateDist_Q18[ 0 ],
|
||||
SKP_MUL( NLSF_MSVQ_Survivors, pRateDist_Q18[ 0 ] ), SKP_FIX_CONST( NLSF_MSVQ_SURV_MAX_REL_RD, 16 ) );
|
||||
while( pRateDist_Q18[ cur_survivors - 1 ] > rateDistThreshold_Q18 && cur_survivors > min_survivors ) {
|
||||
cur_survivors--;
|
||||
}
|
||||
}
|
||||
@@ -228,4 +232,8 @@ void SKP_Silk_NLSF_MSVQ_encode_FIX(
|
||||
/* Decode and stabilize the best survivor */
|
||||
SKP_Silk_NLSF_MSVQ_decode( pNLSF_Q15, psNLSF_CB, NLSFIndices, LPC_order );
|
||||
|
||||
#ifdef USE_UNQUANTIZED_LSFS
|
||||
SKP_memcpy( pNLSF_Q15, NLSF_orig, LPC_order * sizeof( SKP_int ) );
|
||||
#endif
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
@@ -27,6 +27,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "SKP_Silk_main_FIX.h"
|
||||
|
||||
|
||||
/* Compute weighted quantization errors for an LPC_order element input vector, over one codebook stage */
|
||||
void SKP_Silk_NLSF_VQ_sum_error_FIX(
|
||||
SKP_int32 *err_Q20, /* O Weighted quantization errors [N*K] */
|
||||
@@ -77,3 +78,4 @@ void SKP_Silk_NLSF_VQ_sum_error_FIX(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
@@ -34,6 +34,7 @@ Signal Processing, pp. 641-644, 1991.
|
||||
*/
|
||||
|
||||
#define Q_OUT 6
|
||||
#define MIN_NDELTA 3
|
||||
|
||||
/* Laroia low complexity NLSF weights */
|
||||
void SKP_Silk_NLSF_VQ_weights_laroia(
|
||||
@@ -50,28 +51,28 @@ void SKP_Silk_NLSF_VQ_weights_laroia(
|
||||
SKP_assert( ( D & 1 ) == 0 );
|
||||
|
||||
/* First value */
|
||||
tmp1_int = SKP_max_int( pNLSF_Q15[ 0 ], 1 );
|
||||
tmp1_int = SKP_max_int( pNLSF_Q15[ 0 ], MIN_NDELTA );
|
||||
tmp1_int = SKP_DIV32_16( 1 << ( 15 + Q_OUT ), tmp1_int );
|
||||
tmp2_int = SKP_max_int( pNLSF_Q15[ 1 ] - pNLSF_Q15[ 0 ], 1 );
|
||||
tmp2_int = SKP_max_int( pNLSF_Q15[ 1 ] - pNLSF_Q15[ 0 ], MIN_NDELTA );
|
||||
tmp2_int = SKP_DIV32_16( 1 << ( 15 + Q_OUT ), tmp2_int );
|
||||
pNLSFW_Q6[ 0 ] = (SKP_int)SKP_min_int( tmp1_int + tmp2_int, SKP_int16_MAX );
|
||||
SKP_assert( pNLSFW_Q6[ 0 ] > 0 );
|
||||
|
||||
/* Main loop */
|
||||
for( k = 1; k < D - 1; k += 2 ) {
|
||||
tmp1_int = SKP_max_int( pNLSF_Q15[ k + 1 ] - pNLSF_Q15[ k ], 1 );
|
||||
tmp1_int = SKP_max_int( pNLSF_Q15[ k + 1 ] - pNLSF_Q15[ k ], MIN_NDELTA );
|
||||
tmp1_int = SKP_DIV32_16( 1 << ( 15 + Q_OUT ), tmp1_int );
|
||||
pNLSFW_Q6[ k ] = (SKP_int)SKP_min_int( tmp1_int + tmp2_int, SKP_int16_MAX );
|
||||
SKP_assert( pNLSFW_Q6[ k ] > 0 );
|
||||
|
||||
tmp2_int = SKP_max_int( pNLSF_Q15[ k + 2 ] - pNLSF_Q15[ k + 1 ], 1 );
|
||||
tmp2_int = SKP_max_int( pNLSF_Q15[ k + 2 ] - pNLSF_Q15[ k + 1 ], MIN_NDELTA );
|
||||
tmp2_int = SKP_DIV32_16( 1 << ( 15 + Q_OUT ), tmp2_int );
|
||||
pNLSFW_Q6[ k + 1 ] = (SKP_int)SKP_min_int( tmp1_int + tmp2_int, SKP_int16_MAX );
|
||||
SKP_assert( pNLSFW_Q6[ k + 1 ] > 0 );
|
||||
}
|
||||
|
||||
/* Last value */
|
||||
tmp1_int = SKP_max_int( ( 1 << 15 ) - pNLSF_Q15[ D - 1 ], 1 );
|
||||
tmp1_int = SKP_max_int( ( 1 << 15 ) - pNLSF_Q15[ D - 1 ], MIN_NDELTA );
|
||||
tmp1_int = SKP_DIV32_16( 1 << ( 15 + Q_OUT ), tmp1_int );
|
||||
pNLSFW_Q6[ D - 1 ] = (SKP_int)SKP_min_int( tmp1_int + tmp2_int, SKP_int16_MAX );
|
||||
SKP_assert( pNLSFW_Q6[ D - 1 ] > 0 );
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
@@ -106,7 +106,7 @@ void SKP_Silk_NLSF_stabilize(
|
||||
max_center_Q15 -= ( NDeltaMin_Q15[I] - SKP_RSHIFT( NDeltaMin_Q15[I], 1 ) );
|
||||
|
||||
/* Move apart, sorted by value, keeping the same center frequency */
|
||||
center_freq_Q15 = SKP_LIMIT( SKP_RSHIFT_ROUND( (SKP_int32)NLSF_Q15[I-1] + (SKP_int32)NLSF_Q15[I], 1 ),
|
||||
center_freq_Q15 = SKP_LIMIT_32( SKP_RSHIFT_ROUND( (SKP_int32)NLSF_Q15[I-1] + (SKP_int32)NLSF_Q15[I], 1 ),
|
||||
min_center_Q15, max_center_Q15 );
|
||||
NLSF_Q15[I-1] = center_freq_Q15 - SKP_RSHIFT( NDeltaMin_Q15[I], 1 );
|
||||
NLSF_Q15[I] = NLSF_Q15[I-1] + NDeltaMin_Q15[I];
|
||||
@@ -137,18 +137,3 @@ void SKP_Silk_NLSF_stabilize(
|
||||
}
|
||||
}
|
||||
|
||||
/* NLSF stabilizer, over multiple input column data vectors */
|
||||
void SKP_Silk_NLSF_stabilize_multi(
|
||||
SKP_int *NLSF_Q15, /* I/O: Unstable/stabilized normalized LSF vectors in Q15 [LxN] */
|
||||
const SKP_int *NDeltaMin_Q15, /* I: Normalized delta min vector in Q15, NDeltaMin_Q15[L] must be >= 1 [L+1] */
|
||||
const SKP_int N, /* I: Number of input vectors to be stabilized */
|
||||
const SKP_int L /* I: NLSF vector dimension */
|
||||
)
|
||||
{
|
||||
SKP_int n;
|
||||
|
||||
/* loop over input data */
|
||||
for( n = 0; n < N; n++ ) {
|
||||
SKP_Silk_NLSF_stabilize( &NLSF_Q15[n * L], NDeltaMin_Q15, L );
|
||||
}
|
||||
}
|
||||
+105
-128
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
@@ -31,8 +31,8 @@ SKP_INLINE void SKP_Silk_nsq_scale_states(
|
||||
SKP_Silk_nsq_state *NSQ, /* I/O NSQ state */
|
||||
const SKP_int16 x[], /* I input in Q0 */
|
||||
SKP_int32 x_sc_Q10[], /* O input scaled with 1/Gain */
|
||||
SKP_int length, /* I length of input */
|
||||
SKP_int16 sLTP[], /* I re-whitened LTP state in Q0 */
|
||||
SKP_int subfr_length, /* I length of input */
|
||||
const SKP_int16 sLTP[], /* I re-whitened LTP state in Q0 */
|
||||
SKP_int32 sLTP_Q16[], /* O LTP state matching scaled input */
|
||||
SKP_int subfr, /* I subframe number */
|
||||
const SKP_int LTP_scale_Q14, /* I */
|
||||
@@ -44,7 +44,7 @@ SKP_INLINE void SKP_Silk_noise_shape_quantizer(
|
||||
SKP_Silk_nsq_state *NSQ, /* I/O NSQ state */
|
||||
SKP_int sigtype, /* I Signal type */
|
||||
const SKP_int32 x_sc_Q10[], /* I */
|
||||
SKP_int q[], /* O */
|
||||
SKP_int8 q[], /* O */
|
||||
SKP_int16 xq[], /* O */
|
||||
SKP_int32 sLTP_Q16[], /* I/O LTP state */
|
||||
const SKP_int16 a_Q12[], /* I Short term prediction coefs */
|
||||
@@ -67,11 +67,11 @@ void SKP_Silk_NSQ(
|
||||
SKP_Silk_encoder_control *psEncCtrlC, /* I Encoder Control */
|
||||
SKP_Silk_nsq_state *NSQ, /* I/O NSQ state */
|
||||
const SKP_int16 x[], /* I prefiltered input signal */
|
||||
SKP_int q[], /* O quantized qulse signal */
|
||||
SKP_int8 q[], /* O quantized qulse signal */
|
||||
const SKP_int LSFInterpFactor_Q2, /* I LSF interpolation factor in Q2 */
|
||||
const SKP_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefficients */
|
||||
const SKP_int16 LTPCoef_Q14[ LTP_ORDER * NB_SUBFR ], /* I Long term prediction coefficients */
|
||||
const SKP_int16 AR2_Q13[ NB_SUBFR * SHAPE_LPC_ORDER_MAX ], /* I */
|
||||
const SKP_int16 AR2_Q13[ NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I */
|
||||
const SKP_int HarmShapeGain_Q14[ NB_SUBFR ], /* I */
|
||||
const SKP_int Tilt_Q14[ NB_SUBFR ], /* I Spectral tilt */
|
||||
const SKP_int32 LF_shp_Q14[ NB_SUBFR ], /* I */
|
||||
@@ -113,25 +113,26 @@ void SKP_Silk_NSQ(
|
||||
for( k = 0; k < NB_SUBFR; k++ ) {
|
||||
A_Q12 = &PredCoef_Q12[ (( k >> 1 ) | ( 1 - LSF_interpolation_flag )) * MAX_LPC_ORDER ];
|
||||
B_Q14 = <PCoef_Q14[ k * LTP_ORDER ];
|
||||
AR_shp_Q13 = &AR2_Q13[ k * SHAPE_LPC_ORDER_MAX ];
|
||||
AR_shp_Q13 = &AR2_Q13[ k * MAX_SHAPE_LPC_ORDER ];
|
||||
|
||||
/* Noise shape parameters */
|
||||
SKP_assert( HarmShapeGain_Q14[ k ] >= 0 );
|
||||
HarmShapeFIRPacked_Q14 = SKP_RSHIFT( HarmShapeGain_Q14[ k ], 2 );
|
||||
HarmShapeFIRPacked_Q14 = SKP_RSHIFT( HarmShapeGain_Q14[ k ], 2 );
|
||||
HarmShapeFIRPacked_Q14 |= SKP_LSHIFT( ( SKP_int32 )SKP_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 );
|
||||
|
||||
NSQ->rewhite_flag = 0;
|
||||
if( psEncCtrlC->sigtype == SIG_TYPE_VOICED ) {
|
||||
/* Voiced */
|
||||
lag = psEncCtrlC->pitchL[ k ];
|
||||
|
||||
NSQ->rewhite_flag = 0;
|
||||
/* Re-whitening */
|
||||
if( ( k & ( 3 - SKP_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) {
|
||||
|
||||
/* Rewhiten with new A coefs */
|
||||
|
||||
start_idx = psEncC->frame_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2;
|
||||
start_idx = SKP_LIMIT( start_idx, 0, psEncC->frame_length - psEncC->predictLPCOrder ); /* Limit */
|
||||
|
||||
SKP_assert( start_idx >= 0 );
|
||||
SKP_assert( start_idx <= psEncC->frame_length - psEncC->predictLPCOrder );
|
||||
|
||||
SKP_memset( FiltState, 0, psEncC->predictLPCOrder * sizeof( SKP_int32 ) );
|
||||
SKP_Silk_MA_Prediction( &NSQ->xq[ start_idx + k * ( psEncC->frame_length >> 2 ) ],
|
||||
A_Q12, FiltState, sLTP + start_idx, psEncC->frame_length - start_idx, psEncC->predictLPCOrder );
|
||||
@@ -154,14 +155,17 @@ void SKP_Silk_NSQ(
|
||||
pxq += psEncC->subfr_length;
|
||||
}
|
||||
|
||||
/* Save scalars for this layer */
|
||||
NSQ->sLF_AR_shp_Q12 = NSQ->sLF_AR_shp_Q12;
|
||||
NSQ->prev_inv_gain_Q16 = NSQ->prev_inv_gain_Q16;
|
||||
NSQ->lagPrev = psEncCtrlC->pitchL[ NB_SUBFR - 1 ];
|
||||
/* Update lagPrev for next frame */
|
||||
NSQ->lagPrev = psEncCtrlC->pitchL[ NB_SUBFR - 1 ];
|
||||
|
||||
/* Save quantized speech and noise shaping signals */
|
||||
SKP_memcpy( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->frame_length * sizeof( SKP_int16 ) );
|
||||
SKP_memcpy( NSQ->sLTP_shp_Q10, &NSQ->sLTP_shp_Q10[ psEncC->frame_length ], psEncC->frame_length * sizeof( SKP_int32 ) );
|
||||
|
||||
#ifdef USE_UNQUANTIZED_LSFS
|
||||
DEBUG_STORE_DATA( xq_unq_lsfs.pcm, NSQ->xq, psEncC->frame_length * sizeof( SKP_int16 ) );
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/***********************************/
|
||||
@@ -171,7 +175,7 @@ SKP_INLINE void SKP_Silk_noise_shape_quantizer(
|
||||
SKP_Silk_nsq_state *NSQ, /* I/O NSQ state */
|
||||
SKP_int sigtype, /* I Signal type */
|
||||
const SKP_int32 x_sc_Q10[], /* I */
|
||||
SKP_int q[], /* O */
|
||||
SKP_int8 q[], /* O */
|
||||
SKP_int16 xq[], /* O */
|
||||
SKP_int32 sLTP_Q16[], /* I/O LTP state */
|
||||
const SKP_int16 a_Q12[], /* I Short term prediction coefs */
|
||||
@@ -193,29 +197,22 @@ SKP_INLINE void SKP_Silk_noise_shape_quantizer(
|
||||
SKP_int32 LTP_pred_Q14, LPC_pred_Q10, n_AR_Q10, n_LTP_Q14;
|
||||
SKP_int32 n_LF_Q10, r_Q10, q_Q0, q_Q10;
|
||||
SKP_int32 thr1_Q10, thr2_Q10, thr3_Q10;
|
||||
SKP_int32 Atmp, dither;
|
||||
SKP_int32 exc_Q10, LPC_exc_Q10, xq_Q10;
|
||||
SKP_int32 tmp, sLF_AR_shp_Q10;
|
||||
SKP_int32 *psLPC_Q14;
|
||||
SKP_int32 *shp_lag_ptr, *pred_lag_ptr;
|
||||
SKP_int32 a_Q12_tmp[ MAX_LPC_ORDER / 2 ], AR_shp_Q13_tmp[ MAX_LPC_ORDER / 2 ];
|
||||
SKP_int32 dither, exc_Q10, LPC_exc_Q10, xq_Q10;
|
||||
SKP_int32 tmp1, tmp2, sLF_AR_shp_Q10;
|
||||
SKP_int32 *psLPC_Q14, *shp_lag_ptr, *pred_lag_ptr;
|
||||
|
||||
shp_lag_ptr = &NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ];
|
||||
pred_lag_ptr = &sLTP_Q16[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ];
|
||||
|
||||
/* Setup short term AR state */
|
||||
psLPC_Q14 = &NSQ->sLPC_Q14[ MAX_LPC_ORDER - 1 ];
|
||||
psLPC_Q14 = &NSQ->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 ];
|
||||
|
||||
/* Quantization thresholds */
|
||||
thr1_Q10 = SKP_SUB_RSHIFT32( -1536, Lambda_Q10, 1);
|
||||
thr2_Q10 = SKP_SUB_RSHIFT32( -512, Lambda_Q10, 1);
|
||||
thr1_Q10 = SKP_SUB_RSHIFT32( -1536, Lambda_Q10, 1 );
|
||||
thr2_Q10 = SKP_SUB_RSHIFT32( -512, Lambda_Q10, 1 );
|
||||
thr2_Q10 = SKP_ADD_RSHIFT32( thr2_Q10, SKP_SMULBB( offset_Q10, Lambda_Q10 ), 10 );
|
||||
thr3_Q10 = SKP_ADD_RSHIFT32( 512, Lambda_Q10, 1);
|
||||
|
||||
/* Preload LPC coeficients to array on stack. Gives small performance gain */
|
||||
SKP_memcpy( a_Q12_tmp, a_Q12, predictLPCOrder * sizeof( SKP_int16 ) );
|
||||
SKP_memcpy( AR_shp_Q13_tmp, AR_shp_Q13, shapingLPCOrder * sizeof( SKP_int16 ) );
|
||||
|
||||
thr3_Q10 = SKP_ADD_RSHIFT32( 512, Lambda_Q10, 1 );
|
||||
|
||||
for( i = 0; i < length; i++ ) {
|
||||
/* Generate dither */
|
||||
NSQ->rand_seed = SKP_RAND( NSQ->rand_seed );
|
||||
@@ -225,35 +222,23 @@ SKP_INLINE void SKP_Silk_noise_shape_quantizer(
|
||||
|
||||
/* Short-term prediction */
|
||||
SKP_assert( ( predictLPCOrder & 1 ) == 0 ); /* check that order is even */
|
||||
SKP_assert( ( (SKP_int64)a_Q12 & 3 ) == 0 ); /* check that array starts at 4-byte aligned address */
|
||||
/* check that array starts at 4-byte aligned address */
|
||||
SKP_assert( ( ( SKP_int64 )( ( SKP_int8* )a_Q12 - ( SKP_int8* )0 ) & 3 ) == 0 );
|
||||
SKP_assert( predictLPCOrder >= 10 ); /* check that unrolling works */
|
||||
|
||||
/* NOTE: the code below loads two int16 values in an int32, and multiplies each using the */
|
||||
/* SMLAWB and SMLAWT instructions. On a big-endian CPU the two int16 variables would be */
|
||||
/* loaded in reverse order and the code will give the wrong result. In that case swapping */
|
||||
/* the SMLAWB and SMLAWT instructions should solve the problem. */
|
||||
/* Partially unrolled */
|
||||
Atmp = a_Q12_tmp[ 0 ]; /* read two coefficients at once */
|
||||
LPC_pred_Q10 = SKP_SMULWB( psLPC_Q14[ 0 ], Atmp );
|
||||
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psLPC_Q14[ -1 ], Atmp );
|
||||
Atmp = a_Q12_tmp[ 1 ];
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -2 ], Atmp );
|
||||
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psLPC_Q14[ -3 ], Atmp );
|
||||
Atmp = a_Q12_tmp[ 2 ];
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -4 ], Atmp );
|
||||
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psLPC_Q14[ -5 ], Atmp );
|
||||
Atmp = a_Q12_tmp[ 3 ];
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -6 ], Atmp );
|
||||
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psLPC_Q14[ -7 ], Atmp );
|
||||
Atmp = a_Q12_tmp[ 4 ];
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -8 ], Atmp );
|
||||
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psLPC_Q14[ -9 ], Atmp );
|
||||
for( j = 10; j < predictLPCOrder; j += 2 ) {
|
||||
Atmp = a_Q12_tmp[ j >> 1 ]; /* read two coefficients at once */
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -j ], Atmp );
|
||||
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psLPC_Q14[ -j - 1 ], Atmp );
|
||||
LPC_pred_Q10 = SKP_SMULWB( psLPC_Q14[ 0 ], a_Q12[ 0 ] );
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -1 ], a_Q12[ 1 ] );
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -2 ], a_Q12[ 2 ] );
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -3 ], a_Q12[ 3 ] );
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -4 ], a_Q12[ 4 ] );
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -5 ], a_Q12[ 5 ] );
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -6 ], a_Q12[ 6 ] );
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -7 ], a_Q12[ 7 ] );
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -8 ], a_Q12[ 8 ] );
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -9 ], a_Q12[ 9 ] );
|
||||
for( j = 10; j < predictLPCOrder; j ++ ) {
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -j ], a_Q12[ j ] );
|
||||
}
|
||||
|
||||
/* Long-term prediction */
|
||||
if( sigtype == SIG_TYPE_VOICED ) {
|
||||
/* Unrolled loop */
|
||||
@@ -268,83 +253,73 @@ SKP_INLINE void SKP_Silk_noise_shape_quantizer(
|
||||
}
|
||||
|
||||
/* Noise shape feedback */
|
||||
SKP_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
|
||||
SKP_assert( ( (SKP_int64)AR_shp_Q13 & 3 ) == 0 ); /* check that array starts at 4-byte aligned address */
|
||||
SKP_assert( shapingLPCOrder >= 12 ); /* check that unrolling works */
|
||||
|
||||
/* Partially unrolled */
|
||||
Atmp = AR_shp_Q13_tmp[ 0 ]; /* read two coefficients at once */
|
||||
n_AR_Q10 = SKP_SMULWB( psLPC_Q14[ 0 ], Atmp );
|
||||
n_AR_Q10 = SKP_SMLAWT( n_AR_Q10, psLPC_Q14[ -1 ], Atmp );
|
||||
Atmp = AR_shp_Q13_tmp[ 1 ];
|
||||
n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, psLPC_Q14[ -2 ], Atmp );
|
||||
n_AR_Q10 = SKP_SMLAWT( n_AR_Q10, psLPC_Q14[ -3 ], Atmp );
|
||||
Atmp = AR_shp_Q13_tmp[ 2 ];
|
||||
n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, psLPC_Q14[ -4 ], Atmp );
|
||||
n_AR_Q10 = SKP_SMLAWT( n_AR_Q10, psLPC_Q14[ -5 ], Atmp );
|
||||
Atmp = AR_shp_Q13_tmp[ 3 ];
|
||||
n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, psLPC_Q14[ -6 ], Atmp );
|
||||
n_AR_Q10 = SKP_SMLAWT( n_AR_Q10, psLPC_Q14[ -7 ], Atmp );
|
||||
Atmp = AR_shp_Q13_tmp[ 4 ];
|
||||
n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, psLPC_Q14[ -8 ], Atmp );
|
||||
n_AR_Q10 = SKP_SMLAWT( n_AR_Q10, psLPC_Q14[ -9 ], Atmp );
|
||||
Atmp = AR_shp_Q13_tmp[ 5 ];
|
||||
n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, psLPC_Q14[ -10 ], Atmp );
|
||||
n_AR_Q10 = SKP_SMLAWT( n_AR_Q10, psLPC_Q14[ -11 ], Atmp );
|
||||
for( j = 12; j < shapingLPCOrder; j += 2 ) {
|
||||
Atmp = AR_shp_Q13_tmp[ j >> 1 ]; /* read two coefficients at once */
|
||||
n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, psLPC_Q14[ -j ], Atmp );
|
||||
n_AR_Q10 = SKP_SMLAWT( n_AR_Q10, psLPC_Q14[ -j - 1 ], Atmp );
|
||||
SKP_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
|
||||
tmp2 = psLPC_Q14[ 0 ];
|
||||
tmp1 = NSQ->sAR2_Q14[ 0 ];
|
||||
NSQ->sAR2_Q14[ 0 ] = tmp2;
|
||||
n_AR_Q10 = SKP_SMULWB( tmp2, AR_shp_Q13[ 0 ] );
|
||||
for( j = 2; j < shapingLPCOrder; j += 2 ) {
|
||||
tmp2 = NSQ->sAR2_Q14[ j - 1 ];
|
||||
NSQ->sAR2_Q14[ j - 1 ] = tmp1;
|
||||
n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, tmp1, AR_shp_Q13[ j - 1 ] );
|
||||
tmp1 = NSQ->sAR2_Q14[ j + 0 ];
|
||||
NSQ->sAR2_Q14[ j + 0 ] = tmp2;
|
||||
n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, tmp2, AR_shp_Q13[ j ] );
|
||||
}
|
||||
NSQ->sAR2_Q14[ shapingLPCOrder - 1 ] = tmp1;
|
||||
n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, tmp1, AR_shp_Q13[ shapingLPCOrder - 1 ] );
|
||||
|
||||
n_AR_Q10 = SKP_RSHIFT( n_AR_Q10, 1 ); /* Q11 -> Q10 */
|
||||
n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, NSQ->sLF_AR_shp_Q12, Tilt_Q14 );
|
||||
n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, NSQ->sLF_AR_shp_Q12, Tilt_Q14 );
|
||||
|
||||
n_LF_Q10 = SKP_LSHIFT( SKP_SMULWB( NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - 1 ], LF_shp_Q14 ), 2 );
|
||||
n_LF_Q10 = SKP_SMLAWT( n_LF_Q10, NSQ->sLF_AR_shp_Q12, LF_shp_Q14 );
|
||||
n_LF_Q10 = SKP_LSHIFT( SKP_SMULWB( NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - 1 ], LF_shp_Q14 ), 2 );
|
||||
n_LF_Q10 = SKP_SMLAWT( n_LF_Q10, NSQ->sLF_AR_shp_Q12, LF_shp_Q14 );
|
||||
|
||||
SKP_assert( lag > 0 || sigtype == SIG_TYPE_UNVOICED);
|
||||
SKP_assert( lag > 0 || sigtype == SIG_TYPE_UNVOICED );
|
||||
|
||||
/* Long-term shaping */
|
||||
if( lag > 0 ) {
|
||||
/* Symmetric, packed FIR coefficients */
|
||||
n_LTP_Q14 = SKP_SMULWB( SKP_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 );
|
||||
n_LTP_Q14 = SKP_SMLAWT( n_LTP_Q14, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 );
|
||||
shp_lag_ptr++;
|
||||
n_LTP_Q14 = SKP_LSHIFT( n_LTP_Q14, 6 );
|
||||
shp_lag_ptr++;
|
||||
} else {
|
||||
n_LTP_Q14 = 0;
|
||||
}
|
||||
|
||||
/* Input minus prediction plus noise feedback */
|
||||
//r = x[ i ] - LTP_pred - LPC_pred + n_AR + n_Tilt + n_LF + n_LTP;
|
||||
tmp = SKP_SUB32( LTP_pred_Q14, n_LTP_Q14 ); /* Add Q14 stuff */
|
||||
tmp = SKP_RSHIFT_ROUND( tmp, 4 ); /* round to Q10 */
|
||||
tmp = SKP_ADD32( tmp, LPC_pred_Q10 ); /* add Q10 stuff */
|
||||
tmp = SKP_SUB32( tmp, n_AR_Q10 ); /* subtract Q10 stuff */
|
||||
tmp = SKP_SUB32( tmp, n_LF_Q10 ); /* subtract Q10 stuff */
|
||||
r_Q10 = SKP_SUB32( x_sc_Q10[ i ], tmp );
|
||||
|
||||
tmp1 = SKP_SUB32( LTP_pred_Q14, n_LTP_Q14 ); /* Add Q14 stuff */
|
||||
tmp1 = SKP_RSHIFT( tmp1, 4 ); /* convert to Q10 */
|
||||
tmp1 = SKP_ADD32( tmp1, LPC_pred_Q10 ); /* add Q10 stuff */
|
||||
tmp1 = SKP_SUB32( tmp1, n_AR_Q10 ); /* subtract Q10 stuff */
|
||||
tmp1 = SKP_SUB32( tmp1, n_LF_Q10 ); /* subtract Q10 stuff */
|
||||
r_Q10 = SKP_SUB32( x_sc_Q10[ i ], tmp1 );
|
||||
|
||||
/* Flip sign depending on dither */
|
||||
r_Q10 = ( r_Q10 ^ dither ) - dither;
|
||||
r_Q10 = SKP_SUB32( r_Q10, offset_Q10 );
|
||||
r_Q10 = SKP_LIMIT( r_Q10, -64 << 10, 64 << 10 );
|
||||
r_Q10 = SKP_LIMIT_32( r_Q10, -64 << 10, 64 << 10 );
|
||||
|
||||
/* Quantize */
|
||||
if( r_Q10 < thr1_Q10 ) {
|
||||
q_Q0 = SKP_RSHIFT_ROUND( SKP_ADD_RSHIFT32( r_Q10, Lambda_Q10, 1 ), 10 );
|
||||
q_Q10 = SKP_LSHIFT( q_Q0, 10 );
|
||||
} else if( r_Q10 < thr2_Q10 ) {
|
||||
q_Q0 = -1;
|
||||
q_Q10 = -1024;
|
||||
} else if( r_Q10 > thr3_Q10 ) {
|
||||
q_Q0 = SKP_RSHIFT_ROUND( SKP_SUB_RSHIFT32( r_Q10, Lambda_Q10, 1 ), 10 );
|
||||
q_Q10 = SKP_LSHIFT( q_Q0, 10 );
|
||||
q_Q0 = 0;
|
||||
q_Q10 = 0;
|
||||
if( r_Q10 < thr2_Q10 ) {
|
||||
if( r_Q10 < thr1_Q10 ) {
|
||||
q_Q0 = SKP_RSHIFT_ROUND( SKP_ADD_RSHIFT32( r_Q10, Lambda_Q10, 1 ), 10 );
|
||||
q_Q10 = SKP_LSHIFT( q_Q0, 10 );
|
||||
} else {
|
||||
q_Q0 = -1;
|
||||
q_Q10 = -1024;
|
||||
}
|
||||
} else {
|
||||
q_Q0 = 0;
|
||||
q_Q10 = 0;
|
||||
if( r_Q10 > thr3_Q10 ) {
|
||||
q_Q0 = SKP_RSHIFT_ROUND( SKP_SUB_RSHIFT32( r_Q10, Lambda_Q10, 1 ), 10 );
|
||||
q_Q10 = SKP_LSHIFT( q_Q0, 10 );
|
||||
}
|
||||
}
|
||||
q[ i ] = q_Q0;
|
||||
q[ i ] = ( SKP_int8 )q_Q0; /* No saturation needed because max is 64 */
|
||||
|
||||
/* Excitation */
|
||||
exc_Q10 = SKP_ADD32( q_Q10, offset_Q10 );
|
||||
@@ -365,23 +340,24 @@ SKP_INLINE void SKP_Silk_noise_shape_quantizer(
|
||||
NSQ->sLF_AR_shp_Q12 = SKP_LSHIFT( sLF_AR_shp_Q10, 2 );
|
||||
|
||||
NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx ] = SKP_SUB32( sLF_AR_shp_Q10, n_LF_Q10 );
|
||||
sLTP_Q16[NSQ->sLTP_buf_idx] = SKP_LSHIFT( LPC_exc_Q10, 6 );
|
||||
sLTP_Q16[ NSQ->sLTP_buf_idx ] = SKP_LSHIFT( LPC_exc_Q10, 6 );
|
||||
NSQ->sLTP_shp_buf_idx++;
|
||||
NSQ->sLTP_buf_idx++;
|
||||
|
||||
/* Make dither dependent on quantized signal */
|
||||
NSQ->rand_seed += q[ i ];
|
||||
}
|
||||
|
||||
/* Update LPC synth buffer */
|
||||
SKP_memcpy( NSQ->sLPC_Q14, &NSQ->sLPC_Q14[ length ], MAX_LPC_ORDER * sizeof( SKP_int32 ) );
|
||||
SKP_memcpy( NSQ->sLPC_Q14, &NSQ->sLPC_Q14[ length ], NSQ_LPC_BUF_LENGTH * sizeof( SKP_int32 ) );
|
||||
}
|
||||
|
||||
SKP_INLINE void SKP_Silk_nsq_scale_states(
|
||||
SKP_Silk_nsq_state *NSQ, /* I/O NSQ state */
|
||||
const SKP_int16 x[], /* I input in Q0 */
|
||||
SKP_int32 x_sc_Q10[], /* O input scaled with 1/Gain */
|
||||
SKP_int length, /* I length of input */
|
||||
SKP_int16 sLTP[], /* I re-whitened LTP state in Q0 */
|
||||
SKP_int subfr_length, /* I length of input */
|
||||
const SKP_int16 sLTP[], /* I re-whitened LTP state in Q0 */
|
||||
SKP_int32 sLTP_Q16[], /* O LTP state matching scaled input */
|
||||
SKP_int subfr, /* I subframe number */
|
||||
const SKP_int LTP_scale_Q14, /* I */
|
||||
@@ -389,14 +365,14 @@ SKP_INLINE void SKP_Silk_nsq_scale_states(
|
||||
const SKP_int pitchL[ NB_SUBFR ] /* I */
|
||||
)
|
||||
{
|
||||
SKP_int i, scale_length, lag;
|
||||
SKP_int i, lag;
|
||||
SKP_int32 inv_gain_Q16, gain_adj_Q16, inv_gain_Q32;
|
||||
|
||||
inv_gain_Q16 = SKP_DIV32( SKP_int32_MAX, SKP_RSHIFT( Gains_Q16[ subfr ], 1) );
|
||||
inv_gain_Q16 = SKP_INVERSE32_varQ( SKP_max( Gains_Q16[ subfr ], 1 ), 32 );
|
||||
inv_gain_Q16 = SKP_min( inv_gain_Q16, SKP_int16_MAX );
|
||||
lag = pitchL[ subfr ];
|
||||
|
||||
/* After rewhitening the LTP state is un-scaled */
|
||||
/* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */
|
||||
if( NSQ->rewhite_flag ) {
|
||||
inv_gain_Q32 = SKP_LSHIFT( inv_gain_Q16, 16 );
|
||||
if( subfr == 0 ) {
|
||||
@@ -404,39 +380,40 @@ SKP_INLINE void SKP_Silk_nsq_scale_states(
|
||||
inv_gain_Q32 = SKP_LSHIFT( SKP_SMULWB( inv_gain_Q32, LTP_scale_Q14 ), 2 );
|
||||
}
|
||||
for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) {
|
||||
SKP_assert( i < MAX_FRAME_LENGTH );
|
||||
sLTP_Q16[ i ] = SKP_SMULWB( inv_gain_Q32, sLTP[ i ] );
|
||||
}
|
||||
}
|
||||
|
||||
/* Prepare for Worst case. Next frame starts with max lag voiced */
|
||||
scale_length = length * NB_SUBFR; /* approx max lag */
|
||||
scale_length = scale_length - SKP_SMULBB( NB_SUBFR - (subfr + 1), length ); /* subtract samples that will be too old in next frame */
|
||||
scale_length = SKP_max_int( scale_length, lag + LTP_ORDER ); /* make sure to scale whole pitch period if voiced */
|
||||
|
||||
/* Adjust for changing gain */
|
||||
if( inv_gain_Q16 != NSQ->prev_inv_gain_Q16 ) {
|
||||
gain_adj_Q16 = SKP_DIV32_varQ( inv_gain_Q16, NSQ->prev_inv_gain_Q16, 16 );
|
||||
gain_adj_Q16 = SKP_DIV32_varQ( inv_gain_Q16, NSQ->prev_inv_gain_Q16, 16 );
|
||||
|
||||
for( i = NSQ->sLTP_shp_buf_idx - scale_length; i < NSQ->sLTP_shp_buf_idx; i++ ) {
|
||||
/* Scale long-term shaping state */
|
||||
for( i = NSQ->sLTP_shp_buf_idx - subfr_length * NB_SUBFR; i < NSQ->sLTP_shp_buf_idx; i++ ) {
|
||||
NSQ->sLTP_shp_Q10[ i ] = SKP_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q10[ i ] );
|
||||
}
|
||||
|
||||
/* Scale LTP predict state */
|
||||
/* Scale long-term prediction state */
|
||||
if( NSQ->rewhite_flag == 0 ) {
|
||||
for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) {
|
||||
sLTP_Q16[ i ] = SKP_SMULWW( gain_adj_Q16, sLTP_Q16[ i ] );
|
||||
}
|
||||
}
|
||||
|
||||
NSQ->sLF_AR_shp_Q12 = SKP_SMULWW( gain_adj_Q16, NSQ->sLF_AR_shp_Q12 );
|
||||
|
||||
/* scale short term state */
|
||||
for( i = 0; i < MAX_LPC_ORDER; i++ ) {
|
||||
/* Scale short-term prediction and shaping states */
|
||||
for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) {
|
||||
NSQ->sLPC_Q14[ i ] = SKP_SMULWW( gain_adj_Q16, NSQ->sLPC_Q14[ i ] );
|
||||
}
|
||||
for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) {
|
||||
NSQ->sAR2_Q14[ i ] = SKP_SMULWW( gain_adj_Q16, NSQ->sAR2_Q14[ i ] );
|
||||
}
|
||||
}
|
||||
|
||||
/* Scale input */
|
||||
for( i = 0; i < length; i++ ) {
|
||||
for( i = 0; i < subfr_length; i++ ) {
|
||||
x_sc_Q10[ i ] = SKP_RSHIFT( SKP_SMULBB( x[ i ], ( SKP_int16 )inv_gain_Q16 ), 6 );
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
@@ -28,12 +28,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "SKP_Silk_main.h"
|
||||
|
||||
typedef struct {
|
||||
SKP_int RandState[ DECISION_DELAY ];
|
||||
SKP_int32 RandState[ DECISION_DELAY ];
|
||||
SKP_int32 Q_Q10[ DECISION_DELAY ];
|
||||
SKP_int32 Xq_Q10[ DECISION_DELAY ];
|
||||
SKP_int32 Pred_Q16[ DECISION_DELAY ];
|
||||
SKP_int32 Shape_Q10[ DECISION_DELAY ];
|
||||
SKP_int32 Gain_Q16[ DECISION_DELAY ];
|
||||
SKP_int32 sAR2_Q14[ MAX_SHAPE_LPC_ORDER ];
|
||||
SKP_int32 sLPC_Q14[ MAX_FRAME_LENGTH / NB_SUBFR + NSQ_LPC_BUF_LENGTH ];
|
||||
SKP_int32 LF_AR_Q12;
|
||||
SKP_int32 Seed;
|
||||
@@ -61,8 +62,8 @@ SKP_INLINE void SKP_Silk_nsq_del_dec_scale_states(
|
||||
NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */
|
||||
const SKP_int16 x[], /* I Input in Q0 */
|
||||
SKP_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */
|
||||
SKP_int length, /* I Length of input */
|
||||
SKP_int16 sLTP[], /* I Re-whitened LTP state in Q0 */
|
||||
SKP_int subfr_length, /* I Length of input */
|
||||
const SKP_int16 sLTP[], /* I Re-whitened LTP state in Q0 */
|
||||
SKP_int32 sLTP_Q16[], /* O LTP state matching scaled input */
|
||||
SKP_int subfr, /* I Subframe number */
|
||||
SKP_int nStatesDelayedDecision, /* I Number of del dec states */
|
||||
@@ -80,7 +81,7 @@ SKP_INLINE void SKP_Silk_noise_shape_quantizer_del_dec(
|
||||
NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */
|
||||
SKP_int sigtype, /* I Signal type */
|
||||
const SKP_int32 x_Q10[], /* I */
|
||||
SKP_int q[], /* O */
|
||||
SKP_int8 q[], /* O */
|
||||
SKP_int16 xq[], /* O */
|
||||
SKP_int32 sLTP_Q16[], /* I/O LTP filter state */
|
||||
const SKP_int16 a_Q12[], /* I Short term prediction coefs */
|
||||
@@ -96,7 +97,8 @@ SKP_INLINE void SKP_Silk_noise_shape_quantizer_del_dec(
|
||||
SKP_int length, /* I Input length */
|
||||
SKP_int subfr, /* I Subframe number */
|
||||
SKP_int shapingLPCOrder, /* I Shaping LPC filter order */
|
||||
SKP_int predictLPCOrder, /* I Prediction LPC filter order */
|
||||
SKP_int predictLPCOrder, /* I Prediction filter order */
|
||||
SKP_int warping_Q16, /* I */
|
||||
SKP_int nStatesDelayedDecision, /* I Number of states in decision tree */
|
||||
SKP_int *smpl_buf_idx, /* I Index to newest samples in buffers */
|
||||
SKP_int decisionDelay /* I */
|
||||
@@ -107,11 +109,11 @@ void SKP_Silk_NSQ_del_dec(
|
||||
SKP_Silk_encoder_control *psEncCtrlC, /* I Encoder Control */
|
||||
SKP_Silk_nsq_state *NSQ, /* I/O NSQ state */
|
||||
const SKP_int16 x[], /* I Prefiltered input signal */
|
||||
SKP_int q[], /* O Quantized pulse signal */
|
||||
SKP_int8 q[], /* O Quantized pulse signal */
|
||||
const SKP_int LSFInterpFactor_Q2, /* I LSF interpolation factor in Q2 */
|
||||
const SKP_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Prediction coefs */
|
||||
const SKP_int16 LTPCoef_Q14[ LTP_ORDER * NB_SUBFR ], /* I LT prediction coefs */
|
||||
const SKP_int16 AR2_Q13[ NB_SUBFR * SHAPE_LPC_ORDER_MAX ], /* I */
|
||||
const SKP_int16 AR2_Q13[ NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I */
|
||||
const SKP_int HarmShapeGain_Q14[ NB_SUBFR ], /* I */
|
||||
const SKP_int Tilt_Q14[ NB_SUBFR ], /* I Spectral tilt */
|
||||
const SKP_int32 LF_shp_Q14[ NB_SUBFR ], /* I */
|
||||
@@ -130,7 +132,7 @@ void SKP_Silk_NSQ_del_dec(
|
||||
SKP_int offset_Q10;
|
||||
SKP_int32 FiltState[ MAX_LPC_ORDER ], RDmin_Q10;
|
||||
SKP_int32 x_sc_Q10[ MAX_FRAME_LENGTH / NB_SUBFR ];
|
||||
NSQ_del_dec_struct psDelDec[ DEL_DEC_STATES_MAX ];
|
||||
NSQ_del_dec_struct psDelDec[ MAX_DEL_DEC_STATES ];
|
||||
NSQ_del_dec_struct *psDD;
|
||||
|
||||
subfr_length = psEncC->frame_length / NB_SUBFR;
|
||||
@@ -150,17 +152,23 @@ void SKP_Silk_NSQ_del_dec(
|
||||
psDD->LF_AR_Q12 = NSQ->sLF_AR_shp_Q12;
|
||||
psDD->Shape_Q10[ 0 ] = NSQ->sLTP_shp_Q10[ psEncC->frame_length - 1 ];
|
||||
SKP_memcpy( psDD->sLPC_Q14, NSQ->sLPC_Q14, NSQ_LPC_BUF_LENGTH * sizeof( SKP_int32 ) );
|
||||
SKP_memcpy( psDD->sAR2_Q14, NSQ->sAR2_Q14, sizeof( NSQ->sAR2_Q14 ) );
|
||||
}
|
||||
|
||||
offset_Q10 = SKP_Silk_Quantization_Offsets_Q10[ psEncCtrlC->sigtype ][ psEncCtrlC->QuantOffsetType ];
|
||||
smpl_buf_idx = 0; /* index of oldest samples */
|
||||
|
||||
decisionDelay = SKP_min_int( DECISION_DELAY, subfr_length );
|
||||
|
||||
/* For voiced frames limit the decision delay to lower than the pitch lag */
|
||||
if( psEncCtrlC->sigtype == SIG_TYPE_VOICED ) {
|
||||
for( k = 0; k < NB_SUBFR; k++ ) {
|
||||
decisionDelay = SKP_min_int( decisionDelay, psEncCtrlC->pitchL[ k ] - LTP_ORDER / 2 - 1 );
|
||||
}
|
||||
} else {
|
||||
if( lag > 0 ) {
|
||||
decisionDelay = SKP_min_int( decisionDelay, lag - LTP_ORDER / 2 - 1 );
|
||||
}
|
||||
}
|
||||
|
||||
if( LSFInterpFactor_Q2 == ( 1 << 2 ) ) {
|
||||
@@ -177,7 +185,12 @@ void SKP_Silk_NSQ_del_dec(
|
||||
for( k = 0; k < NB_SUBFR; k++ ) {
|
||||
A_Q12 = &PredCoef_Q12[ ( ( k >> 1 ) | ( 1 - LSF_interpolation_flag ) ) * MAX_LPC_ORDER ];
|
||||
B_Q14 = <PCoef_Q14[ k * LTP_ORDER ];
|
||||
AR_shp_Q13 = &AR2_Q13[ k * SHAPE_LPC_ORDER_MAX ];
|
||||
AR_shp_Q13 = &AR2_Q13[ k * MAX_SHAPE_LPC_ORDER ];
|
||||
|
||||
/* Noise shape parameters */
|
||||
SKP_assert( HarmShapeGain_Q14[ k ] >= 0 );
|
||||
HarmShapeFIRPacked_Q14 = SKP_RSHIFT( HarmShapeGain_Q14[ k ], 2 );
|
||||
HarmShapeFIRPacked_Q14 |= SKP_LSHIFT( ( SKP_int32 )SKP_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 );
|
||||
|
||||
NSQ->rewhite_flag = 0;
|
||||
if( psEncCtrlC->sigtype == SIG_TYPE_VOICED ) {
|
||||
@@ -209,7 +222,7 @@ void SKP_Silk_NSQ_del_dec(
|
||||
last_smple_idx = smpl_buf_idx + decisionDelay;
|
||||
for( i = 0; i < decisionDelay; i++ ) {
|
||||
last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK;
|
||||
q[ i - decisionDelay ] = ( SKP_int )SKP_RSHIFT( psDD->Q_Q10[ last_smple_idx ], 10 );
|
||||
q[ i - decisionDelay ] = ( SKP_int8 )SKP_RSHIFT( psDD->Q_Q10[ last_smple_idx ], 10 );
|
||||
pxq[ i - decisionDelay ] = ( SKP_int16 )SKP_SAT16( SKP_RSHIFT_ROUND(
|
||||
SKP_SMULWW( psDD->Xq_Q10[ last_smple_idx ],
|
||||
psDD->Gain_Q16[ last_smple_idx ] ), 10 ) );
|
||||
@@ -221,8 +234,9 @@ void SKP_Silk_NSQ_del_dec(
|
||||
|
||||
/* Rewhiten with new A coefs */
|
||||
start_idx = psEncC->frame_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2;
|
||||
start_idx = SKP_LIMIT( start_idx, 0, psEncC->frame_length - psEncC->predictLPCOrder );
|
||||
|
||||
SKP_assert( start_idx >= 0 );
|
||||
SKP_assert( start_idx <= psEncC->frame_length - psEncC->predictLPCOrder );
|
||||
|
||||
SKP_memset( FiltState, 0, psEncC->predictLPCOrder * sizeof( SKP_int32 ) );
|
||||
SKP_Silk_MA_Prediction( &NSQ->xq[ start_idx + k * psEncC->subfr_length ],
|
||||
A_Q12, FiltState, sLTP + start_idx, psEncC->frame_length - start_idx, psEncC->predictLPCOrder );
|
||||
@@ -232,11 +246,6 @@ void SKP_Silk_NSQ_del_dec(
|
||||
}
|
||||
}
|
||||
|
||||
/* Noise shape parameters */
|
||||
SKP_assert( HarmShapeGain_Q14[ k ] >= 0 );
|
||||
HarmShapeFIRPacked_Q14 = SKP_RSHIFT( HarmShapeGain_Q14[ k ], 2 );
|
||||
HarmShapeFIRPacked_Q14 |= SKP_LSHIFT( ( SKP_int32 )SKP_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 );
|
||||
|
||||
SKP_Silk_nsq_del_dec_scale_states( NSQ, psDelDec, x, x_sc_Q10,
|
||||
subfr_length, sLTP, sLTP_Q16, k, psEncC->nStatesDelayedDecision, smpl_buf_idx,
|
||||
LTP_scale_Q14, Gains_Q16, psEncCtrlC->pitchL );
|
||||
@@ -244,8 +253,7 @@ void SKP_Silk_NSQ_del_dec(
|
||||
SKP_Silk_noise_shape_quantizer_del_dec( NSQ, psDelDec, psEncCtrlC->sigtype, x_sc_Q10, q, pxq, sLTP_Q16,
|
||||
A_Q12, B_Q14, AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ], Gains_Q16[ k ],
|
||||
Lambda_Q10, offset_Q10, psEncC->subfr_length, subfr++, psEncC->shapingLPCOrder, psEncC->predictLPCOrder,
|
||||
psEncC->nStatesDelayedDecision, &smpl_buf_idx, decisionDelay
|
||||
);
|
||||
psEncC->warping_Q16, psEncC->nStatesDelayedDecision, &smpl_buf_idx, decisionDelay );
|
||||
|
||||
x += psEncC->subfr_length;
|
||||
q += psEncC->subfr_length;
|
||||
@@ -268,24 +276,27 @@ void SKP_Silk_NSQ_del_dec(
|
||||
last_smple_idx = smpl_buf_idx + decisionDelay;
|
||||
for( i = 0; i < decisionDelay; i++ ) {
|
||||
last_smple_idx = ( last_smple_idx - 1 ) & DECISION_DELAY_MASK;
|
||||
q[ i - decisionDelay ] = ( SKP_int )SKP_RSHIFT( psDD->Q_Q10[ last_smple_idx ], 10 );
|
||||
q[ i - decisionDelay ] = ( SKP_int8 )SKP_RSHIFT( psDD->Q_Q10[ last_smple_idx ], 10 );
|
||||
pxq[ i - decisionDelay ] = ( SKP_int16 )SKP_SAT16( SKP_RSHIFT_ROUND(
|
||||
SKP_SMULWW( psDD->Xq_Q10[ last_smple_idx ], psDD->Gain_Q16[ last_smple_idx ] ), 10 ) );
|
||||
NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDD->Shape_Q10[ last_smple_idx ];
|
||||
sLTP_Q16[ NSQ->sLTP_buf_idx - decisionDelay + i ] = psDD->Pred_Q16[ last_smple_idx ];
|
||||
|
||||
}
|
||||
SKP_memcpy( NSQ->sLPC_Q14, &psDD->sLPC_Q14[ psEncC->subfr_length ], NSQ_LPC_BUF_LENGTH * sizeof( SKP_int32 ) );
|
||||
SKP_memcpy( NSQ->sAR2_Q14, psDD->sAR2_Q14, sizeof( psDD->sAR2_Q14 ) );
|
||||
|
||||
/* Update states */
|
||||
NSQ->sLF_AR_shp_Q12 = psDD->LF_AR_Q12;
|
||||
NSQ->prev_inv_gain_Q16 = NSQ->prev_inv_gain_Q16;
|
||||
NSQ->lagPrev = psEncCtrlC->pitchL[ NB_SUBFR - 1 ];
|
||||
NSQ->sLF_AR_shp_Q12 = psDD->LF_AR_Q12;
|
||||
NSQ->lagPrev = psEncCtrlC->pitchL[ NB_SUBFR - 1 ];
|
||||
|
||||
/* Save quantized speech and noise shaping signals */
|
||||
SKP_memcpy( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->frame_length * sizeof( SKP_int16 ) );
|
||||
SKP_memcpy( NSQ->sLTP_shp_Q10, &NSQ->sLTP_shp_Q10[ psEncC->frame_length ], psEncC->frame_length * sizeof( SKP_int32 ) );
|
||||
|
||||
#ifdef USE_UNQUANTIZED_LSFS
|
||||
DEBUG_STORE_DATA( xq_unq_lsfs.pcm, NSQ->xq, psEncC->frame_length * sizeof( SKP_int16 ) );
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/******************************************/
|
||||
@@ -296,7 +307,7 @@ SKP_INLINE void SKP_Silk_noise_shape_quantizer_del_dec(
|
||||
NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */
|
||||
SKP_int sigtype, /* I Signal type */
|
||||
const SKP_int32 x_Q10[], /* I */
|
||||
SKP_int q[], /* O */
|
||||
SKP_int8 q[], /* O */
|
||||
SKP_int16 xq[], /* O */
|
||||
SKP_int32 sLTP_Q16[], /* I/O LTP filter state */
|
||||
const SKP_int16 a_Q12[], /* I Short term prediction coefs */
|
||||
@@ -312,7 +323,8 @@ SKP_INLINE void SKP_Silk_noise_shape_quantizer_del_dec(
|
||||
SKP_int length, /* I Input length */
|
||||
SKP_int subfr, /* I Subframe number */
|
||||
SKP_int shapingLPCOrder, /* I Shaping LPC filter order */
|
||||
SKP_int predictLPCOrder, /* I Prediction LPC filter order */
|
||||
SKP_int predictLPCOrder, /* I Prediction filter order */
|
||||
SKP_int warping_Q16, /* I */
|
||||
SKP_int nStatesDelayedDecision, /* I Number of states in decision tree */
|
||||
SKP_int *smpl_buf_idx, /* I Index to newest samples in buffers */
|
||||
SKP_int decisionDelay /* I */
|
||||
@@ -321,25 +333,16 @@ SKP_INLINE void SKP_Silk_noise_shape_quantizer_del_dec(
|
||||
SKP_int i, j, k, Winner_ind, RDmin_ind, RDmax_ind, last_smple_idx;
|
||||
SKP_int32 Winner_rand_state;
|
||||
SKP_int32 LTP_pred_Q14, LPC_pred_Q10, n_AR_Q10, n_LTP_Q14;
|
||||
SKP_int32 n_LF_Q10;
|
||||
SKP_int32 r_Q10, rr_Q20, rd1_Q10, rd2_Q10, RDmin_Q10, RDmax_Q10;
|
||||
SKP_int32 q1_Q10, q2_Q10;
|
||||
SKP_int32 Atmp, dither;
|
||||
SKP_int32 exc_Q10, LPC_exc_Q10, xq_Q10;
|
||||
SKP_int32 tmp, sLF_AR_shp_Q10;
|
||||
SKP_int32 *pred_lag_ptr, *shp_lag_ptr;
|
||||
SKP_int32 *psLPC_Q14;
|
||||
SKP_int32 a_Q12_tmp[ MAX_LPC_ORDER / 2 ], AR_shp_Q13_tmp[ MAX_LPC_ORDER / 2 ];
|
||||
NSQ_sample_struct psSampleState[ DEL_DEC_STATES_MAX ][ 2 ];
|
||||
SKP_int32 n_LF_Q10, r_Q10, rr_Q20, rd1_Q10, rd2_Q10, RDmin_Q10, RDmax_Q10;
|
||||
SKP_int32 q1_Q10, q2_Q10, dither, exc_Q10, LPC_exc_Q10, xq_Q10;
|
||||
SKP_int32 tmp1, tmp2, sLF_AR_shp_Q10;
|
||||
SKP_int32 *pred_lag_ptr, *shp_lag_ptr, *psLPC_Q14;
|
||||
NSQ_sample_struct psSampleState[ MAX_DEL_DEC_STATES ][ 2 ];
|
||||
NSQ_del_dec_struct *psDD;
|
||||
NSQ_sample_struct *psSS;
|
||||
|
||||
shp_lag_ptr = &NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ];
|
||||
pred_lag_ptr = &sLTP_Q16[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ];
|
||||
|
||||
/* Preload LPC coeficients to array on stack. Gives small performance gain */
|
||||
SKP_memcpy( a_Q12_tmp, a_Q12, predictLPCOrder * sizeof( SKP_int16 ) );
|
||||
SKP_memcpy( AR_shp_Q13_tmp, AR_shp_Q13, shapingLPCOrder * sizeof( SKP_int16 ) );
|
||||
|
||||
for( i = 0; i < length; i++ ) {
|
||||
/* Perform common calculations used in all states */
|
||||
@@ -384,85 +387,65 @@ SKP_INLINE void SKP_Silk_noise_shape_quantizer_del_dec(
|
||||
/* Pointer used in short term prediction and shaping */
|
||||
psLPC_Q14 = &psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 + i ];
|
||||
/* Short-term prediction */
|
||||
SKP_assert( ( predictLPCOrder & 1 ) == 0 ); /* check that order is even */
|
||||
SKP_assert( ( (SKP_int64)a_Q12 & 3 ) == 0 ); /* check that array starts at 4-byte aligned address */
|
||||
SKP_assert( predictLPCOrder >= 10 ); /* check that unrolling works */
|
||||
|
||||
SKP_assert( ( predictLPCOrder & 1 ) == 0 ); /* check that order is even */
|
||||
SKP_assert( ( ( ( int )( ( char* )( a_Q12 ) - ( ( char* ) 0 ) ) ) & 3 ) == 0 ); /* check that array starts at 4-byte aligned address */
|
||||
/* Partially unrolled */
|
||||
Atmp = a_Q12_tmp[ 0 ]; /* read two coefficients at once */
|
||||
LPC_pred_Q10 = SKP_SMULWB( psLPC_Q14[ 0 ], Atmp );
|
||||
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psLPC_Q14[ -1 ], Atmp );
|
||||
Atmp = a_Q12_tmp[ 1 ];
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -2 ], Atmp );
|
||||
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psLPC_Q14[ -3 ], Atmp );
|
||||
Atmp = a_Q12_tmp[ 2 ];
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -4 ], Atmp );
|
||||
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psLPC_Q14[ -5 ], Atmp );
|
||||
Atmp = a_Q12_tmp[ 3 ];
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -6 ], Atmp );
|
||||
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psLPC_Q14[ -7 ], Atmp );
|
||||
Atmp = a_Q12_tmp[ 4 ];
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -8 ], Atmp );
|
||||
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psLPC_Q14[ -9 ], Atmp );
|
||||
for( j = 10; j < predictLPCOrder; j += 2 ) {
|
||||
Atmp = a_Q12_tmp[ j >> 1 ]; /* read two coefficients at once */
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -j ], Atmp );
|
||||
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psLPC_Q14[ -j - 1 ], Atmp );
|
||||
LPC_pred_Q10 = SKP_SMULWB( psLPC_Q14[ 0 ], a_Q12[ 0 ] );
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -1 ], a_Q12[ 1 ] );
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -2 ], a_Q12[ 2 ] );
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -3 ], a_Q12[ 3 ] );
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -4 ], a_Q12[ 4 ] );
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -5 ], a_Q12[ 5 ] );
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -6 ], a_Q12[ 6 ] );
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -7 ], a_Q12[ 7 ] );
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -8 ], a_Q12[ 8 ] );
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -9 ], a_Q12[ 9 ] );
|
||||
for( j = 10; j < predictLPCOrder; j ++ ) {
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psLPC_Q14[ -j ], a_Q12[ j ] );
|
||||
}
|
||||
|
||||
/* Noise shape feedback */
|
||||
SKP_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
|
||||
SKP_assert( ( (SKP_int64)AR_shp_Q13 & 3 ) == 0 ); /* check that array starts at 4-byte aligned address */
|
||||
SKP_assert( shapingLPCOrder >= 12 ); /* check that unrolling works */
|
||||
/* NOTE: the code below loads two int16 values in an int32, and multiplies each using the */
|
||||
/* SMLAWB and SMLAWT instructions. On a big-endian CPU the two int16 variables would be */
|
||||
/* loaded in reverse order and the code will give the wrong result. In that case swapping */
|
||||
/* the SMLAWB and SMLAWT instructions should solve the problem. */
|
||||
|
||||
/* Partially unrolled */
|
||||
Atmp = AR_shp_Q13_tmp[ 0 ]; /* read two coefficients at once */
|
||||
n_AR_Q10 = SKP_SMULWB( psLPC_Q14[ 0 ], Atmp );
|
||||
n_AR_Q10 = SKP_SMLAWT( n_AR_Q10, psLPC_Q14[ -1 ], Atmp );
|
||||
Atmp = AR_shp_Q13_tmp[ 1 ];
|
||||
n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, psLPC_Q14[ -2 ], Atmp );
|
||||
n_AR_Q10 = SKP_SMLAWT( n_AR_Q10, psLPC_Q14[ -3 ], Atmp );
|
||||
Atmp = AR_shp_Q13_tmp[ 2 ];
|
||||
n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, psLPC_Q14[ -4 ], Atmp );
|
||||
n_AR_Q10 = SKP_SMLAWT( n_AR_Q10, psLPC_Q14[ -5 ], Atmp );
|
||||
Atmp = AR_shp_Q13_tmp[ 3 ];
|
||||
n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, psLPC_Q14[ -6 ], Atmp );
|
||||
n_AR_Q10 = SKP_SMLAWT( n_AR_Q10, psLPC_Q14[ -7 ], Atmp );
|
||||
Atmp = AR_shp_Q13_tmp[ 4 ];
|
||||
n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, psLPC_Q14[ -8 ], Atmp );
|
||||
n_AR_Q10 = SKP_SMLAWT( n_AR_Q10, psLPC_Q14[ -9 ], Atmp );
|
||||
Atmp = AR_shp_Q13_tmp[ 5 ];
|
||||
n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, psLPC_Q14[ -10 ], Atmp );
|
||||
n_AR_Q10 = SKP_SMLAWT( n_AR_Q10, psLPC_Q14[ -11 ], Atmp );
|
||||
for( j = 12; j < shapingLPCOrder; j += 2 ) {
|
||||
Atmp = AR_shp_Q13_tmp[ j >> 1 ]; /* read two coefficients at once */
|
||||
n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, psLPC_Q14[ -j ], Atmp );
|
||||
n_AR_Q10 = SKP_SMLAWT( n_AR_Q10, psLPC_Q14[ -j - 1 ], Atmp );
|
||||
SKP_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
|
||||
/* Output of lowpass section */
|
||||
tmp2 = SKP_SMLAWB( psLPC_Q14[ 0 ], psDD->sAR2_Q14[ 0 ], warping_Q16 );
|
||||
/* Output of allpass section */
|
||||
tmp1 = SKP_SMLAWB( psDD->sAR2_Q14[ 0 ], psDD->sAR2_Q14[ 1 ] - tmp2, warping_Q16 );
|
||||
psDD->sAR2_Q14[ 0 ] = tmp2;
|
||||
n_AR_Q10 = SKP_SMULWB( tmp2, AR_shp_Q13[ 0 ] );
|
||||
/* Loop over allpass sections */
|
||||
for( j = 2; j < shapingLPCOrder; j += 2 ) {
|
||||
/* Output of allpass section */
|
||||
tmp2 = SKP_SMLAWB( psDD->sAR2_Q14[ j - 1 ], psDD->sAR2_Q14[ j + 0 ] - tmp1, warping_Q16 );
|
||||
psDD->sAR2_Q14[ j - 1 ] = tmp1;
|
||||
n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, tmp1, AR_shp_Q13[ j - 1 ] );
|
||||
/* Output of allpass section */
|
||||
tmp1 = SKP_SMLAWB( psDD->sAR2_Q14[ j + 0 ], psDD->sAR2_Q14[ j + 1 ] - tmp2, warping_Q16 );
|
||||
psDD->sAR2_Q14[ j + 0 ] = tmp2;
|
||||
n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, tmp2, AR_shp_Q13[ j ] );
|
||||
}
|
||||
psDD->sAR2_Q14[ shapingLPCOrder - 1 ] = tmp1;
|
||||
n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, tmp1, AR_shp_Q13[ shapingLPCOrder - 1 ] );
|
||||
|
||||
n_AR_Q10 = SKP_RSHIFT( n_AR_Q10, 1 ); /* Q11 -> Q10 */
|
||||
n_AR_Q10 = SKP_SMLAWB( n_AR_Q10, psDD->LF_AR_Q12, Tilt_Q14 );
|
||||
|
||||
n_LF_Q10 = SKP_LSHIFT( SKP_SMULWB( psDD->Shape_Q10[ *smpl_buf_idx ], LF_shp_Q14 ), 2 );
|
||||
n_LF_Q10 = SKP_SMLAWT( n_LF_Q10, psDD->LF_AR_Q12, LF_shp_Q14 );
|
||||
n_LF_Q10 = SKP_LSHIFT( SKP_SMULWB( psDD->Shape_Q10[ *smpl_buf_idx ], LF_shp_Q14 ), 2 );
|
||||
n_LF_Q10 = SKP_SMLAWT( n_LF_Q10, psDD->LF_AR_Q12, LF_shp_Q14 );
|
||||
|
||||
/* Input minus prediction plus noise feedback */
|
||||
/* r = x[ i ] - LTP_pred - LPC_pred + n_AR + n_Tilt + n_LF + n_LTP */
|
||||
tmp = SKP_SUB32( LTP_pred_Q14, n_LTP_Q14 ); /* Add Q14 stuff */
|
||||
tmp = SKP_RSHIFT_ROUND( tmp, 4 ); /* round to Q10 */
|
||||
tmp = SKP_ADD32( tmp, LPC_pred_Q10 ); /* add Q10 stuff */
|
||||
tmp = SKP_SUB32( tmp, n_AR_Q10 ); /* subtract Q10 stuff */
|
||||
tmp = SKP_SUB32( tmp, n_LF_Q10 ); /* subtract Q10 stuff */
|
||||
r_Q10 = SKP_SUB32( x_Q10[ i ], tmp ); /* residual error Q10 */
|
||||
tmp1 = SKP_SUB32( LTP_pred_Q14, n_LTP_Q14 ); /* Add Q14 stuff */
|
||||
tmp1 = SKP_RSHIFT( tmp1, 4 ); /* convert to Q10 */
|
||||
tmp1 = SKP_ADD32( tmp1, LPC_pred_Q10 ); /* add Q10 stuff */
|
||||
tmp1 = SKP_SUB32( tmp1, n_AR_Q10 ); /* subtract Q10 stuff */
|
||||
tmp1 = SKP_SUB32( tmp1, n_LF_Q10 ); /* subtract Q10 stuff */
|
||||
r_Q10 = SKP_SUB32( x_Q10[ i ], tmp1 ); /* residual error Q10 */
|
||||
|
||||
|
||||
/* Flip sign depending on dither */
|
||||
r_Q10 = ( r_Q10 ^ dither ) - dither;
|
||||
r_Q10 = SKP_SUB32( r_Q10, offset_Q10 );
|
||||
r_Q10 = SKP_LIMIT( r_Q10, -64 << 10, 64 << 10 );
|
||||
r_Q10 = SKP_LIMIT_32( r_Q10, -64 << 10, 64 << 10 );
|
||||
|
||||
/* Find two quantization level candidates and measure their rate-distortion */
|
||||
if( r_Q10 < -1536 ) {
|
||||
@@ -585,7 +568,7 @@ SKP_INLINE void SKP_Silk_noise_shape_quantizer_del_dec(
|
||||
/* Write samples from winner to output and long-term filter states */
|
||||
psDD = &psDelDec[ Winner_ind ];
|
||||
if( subfr > 0 || i >= decisionDelay ) {
|
||||
q[ i - decisionDelay ] = ( SKP_int )SKP_RSHIFT( psDD->Q_Q10[ last_smple_idx ], 10 );
|
||||
q[ i - decisionDelay ] = ( SKP_int8 )SKP_RSHIFT( psDD->Q_Q10[ last_smple_idx ], 10 );
|
||||
xq[ i - decisionDelay ] = ( SKP_int16 )SKP_SAT16( SKP_RSHIFT_ROUND(
|
||||
SKP_SMULWW( psDD->Xq_Q10[ last_smple_idx ], psDD->Gain_Q16[ last_smple_idx ] ), 10 ) );
|
||||
NSQ->sLTP_shp_Q10[ NSQ->sLTP_shp_buf_idx - decisionDelay ] = psDD->Shape_Q10[ last_smple_idx ];
|
||||
@@ -622,8 +605,8 @@ SKP_INLINE void SKP_Silk_nsq_del_dec_scale_states(
|
||||
NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */
|
||||
const SKP_int16 x[], /* I Input in Q0 */
|
||||
SKP_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */
|
||||
SKP_int length, /* I Length of input */
|
||||
SKP_int16 sLTP[], /* I Re-whitened LTP state in Q0 */
|
||||
SKP_int subfr_length, /* I Length of input */
|
||||
const SKP_int16 sLTP[], /* I Re-whitened LTP state in Q0 */
|
||||
SKP_int32 sLTP_Q16[], /* O LTP state matching scaled input */
|
||||
SKP_int subfr, /* I Subframe number */
|
||||
SKP_int nStatesDelayedDecision, /* I Number of del dec states */
|
||||
@@ -633,14 +616,15 @@ SKP_INLINE void SKP_Silk_nsq_del_dec_scale_states(
|
||||
const SKP_int pitchL[ NB_SUBFR ] /* I Pitch lag */
|
||||
)
|
||||
{
|
||||
SKP_int i, k, scale_length, lag;
|
||||
SKP_int i, k, lag;
|
||||
SKP_int32 inv_gain_Q16, gain_adj_Q16, inv_gain_Q32;
|
||||
NSQ_del_dec_struct *psDD;
|
||||
|
||||
inv_gain_Q16 = SKP_DIV32( SKP_int32_MAX, SKP_RSHIFT( Gains_Q16[ subfr ], 1 ) );
|
||||
inv_gain_Q16 = SKP_INVERSE32_varQ( SKP_max( Gains_Q16[ subfr ], 1 ), 32 );
|
||||
inv_gain_Q16 = SKP_min( inv_gain_Q16, SKP_int16_MAX );
|
||||
lag = pitchL[ subfr ];
|
||||
/* After rewhitening the LTP state is un-scaled. So scale with inv_gain_Q16 */
|
||||
|
||||
/* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */
|
||||
if( NSQ->rewhite_flag ) {
|
||||
inv_gain_Q32 = SKP_LSHIFT( inv_gain_Q16, 16 );
|
||||
if( subfr == 0 ) {
|
||||
@@ -657,43 +641,40 @@ SKP_INLINE void SKP_Silk_nsq_del_dec_scale_states(
|
||||
if( inv_gain_Q16 != NSQ->prev_inv_gain_Q16 ) {
|
||||
gain_adj_Q16 = SKP_DIV32_varQ( inv_gain_Q16, NSQ->prev_inv_gain_Q16, 16 );
|
||||
|
||||
/* Scale long-term shaping state */
|
||||
for( i = NSQ->sLTP_shp_buf_idx - subfr_length * NB_SUBFR; i < NSQ->sLTP_shp_buf_idx; i++ ) {
|
||||
NSQ->sLTP_shp_Q10[ i ] = SKP_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q10[ i ] );
|
||||
}
|
||||
|
||||
/* Scale long-term prediction state */
|
||||
if( NSQ->rewhite_flag == 0 ) {
|
||||
for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) {
|
||||
sLTP_Q16[ i ] = SKP_SMULWW( gain_adj_Q16, sLTP_Q16[ i ] );
|
||||
}
|
||||
}
|
||||
|
||||
for( k = 0; k < nStatesDelayedDecision; k++ ) {
|
||||
psDD = &psDelDec[ k ];
|
||||
|
||||
/* Scale scalar states */
|
||||
psDD->LF_AR_Q12 = SKP_SMULWW( gain_adj_Q16, psDD->LF_AR_Q12 );
|
||||
|
||||
/* scale short term state */
|
||||
/* Scale short-term prediction and shaping states */
|
||||
for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) {
|
||||
psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - i - 1 ] = SKP_SMULWW( gain_adj_Q16, psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - i - 1 ] );
|
||||
psDD->sLPC_Q14[ i ] = SKP_SMULWW( gain_adj_Q16, psDD->sLPC_Q14[ i ] );
|
||||
}
|
||||
for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) {
|
||||
psDD->sAR2_Q14[ i ] = SKP_SMULWW( gain_adj_Q16, psDD->sAR2_Q14[ i ] );
|
||||
}
|
||||
for( i = 0; i < DECISION_DELAY; i++ ) {
|
||||
psDD->Pred_Q16[ i ] = SKP_SMULWW( gain_adj_Q16, psDD->Pred_Q16[ i ] );
|
||||
psDD->Shape_Q10[ i ] = SKP_SMULWW( gain_adj_Q16, psDD->Shape_Q10[ i ] );
|
||||
}
|
||||
}
|
||||
|
||||
/* Scale long term shaping state */
|
||||
|
||||
/* Calculate length to be scaled, Worst case: Next frame is voiced with max lag */
|
||||
scale_length = length * NB_SUBFR; /* aprox max lag */
|
||||
scale_length = scale_length - SKP_SMULBB( NB_SUBFR - ( subfr + 1 ), length ); /* subtract samples that will be too old in next frame */
|
||||
scale_length = SKP_max_int( scale_length, lag + LTP_ORDER ); /* make sure to scale whole pitch period if voiced */
|
||||
|
||||
for( i = NSQ->sLTP_shp_buf_idx - scale_length; i < NSQ->sLTP_shp_buf_idx; i++ ) {
|
||||
NSQ->sLTP_shp_Q10[ i ] = SKP_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q10[ i ] );
|
||||
}
|
||||
|
||||
/* Scale LTP predict state */
|
||||
if( NSQ->rewhite_flag == 0 ) {
|
||||
for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) {
|
||||
sLTP_Q16[ i ] = SKP_SMULWW( gain_adj_Q16, sLTP_Q16[ i ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Scale input */
|
||||
for( i = 0; i < length; i++ ) {
|
||||
for( i = 0; i < subfr_length; i++ ) {
|
||||
x_sc_Q10[ i ] = SKP_RSHIFT( SKP_SMULBB( x[ i ], ( SKP_int16 )inv_gain_Q16 ), 6 );
|
||||
}
|
||||
|
||||
@@ -708,12 +689,12 @@ SKP_INLINE void SKP_Silk_copy_del_dec_state(
|
||||
SKP_int LPC_state_idx /* I Index to LPC buffer */
|
||||
)
|
||||
{
|
||||
SKP_memcpy( DD_dst->RandState, DD_src->RandState, DECISION_DELAY * sizeof( SKP_int ) );
|
||||
SKP_memcpy( DD_dst->Q_Q10, DD_src->Q_Q10, DECISION_DELAY * sizeof( SKP_int32 ) );
|
||||
SKP_memcpy( DD_dst->Pred_Q16, DD_src->Pred_Q16, DECISION_DELAY * sizeof( SKP_int32 ) );
|
||||
SKP_memcpy( DD_dst->Shape_Q10, DD_src->Shape_Q10, DECISION_DELAY * sizeof( SKP_int32 ) );
|
||||
SKP_memcpy( DD_dst->Xq_Q10, DD_src->Xq_Q10, DECISION_DELAY * sizeof( SKP_int32 ) );
|
||||
|
||||
SKP_memcpy( DD_dst->RandState, DD_src->RandState, sizeof( DD_src->RandState ) );
|
||||
SKP_memcpy( DD_dst->Q_Q10, DD_src->Q_Q10, sizeof( DD_src->Q_Q10 ) );
|
||||
SKP_memcpy( DD_dst->Pred_Q16, DD_src->Pred_Q16, sizeof( DD_src->Pred_Q16 ) );
|
||||
SKP_memcpy( DD_dst->Shape_Q10, DD_src->Shape_Q10, sizeof( DD_src->Shape_Q10 ) );
|
||||
SKP_memcpy( DD_dst->Xq_Q10, DD_src->Xq_Q10, sizeof( DD_src->Xq_Q10 ) );
|
||||
SKP_memcpy( DD_dst->sAR2_Q14, DD_src->sAR2_Q14, sizeof( DD_src->sAR2_Q14 ) );
|
||||
SKP_memcpy( &DD_dst->sLPC_Q14[ LPC_state_idx ], &DD_src->sLPC_Q14[ LPC_state_idx ], NSQ_LPC_BUF_LENGTH * sizeof( SKP_int32 ) );
|
||||
DD_dst->LF_AR_Q12 = DD_src->LF_AR_Q12;
|
||||
DD_dst->Seed = DD_src->Seed;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
@@ -59,6 +59,8 @@ void SKP_Silk_PLC(
|
||||
/* Generate Signal */
|
||||
/****************************/
|
||||
SKP_Silk_PLC_conceal( psDec, psDecCtrl, signal, length );
|
||||
|
||||
psDec->lossCnt++;
|
||||
} else {
|
||||
/****************************/
|
||||
/* Update state */
|
||||
@@ -150,13 +152,16 @@ void SKP_Silk_PLC_conceal(
|
||||
{
|
||||
SKP_int i, j, k;
|
||||
SKP_int16 *B_Q14, exc_buf[ MAX_FRAME_LENGTH ], *exc_buf_ptr;
|
||||
SKP_int16 rand_scale_Q14, A_Q12_tmp[ MAX_LPC_ORDER ];
|
||||
SKP_int16 rand_scale_Q14;
|
||||
union {
|
||||
SKP_int16 as_int16[ MAX_LPC_ORDER ];
|
||||
SKP_int32 as_int32[ MAX_LPC_ORDER / 2 ];
|
||||
} A_Q12_tmp;
|
||||
SKP_int32 rand_seed, harm_Gain_Q15, rand_Gain_Q15;
|
||||
SKP_int lag, idx, shift1, shift2;
|
||||
SKP_int32 energy1, energy2, *rand_ptr, *pred_lag_ptr, Atmp;
|
||||
SKP_int lag, idx, sLTP_buf_idx, shift1, shift2;
|
||||
SKP_int32 energy1, energy2, *rand_ptr, *pred_lag_ptr;
|
||||
SKP_int32 sig_Q10[ MAX_FRAME_LENGTH ], *sig_Q10_ptr, LPC_exc_Q10, LPC_pred_Q10, LTP_pred_Q14;
|
||||
SKP_Silk_PLC_struct *psPLC;
|
||||
|
||||
psPLC = &psDec->sPLC;
|
||||
|
||||
/* Update LTP buffer */
|
||||
@@ -179,7 +184,7 @@ void SKP_Silk_PLC_conceal(
|
||||
SKP_Silk_sum_sqr_shift( &energy1, &shift1, exc_buf, psDec->subfr_length );
|
||||
SKP_Silk_sum_sqr_shift( &energy2, &shift2, &exc_buf[ psDec->subfr_length ], psDec->subfr_length );
|
||||
|
||||
if( SKP_RSHIFT( energy1, shift2 ) < SKP_RSHIFT( energy1, shift2 ) ) {
|
||||
if( SKP_RSHIFT( energy1, shift2 ) < SKP_RSHIFT( energy2, shift1 ) ) {
|
||||
/* First sub-frame has lowest energy */
|
||||
rand_ptr = &psDec->exc_Q10[ SKP_max_int( 0, 3 * psDec->subfr_length - RAND_BUF_SIZE ) ];
|
||||
} else {
|
||||
@@ -226,9 +231,9 @@ void SKP_Silk_PLC_conceal(
|
||||
}
|
||||
}
|
||||
|
||||
rand_seed = psPLC->rand_seed;
|
||||
lag = SKP_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 );
|
||||
psDec->sLTP_buf_idx = psDec->frame_length;
|
||||
rand_seed = psPLC->rand_seed;
|
||||
lag = SKP_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 );
|
||||
sLTP_buf_idx = psDec->frame_length;
|
||||
|
||||
/***************************/
|
||||
/* LTP synthesis filtering */
|
||||
@@ -236,7 +241,7 @@ void SKP_Silk_PLC_conceal(
|
||||
sig_Q10_ptr = sig_Q10;
|
||||
for( k = 0; k < NB_SUBFR; k++ ) {
|
||||
/* Setup pointer */
|
||||
pred_lag_ptr = &psDec->sLTP_Q16[ psDec->sLTP_buf_idx - lag + LTP_ORDER / 2 ];
|
||||
pred_lag_ptr = &psDec->sLTP_Q16[ sLTP_buf_idx - lag + LTP_ORDER / 2 ];
|
||||
for( i = 0; i < psDec->subfr_length; i++ ) {
|
||||
rand_seed = SKP_RAND( rand_seed );
|
||||
idx = SKP_RSHIFT( rand_seed, 25 ) & RAND_BUF_MASK;
|
||||
@@ -254,8 +259,8 @@ void SKP_Silk_PLC_conceal(
|
||||
LPC_exc_Q10 = SKP_ADD32( LPC_exc_Q10, SKP_RSHIFT_ROUND( LTP_pred_Q14, 4 ) ); /* Harmonic part */
|
||||
|
||||
/* Update states */
|
||||
psDec->sLTP_Q16[ psDec->sLTP_buf_idx ] = SKP_LSHIFT( LPC_exc_Q10, 6 );
|
||||
psDec->sLTP_buf_idx++;
|
||||
psDec->sLTP_Q16[ sLTP_buf_idx ] = SKP_LSHIFT( LPC_exc_Q10, 6 );
|
||||
sLTP_buf_idx++;
|
||||
|
||||
/* Save LPC residual */
|
||||
sig_Q10_ptr[ i ] = LPC_exc_Q10;
|
||||
@@ -279,32 +284,25 @@ void SKP_Silk_PLC_conceal(
|
||||
/***************************/
|
||||
sig_Q10_ptr = sig_Q10;
|
||||
/* Preload LPC coeficients to array on stack. Gives small performance gain */
|
||||
SKP_memcpy( A_Q12_tmp, psPLC->prevLPC_Q12, psDec->LPC_order * sizeof( SKP_int16 ) );
|
||||
SKP_memcpy( A_Q12_tmp.as_int16, psPLC->prevLPC_Q12, psDec->LPC_order * sizeof( SKP_int16 ) );
|
||||
SKP_assert( psDec->LPC_order >= 10 ); /* check that unrolling works */
|
||||
for( k = 0; k < NB_SUBFR; k++ ) {
|
||||
for( i = 0; i < psDec->subfr_length; i++ ){
|
||||
/* unrolled */
|
||||
Atmp = *( ( SKP_int32* )&A_Q12_tmp[ 0 ] ); /* read two coefficients at once */
|
||||
LPC_pred_Q10 = SKP_SMULWB( psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 1 ], Atmp );
|
||||
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 2 ], Atmp );
|
||||
Atmp = *( ( SKP_int32* )&A_Q12_tmp[ 2 ] );
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 3 ], Atmp );
|
||||
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 4 ], Atmp );
|
||||
Atmp = *( ( SKP_int32* )&A_Q12_tmp[ 4 ] );
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 5 ], Atmp );
|
||||
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 6 ], Atmp );
|
||||
Atmp = *( ( SKP_int32* )&A_Q12_tmp[ 6 ] );
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 7 ], Atmp );
|
||||
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 8 ], Atmp );
|
||||
Atmp = *( ( SKP_int32* )&A_Q12_tmp[ 8 ] );
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 9 ], Atmp );
|
||||
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 10 ], Atmp );
|
||||
for( j = 10 ; j < psDec->LPC_order ; j+=2 ) {
|
||||
Atmp = *( ( SKP_int32* )&A_Q12_tmp[ j ] );
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 1 - j ], Atmp );
|
||||
LPC_pred_Q10 = SKP_SMLAWT( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 2 - j ], Atmp );
|
||||
}
|
||||
/* partly unrolled */
|
||||
LPC_pred_Q10 = SKP_SMULWB( psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 1 ], A_Q12_tmp.as_int16[ 0 ] );
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 2 ], A_Q12_tmp.as_int16[ 1 ] );
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 3 ], A_Q12_tmp.as_int16[ 2 ] );
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 4 ], A_Q12_tmp.as_int16[ 3 ] );
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 5 ], A_Q12_tmp.as_int16[ 4 ] );
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 6 ], A_Q12_tmp.as_int16[ 5 ] );
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 7 ], A_Q12_tmp.as_int16[ 6 ] );
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 8 ], A_Q12_tmp.as_int16[ 7 ] );
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 9 ], A_Q12_tmp.as_int16[ 8 ] );
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - 10 ], A_Q12_tmp.as_int16[ 9 ] );
|
||||
|
||||
for( j = 10; j < psDec->LPC_order; j++ ) {
|
||||
LPC_pred_Q10 = SKP_SMLAWB( LPC_pred_Q10, psDec->sLPC_Q14[ MAX_LPC_ORDER + i - j - 1 ], A_Q12_tmp.as_int16[ j ] );
|
||||
}
|
||||
/* Add prediction to LPC residual */
|
||||
sig_Q10_ptr[ i ] = SKP_ADD32( sig_Q10_ptr[ i ], LPC_pred_Q10 );
|
||||
|
||||
@@ -387,3 +385,4 @@ void SKP_Silk_PLC_glue_frames(
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
@@ -28,7 +28,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef SKP_SILK_PLC_FIX_H
|
||||
#define SKP_SILK_PLC_FIX_H
|
||||
|
||||
#include "SKP_Silk_main_FIX.h"
|
||||
#include "SKP_Silk_main.h"
|
||||
|
||||
#define BWE_COEF_Q16 64880 /* 0.99 in Q16 */
|
||||
#define V_PITCH_GAIN_START_MIN_Q14 11469 /* 0.7 in Q14 */
|
||||
@@ -38,7 +38,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define USE_SINGLE_TAP 1
|
||||
#define RAND_BUF_SIZE 128
|
||||
#define RAND_BUF_MASK (RAND_BUF_SIZE - 1)
|
||||
#define LOG2_INV_LPC_GAIN_HIGH_THRES 4 /* 2^4 = 12 dB LPC gain */
|
||||
#define LOG2_INV_LPC_GAIN_HIGH_THRES 3 /* 2^3 = 8 dB LPC gain */
|
||||
#define LOG2_INV_LPC_GAIN_LOW_THRES 8 /* 2^8 = 24 dB LPC gain */
|
||||
#define PITCH_DRIFT_FAC_Q16 655 /* 0.01 in Q16 */
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
@@ -33,173 +33,87 @@ extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#define SigProc_MAX_ORDER_LPC 16 /* max order of the LPC analysis in schur() and k2a() */
|
||||
#define SigProc_MAX_CORRELATION_LENGTH 640 /* max input length to the correlation */
|
||||
#define SKP_Silk_MAX_ORDER_LPC 16 /* max order of the LPC analysis in schur() and k2a() */
|
||||
#define SKP_Silk_MAX_CORRELATION_LENGTH 640 /* max input length to the correlation */
|
||||
#include "SKP_Silk_typedef.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h> /* for abs() */
|
||||
#include "SKP_Silk_macros.h"
|
||||
#include "SKP_Silk_resample_rom.h"
|
||||
#include "SKP_Silk_resampler_structs.h"
|
||||
|
||||
# include "SKP_Silk_macros.h"
|
||||
|
||||
|
||||
|
||||
|
||||
/********************************************************************/
|
||||
/* SIGNAL PROCESSING FUNCTIONS */
|
||||
/********************************************************************/
|
||||
|
||||
/* downsample by a factor 2 */
|
||||
void SKP_Silk_resample_1_2(
|
||||
const SKP_int16 *in, /* I: 16 kHz signal [2*len] */
|
||||
SKP_int32 *S, /* I/O: State vector [6] */
|
||||
SKP_int16 *out, /* O: 8 kHz signal [len] */
|
||||
SKP_int32 *scratch, /* I: Scratch memory [4*len] */
|
||||
const SKP_int32 len /* I: Number of OUTPUT samples */
|
||||
/*!
|
||||
* Initialize/reset the resampler state for a given pair of input/output sampling rates
|
||||
*/
|
||||
SKP_int SKP_Silk_resampler_init(
|
||||
SKP_Silk_resampler_state_struct *S, /* I/O: Resampler state */
|
||||
SKP_int32 Fs_Hz_in, /* I: Input sampling rate (Hz) */
|
||||
SKP_int32 Fs_Hz_out /* I: Output sampling rate (Hz) */
|
||||
);
|
||||
|
||||
/*!
|
||||
* downsample by a factor 2, coarser (good for resampling audio)
|
||||
*/
|
||||
void SKP_Silk_resample_1_2_coarse(
|
||||
const SKP_int16 *in, /* I: 16 kHz signal [2*len] */
|
||||
SKP_int32 *S, /* I/O: state vector [4] */
|
||||
SKP_int16 *out, /* O: 8 kHz signal [len] */
|
||||
SKP_int32 *scratch, /* I: scratch memory [3*len] */
|
||||
const SKP_int32 len /* I: number of OUTPUT samples */
|
||||
);
|
||||
|
||||
/*!
|
||||
* downsample by a factor 2, coarsest (good for signals that are already oversampled, or for analysis purposes)
|
||||
/*!
|
||||
* Clear the states of all resampling filters, without resetting sampling rate ratio
|
||||
*/
|
||||
void SKP_Silk_resample_1_2_coarsest(
|
||||
const SKP_int16 *in, /* I: 16 kHz signal [2*len] */
|
||||
SKP_int32 *S, /* I/O: State vector [2] */
|
||||
SKP_int16 *out, /* O: 8 kHz signal [len] */
|
||||
SKP_int32 *scratch, /* I: Scratch memory [3*len] */
|
||||
const SKP_int32 len /* I: Number of OUTPUT samples */
|
||||
);
|
||||
|
||||
/*!
|
||||
* upsample by a factor 2, coarser (good for resampling audio)
|
||||
*/
|
||||
void SKP_Silk_resample_2_1_coarse(
|
||||
const SKP_int16 *in, /* I: 8 kHz signal [len] */
|
||||
SKP_int32 *S, /* I/O: State vector [4] */
|
||||
SKP_int16 *out, /* O: 16 kHz signal [2*len] */
|
||||
SKP_int32 *scratch, /* I: Scratch memory [3*len] */
|
||||
const SKP_int32 len /* I: Number of INPUT samples */
|
||||
SKP_int SKP_Silk_resampler_clear(
|
||||
SKP_Silk_resampler_state_struct *S /* I/O: Resampler state */
|
||||
);
|
||||
|
||||
/*!
|
||||
* Resamples by a factor 1/3
|
||||
* Resampler: convert from one sampling rate to another
|
||||
*/
|
||||
void SKP_Silk_resample_1_3(
|
||||
SKP_int16 *out, /* O: Fs_low signal [inLen/3] */
|
||||
SKP_int32 *S, /* I/O: State vector [7] */
|
||||
const SKP_int16 *in, /* I: Fs_high signal [inLen] */
|
||||
const SKP_int32 inLen /* I: Input length, must be a multiple of 3 */
|
||||
SKP_int SKP_Silk_resampler(
|
||||
SKP_Silk_resampler_state_struct *S, /* I/O: Resampler state */
|
||||
SKP_int16 out[], /* O: Output signal */
|
||||
const SKP_int16 in[], /* I: Input signal */
|
||||
SKP_int32 inLen /* I: Number of input samples */
|
||||
);
|
||||
|
||||
/*!
|
||||
* Resamples by a factor 3/1
|
||||
Upsample 2x, low quality
|
||||
*/
|
||||
void SKP_Silk_resample_3_1(
|
||||
SKP_int16 *out, /* O: Fs_high signal [inLen*3] */
|
||||
SKP_int32 *S, /* I/O: State vector [7] */
|
||||
const SKP_int16 *in, /* I: Fs_low signal [inLen] */
|
||||
const SKP_int32 inLen /* I: Input length */
|
||||
void SKP_Silk_resampler_up2(
|
||||
SKP_int32 *S, /* I/O: State vector [ 2 ] */
|
||||
SKP_int16 *out, /* O: Output signal [ 2 * len ] */
|
||||
const SKP_int16 *in, /* I: Input signal [ len ] */
|
||||
SKP_int32 len /* I: Number of input samples */
|
||||
);
|
||||
|
||||
/*!
|
||||
* Resamples by a factor 2/3
|
||||
*/
|
||||
void SKP_Silk_resample_2_3(
|
||||
SKP_int16 *out, /* O: Fs_low signal [inLen * 2/3] */
|
||||
SKP_int32 *S, /* I/O: State vector [7+4] */
|
||||
const SKP_int16 *in, /* I: Fs_high signal [inLen] */
|
||||
const SKP_int inLen /* I: Input length, must be a multiple of 3 */
|
||||
);
|
||||
* Downsample 2x, mediocre quality
|
||||
*/
|
||||
void SKP_Silk_resampler_down2(
|
||||
SKP_int32 *S, /* I/O: State vector [ 2 ] */
|
||||
SKP_int16 *out, /* O: Output signal [ len ] */
|
||||
const SKP_int16 *in, /* I: Input signal [ floor(len/2) ] */
|
||||
SKP_int32 inLen /* I: Number of input samples */
|
||||
);
|
||||
|
||||
|
||||
/*!
|
||||
* Resamples by a factor 3/2
|
||||
*/
|
||||
void SKP_Silk_resample_3_2(
|
||||
SKP_int16 *out, /* O: Fs_high signal [inLen*3/2] */
|
||||
SKP_int32 *S, /* I/O: State vector [7+4] */
|
||||
const SKP_int16 *in, /* I: Fs_low signal [inLen] */
|
||||
SKP_int inLen /* I: Input length, must be a multiple of 2 */
|
||||
* Downsample by a factor 2/3, low quality
|
||||
*/
|
||||
void SKP_Silk_resampler_down2_3(
|
||||
SKP_int32 *S, /* I/O: State vector [ 6 ] */
|
||||
SKP_int16 *out, /* O: Output signal [ floor(2*inLen/3) ] */
|
||||
const SKP_int16 *in, /* I: Input signal [ inLen ] */
|
||||
SKP_int32 inLen /* I: Number of input samples */
|
||||
);
|
||||
|
||||
/*!
|
||||
* Resamples by a factor 4/3
|
||||
*/
|
||||
void SKP_Silk_resample_4_3(
|
||||
SKP_int16 *out, /* O: Fs_low signal [inLen * 4/3] */
|
||||
SKP_int32 *S, /* I/O: State vector [7+4+4] */
|
||||
const SKP_int16 *in, /* I: Fs_high signal [inLen] */
|
||||
const SKP_int inLen /* I: input length, must be a multiple of 3 */
|
||||
);
|
||||
|
||||
/*!
|
||||
* Resamples by a factor 3/4
|
||||
*/
|
||||
void SKP_Silk_resample_3_4(
|
||||
SKP_int16 *out, /* O: Fs_high signal [inLen*3/4] */
|
||||
SKP_int32 *S, /* I/O: State vector [7+2+6] */
|
||||
const SKP_int16 *in, /* I: Fs_low signal [inLen] */
|
||||
SKP_int inLen /* I: Input length, must be a multiple of 4 */
|
||||
);
|
||||
|
||||
/*!
|
||||
* resample with a factor 2/3 coarse
|
||||
*/
|
||||
void SKP_Silk_resample_2_3_coarse(
|
||||
SKP_int16 *out, /* O: Output signal */
|
||||
SKP_int16 *S, /* I/O: Resampler state [ SigProc_Resample_2_3_coarse_NUM_FIR_COEFS - 1 ] */
|
||||
const SKP_int16 *in, /* I: Input signal */
|
||||
const SKP_int frameLenIn, /* I: Number of input samples */
|
||||
SKP_int16 *scratch /* I: Scratch memory [ frameLenIn + SigProc_Resample_2_3_coarse_NUM_FIR_COEFS - 1 ] */
|
||||
);
|
||||
|
||||
/*!
|
||||
* resample with a factor 2/3 coarsest
|
||||
*/
|
||||
void SKP_Silk_resample_2_3_coarsest(
|
||||
SKP_int16 *out, /* O: Output signal */
|
||||
SKP_int16 *S, /* I/O: Resampler state [ SigProc_Resample_2_3_coarsest_NUM_FIR_COEFS - 1 ] */
|
||||
const SKP_int16 *in, /* I: Input signal */
|
||||
const SKP_int frameLenIn, /* I: Number of input samples */
|
||||
SKP_int16 *scratch /* I: Scratch memory [ frameLenIn + SigProc_Resample_2_3_coarsest_NUM_FIR_COEFS - 1 ] */
|
||||
);
|
||||
|
||||
/*!
|
||||
* First order low-pass filter, with input as SKP_int16, running at 48 kHz
|
||||
*/
|
||||
void SKP_Silk_lowpass_short(
|
||||
const SKP_int16 *in, /* I: Q15 48 kHz signal; [len] */
|
||||
SKP_int32 *S, /* I/O: Q25 state; length = 1 */
|
||||
SKP_int32 *out, /* O: Q25 48 kHz signal; [len] */
|
||||
const SKP_int32 len /* O: Signal length */
|
||||
);
|
||||
|
||||
/*!
|
||||
* First order low-pass filter, with input as SKP_int32, running at 48 kHz
|
||||
*/
|
||||
void SKP_Silk_lowpass_int(
|
||||
const SKP_int32 *in, /* I: Q25 48 kHz signal; length = len */
|
||||
SKP_int32 *S, /* I/O: Q25 state; length = 1 */
|
||||
SKP_int32 *out, /* O: Q25 48 kHz signal; length = len */
|
||||
const SKP_int32 len /* I: Number of samples */
|
||||
);
|
||||
|
||||
/*!
|
||||
* First-order allpass filter
|
||||
*/
|
||||
void SKP_Silk_allpass_int(
|
||||
const SKP_int32 *in, /* I: Q25 input signal [len] */
|
||||
SKP_int32 *S, /* I/O: Q25 state [1] */
|
||||
SKP_int A, /* I: Q15 coefficient (0 <= A < 32768) */
|
||||
SKP_int32 *out, /* O: Q25 output signal [len] */
|
||||
const SKP_int32 len /* I: Number of samples */
|
||||
* Downsample by a factor 3, low quality
|
||||
*/
|
||||
void SKP_Silk_resampler_down3(
|
||||
SKP_int32 *S, /* I/O: State vector [ 8 ] */
|
||||
SKP_int16 *out, /* O: Output signal [ floor(inLen/3) ] */
|
||||
const SKP_int16 *in, /* I: Input signal [ inLen ] */
|
||||
SKP_int32 inLen /* I: Number of input samples */
|
||||
);
|
||||
|
||||
/*!
|
||||
@@ -240,15 +154,6 @@ void SKP_Silk_MA_Prediction(
|
||||
const SKP_int32 order /* I: Filter order */
|
||||
);
|
||||
|
||||
void SKP_Silk_MA_Prediction_Q13(
|
||||
const SKP_int16 *in, /* I: input signal */
|
||||
const SKP_int16 *B, /* I: MA prediction coefficients, Q13 [order] */
|
||||
SKP_int32 *S, /* I/O: state vector [order] */
|
||||
SKP_int16 *out, /* O: output signal */
|
||||
SKP_int32 len, /* I: signal length */
|
||||
SKP_int32 order /* I: filter order */
|
||||
);
|
||||
|
||||
/*!
|
||||
* 16th order AR filter for LPC synthesis, coefficients are in Q12
|
||||
*/
|
||||
@@ -305,10 +210,10 @@ SKP_int SKP_Silk_LPC_inverse_pred_gain( /* O: Returns 1 if unstable, otherwise
|
||||
const SKP_int order /* I: Prediction order */
|
||||
);
|
||||
|
||||
SKP_int SKP_Silk_LPC_inverse_pred_gain_Q13( /* O: returns 1 if unstable, otherwise 0 */
|
||||
SKP_int32 *invGain_Q30, /* O: Inverse prediction gain, Q30 energy domain */
|
||||
const SKP_int16 *A_Q13, /* I: Prediction coefficients, Q13 [order] */
|
||||
const SKP_int order /* I: Prediction order */
|
||||
SKP_int SKP_Silk_LPC_inverse_pred_gain_Q24( /* O: Returns 1 if unstable, otherwise 0 */
|
||||
SKP_int32 *invGain_Q30, /* O: Inverse prediction gain, Q30 energy domain */
|
||||
const SKP_int32 *A_Q24, /* I: Prediction coefficients, Q24 [order] */
|
||||
const SKP_int order /* I: Prediction order */
|
||||
);
|
||||
|
||||
/* split signal in two decimated bands using first-order allpass filters */
|
||||
@@ -353,12 +258,12 @@ void SKP_Silk_sum_sqr_shift(
|
||||
|
||||
/* Calculates the reflection coefficients from the correlation sequence */
|
||||
/* Faster than schur64(), but much less accurate. */
|
||||
/* Uses SMLAWB(), requiring armv5E and higher. */
|
||||
void SKP_Silk_schur(
|
||||
SKP_int16 *rc_Q15, /* O: reflection coefficients [order] Q15 */
|
||||
const SKP_int32 *c, /* I: correlations [order+1] */
|
||||
const SKP_int32 order /* I: prediction order */
|
||||
);
|
||||
/* uses SMLAWB(), requiring armv5E and higher. */
|
||||
SKP_int32 SKP_Silk_schur( /* O: Returns residual energy */
|
||||
SKP_int16 *rc_Q15, /* O: reflection coefficients [order] Q15 */
|
||||
const SKP_int32 *c, /* I: correlations [order+1] */
|
||||
const SKP_int32 order /* I: prediction order */
|
||||
);;
|
||||
|
||||
/* Calculates the reflection coefficients from the correlation sequence */
|
||||
/* Slower than schur(), but more accurate. */
|
||||
@@ -385,30 +290,30 @@ void SKP_Silk_k2a_Q16(
|
||||
|
||||
/* Apply sine window to signal vector. */
|
||||
/* Window types: */
|
||||
/* 0 -> sine window from 0 to pi */
|
||||
/* 1 -> sine window from 0 to pi/2 */
|
||||
/* 2 -> sine window from pi/2 to pi */
|
||||
/* every other sample of window is linearly interpolated, for speed */
|
||||
void SKP_Silk_apply_sine_window(
|
||||
SKP_int16 px_win[], /* O Pointer to windowed signal */
|
||||
const SKP_int16 px[], /* I Pointer to input signal */
|
||||
const SKP_int win_type, /* I Selects a window type */
|
||||
const SKP_int length /* I Window length, multiple of 4 */
|
||||
/* Every other sample is linearly interpolated, for speed. */
|
||||
/* Window length must be between 16 and 120 (incl) and a multiple of 4. */
|
||||
void SKP_Silk_apply_sine_window_new(
|
||||
SKP_int16 px_win[], /* O Pointer to windowed signal */
|
||||
const SKP_int16 px[], /* I Pointer to input signal */
|
||||
const SKP_int win_type, /* I Selects a window type */
|
||||
const SKP_int length /* I Window length, multiple of 4 */
|
||||
);
|
||||
|
||||
/* Compute autocorrelation */
|
||||
void SKP_Silk_autocorr(
|
||||
SKP_int32 *results, /* O Result (length correlationCount) */
|
||||
SKP_int32 *scale, /* O Scaling of the correlation vector */
|
||||
SKP_int *scale, /* O Scaling of the correlation vector */
|
||||
const SKP_int16 *inputData, /* I Input data to correlate */
|
||||
const SKP_int inputDataSize, /* I Length of input */
|
||||
const SKP_int correlationCount /* I Number of correlation taps to compute */
|
||||
);
|
||||
|
||||
/* Pitch estimator */
|
||||
#define SigProc_PITCH_EST_MIN_COMPLEX 0
|
||||
#define SigProc_PITCH_EST_MID_COMPLEX 1
|
||||
#define SigProc_PITCH_EST_MAX_COMPLEX 2
|
||||
#define SKP_Silk_PITCH_EST_MIN_COMPLEX 0
|
||||
#define SKP_Silk_PITCH_EST_MID_COMPLEX 1
|
||||
#define SKP_Silk_PITCH_EST_MAX_COMPLEX 2
|
||||
|
||||
void SKP_Silk_decode_pitch(
|
||||
SKP_int lagIndex, /* I */
|
||||
@@ -417,17 +322,18 @@ void SKP_Silk_decode_pitch(
|
||||
SKP_int Fs_kHz /* I sampling frequency (kHz) */
|
||||
);
|
||||
|
||||
SKP_int SKP_Silk_pitch_analysis_core( /* O Voicing estimate: 0 voiced, 1 unvoiced */
|
||||
const SKP_int16 *signal, /* I Signal of length PITCH_EST_FRAME_LENGTH_MS*Fs_kHz */
|
||||
SKP_int *pitch_out, /* O 4 pitch lag values */
|
||||
SKP_int *lagIndex, /* O Lag Index */
|
||||
SKP_int *contourIndex, /* O Pitch contour Index */
|
||||
SKP_int *LTPCorr_Q15, /* I/O Normalized correlation; input: value from previous frame */
|
||||
SKP_int prevLag, /* I Last lag of previous frame; set to zero is unvoiced */
|
||||
const SKP_int32 search_thres1_Q16, /* I First stage threshold for lag candidates 0 - 1 */
|
||||
const SKP_int search_thres2_Q15, /* I Final threshold for lag candidates 0 - 1 */
|
||||
const SKP_int Fs_kHz, /* I Sample frequency (kHz) */
|
||||
const SKP_int complexity /* I Complexity setting, 0-2, where 2 is highest */
|
||||
SKP_int SKP_Silk_pitch_analysis_core( /* O Voicing estimate: 0 voiced, 1 unvoiced */
|
||||
const SKP_int16 *signal, /* I Signal of length PITCH_EST_FRAME_LENGTH_MS*Fs_kHz */
|
||||
SKP_int *pitch_out, /* O 4 pitch lag values */
|
||||
SKP_int *lagIndex, /* O Lag Index */
|
||||
SKP_int *contourIndex, /* O Pitch contour Index */
|
||||
SKP_int *LTPCorr_Q15, /* I/O Normalized correlation; input: value from previous frame */
|
||||
SKP_int prevLag, /* I Last lag of previous frame; set to zero is unvoiced */
|
||||
const SKP_int32 search_thres1_Q16, /* I First stage threshold for lag candidates 0 - 1 */
|
||||
const SKP_int search_thres2_Q15, /* I Final threshold for lag candidates 0 - 1 */
|
||||
const SKP_int Fs_kHz, /* I Sample frequency (kHz) */
|
||||
const SKP_int complexity, /* I Complexity setting, 0-2, where 2 is highest */
|
||||
const SKP_int forLJC /* I 1 if this function is called from LJC code, 0 otherwise. */
|
||||
);
|
||||
|
||||
/* parameter defining the size and accuracy of the piecewise linear */
|
||||
@@ -437,13 +343,6 @@ SKP_int SKP_Silk_pitch_analysis_core( /* O Voicing estimate: 0 voiced, 1
|
||||
/* rom table with cosine values */
|
||||
extern const SKP_int SKP_Silk_LSFCosTab_FIX_Q12[ LSF_COS_TAB_SZ_FIX + 1 ];
|
||||
|
||||
void SKP_Silk_LPC_fit(
|
||||
SKP_int16 *a_QQ, /* O stabilized LPC vector, Q(24-rshift) [L] */
|
||||
SKP_int32 *a_Q24, /* I LPC vector [L] */
|
||||
const SKP_int QQ, /* I Q domain of output LPC vector */
|
||||
const SKP_int L /* I Number of LPC parameters in the input vector */
|
||||
);
|
||||
|
||||
/* Compute Normalized Line Spectral Frequencies (NLSFs) from whitening filter coefficients */
|
||||
/* If not all roots are found, the a_Q16 coefficients are bandwidth expanded until convergence. */
|
||||
void SKP_Silk_A2NLSF(
|
||||
@@ -466,13 +365,6 @@ void SKP_Silk_insertion_sort_increasing(
|
||||
const SKP_int K /* I: Number of correctly sorted positions */
|
||||
);
|
||||
|
||||
void SKP_Silk_insertion_sort_decreasing(
|
||||
SKP_int *a, /* I/O: Unsorted / Sorted vector */
|
||||
SKP_int *index, /* O: Index vector for the sorted elements */
|
||||
const SKP_int L, /* I: Vector length */
|
||||
const SKP_int K /* I: Number of correctly sorted positions */
|
||||
);
|
||||
|
||||
void SKP_Silk_insertion_sort_decreasing_int16(
|
||||
SKP_int16 *a, /* I/O: Unsorted / Sorted vector */
|
||||
SKP_int *index, /* O: Index vector for the sorted elements */
|
||||
@@ -492,14 +384,6 @@ void SKP_Silk_NLSF_stabilize(
|
||||
const SKP_int L /* I: Number of NLSF parameters in the input vector */
|
||||
);
|
||||
|
||||
/* NLSF stabilizer, over multiple input column data vectors */
|
||||
void SKP_Silk_NLSF_stabilize_multi(
|
||||
SKP_int *NLSF_Q15, /* I/O: Unstable/stabilized normalized LSF vectors in Q15 [LxN] */
|
||||
const SKP_int *NDeltaMin_Q15, /* I: Normalized delta min vector in Q15, NDeltaMin_Q15[L] must be >= 1 [L+1] */
|
||||
const SKP_int N, /* I: Number of input vectors to be stabilized */
|
||||
const SKP_int L /* I: NLSF vector dimension */
|
||||
);
|
||||
|
||||
/* Laroia low complexity NLSF weights */
|
||||
void SKP_Silk_NLSF_VQ_weights_laroia(
|
||||
SKP_int *pNLSFW_Q6, /* O: Pointer to input vector weights [D x 1] */
|
||||
@@ -519,13 +403,6 @@ void SKP_Silk_burg_modified(
|
||||
const SKP_int D /* I order */
|
||||
);
|
||||
|
||||
/* Multiply a vector by a constant */
|
||||
void SKP_Silk_scale_vector16_Q14(
|
||||
SKP_int16 *data1,
|
||||
SKP_int gain_Q14, /* Gain in Q14 */
|
||||
SKP_int dataSize
|
||||
);
|
||||
|
||||
/* Copy and multiply a vector by a constant */
|
||||
void SKP_Silk_scale_copy_vector16(
|
||||
SKP_int16 *data_out,
|
||||
@@ -534,19 +411,6 @@ void SKP_Silk_scale_copy_vector16(
|
||||
const SKP_int dataSize /* I: length */
|
||||
);
|
||||
|
||||
void SKP_Silk_scale_vector32_16_Q14(
|
||||
SKP_int32 *data1, /* I/O: Q0/Q0 */
|
||||
SKP_int gain_Q14, /* I: Q14 */
|
||||
SKP_int dataSize /* I: length */
|
||||
);
|
||||
|
||||
/* Multiply a vector by a constant, does not saturate output data */
|
||||
void SKP_Silk_scale_vector32_Q16(
|
||||
SKP_int32 *data1, /* I/O: Q0/Q0 */
|
||||
SKP_int32 gain_Q16, /* I: gain in Q16 ( SKP_int16_MIN <= gain_Q16 <= SKP_int16_MAX + 65536 ) */
|
||||
const SKP_int dataSize /* I: length */
|
||||
);
|
||||
|
||||
/* Some for the LTP related function requires Q26 to work.*/
|
||||
void SKP_Silk_scale_vector32_Q26_lshift_18(
|
||||
SKP_int32 *data1, /* I/O: Q0/Q18 */
|
||||
@@ -566,31 +430,32 @@ SKP_int32 SKP_Silk_inner_prod_aligned(
|
||||
const SKP_int len /* I vector lengths */
|
||||
);
|
||||
|
||||
SKP_int32 SKP_Silk_inner_prod16_aligned_sat(
|
||||
const SKP_int16* const inVec1, /* I input vector 1 */
|
||||
const SKP_int16* const inVec2, /* I input vector 2 */
|
||||
const SKP_int len /* I vector lengths */
|
||||
);
|
||||
|
||||
SKP_int64 SKP_Silk_inner_prod_aligned_64(
|
||||
const SKP_int32 *inVec1, /* I input vector 1 */
|
||||
const SKP_int32 *inVec2, /* I input vector 2 */
|
||||
const SKP_int len /* I vector lengths */
|
||||
);
|
||||
|
||||
SKP_int64 SKP_Silk_inner_prod16_aligned_64(
|
||||
const SKP_int16 *inVec1, /* I input vector 1 */
|
||||
const SKP_int16 *inVec1, /* I input vector 1 */
|
||||
const SKP_int16 *inVec2, /* I input vector 2 */
|
||||
const SKP_int len /* I vector lengths */
|
||||
);
|
||||
/********************************************************************/
|
||||
/* MACROS */
|
||||
/* MACROS */
|
||||
/********************************************************************/
|
||||
|
||||
/* Define 4-byte aligned array of SKP_int16 */
|
||||
#define SKP_array_of_int16_4_byte_aligned( arrayName, nElements ) \
|
||||
SKP_int32 dummy_int32 ## arrayName; \
|
||||
SKP_int16 arrayName[ (nElements) ]
|
||||
/* Rotate a32 right by 'rot' bits. Negative rot values result in rotating
|
||||
left. Output is 32bit int.
|
||||
Note: contemporary compilers recognize the C expression below and
|
||||
compile it into a 'ror' instruction if available. No need for inline ASM! */
|
||||
SKP_INLINE SKP_int32 SKP_ROR32( SKP_int32 a32, SKP_int rot )
|
||||
{
|
||||
SKP_uint32 x = (SKP_uint32) a32;
|
||||
SKP_uint32 r = (SKP_uint32) rot;
|
||||
SKP_uint32 m = (SKP_uint32) -rot;
|
||||
if(rot <= 0)
|
||||
return (SKP_int32) ((x << m) | (x >> (32 - m)));
|
||||
else
|
||||
return (SKP_int32) ((x << (32 - r)) | (x >> r));
|
||||
}
|
||||
|
||||
/* Allocate SKP_int16 alligned to 4-byte memory address */
|
||||
#define SKP_DWORD_ALIGN
|
||||
|
||||
/* Useful Macros that can be adjusted to other platforms */
|
||||
#define SKP_memcpy(a, b, c) memcpy((a), (b), (c)) /* Dest, Src, ByteCount */
|
||||
@@ -607,12 +472,6 @@ SKP_int64 SKP_Silk_inner_prod16_aligned_64(
|
||||
// a32 + (b32 * c32) output have to be 32bit int
|
||||
#define SKP_MLA(a32, b32, c32) SKP_ADD32((a32),((b32) * (c32)))
|
||||
|
||||
// a32 + (b32 * c32) output have to be 32bit uint
|
||||
#define SKP_MLA_uint(a32, b32, c32) SKP_MLA(a32, b32, c32)
|
||||
|
||||
// ((a32 >> 16) * (b32 >> 16)) output have to be 32bit int
|
||||
#define SKP_SMULTT(a32, b32) (((a32) >> 16) * ((b32) >> 16))
|
||||
|
||||
// a32 + ((a32 >> 16) * (b32 >> 16)) output have to be 32bit int
|
||||
#define SKP_SMLATT(a32, b32, c32) SKP_ADD32((a32),((b32) >> 16) * ((c32) >> 16))
|
||||
|
||||
@@ -626,70 +485,40 @@ SKP_int64 SKP_Silk_inner_prod16_aligned_64(
|
||||
#ifndef SKP_SMLABB_ovflw
|
||||
# define SKP_SMLABB_ovflw(a32, b32, c32) SKP_SMLABB(a32, b32, c32)
|
||||
#endif
|
||||
#define SKP_SMLABT_ovflw(a32, b32, c32) SKP_SMLABT(a32, b32, c32)
|
||||
#define SKP_SMLATT_ovflw(a32, b32, c32) SKP_SMLATT(a32, b32, c32)
|
||||
#define SKP_SMLAWB_ovflw(a32, b32, c32) SKP_SMLAWB(a32, b32, c32)
|
||||
#define SKP_SMLAWT_ovflw(a32, b32, c32) SKP_SMLAWT(a32, b32, c32)
|
||||
|
||||
#define SKP_DIV64_32(a64, b32) ((a64)/(b32)) /* TODO: rewrite it as a set of SKP_DIV32.*/
|
||||
|
||||
#define SKP_DIV32_16(a32, b16) ((SKP_int32)((a32) / (b16)))
|
||||
#define SKP_DIV32(a32, b32) ((SKP_int32)((a32) / (b32)))
|
||||
|
||||
// These macros enables checking for overflow in SKP_Silk_API_Debug.h
|
||||
#define SKP_ADD16(a, b) ((a) + (b))
|
||||
#define SKP_ADD32(a, b) ((a) + (b))
|
||||
#define SKP_ADD64(a, b) ((a) + (b))
|
||||
|
||||
#define SKP_SUB16(a, b) ((a) - (b))
|
||||
#define SKP_SUB32(a, b) ((a) - (b))
|
||||
#define SKP_SUB64(a, b) ((a) - (b))
|
||||
|
||||
#define SKP_SAT8(a) ((a) > SKP_int8_MAX ? SKP_int8_MAX : \
|
||||
((a) < SKP_int8_MIN ? SKP_int8_MIN : (a)))
|
||||
#define SKP_SAT16(a) ((a) > SKP_int16_MAX ? SKP_int16_MAX : \
|
||||
((a) < SKP_int16_MIN ? SKP_int16_MIN : (a)))
|
||||
#define SKP_SAT32(a) ((a) > SKP_int32_MAX ? SKP_int32_MAX : \
|
||||
((a) < SKP_int32_MIN ? SKP_int32_MIN : (a)))
|
||||
|
||||
#define SKP_CHECK_FIT8(a) (a)
|
||||
#define SKP_CHECK_FIT16(a) (a)
|
||||
#define SKP_CHECK_FIT32(a) (a)
|
||||
|
||||
#define SKP_ADD_SAT16(a, b) (SKP_int16)SKP_SAT16( SKP_ADD32( (SKP_int32)(a), (b) ) )
|
||||
#define SKP_ADD_SAT64(a, b) ((((a) + (b)) & 0x8000000000000000LL) == 0 ? \
|
||||
((((a) & (b)) & 0x8000000000000000LL) != 0 ? SKP_int64_MIN : (a)+(b)) : \
|
||||
((((a) | (b)) & 0x8000000000000000LL) == 0 ? SKP_int64_MAX : (a)+(b)) )
|
||||
|
||||
#define SKP_SUB_SAT16(a, b) (SKP_int16)SKP_SAT16( SKP_SUB32( (SKP_int32)(a), (b) ) )
|
||||
#define SKP_SUB_SAT64(a, b) ((((a)-(b)) & 0x8000000000000000LL) == 0 ? \
|
||||
(( (a) & ((b)^0x8000000000000000LL) & 0x8000000000000000LL) ? SKP_int64_MIN : (a)-(b)) : \
|
||||
((((a)^0x8000000000000000LL) & (b) & 0x8000000000000000LL) ? SKP_int64_MAX : (a)-(b)) )
|
||||
|
||||
/* Saturation for positive input values */
|
||||
#define SKP_POS_SAT32(a) ((a) > SKP_int32_MAX ? SKP_int32_MAX : (a))
|
||||
|
||||
/* Add with saturation for positive input values */
|
||||
#define SKP_ADD_POS_SAT8(a, b) ((((a)+(b)) & 0x80) ? SKP_int8_MAX : ((a)+(b)))
|
||||
#define SKP_ADD_POS_SAT16(a, b) ((((a)+(b)) & 0x8000) ? SKP_int16_MAX : ((a)+(b)))
|
||||
#define SKP_ADD_POS_SAT32(a, b) ((((a)+(b)) & 0x80000000) ? SKP_int32_MAX : ((a)+(b)))
|
||||
#define SKP_ADD_POS_SAT64(a, b) ((((a)+(b)) & 0x8000000000000000LL) ? SKP_int64_MAX : ((a)+(b)))
|
||||
|
||||
#define SKP_LSHIFT8(a, shift) ((a)<<(shift)) // shift >= 0, shift < 8
|
||||
#define SKP_LSHIFT16(a, shift) ((a)<<(shift)) // shift >= 0, shift < 16
|
||||
#define SKP_LSHIFT32(a, shift) ((a)<<(shift)) // shift >= 0, shift < 32
|
||||
#define SKP_LSHIFT64(a, shift) ((a)<<(shift)) // shift >= 0, shift < 64
|
||||
#define SKP_LSHIFT(a, shift) SKP_LSHIFT32(a, shift) // shift >= 0, shift < 32
|
||||
|
||||
#define SKP_RSHIFT8(a, shift) ((a)>>(shift)) // shift >= 0, shift < 8
|
||||
#define SKP_RSHIFT16(a, shift) ((a)>>(shift)) // shift >= 0, shift < 16
|
||||
#define SKP_RSHIFT32(a, shift) ((a)>>(shift)) // shift >= 0, shift < 32
|
||||
#define SKP_RSHIFT64(a, shift) ((a)>>(shift)) // shift >= 0, shift < 64
|
||||
#define SKP_RSHIFT(a, shift) SKP_RSHIFT32(a, shift) // shift >= 0, shift < 32
|
||||
|
||||
/* saturates before shifting */
|
||||
#define SKP_LSHIFT_SAT16(a, shift) (SKP_LSHIFT16( SKP_LIMIT( (a), SKP_RSHIFT16( SKP_int16_MIN, (shift) ), \
|
||||
SKP_RSHIFT16( SKP_int16_MAX, (shift) ) ), (shift) ))
|
||||
#define SKP_LSHIFT_SAT32(a, shift) (SKP_LSHIFT32( SKP_LIMIT( (a), SKP_RSHIFT32( SKP_int32_MIN, (shift) ), \
|
||||
SKP_RSHIFT32( SKP_int32_MAX, (shift) ) ), (shift) ))
|
||||
|
||||
@@ -699,7 +528,6 @@ SKP_int64 SKP_Silk_inner_prod16_aligned_64(
|
||||
|
||||
#define SKP_ADD_LSHIFT(a, b, shift) ((a) + SKP_LSHIFT((b), (shift))) // shift >= 0
|
||||
#define SKP_ADD_LSHIFT32(a, b, shift) SKP_ADD32((a), SKP_LSHIFT32((b), (shift))) // shift >= 0
|
||||
#define SKP_ADD_LSHIFT_uint(a, b, shift) ((a) + SKP_LSHIFT_uint((b), (shift))) // shift >= 0
|
||||
#define SKP_ADD_RSHIFT(a, b, shift) ((a) + SKP_RSHIFT((b), (shift))) // shift >= 0
|
||||
#define SKP_ADD_RSHIFT32(a, b, shift) SKP_ADD32((a), SKP_RSHIFT32((b), (shift))) // shift >= 0
|
||||
#define SKP_ADD_RSHIFT_uint(a, b, shift) ((a) + SKP_RSHIFT_uint((b), (shift))) // shift >= 0
|
||||
@@ -712,32 +540,23 @@ SKP_int64 SKP_Silk_inner_prod16_aligned_64(
|
||||
|
||||
/* Number of rightshift required to fit the multiplication */
|
||||
#define SKP_NSHIFT_MUL_32_32(a, b) ( -(31- (32-SKP_Silk_CLZ32(SKP_abs(a)) + (32-SKP_Silk_CLZ32(SKP_abs(b))))) )
|
||||
#define SKP_NSHIFT_MUL_16_16(a, b) ( -(15- (16-SKP_Silk_CLZ16(SKP_abs(a)) + (16-SKP_Silk_CLZ16(SKP_abs(b))))) )
|
||||
|
||||
|
||||
#define SKP_min(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define SKP_max(a, b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
/* Macro to convert floating-point constants to fixed-point */
|
||||
#define SKP_FIX_CONST( C, Q ) ((SKP_int32)((C) * (1 << (Q)) + 0.5))
|
||||
#define SKP_FIX_CONST( C, Q ) ((SKP_int32)((C) * ((SKP_int64)1 << (Q)) + 0.5))
|
||||
|
||||
/* SKP_min() versions with typecast in the function call */
|
||||
SKP_INLINE SKP_int SKP_min_int(SKP_int a, SKP_int b)
|
||||
{
|
||||
return (((a) < (b)) ? (a) : (b));
|
||||
}
|
||||
SKP_INLINE SKP_int16 SKP_min_16(SKP_int16 a, SKP_int16 b)
|
||||
{
|
||||
return (((a) < (b)) ? (a) : (b));
|
||||
}
|
||||
|
||||
SKP_INLINE SKP_int32 SKP_min_32(SKP_int32 a, SKP_int32 b)
|
||||
{
|
||||
return (((a) < (b)) ? (a) : (b));
|
||||
}
|
||||
SKP_INLINE SKP_int64 SKP_min_64(SKP_int64 a, SKP_int64 b)
|
||||
{
|
||||
return (((a) < (b)) ? (a) : (b));
|
||||
}
|
||||
|
||||
/* SKP_min() versions with typecast in the function call */
|
||||
SKP_INLINE SKP_int SKP_max_int(SKP_int a, SKP_int b)
|
||||
@@ -752,24 +571,17 @@ SKP_INLINE SKP_int32 SKP_max_32(SKP_int32 a, SKP_int32 b)
|
||||
{
|
||||
return (((a) > (b)) ? (a) : (b));
|
||||
}
|
||||
SKP_INLINE SKP_int64 SKP_max_64(SKP_int64 a, SKP_int64 b)
|
||||
{
|
||||
return (((a) > (b)) ? (a) : (b));
|
||||
}
|
||||
|
||||
#define SKP_LIMIT( a, limit1, limit2) ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \
|
||||
: ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a))))
|
||||
|
||||
#define SKP_LIMIT_int SKP_LIMIT
|
||||
#define SKP_LIMIT_32 SKP_LIMIT
|
||||
|
||||
//#define SKP_non_neg(a) ((a) & ((-(a)) >> (8 * sizeof(a) - 1))) /* doesn't seem faster than SKP_max(0, a);
|
||||
|
||||
#define SKP_abs(a) (((a) > 0) ? (a) : -(a)) // Be careful, SKP_abs returns wrong when input equals to SKP_intXX_MIN
|
||||
#define SKP_abs_int(a) (((a) ^ ((a) >> (8 * sizeof(a) - 1))) - ((a) >> (8 * sizeof(a) - 1)))
|
||||
#define SKP_abs_int32(a) (((a) ^ ((a) >> 31)) - ((a) >> 31))
|
||||
#define SKP_abs_int64(a) (((a) > 0) ? (a) : -(a))
|
||||
|
||||
#define SKP_sign(a) ((a) > 0 ? 1 : ( (a) < 0 ? -1 : 0 ))
|
||||
|
||||
#define SKP_sqrt(a) (sqrt(a))
|
||||
|
||||
/* PSEUDO-RANDOM GENERATOR */
|
||||
/* Make sure to store the result as the seed for the next call (also in between */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
@@ -141,7 +141,7 @@ SKP_int SKP_Silk_VAD_GetSA_Q8( /* O Retu
|
||||
for( s = 0; s < VAD_INTERNAL_SUBFRAMES; s++ ) {
|
||||
sumSquared = 0;
|
||||
for( i = 0; i < dec_subframe_length; i++ ) {
|
||||
/* The energy will be less than dec_subframe_length * ( SKP_int16_MIN / 8 )^2. */
|
||||
/* The energy will be less than dec_subframe_length * ( SKP_int16_MIN / 8 ) ^ 2. */
|
||||
/* Therefore we can accumulate with no risk of overflow (unless dec_subframe_length > 128) */
|
||||
x_tmp = SKP_RSHIFT( X[ b ][ i + dec_subframe_offset ], 3 );
|
||||
sumSquared = SKP_SMLABB( sumSquared, x_tmp, x_tmp );
|
||||
@@ -150,11 +150,11 @@ SKP_int SKP_Silk_VAD_GetSA_Q8( /* O Retu
|
||||
SKP_assert( sumSquared >= 0 );
|
||||
}
|
||||
|
||||
/* add/saturate summed energy of current subframe */
|
||||
/* Add/saturate summed energy of current subframe */
|
||||
if( s < VAD_INTERNAL_SUBFRAMES - 1 ) {
|
||||
Xnrg[ b ] = SKP_ADD_POS_SAT32( Xnrg[ b ], sumSquared );
|
||||
} else {
|
||||
/* look-ahead subframe */
|
||||
/* Look-ahead subframe */
|
||||
Xnrg[ b ] = SKP_ADD_POS_SAT32( Xnrg[ b ], SKP_RSHIFT( sumSquared, 1 ) );
|
||||
}
|
||||
|
||||
@@ -201,7 +201,7 @@ SKP_int SKP_Silk_VAD_GetSA_Q8( /* O Retu
|
||||
}
|
||||
|
||||
/* Mean-of-squares */
|
||||
sumSquared = SKP_DIV32_16( sumSquared, VAD_N_BANDS ); /* Q14 */
|
||||
sumSquared = SKP_DIV32_16( sumSquared, VAD_N_BANDS ); /* Q14 */
|
||||
|
||||
/* Root-mean-square approximation, scale to dBs, and write to output pointer */
|
||||
*pSNR_dB_Q7 = ( SKP_int16 )( 3 * SKP_Silk_SQRT_APPROX( sumSquared ) ); /* Q7 */
|
||||
@@ -240,7 +240,7 @@ SKP_int SKP_Silk_VAD_GetSA_Q8( /* O Retu
|
||||
/***********************************/
|
||||
/* Energy Level and SNR estimation */
|
||||
/***********************************/
|
||||
/* smoothing coefficient */
|
||||
/* Smoothing coefficient */
|
||||
smooth_coef_Q16 = SKP_SMULWB( VAD_SNR_SMOOTH_COEF_Q18, SKP_SMULWB( SA_Q15, SA_Q15 ) );
|
||||
for( b = 0; b < VAD_N_BANDS; b++ ) {
|
||||
/* compute smoothed energy-to-noise ratio per band */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
@@ -41,60 +41,57 @@ void SKP_Silk_VQ_WMat_EC_FIX(
|
||||
{
|
||||
SKP_int k;
|
||||
const SKP_int16 *cb_row_Q14;
|
||||
SKP_int32 sum1_Q14, sum2_Q16, diff_Q14_01, diff_Q14_23, diff_Q14_4;
|
||||
SKP_int16 diff_Q14[ 5 ];
|
||||
SKP_int32 sum1_Q14, sum2_Q16;
|
||||
|
||||
/* Loop over codebook */
|
||||
*rate_dist_Q14 = SKP_int32_MAX;
|
||||
cb_row_Q14 = cb_Q14;
|
||||
for( k = 0; k < L; k++ ) {
|
||||
/* Pack pairs of int16 values per int32 */
|
||||
diff_Q14_01 = (SKP_uint16)( in_Q14[ 0 ] - cb_row_Q14[ 0 ] ) | SKP_LSHIFT( ( SKP_int32 )in_Q14[ 1 ] - cb_row_Q14[ 1 ], 16 );
|
||||
diff_Q14_23 = (SKP_uint16)( in_Q14[ 2 ] - cb_row_Q14[ 2 ] ) | SKP_LSHIFT( ( SKP_int32 )in_Q14[ 3 ] - cb_row_Q14[ 3 ], 16 );
|
||||
diff_Q14_4 = in_Q14[ 4 ] - cb_row_Q14[ 4 ];
|
||||
diff_Q14[ 0 ] = in_Q14[ 0 ] - cb_row_Q14[ 0 ];
|
||||
diff_Q14[ 1 ] = in_Q14[ 1 ] - cb_row_Q14[ 1 ];
|
||||
diff_Q14[ 2 ] = in_Q14[ 2 ] - cb_row_Q14[ 2 ];
|
||||
diff_Q14[ 3 ] = in_Q14[ 3 ] - cb_row_Q14[ 3 ];
|
||||
diff_Q14[ 4 ] = in_Q14[ 4 ] - cb_row_Q14[ 4 ];
|
||||
|
||||
/* Weighted rate */
|
||||
sum1_Q14 = SKP_SMULBB( mu_Q8, cl_Q6[ k ] );
|
||||
|
||||
SKP_assert( sum1_Q14 >= 0 );
|
||||
|
||||
/* Add weighted quantization error, assuming W_Q18 is symmetric */
|
||||
/* NOTE: the code below loads two int16 values as one int32, and multiplies each using the */
|
||||
/* SMLAWB and SMLAWT instructions. On a big-endian CPU the two int16 variables would be */
|
||||
/* loaded in reverse order and the code will give the wrong result. In that case swapping */
|
||||
/* the SMLAWB and SMLAWT instructions should solve the problem. */
|
||||
/* first row of W_Q18 */
|
||||
sum2_Q16 = SKP_SMULWT( W_Q18[ 1 ], diff_Q14_01 );
|
||||
sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 2 ], diff_Q14_23 );
|
||||
sum2_Q16 = SKP_SMLAWT( sum2_Q16, W_Q18[ 3 ], diff_Q14_23 );
|
||||
sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 4 ], diff_Q14_4 );
|
||||
sum2_Q16 = SKP_SMULWB( W_Q18[ 1 ], diff_Q14[ 1 ] );
|
||||
sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 2 ], diff_Q14[ 2 ] );
|
||||
sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 3 ], diff_Q14[ 3 ] );
|
||||
sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 4 ], diff_Q14[ 4 ] );
|
||||
sum2_Q16 = SKP_LSHIFT( sum2_Q16, 1 );
|
||||
sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 0 ], diff_Q14_01 );
|
||||
sum1_Q14 = SKP_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14_01 );
|
||||
sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 0 ], diff_Q14[ 0 ] );
|
||||
sum1_Q14 = SKP_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 0 ] );
|
||||
|
||||
/* second row of W_Q18 */
|
||||
sum2_Q16 = SKP_SMULWB( W_Q18[ 7 ], diff_Q14_23 );
|
||||
sum2_Q16 = SKP_SMLAWT( sum2_Q16, W_Q18[ 8 ], diff_Q14_23 );
|
||||
sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 9 ], diff_Q14_4 );
|
||||
sum2_Q16 = SKP_SMULWB( W_Q18[ 7 ], diff_Q14[ 2 ] );
|
||||
sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 8 ], diff_Q14[ 3 ] );
|
||||
sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 9 ], diff_Q14[ 4 ] );
|
||||
sum2_Q16 = SKP_LSHIFT( sum2_Q16, 1 );
|
||||
sum2_Q16 = SKP_SMLAWT( sum2_Q16, W_Q18[ 6 ], diff_Q14_01 );
|
||||
sum1_Q14 = SKP_SMLAWT( sum1_Q14, sum2_Q16, diff_Q14_01 );
|
||||
sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 6 ], diff_Q14[ 1 ] );
|
||||
sum1_Q14 = SKP_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 1 ] );
|
||||
|
||||
/* third row of W_Q18 */
|
||||
sum2_Q16 = SKP_SMULWT( W_Q18[ 13 ], diff_Q14_23 );
|
||||
sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 14 ], diff_Q14_4 );
|
||||
sum2_Q16 = SKP_SMULWB( W_Q18[ 13 ], diff_Q14[ 3 ] );
|
||||
sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 14 ], diff_Q14[ 4 ] );
|
||||
sum2_Q16 = SKP_LSHIFT( sum2_Q16, 1 );
|
||||
sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 12 ], diff_Q14_23 );
|
||||
sum1_Q14 = SKP_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14_23 );
|
||||
sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 12 ], diff_Q14[ 2 ] );
|
||||
sum1_Q14 = SKP_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 2 ] );
|
||||
|
||||
/* fourth row of W_Q18 */
|
||||
sum2_Q16 = SKP_SMULWB( W_Q18[ 19 ], diff_Q14_4 );
|
||||
sum2_Q16 = SKP_SMULWB( W_Q18[ 19 ], diff_Q14[ 4 ] );
|
||||
sum2_Q16 = SKP_LSHIFT( sum2_Q16, 1 );
|
||||
sum2_Q16 = SKP_SMLAWT( sum2_Q16, W_Q18[ 18 ], diff_Q14_23 );
|
||||
sum1_Q14 = SKP_SMLAWT( sum1_Q14, sum2_Q16, diff_Q14_23 );
|
||||
sum2_Q16 = SKP_SMLAWB( sum2_Q16, W_Q18[ 18 ], diff_Q14[ 3 ] );
|
||||
sum1_Q14 = SKP_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 3 ] );
|
||||
|
||||
/* last row of W_Q18 */
|
||||
sum2_Q16 = SKP_SMULWB( W_Q18[ 24 ], diff_Q14_4 );
|
||||
sum1_Q14 = SKP_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14_4 );
|
||||
sum2_Q16 = SKP_SMULWB( W_Q18[ 24 ], diff_Q14[ 4 ] );
|
||||
sum1_Q14 = SKP_SMLAWB( sum1_Q14, sum2_Q16, diff_Q14[ 4 ] );
|
||||
|
||||
SKP_assert( sum1_Q14 >= 0 );
|
||||
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, 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.
|
||||
***********************************************************************/
|
||||
|
||||
/* *
|
||||
* SKP_Silk_allpass_int.c *
|
||||
* *
|
||||
* First-order allpass filter with *
|
||||
* transfer function: *
|
||||
* *
|
||||
* A + Z^(-1) *
|
||||
* H(z) = ------------ *
|
||||
* 1 + A*Z^(-1) *
|
||||
* *
|
||||
* Implemented using minimum multiplier filter design. *
|
||||
* *
|
||||
* Reference: http://www.univ.trieste.it/~ramponi/teaching/ *
|
||||
* DSP/materiale/Ch6(2).pdf *
|
||||
* *
|
||||
* Copyright 2007 (c), Skype Limited *
|
||||
* Date: 070525 *
|
||||
* */
|
||||
#include "SKP_Silk_SigProc_FIX.h"
|
||||
|
||||
|
||||
/* First-order allpass filter */
|
||||
void SKP_Silk_allpass_int(
|
||||
const SKP_int32 *in, /* I: Q25 input signal [len] */
|
||||
SKP_int32 *S, /* I/O: Q25 state [1] */
|
||||
SKP_int A, /* I: Q15 coefficient (0 <= A < 32768) */
|
||||
SKP_int32 *out, /* O: Q25 output signal [len] */
|
||||
const SKP_int32 len /* I: Number of samples */
|
||||
)
|
||||
{
|
||||
SKP_int32 Y2, X2, S0;
|
||||
SKP_int k;
|
||||
|
||||
S0 = S[ 0 ];
|
||||
for( k = len - 1; k >= 0; k-- ) {
|
||||
Y2 = *in - S0;
|
||||
X2 = ( Y2 >> 15 ) * A + ( ( ( Y2 & 0x00007FFF ) * A ) >> 15 );
|
||||
( *out++ ) = S0 + X2;
|
||||
S0 = ( *in++ ) + X2;
|
||||
}
|
||||
S[ 0 ] = S0;
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
@@ -36,38 +36,45 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "SKP_Silk_SigProc_FIX.h"
|
||||
|
||||
/* Coefficients for 2-band filter bank based on first-order allpass filters */
|
||||
static SKP_int16 A_fb1_20[ 1 ] = { 5394 };
|
||||
static SKP_int16 A_fb1_21[ 1 ] = { 20623 };
|
||||
// old
|
||||
static SKP_int16 A_fb1_20[ 1 ] = { 5394 << 1 };
|
||||
static SKP_int16 A_fb1_21[ 1 ] = { 20623 << 1 }; /* wrap-around to negative number is intentional */
|
||||
|
||||
/* Split signal into two decimated bands using first-order allpass filters */
|
||||
void SKP_Silk_ana_filt_bank_1(
|
||||
const SKP_int16 *in, /* I: Input signal [N] */
|
||||
const SKP_int16 *in, /* I: Input signal [N] */
|
||||
SKP_int32 *S, /* I/O: State vector [2] */
|
||||
SKP_int16 *outL, /* O: Low band [N/2] */
|
||||
SKP_int16 *outH, /* O: High band [N/2] */
|
||||
SKP_int32 *scratch, /* I: Scratch memory [3*N/2] */
|
||||
SKP_int16 *outL, /* O: Low band [N/2] */
|
||||
SKP_int16 *outH, /* O: High band [N/2] */
|
||||
SKP_int32 *scratch, /* I: Scratch memory [3*N/2] */ // todo: remove - no longer used
|
||||
const SKP_int32 N /* I: Number of input samples */
|
||||
)
|
||||
{
|
||||
SKP_int k, N2 = SKP_RSHIFT( N, 1 );
|
||||
SKP_int32 out_tmp;
|
||||
SKP_int k, N2 = SKP_RSHIFT( N, 1 );
|
||||
SKP_int32 in32, X, Y, out_1, out_2;
|
||||
|
||||
/* De-interleave three allpass inputs, and convert Q15 -> Q25 */
|
||||
/* Internal variables and state are in Q10 format */
|
||||
for( k = 0; k < N2; k++ ) {
|
||||
scratch[ k + N ] = SKP_LSHIFT( (SKP_int32)in[ 2 * k ], 10 );
|
||||
scratch[ k + N2 ] = SKP_LSHIFT( (SKP_int32)in[ 2 * k + 1 ], 10 );
|
||||
/* Convert to Q10 */
|
||||
in32 = SKP_LSHIFT( (SKP_int32)in[ 2 * k ], 10 );
|
||||
|
||||
/* All-pass section for even input sample */
|
||||
Y = SKP_SUB32( in32, S[ 0 ] );
|
||||
X = SKP_SMLAWB( Y, Y, A_fb1_21[ 0 ] );
|
||||
out_1 = SKP_ADD32( S[ 0 ], X );
|
||||
S[ 0 ] = SKP_ADD32( in32, X );
|
||||
|
||||
/* Convert to Q10 */
|
||||
in32 = SKP_LSHIFT( (SKP_int32)in[ 2 * k + 1 ], 10 );
|
||||
|
||||
/* All-pass section for odd input sample */
|
||||
Y = SKP_SUB32( in32, S[ 1 ] );
|
||||
X = SKP_SMULWB( Y, A_fb1_20[ 0 ] );
|
||||
out_2 = SKP_ADD32( S[ 1 ], X );
|
||||
S[ 1 ] = SKP_ADD32( in32, X );
|
||||
|
||||
/* Add/subtract, convert back to int16 and store to output */
|
||||
outL[ k ] = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( SKP_ADD32( out_2, out_1 ), 11 ) );
|
||||
outH[ k ] = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( SKP_SUB32( out_2, out_1 ), 11 ) );
|
||||
}
|
||||
|
||||
/* Allpass filters */
|
||||
SKP_Silk_allpass_int( scratch + N2, S+0, A_fb1_20[ 0 ], scratch, N2 );
|
||||
SKP_Silk_allpass_int( scratch + N, S+1, A_fb1_21[ 0 ], scratch + N2, N2 );
|
||||
|
||||
/* Add and subtract two allpass outputs to create bands */
|
||||
for( k = 0; k < N2; k++ ) {
|
||||
out_tmp = scratch[ k ] + scratch[ k + N2 ];
|
||||
outL[ k ] = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( out_tmp, 11 ) );
|
||||
|
||||
out_tmp = scratch[ k ] - scratch[ k + N2 ];
|
||||
outH[ k ] = (SKP_int16)SKP_SAT16( SKP_RSHIFT_ROUND( out_tmp, 11 ) );
|
||||
}
|
||||
}
|
||||
+38
-29
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
@@ -29,64 +29,73 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
/* Apply sine window to signal vector. */
|
||||
/* Window types: */
|
||||
/* 0 -> sine window from 0 to pi */
|
||||
/* 1 -> sine window from 0 to pi/2 */
|
||||
/* 2 -> sine window from pi/2 to pi */
|
||||
/* every other sample of window is linearly interpolated, for speed */
|
||||
void SKP_Silk_apply_sine_window(
|
||||
/* Every other sample is linearly interpolated, for speed. */
|
||||
/* Window length must be between 16 and 120 (incl) and a multiple of 4. */
|
||||
|
||||
/* Matlab code for table:
|
||||
for k=16:9*4:16+2*9*4, fprintf(' %7.d,', -round(65536*pi ./ (k:4:k+8*4))); fprintf('\n'); end
|
||||
*/
|
||||
static SKP_int16 freq_table_Q16[ 27 ] = {
|
||||
12111, 9804, 8235, 7100, 6239, 5565, 5022, 4575, 4202,
|
||||
3885, 3612, 3375, 3167, 2984, 2820, 2674, 2542, 2422,
|
||||
2313, 2214, 2123, 2038, 1961, 1889, 1822, 1760, 1702,
|
||||
};
|
||||
|
||||
|
||||
void SKP_Silk_apply_sine_window_new(
|
||||
SKP_int16 px_win[], /* O Pointer to windowed signal */
|
||||
const SKP_int16 px[], /* I Pointer to input signal */
|
||||
const SKP_int win_type, /* I Selects a window type */
|
||||
const SKP_int length /* I Window length, multiple of 4 */
|
||||
)
|
||||
{
|
||||
SKP_int k;
|
||||
SKP_int32 px32, f_Q16, c_Q20, S0_Q16, S1_Q16;
|
||||
SKP_int k, f_Q16, c_Q16;
|
||||
SKP_int32 S0_Q16, S1_Q16;
|
||||
SKP_assert( win_type == 1 || win_type == 2 );
|
||||
|
||||
/* Length must be multiple of 4 */
|
||||
/* Length must be in a range from 16 to 120 and a multiple of 4 */
|
||||
SKP_assert( length >= 16 && length <= 120 );
|
||||
SKP_assert( ( length & 3 ) == 0 );
|
||||
|
||||
/* Input pointer must be 4-byte aligned */
|
||||
SKP_assert( ( (SKP_int64)px & 3 ) == 0 );
|
||||
SKP_assert( ( ( SKP_int64 )( ( SKP_int8* )px - ( SKP_int8* )0 ) & 3 ) == 0 );
|
||||
|
||||
if( win_type == 0 ) {
|
||||
f_Q16 = SKP_DIV32_16( 411775, length + 1 ); // 411775 = 2 * 65536 * pi
|
||||
} else {
|
||||
f_Q16 = SKP_DIV32_16( 205887, length + 1 ); // 205887 = 65536 * pi
|
||||
}
|
||||
/* Frequency */
|
||||
k = ( length >> 2 ) - 4;
|
||||
SKP_assert( k >= 0 && k <= 26 );
|
||||
f_Q16 = (SKP_int)freq_table_Q16[ k ];
|
||||
|
||||
/* factor used for cosine approximation */
|
||||
c_Q20 = -SKP_RSHIFT( SKP_MUL( f_Q16, f_Q16 ), 12 );
|
||||
|
||||
/* c_Q20 becomes too large if length is too small */
|
||||
SKP_assert( c_Q20 >= -32768 );
|
||||
/* Factor used for cosine approximation */
|
||||
c_Q16 = SKP_SMULWB( f_Q16, -f_Q16 );
|
||||
SKP_assert( c_Q16 >= -32768 );
|
||||
|
||||
/* initialize state */
|
||||
if( win_type < 2 ) {
|
||||
if( win_type == 1 ) {
|
||||
/* start from 0 */
|
||||
S0_Q16 = 0;
|
||||
/* approximation of sin(f) */
|
||||
S1_Q16 = f_Q16;
|
||||
S1_Q16 = f_Q16 + SKP_RSHIFT( length, 3 );
|
||||
} else {
|
||||
/* start from 1 */
|
||||
S0_Q16 = ( 1 << 16 );
|
||||
/* approximation of cos(f) */
|
||||
S1_Q16 = ( 1 << 16 ) + SKP_RSHIFT( c_Q20, 5 );
|
||||
S1_Q16 = ( 1 << 16 ) + SKP_RSHIFT( c_Q16, 1 ) + SKP_RSHIFT( length, 4 );
|
||||
}
|
||||
|
||||
/* Uses the recursive equation: sin(n*f) = 2 * cos(f) * sin((n-1)*f) - sin((n-2)*f) */
|
||||
/* 4 samples at a time */
|
||||
for( k = 0; k < length; k += 4 ) {
|
||||
px32 = *( (SKP_int32 *)&px[ k ] ); /* load two values at once */
|
||||
px_win[ k ] = (SKP_int16)SKP_SMULWB( SKP_RSHIFT( S0_Q16 + S1_Q16, 1 ), px32 );
|
||||
px_win[ k + 1 ] = (SKP_int16)SKP_SMULWT( S1_Q16, px32 );
|
||||
S0_Q16 = SKP_RSHIFT( SKP_MUL( c_Q20, S1_Q16 ), 20 ) + SKP_LSHIFT( S1_Q16, 1 ) - S0_Q16 + 1;
|
||||
px_win[ k ] = (SKP_int16)SKP_SMULWB( SKP_RSHIFT( S0_Q16 + S1_Q16, 1 ), px[ k ] );
|
||||
px_win[ k + 1 ] = (SKP_int16)SKP_SMULWB( S1_Q16, px[ k + 1] );
|
||||
S0_Q16 = SKP_SMULWB( S1_Q16, c_Q16 ) + SKP_LSHIFT( S1_Q16, 1 ) - S0_Q16 + 1;
|
||||
S0_Q16 = SKP_min( S0_Q16, ( 1 << 16 ) );
|
||||
|
||||
px32 = *( (SKP_int32 *)&px[k + 2] ); /* load two values at once */
|
||||
px_win[ k + 2 ] = (SKP_int16)SKP_SMULWB( SKP_RSHIFT( S0_Q16 + S1_Q16, 1 ), px32 );
|
||||
px_win[ k + 3 ] = (SKP_int16)SKP_SMULWT( S0_Q16, px32 );
|
||||
S1_Q16 = SKP_RSHIFT( SKP_MUL( c_Q20, S0_Q16 ), 20 ) + SKP_LSHIFT( S0_Q16, 1 ) - S1_Q16;
|
||||
px_win[ k + 2 ] = (SKP_int16)SKP_SMULWB( SKP_RSHIFT( S0_Q16 + S1_Q16, 1 ), px[ k + 2] );
|
||||
px_win[ k + 3 ] = (SKP_int16)SKP_SMULWB( S0_Q16, px[ k + 3 ] );
|
||||
S1_Q16 = SKP_SMULWB( S0_Q16, c_Q16 ) + SKP_LSHIFT( S0_Q16, 1 ) - S1_Q16;
|
||||
S1_Q16 = SKP_min( S1_Q16, ( 1 << 16 ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/***********************************************************************
|
||||
Copyright (c) 2006-2010, Skype Limited. All rights reserved.
|
||||
Copyright (c) 2006-2011, 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:
|
||||
@@ -43,6 +43,7 @@ SKP_int16 SKP_Silk_int16_array_maxabs( /* O Maximum absolute value, max: 2
|
||||
)
|
||||
{
|
||||
SKP_int32 max = 0, i, lvl = 0, ind;
|
||||
if( len == 0 ) return 0;
|
||||
|
||||
ind = len - 1;
|
||||
max = SKP_SMULBB( vec[ ind ], vec[ ind ] );
|
||||
@@ -55,10 +56,13 @@ SKP_int16 SKP_Silk_int16_array_maxabs( /* O Maximum absolute value, max: 2
|
||||
}
|
||||
|
||||
/* Do not return 32768, as it will not fit in an int16 so may lead to problems later on */
|
||||
lvl = SKP_abs( vec[ ind ] );
|
||||
if( lvl > SKP_int16_MAX ) {
|
||||
if( max >= 1073676289 ) { // (2^15-1)^2 = 1073676289
|
||||
return( SKP_int16_MAX );
|
||||
} else {
|
||||
return( (SKP_int16)lvl );
|
||||
if( vec[ ind ] < 0 ) {
|
||||
return( -vec[ ind ] );
|
||||
} else {
|
||||
return( vec[ ind ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
Loaded 100 of 407 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user