aboutsummaryrefslogtreecommitdiffstats
path: root/src/codec/gsm620.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/codec/gsm620.c')
-rw-r--r--src/codec/gsm620.c72
1 files changed, 50 insertions, 22 deletions
diff --git a/src/codec/gsm620.c b/src/codec/gsm620.c
index 282781fd..49ee7243 100644
--- a/src/codec/gsm620.c
+++ b/src/codec/gsm620.c
@@ -17,17 +17,12 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
*/
#include <stdint.h>
#include <stdbool.h>
+#include <string.h>
-#include <osmocom/core/bitvec.h>
-#include <osmocom/core/utils.h>
#include <osmocom/codec/codec.h>
/* GSM HR unvoiced (mode=0) frames - subjective importance bit ordering */
@@ -268,30 +263,63 @@ const uint16_t gsm620_voiced_bitorder[112] = {
81, /* Code 3:7 */
};
-static inline uint16_t mask(const uint8_t msb)
-{
- const uint16_t m = (uint16_t)1 << (msb - 1);
- return (m - 1) ^ m;
-}
-
/*! Check whether RTP frame contains HR SID code word according to
* TS 101 318 ยง5.2.2
* \param[in] rtp_payload Buffer with RTP payload
* \param[in] payload_len Length of payload
* \returns true if code word is found, false otherwise
+ *
+ * Note that this function checks only for a perfect, error-free SID.
+ * Unlike GSM 06.31 for FR or GSM 06.81 for EFR, GSM 06.41 spec for HR
+ * does not prescribe exact bit counting rules, hence detection of
+ * partially corrupted SID frames in downstream network elements
+ * without out-of-band indication is not possible.
*/
bool osmo_hr_check_sid(const uint8_t *rtp_payload, size_t payload_len)
{
- uint8_t i, bits[] = { 1, 2, 8, 9, 5, 4, 9, 5, 4, 9, 5, 4, 9, 5 };
- struct bitvec bv;
- bv.data = (uint8_t *) rtp_payload;
- bv.data_len = payload_len;
- bv.cur_bit = 33;
+ static const uint8_t all_ff_bytes[9] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF};
- /* code word is all 1 at given bits, numbered from 1, MODE is always 3 */
- for (i = 0; i < ARRAY_SIZE(bits); i++)
- if (bitvec_get_uint(&bv, bits[i]) != mask(bits[i]))
- return false;
+ if (payload_len < GSM_HR_BYTES)
+ return false;
- return true;
+ /* A SID frame is identified by a SID codeword consisting of 79 bits
+ * which are all 1, so we basically check if all bits in range
+ * r34..r112 (inclusive) are 1. However, given the position of
+ * these bits in the frame, the most efficient way to perform
+ * this check does not use any bit-level operations. */
+ if ((rtp_payload[4] & 0x7F) != 0x7F)
+ return false;
+ if (memcmp(rtp_payload + 5, all_ff_bytes, 9) == 0)
+ return true;
+ else
+ return false;
+}
+
+/*! Reset the SID field of a potentially corrupted, but still valid GSM-HR
+ * SID frame in TS 101 318 format to its pristine state (full SID codeword).
+ * \param[in] rtp_payload Buffer with RTP payload - must be writable!
+ *
+ * Per GSM 06.22 section 5.3, a freshly minted SID frame consists of 33 bits
+ * of comfort noise parameters and 79 bits of SID codeword (all 1s). Network
+ * elements that receive SID frames from call leg A uplink and need to
+ * retransmit them on leg B downlink should "rejuvenate" received SID frames
+ * prior to retransmission by resetting the SID field to its pristine state
+ * of all 1s; this function does the job.
+ *
+ * Important note: because of HR-specific quirks (lack of exact bit counting
+ * rules in GSM 06.41 spec compared to 06.31 & 06.81, plus the fact that such
+ * bit counting can only be done efficiently in the GSM 05.03 channel decoder
+ * prior to bit reordering based on voiced or unvoiced mode), a generic
+ * (usable from any network element) SID classification function similar to
+ * osmo_{fr,efr}_sid_classify() unfortunately cannot exist for HR. Therefore,
+ * the triggering condition for invoking this SID rejuvenation/reset function
+ * can only be an out-of-band SID indication, as in GSM 08.61 TRAU frames
+ * or RFC 5993 ToC octet.
+ */
+void osmo_hr_sid_reset(uint8_t *rtp_payload)
+{
+ /* set all 79 SID codeword bits to 1 */
+ rtp_payload[4] |= 0x7F;
+ memset(rtp_payload + 5, 0xFF, 9);
}