From: Andreas Eversberg Date: Tue, 26 Mar 2013 07:57:58 +0000 (+0100) Subject: AMR codec support X-Git-Url: http://git.eversberg.eu/gitweb.cgi?p=lcr.git;a=commitdiff_plain;h=9f48d53fc7d6dff69a2bc688a5b5d9d7be082659;hp=9b2cabced47630e31cfc57c1384af805170b6d2f AMR codec support --- 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] = {