forked from retronetworking/osmo-v5
Added echo suppressor option
This commit is contained in:
parent
c2bf2598b1
commit
5268c0fc9b
19
src/layer1.c
19
src/layer1.c
|
@ -118,7 +118,7 @@ static void echo_tx(struct v5x_echo_proc *ep, uint8_t *data, int len)
|
|||
int in;
|
||||
int16_t tx;
|
||||
|
||||
if (!ep->ec || !ep->enabled)
|
||||
if (!ep->enabled)
|
||||
return;
|
||||
|
||||
while (len--) {
|
||||
|
@ -144,7 +144,7 @@ static void echo_rx(struct v5x_echo_proc *ep, uint8_t *data, int len)
|
|||
int i;
|
||||
int rc;
|
||||
|
||||
if (!ep->ec || !ep->enabled)
|
||||
if (!ep->enabled)
|
||||
return;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
|
@ -157,19 +157,26 @@ static void echo_rx(struct v5x_echo_proc *ep, uint8_t *data, int len)
|
|||
}
|
||||
if (ulaw) {
|
||||
rx = g711_ulaw_flipped_to_linear[*data];
|
||||
rx_can = echo_can_update(ep->ec, tx, rx);
|
||||
if (ep->port->use_line_echo == USE_ECHO_CANCELER)
|
||||
rx_can = echo_can_update(ep->ec, tx, rx);
|
||||
else
|
||||
rx_can = echo_sup_update(ep->es, tx, rx);
|
||||
*data++ = g711_linear_to_ulaw_flipped[(uint16_t)rx_can];
|
||||
} else {
|
||||
rx = g711_alaw_flipped_to_linear[*data];
|
||||
rx_can = echo_can_update(ep->ec, tx, rx);
|
||||
if (ep->port->use_line_echo == USE_ECHO_CANCELER)
|
||||
rx_can = echo_can_update(ep->ec, tx, rx);
|
||||
else
|
||||
rx_can = echo_sup_update(ep->es, tx, rx);
|
||||
*data++ = g711_linear_to_alaw_flipped[(uint16_t)rx_can];
|
||||
}
|
||||
answer_buffer[i] = rx + tx; /* yes, may overflow, but then it is no valid tone anyway */
|
||||
}
|
||||
|
||||
rc = answertone_process(&ep->at, answer_buffer, len);
|
||||
rc = answertone_process(&ep->at, answer_buffer, len, (ep->port->use_line_echo == USE_ECHO_CANCELER));
|
||||
if (rc > 0) {
|
||||
LOGP(DV5, LOGL_NOTICE, "Detected answer tone, disable echo chanceler of %s port %d.\n",
|
||||
LOGP(DV5, LOGL_NOTICE, "Detected answer tone, disable echo %s of %s port %d.\n",
|
||||
(ep->port->use_line_echo == USE_ECHO_CANCELER) ? "canceler" : "suppressor",
|
||||
(v5up->type == V5X_USER_TYPE_PSTN) ? "PSTN" : "ISDN", v5up->nr);
|
||||
ep->enabled = 0;
|
||||
}
|
||||
|
|
|
@ -986,31 +986,59 @@ DEFUN(cfg_no_port_isdn, cfg_no_port_isdn_cmd,
|
|||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_echo, cfg_echo_cmd,
|
||||
DEFUN(cfg_echo_can, cfg_echo_can_cmd,
|
||||
"line-echo-canceler",
|
||||
"Enable line echo canceler for all calls")
|
||||
{
|
||||
struct v5x_user_port *v5up = vty->index;
|
||||
|
||||
v5up->echo_configured = 1;
|
||||
v5up->use_line_echo = USE_ECHO_CANCELER;
|
||||
if (v5up->ts[0] && v5up->ts[0]->b_activated)
|
||||
v5x_echo_reset(&v5up->ep[0], v5up->echo_configured);
|
||||
v5x_echo_reset(&v5up->ep[0], v5up->use_line_echo);
|
||||
if (v5up->ts[1] && v5up->ts[1]->b_activated)
|
||||
v5x_echo_reset(&v5up->ep[1], v5up->echo_configured);
|
||||
v5x_echo_reset(&v5up->ep[1], v5up->use_line_echo);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_no_echo, cfg_no_echo_cmd,
|
||||
DEFUN(cfg_no_echo_can, cfg_no_echo_can_cmd,
|
||||
"no line-echo-canceler",
|
||||
NO_STR "Disable line echo canceler for all calls")
|
||||
{
|
||||
struct v5x_user_port *v5up = vty->index;
|
||||
|
||||
v5up->echo_configured = 0;
|
||||
v5up->use_line_echo = 0;
|
||||
if (v5up->ts[0] && v5up->ts[0]->b_activated)
|
||||
v5x_echo_reset(&v5up->ep[0], v5up->echo_configured);
|
||||
v5x_echo_reset(&v5up->ep[0], v5up->use_line_echo);
|
||||
if (v5up->ts[1] && v5up->ts[1]->b_activated)
|
||||
v5x_echo_reset(&v5up->ep[1], v5up->echo_configured);
|
||||
v5x_echo_reset(&v5up->ep[1], v5up->use_line_echo);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_echo_sup, cfg_echo_sup_cmd,
|
||||
"line-echo-suppressor",
|
||||
"Enable line echo suppressor for all calls")
|
||||
{
|
||||
struct v5x_user_port *v5up = vty->index;
|
||||
|
||||
v5up->use_line_echo = USE_ECHO_SUPPRESSOR;
|
||||
if (v5up->ts[0] && v5up->ts[0]->b_activated)
|
||||
v5x_echo_reset(&v5up->ep[0], v5up->use_line_echo);
|
||||
if (v5up->ts[1] && v5up->ts[1]->b_activated)
|
||||
v5x_echo_reset(&v5up->ep[1], v5up->use_line_echo);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
DEFUN(cfg_no_echo_sup, cfg_no_echo_sup_cmd,
|
||||
"no line-echo-suppressor",
|
||||
NO_STR "Disable line echo suppressor for all calls")
|
||||
{
|
||||
struct v5x_user_port *v5up = vty->index;
|
||||
|
||||
v5up->use_line_echo = 0;
|
||||
if (v5up->ts[0] && v5up->ts[0]->b_activated)
|
||||
v5x_echo_reset(&v5up->ep[0], v5up->use_line_echo);
|
||||
if (v5up->ts[1] && v5up->ts[1]->b_activated)
|
||||
v5x_echo_reset(&v5up->ep[1], v5up->use_line_echo);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1038,8 +1066,10 @@ static void config_write_user_port(struct vty *vty, struct v5x_interface *v5if)
|
|||
vty_out(vty, " port isdn %d%s", v5up->nr, VTY_NEWLINE);
|
||||
break;
|
||||
}
|
||||
if (v5up->echo_configured)
|
||||
if (v5up->use_line_echo == USE_ECHO_CANCELER)
|
||||
vty_out(vty, " line-echo-canceler%s", VTY_NEWLINE);
|
||||
if (v5up->use_line_echo == USE_ECHO_SUPPRESSOR)
|
||||
vty_out(vty, " line-echo-suppressor%s", VTY_NEWLINE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1173,8 +1203,10 @@ int v5le_vty_init(void)
|
|||
install_element(LINK_NODE, &cfg_e1_line_cmd);
|
||||
install_element(LINK_NODE, &cfg_no_e1_line_cmd);
|
||||
install_node(&port_node, NULL);
|
||||
install_element(PORT_NODE, &cfg_echo_cmd);
|
||||
install_element(PORT_NODE, &cfg_no_echo_cmd);
|
||||
install_element(PORT_NODE, &cfg_echo_can_cmd);
|
||||
install_element(PORT_NODE, &cfg_no_echo_can_cmd);
|
||||
install_element(PORT_NODE, &cfg_echo_sup_cmd);
|
||||
install_element(PORT_NODE, &cfg_no_echo_sup_cmd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -429,6 +429,11 @@ struct v5x_user_port *v5x_user_port_create(struct v5x_interface *v5if, uint16_t
|
|||
LOGP(DV5, LOGL_ERROR, "Failed to create line echo canceler\n");
|
||||
goto error;
|
||||
}
|
||||
v5up->ep[i].es = echo_sup_create(v5up, 8000);
|
||||
if (!v5up->ep[i].es) {
|
||||
LOGP(DV5, LOGL_ERROR, "Failed to create line echo suppressor\n");
|
||||
goto error;
|
||||
}
|
||||
rc = answertone_init(&v5up->ep[i].at, 8000);
|
||||
if (rc < 0) {
|
||||
LOGP(DV5, LOGL_ERROR, "Failed to create answer tone detector\n");
|
||||
|
@ -468,9 +473,14 @@ void v5x_user_port_destroy(struct v5x_user_port *v5up)
|
|||
/* destory line echo canceler */
|
||||
if (v5up->ep[i].ec) {
|
||||
echo_can_free(v5up->ep[i].ec);
|
||||
answertone_exit(&v5up->ep[i].at);
|
||||
v5up->ep[i].ec = NULL;
|
||||
}
|
||||
/* destory line echo suppressor */
|
||||
if (v5up->ep[i].es) {
|
||||
echo_sup_free(v5up->ep[i].es);
|
||||
v5up->ep[i].es = NULL;
|
||||
}
|
||||
answertone_exit(&v5up->ep[i].at);
|
||||
|
||||
/* unassign ports */
|
||||
if (v5up->ts[i]) {
|
||||
|
@ -499,8 +509,8 @@ void v5x_echo_reset(struct v5x_echo_proc *ep, int enable)
|
|||
answertone_reset(&ep->at);
|
||||
ep->tx_buffer_in = 0;
|
||||
ep->tx_buffer_out = 0;
|
||||
if (ep->ec)
|
||||
echo_can_flush(ep->ec);
|
||||
echo_can_flush(ep->ec);
|
||||
echo_sup_flush(ep->es);
|
||||
}
|
||||
|
||||
struct v5x_user_port *v5x_user_port_find(struct v5x_interface *v5if, uint16_t nr, bool is_isdn)
|
||||
|
|
|
@ -32,7 +32,8 @@
|
|||
#include <osmocom/gsm/lapd_core.h>
|
||||
#include <osmocom/abis/e1_input.h>
|
||||
|
||||
#include "libecho/echo.h"
|
||||
#include "libecho/echo_cancel.h"
|
||||
#include "libecho/echo_suppress.h"
|
||||
#include "libecho/answertone.h"
|
||||
#include "ph_socket.h"
|
||||
|
||||
|
@ -301,10 +302,14 @@ struct v5x_mgmt_proto {
|
|||
#define EC_BUFFER 1024
|
||||
#define EC_TAPS 256
|
||||
|
||||
#define USE_ECHO_CANCELER 1
|
||||
#define USE_ECHO_SUPPRESSOR 2
|
||||
|
||||
struct v5x_echo_proc {
|
||||
struct v5x_user_port *port; /* back pointer to user port */
|
||||
int enabled; /* line echo canceler enabled (configured and not disabled by ANS) */
|
||||
echo_can_state_t *ec; /* echo canceler state */
|
||||
echo_sup_state_t *es; /* echo suppressor state */
|
||||
int16_t tx_buffer[EC_BUFFER]; /* buffer to store TX audio */
|
||||
int tx_buffer_in; /* next pos to write to buffer */
|
||||
int tx_buffer_out; /* next pos to read from buffer */
|
||||
|
@ -331,7 +336,7 @@ struct v5x_user_port {
|
|||
ph_socket_t ph_socket; /* unix socket to connect port to */
|
||||
bool le_unblocked; /* if port is not blocked by LE */
|
||||
bool an_unblocked; /* if port is not blocked by AN */
|
||||
int echo_configured; /* line echo canceler is configured */
|
||||
int use_line_echo; /* line echo canceler/suppressor is configured */
|
||||
struct v5x_echo_proc ep[2]; /* echo canceler process */
|
||||
};
|
||||
|
||||
|
|
|
@ -2265,7 +2265,7 @@ void v5x_le_channel_assign(struct v5x_user_port *v5up, int channel)
|
|||
OSMO_ASSERT(channel >= 1 && channel <= 2);
|
||||
|
||||
/* reset echo canceler state */
|
||||
v5x_echo_reset(&v5up->ep[channel - 1], v5up->echo_configured);
|
||||
v5x_echo_reset(&v5up->ep[channel - 1], v5up->use_line_echo);
|
||||
|
||||
/* the channels are pre-assigned with V5.1, so only activation state is set */
|
||||
if (v5if->dialect == V5X_DIALECT_V51) {
|
||||
|
|
Loading…
Reference in New Issue