falconia has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-abis/+/39494?usp=email )
Change subject: trau: implement TFO frame decoding functions ......................................................................
trau: implement TFO frame decoding functions
TFO frames of 3GPP TS 28.062 are slightly modified TRAU-UL frames, and thus require slightly modified encoding and decoding functions. Adding TFO frame encoding and decoding functions to libosmotrau will allow TFO applications (sw implementations of a TFO-capable speech transcoder) to reuse those parts of TRAU frame encoding and decoding that are common between regular TRAU frames and TFO.
Change-Id: Ia095598622645068d62301bc4bf7de9f68065e84 --- M include/osmocom/trau/trau_frame.h M src/trau/trau_frame.c 2 files changed, 116 insertions(+), 0 deletions(-)
Approvals: laforge: Looks good to me, but someone else must approve pespin: Looks good to me, approved Jenkins Builder: Verified
diff --git a/include/osmocom/trau/trau_frame.h b/include/osmocom/trau/trau_frame.h index 5f1d708..8bdeb73 100644 --- a/include/osmocom/trau/trau_frame.h +++ b/include/osmocom/trau/trau_frame.h @@ -148,4 +148,11 @@ /*! Determine the time alignment in us requested by CCU in a UL frame */ int osmo_trau_frame_dl_ta_us(const struct osmo_trau_frame *fr);
+/* TFO frames are slightly modified TRAU-UL frames, and thus require slightly + * modified encoding and decoding functions. */ + +int osmo_trau_frame_decode_tfo_16k(struct osmo_trau_frame *fr, const ubit_t *bits); +int osmo_trau_frame_decode_tfo_hr1(struct osmo_trau_frame *fr, const ubit_t *bits); +int osmo_trau_frame_decode_tfo_amr_8k(struct osmo_trau_frame *fr, const ubit_t *bits); + /* }@ */ diff --git a/src/trau/trau_frame.c b/src/trau/trau_frame.c index 21e4f00..df4404d 100644 --- a/src/trau/trau_frame.c +++ b/src/trau/trau_frame.c @@ -1379,6 +1379,49 @@ } }
+/*! Decode/parse a 16k TFO frame from unpacked bits to decoded format. + * \param[out] fr caller-allocated output data structure + * \param[in] bits unpacked bits containing raw TFO frame; must be aligned + * \returns 0 in case of success; negative on error + * + * TFO applications that need to decode TFO frames of TS 28.062 section 5.2.1 + * (FR/EFR) or section 5.2.2.1 (AMR_TFO_16k) should use this function instead + * of regular osmo_trau_frame_decode_16k() in order to get appropriately + * modified handling of C1..C5 frame type bits: + * + * - C5 needs to be ignored because it is EMBED bit in TFO frames; + * - For interoperability with other potential TFO-AMR implementations + * out in the world that aren't GSM AMR-FR, we need to recognize additional + * C1..C4 bit patterns as being AMR equivalents: see Table 5.2.2.1-2 in + * 3GPP TS 28.062. + */ +int osmo_trau_frame_decode_tfo_16k(struct osmo_trau_frame *fr, const ubit_t *bits) +{ + uint8_t cbits4 = get_bits(bits, 17, 4); + /* We don't look at bit C5 because it is EMBED bit in TFO frames */ + + fr->type = OSMO_TRAU_FT_NONE; + fr->dir = OSMO_TRAU_DIR_UL; /* TFO frames are modified TRAU-UL */ + fr->dl_ta_usec = 0; + + switch (cbits4) { + case TRAU_FT_FR_UP >> 1: + fr->type = OSMO_TRAU16_FT_FR; + return decode16_fr(fr, bits, fr->dir); + case TRAU_FT_EFR >> 1: + fr->type = OSMO_TRAU16_FT_EFR; + return decode16_fr(fr, bits, fr->dir); + case TRAU_FT_AMR >> 1: + case 0x4: /* HR_AMR */ + case 0x6: /* UMTS_AMR_2 */ + case 0xB: /* OHR_AMR */ + fr->type = OSMO_TRAU16_FT_AMR; + return decode16_amr(fr, bits, fr->dir); + default: + return -EINVAL; + } +} + #define TRAU8_FT_AMR_NO_SPEECH_CMI 0x10 /* 1, 0, 0, 0, 0 */ #define TRAU8_FT_AMR_NO_SPEECH_CMR 0x14 /* 1, 0, 1, 0, 0 */ #define TRAU8_FT_AMR_475_515_590 0..7 @@ -1521,4 +1564,70 @@ return -EINVAL; }
+/*! Decode/parse an HRv1 TFO frame from unpacked bits to decoded format. + * \param[out] fr caller-allocated output data structure + * \param[in] bits 160 bits containing the lsb extracted from PCM samples; + * must be aligned + * \returns 0 in case of success; negative on error + * + * TFO applications that need to decode TFO frames of TS 28.062 section 5.3.1 + * (GSM_HR codec) should use this function instead of regular + * osmo_trau_frame_decode_8k() in order to get these two behavior + * modifications: + * + * - The sync pattern check needs to be skipped because the sync pattern + * may be partially overwritten by embedded TFO messages; + * - C5 needs to be ignored because it is EMBED bit in TFO frames. + * + * In the case of TFO, unlike regular TRAU-UL frames on Abis/Ater, there is + * no need to distinguish between HRv1 and AMR-8k frames by their respective + * sync patterns: per TS 28.062, these two TFO frame types never occur + * in the same bit position in TFO-superimposed PCM speech octets. + * Because HRv1 is the only TFO frame type that can occur in the configuration + * of TS 28.062 section 5.3 (only the one lsb in each PCM speech octet is + * overwritten), this function skips all attempts at frame type classification: + * the TFO application is responsible for detecting the presence of valid + * TFO frames for the negotiated codec type. + */ +int osmo_trau_frame_decode_tfo_hr1(struct osmo_trau_frame *fr, const ubit_t *bits) +{ + fr->type = OSMO_TRAU8_SPEECH; + fr->dir = OSMO_TRAU_DIR_UL; /* TFO frames are modified TRAU-UL */ + fr->dl_ta_usec = 0; + return decode8_hr(fr, bits, fr->dir); +} + +/*! Decode/parse an AMR_TFO_8+8k frame from unpacked bits to decoded format. + * \param[out] fr caller-allocated output data structure + * \param[in] bits 160 bits containing the second lsb extracted from + * PCM samples; must be aligned + * \returns 0 in case of success; negative on error + * + * This function is provided for TFO applications that need to decode + * TFO frames of TS 28.062 section 5.2.2.2, format named AMR_TFO_8+8k. + * The second lsb extracted from PCM samples is the entity being decoded here. + * Compared to osmo_trau_frame_decode_8k(), the present function requires + * the direction to be TRAU-UL (as always the case in TFO) and accepts + * only AMR-8k frame types. + */ +int osmo_trau_frame_decode_tfo_amr_8k(struct osmo_trau_frame *fr, const ubit_t *bits) +{ + fr->type = OSMO_TRAU_FT_NONE; + fr->dir = OSMO_TRAU_DIR_UL; /* TFO frames are modified TRAU-UL */ + fr->dl_ta_usec = 0; + + if (is_amr_low(bits)) { + fr->type = OSMO_TRAU8_AMR_LOW; + return decode8_amr_low(fr, bits, fr->dir); + } else if (is_amr_67(bits)) { + fr->type = OSMO_TRAU8_AMR_6k7; + return decode8_amr_67(fr, bits, fr->dir); + } else if (is_amr_74(bits)) { + fr->type = OSMO_TRAU8_AMR_7k4; + return decode8_amr_74(fr, bits, fr->dir); + } + + return -EINVAL; +} + /* }@ */