osmo-bts-trx: perform error concealment for FR frames
When a bad voice frame is received, it is replaced by a silence frame. This may cause unpleasant audio effects. This change implements a functionality to craft a replacement frame from the last known good frame using ECU implementation from libosmocodec. At the moment, only FR is supported. Depends: libosmocore I06a21f60db01bfe1c2b838f93866fad1d53fdcd1 Change-Id: Iae9e69a9578ae305bca42f834694af96a29084e6
This commit is contained in:
parent
dd4a6518f2
commit
69d0d50677
|
@ -5,6 +5,7 @@
|
|||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <osmocom/codec/ecu.h>
|
||||
#include <osmocom/core/timer.h>
|
||||
#include <osmocom/core/bitvec.h>
|
||||
#include <osmocom/core/statistics.h>
|
||||
|
@ -316,6 +317,11 @@ struct gsm_lchan {
|
|||
} ms_power_ctrl;
|
||||
|
||||
struct msgb *pending_rel_ind_msg;
|
||||
|
||||
/* ECU (Error Concealment Unit) state */
|
||||
union {
|
||||
struct osmo_ecu_fr_state fr;
|
||||
} ecu_state;
|
||||
};
|
||||
|
||||
extern const struct value_string lchan_ciph_state_names[];
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <osmocom/core/msgb.h>
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/codec/codec.h>
|
||||
#include <osmocom/codec/ecu.h>
|
||||
#include <osmocom/core/bits.h>
|
||||
#include <osmocom/gsm/a5.h>
|
||||
#include <osmocom/coding/gsm0503_coding.h>
|
||||
|
@ -964,6 +965,7 @@ int rx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
|||
uint8_t tch_data[128]; /* just to be safe */
|
||||
int rc, amr = 0;
|
||||
int n_errors, n_bits_total;
|
||||
bool bfi_flag = false;
|
||||
struct gsm_lchan *lchan =
|
||||
get_lchan_by_chan_nr(l1t->trx, trx_chan_desc[chan].chan_nr | tn);
|
||||
|
||||
|
@ -1054,11 +1056,13 @@ int rx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
|
|||
if (rc < 0) {
|
||||
LOGL1S(DL1P, LOGL_NOTICE, l1t, tn, chan, fn, "Received bad data (%u/%u)\n",
|
||||
fn % l1ts->mf_period, l1ts->mf_period);
|
||||
bfi_flag = true;
|
||||
goto bfi;
|
||||
}
|
||||
if (rc < 4) {
|
||||
LOGL1S(DL1P, LOGL_NOTICE, l1t, tn, chan, fn, "Received bad data (%u/%u) "
|
||||
"with invalid codec mode %d\n", fn % l1ts->mf_period, l1ts->mf_period, rc);
|
||||
bfi_flag = true;
|
||||
goto bfi;
|
||||
}
|
||||
|
||||
|
@ -1075,8 +1079,14 @@ bfi:
|
|||
case GSM48_CMODE_SPEECH_V1: /* FR */
|
||||
if (lchan->tch.dtx.ul_sid)
|
||||
return 0; /* DTXu: pause in progress */
|
||||
memset(tch_data, 0, GSM_FR_BYTES);
|
||||
tch_data[0] = 0xd0;
|
||||
|
||||
/* Perform error concealment if possible */
|
||||
rc = osmo_ecu_fr_conceal(&lchan->ecu_state.fr, tch_data);
|
||||
if (rc) {
|
||||
memset(tch_data, 0, GSM_FR_BYTES);
|
||||
tch_data[0] = 0xd0;
|
||||
}
|
||||
|
||||
rc = GSM_FR_BYTES;
|
||||
break;
|
||||
case GSM48_CMODE_SPEECH_EFR: /* EFR */
|
||||
|
@ -1104,6 +1114,10 @@ bfi:
|
|||
if (rsl_cmode != RSL_CMOD_SPD_SPEECH)
|
||||
return 0;
|
||||
|
||||
/* Reset ECU with a good frame */
|
||||
if (!bfi_flag && tch_mode == GSM48_CMODE_SPEECH_V1)
|
||||
osmo_ecu_fr_reset(&lchan->ecu_state.fr, tch_data);
|
||||
|
||||
/* TCH or BFI */
|
||||
return _sched_compose_tch_ind(l1t, tn, (fn + GSM_HYPERFRAME - 7) % GSM_HYPERFRAME, chan,
|
||||
tch_data, rc);
|
||||
|
|
Loading…
Reference in New Issue