changeset 103:4edffa52802d

TRAU-AMR-8k: implement low speech decoding
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 20 Nov 2025 20:51:40 +0000
parents b59a61446c34
children 9cc76853d291
files trau-decode/amr8-common.c
diffstat 1 files changed, 134 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/trau-decode/amr8-common.c	Thu Nov 20 19:18:26 2025 +0000
+++ b/trau-decode/amr8-common.c	Thu Nov 20 20:51:40 2025 +0000
@@ -34,7 +34,7 @@
 	"Sid_Bad", "Sid_Update", "Onset", "Sid_First"
 };
 
-static const uint8_t params_lsf_475_515[] = {8, 8, 7, 0};
+static const uint8_t params_lsf_475_515[]  = {8, 8, 7, 0};
 static const uint8_t params_lsf_59_67_74[] = {8, 9, 9, 0};
 
 static const uint8_t params_475_sf1[]  = {8, 7, 2, 8, 0};
@@ -179,15 +179,135 @@
 }
 
 static void
+decode_mode_0(c_bits, d_bits)
+	ubit_t *c_bits, *d_bits;
+{
+	ubit_t crc_collect[36];
+	int crc1, crc2, crc3, crc4;
+
+	bcopy(c_bits, crc_collect, 5);
+	bcopy(d_bits + 3, crc_collect + 5, 16);
+	bcopy(d_bits + 20, crc_collect + 21, 2);
+	bcopy(d_bits + 23, crc_collect + 23, 9);
+	bcopy(d_bits + 47, crc_collect + 32, 4);
+	crc1 = osmo_crc8gen_check_bits(&gsm0860_amr_crc3, crc_collect, 36,
+					d_bits + 51);
+	crc2 = osmo_crc8gen_check_bits(&gsm0860_amr_crc3, d_bits + 54, 7,
+					d_bits + 72);
+	bcopy(d_bits + 75, crc_collect, 2);
+	bcopy(d_bits + 92, crc_collect + 2, 4);
+	crc3 = osmo_crc8gen_check_bits(&gsm0860_amr_crc3, crc_collect, 6,
+					d_bits + 96);
+	crc4 = osmo_crc8gen_check_bits(&gsm0860_amr_crc3, d_bits + 99, 2,
+					d_bits + 112);
+	printf("    CRC %s %s %s %s\n",
+		crc1 ? "bad" : "good", crc2 ? "bad" : "good",
+		crc3 ? "bad" : "good", crc4 ? "bad" : "good");
+	if (crc1)
+		saved_mode_valid = 0;
+	print_speech_params(d_bits + 3, params_lsf_475_515);
+	print_speech_params(d_bits + 26, params_475_sf1);
+	print_speech_params(d_bits + 59, params_475_sf24);
+	print_speech_params(d_bits + 75, params_475_sf3);
+	print_speech_params(d_bits + 99, params_475_sf24);
+	check_spare_bits(d_bits, 3, "D1..D3");
+	check_spare_bits(d_bits + 115, 126 - 115, "D116..D126");
+}
+
+static void
+decode_mode_1(c_bits, d_bits)
+	ubit_t *c_bits, *d_bits;
+{
+	ubit_t crc_collect[37];
+	int crc1, crc2, crc3, crc4;
+
+	bcopy(c_bits, crc_collect, 5);
+	bcopy(d_bits + 5, crc_collect + 5, 16);
+	bcopy(d_bits + 23, crc_collect + 21, 11);
+	bcopy(d_bits + 46, crc_collect + 32, 5);
+	crc1 = osmo_crc8gen_check_bits(&gsm0860_amr_crc3, crc_collect, 37,
+					d_bits + 51);
+	bcopy(d_bits + 54, crc_collect, 7);
+	bcopy(d_bits + 73, crc_collect + 7, 5);
+	crc2 = osmo_crc8gen_check_bits(&gsm0860_amr_crc3, crc_collect, 12,
+					d_bits + 78);
+	bcopy(d_bits + 81, crc_collect, 2);
+	bcopy(d_bits + 95, crc_collect + 2, 5);
+	crc3 = osmo_crc8gen_check_bits(&gsm0860_amr_crc3, crc_collect, 7,
+					d_bits + 100);
+	bcopy(d_bits + 103, crc_collect, 2);
+	bcopy(d_bits + 117, crc_collect + 2, 5);
+	crc4 = osmo_crc8gen_check_bits(&gsm0860_amr_crc3, crc_collect, 7,
+					d_bits + 122);
+	printf("    CRC %s %s %s %s\n",
+		crc1 ? "bad" : "good", crc2 ? "bad" : "good",
+		crc3 ? "bad" : "good", crc4 ? "bad" : "good");
+	if (crc1)
+		saved_mode_valid = 0;
+	print_speech_params(d_bits + 5, params_lsf_475_515);
+	print_speech_params(d_bits + 28, params_515_sf1);
+	print_speech_params(d_bits + 59, params_515_sf234);
+	print_speech_params(d_bits + 81, params_515_sf234);
+	print_speech_params(d_bits + 103, params_515_sf234);
+	check_spare_bits(d_bits, 5, "D1..D5");
+	if (!d_bits[125])
+		puts("    Bit D126 is 0 (expected 1)");
+}
+
+static void
+decode_mode_2(c_bits, d_bits)
+	ubit_t *c_bits, *d_bits;
+{
+	ubit_t crc_collect[34];
+	int crc1;
+
+	bcopy(c_bits, crc_collect, 5);
+	bcopy(d_bits, crc_collect + 5, 17);
+	bcopy(d_bits + 26, crc_collect + 22, 8);
+	bcopy(d_bits + 47, crc_collect + 30, 4);
+	crc1 = osmo_crc8gen_check_bits(&gsm0860_amr_crc3, crc_collect, 34,
+					d_bits + 51);
+	printf("    CRC %s\n", crc1 ? "bad" : "good");
+	if (crc1)
+		saved_mode_valid = 0;
+	print_speech_params(d_bits, params_lsf_59_67_74);
+	print_speech_params(d_bits + 26, params_59_sf13);
+	print_speech_params(d_bits + 59, params_59_sf24);
+	print_speech_params(d_bits + 80, params_59_sf13);
+	print_speech_params(d_bits + 105, params_59_sf24);
+}
+
+static void (*per_mode_decode[3])() = {
+	decode_mode_0,
+	decode_mode_1,
+	decode_mode_2
+};
+
+static void
 decode_speech_frame(c_bits, d_bits)
 	ubit_t *c_bits, *d_bits;
 {
 	unsigned c1_3 = bits_to_num(c_bits, 3);
 	unsigned rif = (c1_3 >= 3);
 	unsigned c4_5 = bits_to_num(c_bits + 3, 2);
+	unsigned mode;
 
 	printf("  Speech: RIF=%u, %s\n", rif, fclass_names[c4_5]);
-	/* to be continued */
+	if (rif) {
+		printf("  CMR=%u\n", c1_3 - 3);
+		if (!saved_mode_valid) {
+			puts("  Mode unknown, cannot decode");
+			return;
+		}
+		mode = saved_mode;
+		saved_mode_valid = 0;
+	} else {
+		mode = c1_3;
+		saved_mode = mode;
+		saved_mode_valid = 1;
+	}
+	printf("  Decoding per speech mode %u\n", mode);
+	per_mode_decode[mode](c_bits, d_bits);
 }
 
 static void
