mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-04-19 17:57:22 +00:00
implemented zap gains, not tested
git-svn-id: http://svn.openzap.org/svn/openzap/branches/sangoma_boost@948 a93c3328-9c30-0410-af19-c9cd2b2d52af
This commit is contained in:
parent
5aa9ff86a8
commit
4a5762ada3
@ -2665,7 +2665,7 @@ void dump_chan_xml(zap_span_t *span, uint32_t chan_id, switch_stream_handle_t *s
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define OZ_SYNTAX "list || dump <span_id> [<chan_id>] || q931_pcap <span_id> on|off [pcapfilename without suffix]"
|
#define OZ_SYNTAX "list || dump <span_id> [<chan_id>] || q931_pcap <span_id> on|off [pcapfilename without suffix] || gains <span> <txgain> <rxgain>"
|
||||||
SWITCH_STANDARD_API(oz_function)
|
SWITCH_STANDARD_API(oz_function)
|
||||||
{
|
{
|
||||||
char *mycmd = NULL, *argv[10] = { 0 };
|
char *mycmd = NULL, *argv[10] = { 0 };
|
||||||
@ -2750,7 +2750,7 @@ SWITCH_STANDARD_API(oz_function)
|
|||||||
for (j = 0 ; j < ZAP_MAX_SPANS_INTERFACE; j++) {
|
for (j = 0 ; j < ZAP_MAX_SPANS_INTERFACE; j++) {
|
||||||
if (SPAN_CONFIG[j].span) {
|
if (SPAN_CONFIG[j].span) {
|
||||||
const char *flags = "none";
|
const char *flags = "none";
|
||||||
zap_channel_sig_status_t chanstatus;
|
zap_signaling_status_t sigstatus;
|
||||||
|
|
||||||
if (SPAN_CONFIG[j].analog_options & ANALOG_OPTION_3WAY) {
|
if (SPAN_CONFIG[j].analog_options & ANALOG_OPTION_3WAY) {
|
||||||
flags = "3way";
|
flags = "3way";
|
||||||
@ -2758,8 +2758,7 @@ SWITCH_STANDARD_API(oz_function)
|
|||||||
flags = "call swap";
|
flags = "call swap";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check signaling status just in the first span channel */
|
if ((ZAP_SUCCESS == zap_span_get_sig_status(SPAN_CONFIG[j].span, &sigstatus))) {
|
||||||
if ((ZAP_SUCCESS == zap_channel_get_sig_status(SPAN_CONFIG[j].span->channels[1], &chanstatus))) {
|
|
||||||
stream->write_function(stream,
|
stream->write_function(stream,
|
||||||
"+OK\n"
|
"+OK\n"
|
||||||
"span: %u (%s)\n"
|
"span: %u (%s)\n"
|
||||||
@ -2775,7 +2774,7 @@ SWITCH_STANDARD_API(oz_function)
|
|||||||
j,
|
j,
|
||||||
SPAN_CONFIG[j].span->name,
|
SPAN_CONFIG[j].span->name,
|
||||||
SPAN_CONFIG[j].type,
|
SPAN_CONFIG[j].type,
|
||||||
zap_sig_status2str(chanstatus),
|
zap_signaling_status2str(sigstatus),
|
||||||
SPAN_CONFIG[j].span->chan_count,
|
SPAN_CONFIG[j].span->chan_count,
|
||||||
SPAN_CONFIG[j].dialplan,
|
SPAN_CONFIG[j].dialplan,
|
||||||
SPAN_CONFIG[j].context,
|
SPAN_CONFIG[j].context,
|
||||||
@ -2883,6 +2882,44 @@ SWITCH_STANDARD_API(oz_function)
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if (!strcasecmp(argv[0], "gains")) {
|
||||||
|
int i = 0;
|
||||||
|
float txgain = 0.0;
|
||||||
|
float rxgain = 0.0;
|
||||||
|
uint32_t chan_id = 0;
|
||||||
|
zap_span_t *span = NULL;
|
||||||
|
if (argc < 4) {
|
||||||
|
stream->write_function(stream, "-ERR Usage: oz gains <txgain> <rxgain> <span_id> [<chan_id>]\n");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
zap_span_find_by_name(argv[3], &span);
|
||||||
|
if (!span) {
|
||||||
|
stream->write_function(stream, "-ERR invalid span\n");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (argc > 4) {
|
||||||
|
chan_id = atoi(argv[4]);
|
||||||
|
if (chan_id > span->chan_count) {
|
||||||
|
stream->write_function(stream, "-ERR invalid chan\n");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i = sscanf(argv[1], "%f", &rxgain);
|
||||||
|
i += sscanf(argv[2], "%f", &txgain);
|
||||||
|
if (i != 2) {
|
||||||
|
stream->write_function(stream, "-ERR invalid gains\n");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (chan_id) {
|
||||||
|
zap_channel_command(span->channels[chan_id], ZAP_COMMAND_SET_RX_GAIN, &rxgain);
|
||||||
|
zap_channel_command(span->channels[chan_id], ZAP_COMMAND_SET_TX_GAIN, &txgain);
|
||||||
|
} else {
|
||||||
|
for (i = 1; i < span->chan_count; i++) {
|
||||||
|
zap_channel_command(span->channels[i], ZAP_COMMAND_SET_RX_GAIN, &rxgain);
|
||||||
|
zap_channel_command(span->channels[i], ZAP_COMMAND_SET_TX_GAIN, &txgain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stream->write_function(stream, "+OK gains set to Rx %f and Tx %f\n", rxgain, txgain);
|
||||||
} else {
|
} else {
|
||||||
char *rply = zap_api_execute(cmd, NULL);
|
char *rply = zap_api_execute(cmd, NULL);
|
||||||
|
|
||||||
|
@ -473,7 +473,8 @@ typedef enum {
|
|||||||
ZAP_TYPE_CHANNEL
|
ZAP_TYPE_CHANNEL
|
||||||
} zap_data_type_t;
|
} zap_data_type_t;
|
||||||
|
|
||||||
|
/* 2^8 table size, one for each byte value */
|
||||||
|
#define ZAP_GAINS_TABLE_SIZE 256
|
||||||
struct zap_channel {
|
struct zap_channel {
|
||||||
zap_data_type_t data_type;
|
zap_data_type_t data_type;
|
||||||
uint32_t span_id;
|
uint32_t span_id;
|
||||||
@ -535,6 +536,10 @@ struct zap_channel {
|
|||||||
zap_hash_t *variable_hash;
|
zap_hash_t *variable_hash;
|
||||||
unsigned char rx_cas_bits;
|
unsigned char rx_cas_bits;
|
||||||
uint32_t pre_buffer_size;
|
uint32_t pre_buffer_size;
|
||||||
|
unsigned char rxgain_table[ZAP_GAINS_TABLE_SIZE];
|
||||||
|
unsigned char txgain_table[ZAP_GAINS_TABLE_SIZE];
|
||||||
|
float rxgain;
|
||||||
|
float txgain;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -73,6 +73,7 @@ struct zap_io_interface;
|
|||||||
|
|
||||||
#define ZAP_COMMAND_OBJ_INT *((int *)obj)
|
#define ZAP_COMMAND_OBJ_INT *((int *)obj)
|
||||||
#define ZAP_COMMAND_OBJ_CHAR_P (char *)obj
|
#define ZAP_COMMAND_OBJ_CHAR_P (char *)obj
|
||||||
|
#define ZAP_COMMAND_OBJ_FLOAT *(float *)obj
|
||||||
#define ZAP_FSK_MOD_FACTOR 0x10000
|
#define ZAP_FSK_MOD_FACTOR 0x10000
|
||||||
#define ZAP_DEFAULT_DTMF_ON 250
|
#define ZAP_DEFAULT_DTMF_ON 250
|
||||||
#define ZAP_DEFAULT_DTMF_OFF 50
|
#define ZAP_DEFAULT_DTMF_OFF 50
|
||||||
@ -403,7 +404,9 @@ typedef enum {
|
|||||||
ZAP_CHANNEL_PROGRESS = (1 << 21),
|
ZAP_CHANNEL_PROGRESS = (1 << 21),
|
||||||
ZAP_CHANNEL_MEDIA = (1 << 22),
|
ZAP_CHANNEL_MEDIA = (1 << 22),
|
||||||
ZAP_CHANNEL_ANSWERED = (1 << 23),
|
ZAP_CHANNEL_ANSWERED = (1 << 23),
|
||||||
ZAP_CHANNEL_MUTE = (1 << 24)
|
ZAP_CHANNEL_MUTE = (1 << 24),
|
||||||
|
ZAP_CHANNEL_USE_RX_GAIN = (1 << 25),
|
||||||
|
ZAP_CHANNEL_USE_TX_GAIN = (1 << 26),
|
||||||
} zap_channel_flag_t;
|
} zap_channel_flag_t;
|
||||||
#if defined(__cplusplus) && defined(WIN32)
|
#if defined(__cplusplus) && defined(WIN32)
|
||||||
// fix C2676
|
// fix C2676
|
||||||
|
@ -33,7 +33,7 @@
|
|||||||
* Contributors:
|
* Contributors:
|
||||||
*
|
*
|
||||||
* Moises Silva <moy@sangoma.com>
|
* Moises Silva <moy@sangoma.com>
|
||||||
* David Yatzin <davidy@sangoma.com>
|
* David Yat Sin <davidy@sangoma.com>
|
||||||
* Nenad Corbic <ncorbic@sangoma.com>
|
* Nenad Corbic <ncorbic@sangoma.com>
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
@ -587,17 +587,65 @@ OZ_DECLARE(zap_status_t) zap_span_load_tones(zap_span_t *span, const char *mapna
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define ZAP_SLINEAR_MAX_VALUE 32767
|
||||||
|
#define ZAP_SLINEAR_MIN_VALUE -32767
|
||||||
|
static void reset_gain_table(unsigned char *gain_table, float new_gain, zap_codec_t codec_gain)
|
||||||
|
{
|
||||||
|
/* sample value */
|
||||||
|
unsigned sv = 0;
|
||||||
|
/* linear gain factor */
|
||||||
|
float lingain = 0;
|
||||||
|
/* linear value for each table sample */
|
||||||
|
float linvalue = 0;
|
||||||
|
/* amplified (or attenuated in case of negative amplification) sample value */
|
||||||
|
int ampvalue = 0;
|
||||||
|
|
||||||
|
/* gain tables are only for alaw and ulaw */
|
||||||
|
if (codec_gain != ZAP_CODEC_ALAW && codec_gain != ZAP_CODEC_ULAW) {
|
||||||
|
zap_log(ZAP_LOG_WARNING, "Not resetting gain table because codec is not ALAW or ULAW but %d\n", codec_gain);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!new_gain) {
|
||||||
|
/* for a 0.0db gain table, each alaw/ulaw sample value is left untouched (0 ==0, 1 == 1, 2 == 2 etc)*/
|
||||||
|
for (sv = 0; sv < ZAP_GAINS_TABLE_SIZE; sv++) {
|
||||||
|
gain_table[sv] = sv;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* use the 20log rule to increase the gain: http://en.wikipedia.org/wiki/Gain, http:/en.wipedia.org/wiki/20_log_rule#Definitions */
|
||||||
|
lingain = pow(10.0, new_gain/ 20.0);
|
||||||
|
for (sv = 0; sv < ZAP_GAINS_TABLE_SIZE; sv++) {
|
||||||
|
/* get the linear value for this alaw/ulaw sample value */
|
||||||
|
linvalue = codec_gain == ZAP_CODEC_ALAW ? alaw_to_linear(sv) : ulaw_to_linear(sv);
|
||||||
|
|
||||||
|
/* multiply the linear value and the previously calculated linear gain */
|
||||||
|
ampvalue = (int)(linvalue * lingain);
|
||||||
|
|
||||||
|
/* chop it if goes beyond the limits */
|
||||||
|
if (ampvalue > ZAP_SLINEAR_MAX_VALUE) {
|
||||||
|
ampvalue = ZAP_SLINEAR_MAX_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ampvalue < ZAP_SLINEAR_MIN_VALUE) {
|
||||||
|
ampvalue = ZAP_SLINEAR_MIN_VALUE;
|
||||||
|
}
|
||||||
|
gain_table[sv] = codec_gain == ZAP_CODEC_ALAW ? linear_to_alaw(ampvalue) : linear_to_ulaw(ampvalue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
OZ_DECLARE(zap_status_t) zap_span_add_channel(zap_span_t *span, zap_socket_t sockfd, zap_chan_type_t type, zap_channel_t **chan)
|
OZ_DECLARE(zap_status_t) zap_span_add_channel(zap_span_t *span, zap_socket_t sockfd, zap_chan_type_t type, zap_channel_t **chan)
|
||||||
{
|
{
|
||||||
|
unsigned i = 0;
|
||||||
if (span->chan_count < ZAP_MAX_CHANNELS_SPAN) {
|
if (span->chan_count < ZAP_MAX_CHANNELS_SPAN) {
|
||||||
zap_channel_t *new_chan = span->channels[++span->chan_count];
|
zap_channel_t *new_chan = span->channels[++span->chan_count];
|
||||||
|
|
||||||
if (!new_chan) {
|
if (!new_chan) {
|
||||||
if (!(new_chan = zap_malloc(sizeof(*new_chan)))) {
|
if (!(new_chan = zap_calloc(1, sizeof(*new_chan)))) {
|
||||||
return ZAP_FAIL;
|
return ZAP_FAIL;
|
||||||
}
|
}
|
||||||
span->channels[span->chan_count] = new_chan;
|
span->channels[span->chan_count] = new_chan;
|
||||||
memset(new_chan, 0, sizeof(*new_chan));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
new_chan->type = type;
|
new_chan->type = type;
|
||||||
@ -626,6 +674,12 @@ OZ_DECLARE(zap_status_t) zap_span_add_channel(zap_span_t *span, zap_socket_t soc
|
|||||||
|
|
||||||
new_chan->dtmf_hangup_buf = zap_calloc (span->dtmf_hangup_len + 1, sizeof (char));
|
new_chan->dtmf_hangup_buf = zap_calloc (span->dtmf_hangup_len + 1, sizeof (char));
|
||||||
|
|
||||||
|
/* set 0.0db gain table */
|
||||||
|
for (i = 0; i < sizeof(new_chan->txgain_table); i++) {
|
||||||
|
new_chan->txgain_table[i] = i;
|
||||||
|
new_chan->rxgain_table[i] = i;
|
||||||
|
}
|
||||||
|
|
||||||
zap_set_flag(new_chan, ZAP_CHANNEL_CONFIGURED | ZAP_CHANNEL_READY);
|
zap_set_flag(new_chan, ZAP_CHANNEL_CONFIGURED | ZAP_CHANNEL_READY);
|
||||||
*chan = new_chan;
|
*chan = new_chan;
|
||||||
return ZAP_SUCCESS;
|
return ZAP_SUCCESS;
|
||||||
@ -1833,6 +1887,40 @@ OZ_DECLARE(zap_status_t) zap_channel_command(zap_channel_t *zchan, zap_command_t
|
|||||||
zap_mutex_unlock(zchan->pre_buffer_mutex);
|
zap_mutex_unlock(zchan->pre_buffer_mutex);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* FIXME: validate user gain values */
|
||||||
|
case ZAP_COMMAND_SET_RX_GAIN:
|
||||||
|
{
|
||||||
|
zchan->rxgain = ZAP_COMMAND_OBJ_FLOAT;
|
||||||
|
reset_gain_table(zchan->rxgain_table, zchan->rxgain, zchan->native_codec);
|
||||||
|
if (zchan->rxgain == 0.0) {
|
||||||
|
zap_clear_flag(zchan, ZAP_CHANNEL_USE_RX_GAIN);
|
||||||
|
} else {
|
||||||
|
zap_set_flag(zchan, ZAP_CHANNEL_USE_RX_GAIN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ZAP_COMMAND_GET_RX_GAIN:
|
||||||
|
{
|
||||||
|
ZAP_COMMAND_OBJ_FLOAT = zchan->rxgain;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ZAP_COMMAND_SET_TX_GAIN:
|
||||||
|
{
|
||||||
|
zchan->txgain = ZAP_COMMAND_OBJ_FLOAT;
|
||||||
|
reset_gain_table(zchan->txgain_table, zchan->txgain, zchan->native_codec);
|
||||||
|
if (zchan->txgain == 0.0) {
|
||||||
|
zap_clear_flag(zchan, ZAP_CHANNEL_USE_TX_GAIN);
|
||||||
|
} else {
|
||||||
|
zap_set_flag(zchan, ZAP_CHANNEL_USE_TX_GAIN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ZAP_COMMAND_GET_TX_GAIN:
|
||||||
|
{
|
||||||
|
ZAP_COMMAND_OBJ_FLOAT = zchan->txgain;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2212,10 +2300,10 @@ OZ_DECLARE(zap_status_t) zap_channel_read(zap_channel_t *zchan, void *data, zap_
|
|||||||
zap_status_t status = ZAP_FAIL;
|
zap_status_t status = ZAP_FAIL;
|
||||||
zio_codec_t codec_func = NULL;
|
zio_codec_t codec_func = NULL;
|
||||||
zap_size_t max = *datalen;
|
zap_size_t max = *datalen;
|
||||||
|
unsigned i = 0;
|
||||||
|
|
||||||
assert(zchan != NULL);
|
assert(zchan != NULL);
|
||||||
assert(zchan->zio != NULL);
|
assert(zchan->zio != NULL);
|
||||||
assert(zchan->zio != NULL);
|
|
||||||
|
|
||||||
if (!zap_test_flag(zchan, ZAP_CHANNEL_OPEN)) {
|
if (!zap_test_flag(zchan, ZAP_CHANNEL_OPEN)) {
|
||||||
snprintf(zchan->last_error, sizeof(zchan->last_error), "channel not open");
|
snprintf(zchan->last_error, sizeof(zchan->last_error), "channel not open");
|
||||||
@ -2237,6 +2325,13 @@ OZ_DECLARE(zap_status_t) zap_channel_read(zap_channel_t *zchan, void *data, zap_
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (status == ZAP_SUCCESS) {
|
if (status == ZAP_SUCCESS) {
|
||||||
|
if (zap_test_flag(zchan, ZAP_CHANNEL_USE_RX_GAIN)
|
||||||
|
&& (zchan->native_codec == ZAP_CODEC_ALAW || zchan->native_codec == ZAP_CODEC_ULAW)) {
|
||||||
|
unsigned char *rdata = data;
|
||||||
|
for (i = 0; i < *datalen; i++) {
|
||||||
|
rdata[i] = zchan->rxgain_table[rdata[i]];
|
||||||
|
}
|
||||||
|
}
|
||||||
handle_dtmf(zchan, *datalen);
|
handle_dtmf(zchan, *datalen);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2435,6 +2530,7 @@ OZ_DECLARE(zap_status_t) zap_channel_write(zap_channel_t *zchan, void *data, zap
|
|||||||
zap_status_t status = ZAP_FAIL;
|
zap_status_t status = ZAP_FAIL;
|
||||||
zio_codec_t codec_func = NULL;
|
zio_codec_t codec_func = NULL;
|
||||||
zap_size_t max = datasize;
|
zap_size_t max = datasize;
|
||||||
|
unsigned int i = 0;
|
||||||
|
|
||||||
assert(zchan != NULL);
|
assert(zchan != NULL);
|
||||||
assert(zchan->zio != NULL);
|
assert(zchan->zio != NULL);
|
||||||
@ -2484,6 +2580,13 @@ OZ_DECLARE(zap_status_t) zap_channel_write(zap_channel_t *zchan, void *data, zap
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (zap_test_flag(zchan, ZAP_CHANNEL_USE_TX_GAIN)
|
||||||
|
&& (zchan->native_codec == ZAP_CODEC_ALAW || zchan->native_codec == ZAP_CODEC_ULAW)) {
|
||||||
|
unsigned char *wdata = data;
|
||||||
|
for (i = 0; i < *datalen; i++) {
|
||||||
|
wdata[i] = zchan->txgain_table[wdata[i]];
|
||||||
|
}
|
||||||
|
}
|
||||||
status = zchan->zio->write(zchan, data, datalen);
|
status = zchan->zio->write(zchan, data, datalen);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user