From 9f48d53fc7d6dff69a2bc688a5b5d9d7be082659 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Tue, 26 Mar 2013 08:57:58 +0100 Subject: [PATCH] AMR codec support --- gsm.cpp | 45 ++++++++++++++++++++++++++++++++++++++++++++- gsm.h | 1 + gsm_audio.c | 2 +- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/gsm.cpp b/gsm.cpp index 7502eed..6a7445d 100644 --- a/gsm.cpp +++ b/gsm.cpp @@ -186,6 +186,8 @@ Pgsm::Pgsm(int type, char *portname, struct port_settings *settings, struct inte p_g_hr_encoder = NULL; p_g_amr_decoder = NULL; p_g_amr_encoder = NULL; + p_g_amr_cmr = 0; + p_g_amr_cmr_valid = 0; #ifdef WITH_GSMFR p_g_fr_decoder = gsm_fr_create(); p_g_fr_encoder = gsm_fr_create(); @@ -248,7 +250,7 @@ void Pgsm::frame_receive(void *arg) { struct gsm_data_frame *frame = (struct gsm_data_frame *)arg; unsigned char data[160]; - int i; + int i, cmr; if (!p_g_fr_decoder) return; @@ -294,6 +296,30 @@ void Pgsm::frame_receive(void *arg) } #endif break; + case GSM_TCH_FRAME_AMR: + if (p_g_media_type != MEDIA_TYPE_AMR) { + PERROR("AMR frame, but current media type mismatches.\n"); + return; + } + if (!p_g_amr_decoder) { + PERROR("AMR frame, but decoder not created.\n"); + return; + } + cmr = (frame->data[1] >> 4); + if (cmr <= 7) { + p_g_amr_cmr = cmr; + p_g_amr_cmr_valid = 1; + } + if (!(frame->data[2] & 0x04)) + goto bfi; +#ifdef WITH_GSMAMR + /* decode (skip length byte in front) */ + gsm_amr_decode(p_g_amr_decoder, frame->data + 1, p_g_samples); + for (i = 0; i < 160; i++) { + data[i] = audio_s16_to_law[p_g_samples[i] & 0xffff]; + } +#endif + break; case GSM_BAD_FRAME: default: bfi: @@ -341,6 +367,7 @@ int Pgsm::bridge_rx(unsigned char *data, int len) int Pgsm::audio_send(unsigned char *data, int len) { unsigned char frame[33]; + int ret; /* record data */ if (p_record) @@ -386,6 +413,22 @@ int Pgsm::audio_send(unsigned char *data, int len) frame_send(frame, 31, GSM_TCHF_FRAME_EFR); #endif break; + case MEDIA_TYPE_AMR: + if (!p_g_amr_encoder) { + PERROR("AMR frame, but encoder not created.\n"); + break; + } + if (!p_g_amr_cmr_valid) { + PDEBUG(DEBUG_GSM, "no valid CMR yet.\n"); + break; + } +#ifdef WITH_GSMAMR + /* encode data (prefix a length byte) */ + ret = gsm_amr_encode(p_g_amr_encoder, p_g_rxdata, frame + 1, p_g_amr_cmr); + frame[0] = ret; + frame_send(frame, ret + 1, GSM_TCH_FRAME_AMR); +#endif + break; } } diff --git a/gsm.h b/gsm.h index b39b005..b0b9b89 100644 --- a/gsm.h +++ b/gsm.h @@ -51,6 +51,7 @@ class Pgsm : public Port void *p_g_fr_encoder, *p_g_fr_decoder; /* gsm handle */ void *p_g_hr_encoder, *p_g_hr_decoder; /* gsm handle */ void *p_g_amr_encoder, *p_g_amr_decoder;/* gsm handle */ + int p_g_amr_cmr, p_g_amr_cmr_valid; signed short p_g_rxdata[160]; /* receive audio buffer */ int p_g_rxpos; /* position in audio buffer 0..159 */ int p_g_tch_connected; /* indicates if audio is connected */ diff --git a/gsm_audio.c b/gsm_audio.c index eabf2f5..64756c7 100644 --- a/gsm_audio.c +++ b/gsm_audio.c @@ -132,7 +132,7 @@ int gsm_amr_encode(void *arg, signed short *samples, unsigned char *frame, int m frame[0] = 0xf0; /* no request */ - return rv; + return rv + 1; } const unsigned short gsm690_12_2_bitorder[244] = { -- 2.13.6