shithub: sox

Download patch

ref: 321dbca6e023b24620df303b5e71e05ca0e46684
parent: 70ae0bcb338d941527573539e85ec30dddf9fc18
author: rrt <rrt>
date: Mon Dec 18 17:21:46 EST 2006

Re-add over-zealously excised lookup-table generation code.

--- a/src/g711.c
+++ b/src/g711.c
@@ -2151,6 +2151,216 @@
 
 /* The following code was used to generate the lookup tables */
 #ifdef GENERATE_TABLES
+
+#define	SIGN_BIT	(0x80)		/* Sign bit for a A-law byte. */
+#define	QUANT_MASK	(0xf)		/* Quantization field mask. */
+#define	NSEGS		(8)		/* Number of A-law segments. */
+#define	SEG_SHIFT	(4)		/* Left shift for segment number. */
+#define	SEG_MASK	(0x70)		/* Segment field mask. */
+
+static int16_t seg_aend[8] = {0x1F, 0x3F, 0x7F, 0xFF,
+			      0x1FF, 0x3FF, 0x7FF, 0xFFF};
+static int16_t seg_uend[8] = {0x3F, 0x7F, 0xFF, 0x1FF,
+			      0x3FF, 0x7FF, 0xFFF, 0x1FFF};
+
+static int16_t search(
+	int16_t	val,
+	int16_t *table,
+	int size)
+{
+	int i;
+
+	for (i = 0; i < size; i++) {
+		if (val <= *table++)
+			return (i);
+	}
+	return (size);
+}
+
+/*
+ * linear2alaw() accepts an 13-bit signed integer and encodes it as A-law data
+ * stored in a unsigned char.  This function should only be called with
+ * the data shifted such that it only contains information in the lower
+ * 13-bits.
+ *
+ *		Linear Input Code	Compressed Code
+ *	------------------------	---------------
+ *	0000000wxyza			000wxyz
+ *	0000001wxyza			001wxyz
+ *	000001wxyzab			010wxyz
+ *	00001wxyzabc			011wxyz
+ *	0001wxyzabcd			100wxyz
+ *	001wxyzabcde			101wxyz
+ *	01wxyzabcdef			110wxyz
+ *	1wxyzabcdefg			111wxyz
+ *
+ * For further information see John C. Bellamy's Digital Telephony, 1982,
+ * John Wiley & Sons, pps 98-111 and 472-476.
+ */
+unsigned char st_13linear2alaw(
+	int16_t		pcm_val)	/* 2's complement (13-bit range) */
+{
+	int16_t		mask;
+	short		seg;
+	unsigned char	aval;
+
+	/* Have calling software do it since its already doing a shift
+	 * from 32-bits down to 16-bits.
+	 */
+	/* pcm_val = pcm_val >> 3; */
+
+	if (pcm_val >= 0) {
+		mask = 0xD5;		/* sign (7th) bit = 1 */
+	} else {
+		mask = 0x55;		/* sign bit = 0 */
+		pcm_val = -pcm_val - 1;
+	}
+
+	/* Convert the scaled magnitude to segment number. */
+	seg = search(pcm_val, seg_aend, 8);
+
+	/* Combine the sign, segment, and quantization bits. */
+
+	if (seg >= 8)		/* out of range, return maximum value. */
+		return (unsigned char) (0x7F ^ mask);
+	else {
+		aval = (unsigned char) seg << SEG_SHIFT;
+		if (seg < 2)
+			aval |= (pcm_val >> 1) & QUANT_MASK;
+		else
+			aval |= (pcm_val >> seg) & QUANT_MASK;
+		return (aval ^ mask);
+	}
+}
+
+/*
+ * alaw2linear() - Convert an A-law value to 16-bit signed linear PCM
+ *
+ */
+int16_t st_alaw2linear16(
+	unsigned char	a_val)
+{
+	int16_t t;
+	int16_t seg;
+
+	a_val ^= 0x55;
+
+	t = (a_val & QUANT_MASK) << 4;
+	seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT;
+	switch (seg) {
+	case 0:
+		t += 8;
+		break;
+	case 1:
+		t += 0x108;
+		break;
+	default:
+		t += 0x108;
+		t <<= seg - 1;
+	}
+	return ((a_val & SIGN_BIT) ? t : -t);
+}
+
+#define	BIAS		(0x84)		/* Bias for linear code. */
+#define CLIP            8159
+
+/*
+ * linear2ulaw() accepts a 14-bit signed integer and encodes it as u-law data
+ * stored in a unsigned char.  This function should only be called with
+ * the data shifted such that it only contains information in the lower
+ * 14-bits.
+ *
+ * In order to simplify the encoding process, the original linear magnitude
+ * is biased by adding 33 which shifts the encoding range from (0 - 8158) to
+ * (33 - 8191). The result can be seen in the following encoding table:
+ *
+ *	Biased Linear Input Code	Compressed Code
+ *	------------------------	---------------
+ *	00000001wxyza			000wxyz
+ *	0000001wxyzab			001wxyz
+ *	000001wxyzabc			010wxyz
+ *	00001wxyzabcd			011wxyz
+ *	0001wxyzabcde			100wxyz
+ *	001wxyzabcdef			101wxyz
+ *	01wxyzabcdefg			110wxyz
+ *	1wxyzabcdefgh			111wxyz
+ *
+ * Each biased linear code has a leading 1 which identifies the segment
+ * number. The value of the segment number is equal to 7 minus the number
+ * of leading 0's. The quantization interval is directly available as the
+ * four bits wxyz.  * The trailing bits (a - h) are ignored.
+ *
+ * Ordinarily the complement of the resulting code word is used for
+ * transmission, and so the code word is complemented before it is returned.
+ *
+ * For further information see John C. Bellamy's Digital Telephony, 1982,
+ * John Wiley & Sons, pps 98-111 and 472-476.
+ */
+unsigned char st_14linear2ulaw(
+	int16_t		pcm_val)	/* 2's complement (14-bit range) */
+{
+	int16_t		mask;
+	int16_t		seg;
+	unsigned char	uval;
+
+	/* Have calling software do it since its already doing a shift
+	 * from 32-bits down to 16-bits.
+	 */
+	/* pcm_val = pcm_val >> 2; */
+
+	/* Get the sign and the magnitude of the value. */
+	if (pcm_val < 0) {
+		pcm_val = -pcm_val;
+		mask = 0x7F;
+	} else {
+		mask = 0xFF;
+	}
+        if ( pcm_val > CLIP ) pcm_val = CLIP;		/* clip the magnitude */
+	pcm_val += (BIAS >> 2);
+
+	/* Convert the scaled magnitude to segment number. */
+	seg = search(pcm_val, seg_uend, 8);
+
+	/*
+	 * Combine the sign, segment, quantization bits;
+	 * and complement the code word.
+	 */
+	if (seg >= 8)		/* out of range, return maximum value. */
+		return (unsigned char) (0x7F ^ mask);
+	else {
+		uval = (unsigned char) (seg << 4) | ((pcm_val >> (seg + 1)) & 0xF);
+		return (uval ^ mask);
+	}
+
+}
+
+/*
+ * ulaw2linear() - Convert a u-law value to 16-bit linear PCM
+ *
+ * First, a biased linear code is derived from the code word. An unbiased
+ * output can then be obtained by subtracting 33 from the biased code.
+ *
+ * Note that this function expects to be passed the complement of the
+ * original code word. This is in keeping with ISDN conventions.
+ */
+int16_t st_ulaw2linear16(
+	unsigned char	u_val)
+{
+	int16_t		t;
+
+	/* Complement to obtain normal u-law value. */
+	u_val = ~u_val;
+
+	/*
+	 * Extract and bias the quantization bits. Then
+	 * shift up by the segment number and subtract out the bias.
+	 */
+	t = ((u_val & QUANT_MASK) << 3) + BIAS;
+	t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT;
+
+	return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS));
+}
+
 int main(void)
 {
     int x, y, find2a = 0;