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:
Moises Silva committed 2011-09-28 12:19:48 -04:00
commit b004bcfc6d
407 files changed
+25813 -41133

No files matched your search

+342 -585
View File
File diff suppressed because it is too large. Load diff
+4 -4
View File
@@ -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
View File
File diff suppressed because it is too large. Load diff
+25
View File
@@ -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);
+38
View File
@@ -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},
+3
View File
@@ -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);
+5
View File
@@ -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);
+16
View File
@@ -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 ;
+1
View File
@@ -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;
+52
View File
@@ -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},
+8
View File
@@ -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;
+43
View File
@@ -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)
+1
View File
@@ -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);
+1
View File
@@ -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)
+53
View File
@@ -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},
+46
View File
@@ -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);
+33
View File
@@ -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] = "";
+19 -3
View File
@@ -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);
}
+9
View File
@@ -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) {
+21 -3
View File
@@ -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
+1
View File
@@ -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
+1
View File
@@ -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);
+8
View File
@@ -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
+5
View File
@@ -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"/>-->
+79 -2
View File
@@ -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
+40
View File
@@ -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}
===============================================================================
])
+76
View File
@@ -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.
+318 -101
View File
@@ -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;
}
}
+25 -4
View File
@@ -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
View File
@@ -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;
+24 -1
View File
@@ -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
+3 -3
View File
@@ -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.
*
+110 -52
View File
@@ -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:
+57 -6
View File
@@ -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--;
-1407
View File
File diff suppressed because it is too large. Load diff
-1504
View File
File diff suppressed because it is too large. Load diff
-17354
View File
File diff suppressed because it is too large. Load diff
+1 -6
View File
@@ -673,12 +673,7 @@ CFLAGS
LDFLAGS
LIBS
CPPFLAGS
CPP
CPPFLAGS
CC
LDFLAGS
LIBS
CPPFLAGS'
CPP'
# Initialize some variables set by options.
+6
View File
@@ -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
View File
File diff suppressed because it is too large. Load diff
+2 -2
View File
@@ -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
+64 -39
View File
@@ -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:
+17 -8
View File
@@ -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
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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
+3
View File
@@ -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
View File
@@ -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 -2
View File
@@ -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
+10 -12
View File
@@ -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 */
);
/**************************/
+10 -7
View File
@@ -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;
+15 -19
View File
@@ -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 -1
View File
@@ -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
View File
@@ -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
+13 -14
View File
@@ -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 */
}
+2 -2
View File
@@ -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 );
/********************************/
+13 -17
View File
@@ -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 -1
View File
@@ -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 -77
View File
@@ -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 );
}
-132
View File
@@ -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 );
}
}
+18 -32
View File
@@ -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 );
}
}
+52 -71
View File
@@ -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 );
}
}
+9 -6
View File
@@ -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 -1
View File
@@ -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++;
}
+2 -2
View File
@@ -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
View File
@@ -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 ];
+5 -4
View File
@@ -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 );
+3 -2
View File
@@ -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 -1
View File
@@ -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:
+18 -10
View File
@@ -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 );
+2 -17
View File
@@ -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
View File
@@ -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 = &LTPCoef_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 );
}
+118 -137
View File
@@ -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 = &LTPCoef_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;
+33 -34
View File
@@ -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(
}
}
+3 -3
View File
@@ -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 */
+110 -298
View File
@@ -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 */
+6 -6
View File
@@ -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 );
-69
View File
@@ -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;
}
+32 -25
View File
@@ -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 ) );
}
}
@@ -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 ) );
}
}
+8 -4
View File
@@ -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