@@ -195,16 +315,22 @@
 	ubit_t *c_bits, *d_bits;
 {
 	ubit_t crc_collect[5 + 51];
+	unsigned cmi, cmr;
 	int crc_stat;
 
 	printf("  No_Speech: RIF=%u TA=%u UFE/DFE=%u\n", c_bits[2],
 		bits_to_num(d_bits, 6), d_bits[6]);
+	cmi = bits_to_num(d_bits + 10, 3);
+	cmr = bits_to_num(d_bits + 13, 3);
 	printf("  No_Spch_Class=%u%u%u (%s) CMI=%u CMR=%u\n",
 		d_bits[7], d_bits[8], d_bits[9],
-		nospch_class_names[bits_to_num(d_bits + 7, 3)],
-		bits_to_num(d_bits + 10, 3), bits_to_num(d_bits + 13, 3));
-	saved_mode = bits_to_num(d_bits + 7, 3);
-	saved_mode_valid = 1;
+		nospch_class_names[bits_to_num(d_bits + 7, 3)], cmi, cmr);
+	if (cmi <= 2) {
+		saved_mode = cmi;
+		saved_mode_valid = 1;
+	} else {
+		saved_mode_valid = 0;
+	}
 	bcopy(c_bits, crc_collect, 5);
 	bcopy(d_bits, crc_collect + 5, 51);
 	crc_stat = osmo_crc8gen_check_bits(&gsm0860_amr_crc3, crc_collect,
@@ -261,8 +387,7 @@
 	ubit_t *frame_bits;
 {
 	puts("  TRAU-AMR-8k MR67 format, decoding to be implemented");
-	saved_mode = 3;
-	saved_mode_valid = 1;
+	saved_mode_valid = 0;
 }
 
 static void
@@ -270,8 +395,7 @@
 	ubit_t *frame_bits;
 {
 	puts("  TRAU-AMR-8k MR74 format, decoding to be implemented");
-	saved_mode = 4;
-	saved_mode_valid = 1;
+	saved_mode_valid = 0;
 }
 
 void