From 1e778230b935453d1183d8a457438221030dd5ee Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Fri, 20 Jan 2012 20:28:55 +0100 Subject: [PATCH] Adding handling of bad GSM audio frames In this case the frame is dropped, but audio of the last frame is repeated with a reduced level. The level is reduced again an again until a new valid frame is received. This way there is no silent gap in the audio stream. --- gsm.cpp | 35 ++++++++++++++++++++++++++++------- gsm.h | 1 + gsm_bs.cpp | 3 ++- gsm_ms.cpp | 3 ++- mncc.h | 1 + 5 files changed, 34 insertions(+), 9 deletions(-) diff --git a/gsm.cpp b/gsm.cpp index 8e5a2d6..9bfa1a5 100644 --- a/gsm.cpp +++ b/gsm.cpp @@ -139,6 +139,7 @@ Pgsm::Pgsm(int type, char *portname, struct port_settings *settings, struct inte p_g_rtp_bridge = 0; if (interface->rtp_bridge) p_g_rtp_bridge = 1; + memset(&p_g_samples, 0, sizeof(p_g_samples)); SCPY(p_g_interface_name, interface->name); p_callerinfo.itype = (interface->extension)?INFO_ITYPE_ISDN_EXTENSION:INFO_ITYPE_ISDN; memset(&p_g_delete, 0, sizeof(p_g_delete)); @@ -193,22 +194,42 @@ Pgsm::~Pgsm() void Pgsm::frame_receive(void *arg) { struct gsm_data_frame *frame = (struct gsm_data_frame *)arg; - signed short samples[160]; unsigned char data[160]; int i; if (!p_g_decoder) return; - if ((frame->data[0]>>4) != 0xd) - PERROR("received GSM frame with wrong magig 0x%x\n", frame->data[0]>>4); + if (frame->msg_type != GSM_TCHF_BAD_FRAME) { + if ((frame->data[0]>>4) != 0xd) + PERROR("received GSM frame with wrong magig 0x%x\n", frame->data[0]>>4); - /* decode */ - gsm_audio_decode(p_g_decoder, frame->data, samples); - for (i = 0; i < 160; i++) { - data[i] = audio_s16_to_law[samples[i] & 0xffff]; + /* decode */ + gsm_audio_decode(p_g_decoder, frame->data, p_g_samples); + for (i = 0; i < 160; i++) { + data[i] = audio_s16_to_law[p_g_samples[i] & 0xffff]; + } + } else if (p_echotest) { + /* beep on bad frame */ + for (i = 0; i < 160; i++) { + if ((i & 3) > 2) + p_g_samples[i] = 15000; + else + p_g_samples[i] = -15000; + data[i] = audio_s16_to_law[p_g_samples[i] & 0xffff]; + } + } else { + /* repeat on bad frame */ + for (i = 0; i < 160; i++) { + p_g_samples[i] = (p_g_samples[i] * 14) >> 4; + data[i] = audio_s16_to_law[p_g_samples[i] & 0xffff]; + } } + /* local echo */ + if (p_echotest) + bridge_rx(data, 160); + /* send to remote*/ bridge_tx(data, 160); } diff --git a/gsm.h b/gsm.h index 724a4c2..0ccac2b 100644 --- a/gsm.h +++ b/gsm.h @@ -35,6 +35,7 @@ class Pgsm : public Port ~Pgsm(); char p_g_interface_name[64]; + signed short p_g_samples[160]; /* last received audi packet */ int p_g_tones; /* set, if tones are to be generated */ int p_g_earlyb; /* set, if patterns are available */ struct lcr_gsm *p_g_lcr_gsm; /* pointer to network/ms instance */ diff --git a/gsm_bs.cpp b/gsm_bs.cpp index 7748f7a..d062e3d 100644 --- a/gsm_bs.cpp +++ b/gsm_bs.cpp @@ -396,7 +396,8 @@ int message_bsc(struct lcr_gsm *lcr_gsm, int msg_type, void *arg) port = port->next; } - if (msg_type == GSM_TCHF_FRAME) { + if (msg_type == GSM_TCHF_FRAME + || msg_type == GSM_TCHF_BAD_FRAME) { if (port) { /* inject DTMF, if enabled */ if (pgsm_bs->p_g_dtmf) { diff --git a/gsm_ms.cpp b/gsm_ms.cpp index cfb1bf6..bb2ad67 100644 --- a/gsm_ms.cpp +++ b/gsm_ms.cpp @@ -345,7 +345,8 @@ int message_ms(struct lcr_gsm *gsm_ms, int msg_type, void *arg) port = port->next; } - if (msg_type == GSM_TCHF_FRAME) { + if (msg_type == GSM_TCHF_FRAME + || msg_type == GSM_TCHF_BAD_FRAME) { if (port) pgsm_ms->frame_receive(arg); return 0; diff --git a/mncc.h b/mncc.h index 04b3241..4028b67 100644 --- a/mncc.h +++ b/mncc.h @@ -58,6 +58,7 @@ #define GSM_TCHF_FRAME 0x0300 #define GSM_TCHF_FRAME_EFR 0x0301 +#define GSM_TCHF_BAD_FRAME 0x03ff #define GSM_MAX_FACILITY 128 #define GSM_MAX_SSVERSION 128 -- 2.13.6