);
}
-#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)
{
char *mycmd = NULL, *argv[10] = { 0 };
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 {
char *rply = zap_api_execute(cmd, NULL);
#ifndef WIN32
#endif
#include "openzap.h"
-//#include "zap_isdn.h"
-//#include "zap_ss7_boost.h"
#include <stdarg.h>
#ifdef WIN32
#include <io.h>
}
+#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)*/
+ sv = 0;
+ while (1) {
+ gain_table[sv] = sv;
+ if (sv == (ZAP_GAINS_TABLE_SIZE - 1)) {
+ break;
+ }
+ sv++;
+ }
+ return;
+ }
+
+ /* use the 20log rule to increase the gain: http://en.wikipedia.org/wiki/Gain, http:/en.wikipedia.org/wiki/20_log_rule#Definitions */
+ lingain = pow(10.0, new_gain/ 20.0);
+ sv = 0;
+ while (1) {
+ /* 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);
+ if (sv == (ZAP_GAINS_TABLE_SIZE-1)) {
+ break;
+ }
+ sv++;
+ }
+}
+
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) {
zap_channel_t *new_chan = span->channels[++span->chan_count];
new_chan->dtmf_hangup_buf = calloc (span->dtmf_hangup_len + 1, sizeof (char));
+ /* set 0.0db gain table */
+ i = 0;
+ while (1) {
+ new_chan->txgain_table[i] = i;
+ new_chan->rxgain_table[i] = i;
+ if (i == (sizeof(new_chan->txgain_table)-1)) {
+ break;
+ }
+ i++;
+ }
+
zap_set_flag(new_chan, ZAP_CHANNEL_CONFIGURED | ZAP_CHANNEL_READY);
*chan = new_chan;
return ZAP_SUCCESS;
zap_mutex_unlock(zchan->pre_buffer_mutex);
}
break;
+
+ 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:
break;
}
zap_status_t status = ZAP_FAIL;
zio_codec_t codec_func = NULL;
zap_size_t max = *datalen;
+ unsigned i = 0;
assert(zchan != NULL);
assert(zchan->zio != NULL);
- assert(zchan->zio != NULL);
if (!zap_test_flag(zchan, ZAP_CHANNEL_OPEN)) {
snprintf(zchan->last_error, sizeof(zchan->last_error), "channel not open");
}
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);
}
zap_status_t status = ZAP_FAIL;
zio_codec_t codec_func = NULL;
zap_size_t max = datasize;
+ unsigned i = 0;
assert(zchan != NULL);
assert(zchan->zio != NULL);
}
}
+ 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);
return status;