codec: new function osmo_hr_sid_reset()

If a network element that receives call leg A UL and is responsible
for preparing leg B DL receives a GSM-HR SID frame whose SID field
is not all 1s but which is marked as valid SID by out-of-band means
(TRAU-UL frame control bits or the FT field in RFC 5993 ToC octet),
this SID frame should be rejuvenated (SID field reset to all 1s)
prior to retransmission on call leg B DL.  Provide a function
that performs this operation.

Related: OS#6036
Change-Id: Iebc0863ffcc3f8f25aeb54d4b14fac0487bc2bbb
diff --git a/include/osmocom/codec/codec.h b/include/osmocom/codec/codec.h
index 4dbe129..c5981f8 100644
--- a/include/osmocom/codec/codec.h
+++ b/include/osmocom/codec/codec.h
@@ -131,6 +131,7 @@
 bool osmo_efr_sid_preen(uint8_t *rtp_payload);
 
 void osmo_fr_sid_reset(uint8_t *rtp_payload);
+void osmo_hr_sid_reset(uint8_t *rtp_payload);
 void osmo_efr_sid_reset(uint8_t *rtp_payload);
 
 int osmo_amr_rtp_enc(uint8_t *payload, uint8_t cmr, enum osmo_amr_type ft,
diff --git a/src/codec/gsm620.c b/src/codec/gsm620.c
index 4eae514..ef1d3b9 100644
--- a/src/codec/gsm620.c
+++ b/src/codec/gsm620.c
@@ -21,6 +21,7 @@
 
 #include <stdint.h>
 #include <stdbool.h>
+#include <string.h>
 
 #include <osmocom/core/bitvec.h>
 #include <osmocom/core/utils.h>
@@ -285,3 +286,31 @@
 
 	return true;
 }
+
+/*! 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);
+}