annotate doc/PCM8-conversions @ 266:8821ffaa93a5

libgsmfr2: integrate decoder main function from libgsm
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 14 Apr 2024 00:36:16 +0000
parents e4a4bf11f37c
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
235
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
1 What is the authoritatively correct, officially endorsed bidirectional mapping
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
2 between G.711 A-law and mu-law encodings on one side and 16-bit 2's complement
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
3 linear PCM on the other side? Surprisingly, there is no official answer to this
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
4 problem anywhere in the specs! Instead the specs provide the following partial
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
5 answers:
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
6
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
7 * The G.711 spec itself provides one mapping from A-law code octets to linear
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
8 numeric values in range [-4032,4032] and another mapping from mu-law code
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
9 octets to linear numeric values in range [-8031,8031]. The output from each
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
10 of these mapping is given in "pure mathematical" form, without specifying any
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
11 bit-level encoding, and furthermore, mu-law decoder output in its pure
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
12 "conceptual" form has both +0 and -0 values. (The same signed zero problem
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
13 does not occur in A-law because it's a mid-riser code rather than mid-tread,
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
14 and thus has no quantized values equal to 0.)
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
15
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
16 * If one takes the "pure mathematical" output from the spec-prescribed G.711
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
17 decoder and represents it in 2's complement form, squashing +0 and -0 outputs
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
18 from the canonical mu-law decoder into "plain 0" at this step, the result is
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
19 a 13 bits wide 2's complement value for A-law decoding and a 14 bits wide 2's
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
20 complement value for mu-law.
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
21
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
22 * All GSM speech encoders take 13-bit 2's complement linear PCM samples as their
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
23 input. How should this 13-bit GSM codec input be derived from A-law or mu-law
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
24 code octets? GSM specs refer to ITU's G.726 spec for ADPCM - it just so
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
25 happens that inside the ADPCM algorithm of G.726 (a totally unrelated codec of
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
26 no relevance to GSM codec work outside of this reference) there is a pair of
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
27 functions for expanding A-law and mu-law to linear PCM and compressing linear
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
28 PCM back to A-law or mu-law.
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
29
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
30 * Following this obscure G.726 reference, we eventually conclude that in the
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
31 case of A-law, GSM specs call for the obvious treatment: take the "natural"
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
32 output from the canonical A-law decoder, represent it in 2's complement form,
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
33 the result is 13 bits wide, and just feed that 13-bit 2's complement form to
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
34 the input of GSM speech encoders. However, in the case of mu-law the
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
35 "natural" G.711 decoder output is one sign bit plus 13 bits of magnitude,
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
36 requiring 14 bits in 2's complement representation - and none of the specs I
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
37 could find says anything about exactly how this 14-bit input should be reduced
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
38 to 13 bits for feeding to GSM speech encoders. Canonical C implementations
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
39 of all GSM speech encoders take their input in 16-bit words and clear the 3
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
40 least significant bits as their first step; if the 14-bit mu-law decoder
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
41 output is represented in 16-bit words by padding 2 zero bits on the right and
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
42 this output is then fed to GSM speech encoder functions, the end effect is
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
43 that the least-significant bit of the 14-bit decoder output is simply cut off.
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
44 This form of mu-law-to-GSM transcoder implementation is consistent with
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
45 TESTx-U.INP and TESTx-U.COD sequences provided in the GSM 06.54 package for
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
46 EFR.
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
47
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
48 Based on the above considerations, we have our answer for how we should convert
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
49 from G.711 to 16-bit 2's complement linear PCM:
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
50
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
51 * For A-law, we emit the "natural" output in 13-bit 2's complement form and
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
52 append 3 zero bits on the right; this transformation is fully lossless.
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
53
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
54 * For mu-law, we emit the "natural" output in 14-bit 2's complement form and
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
55 append 2 zero bits on the right. This transformation is almost lossless,
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
56 with just one exception: the "pure" decoder's -0 output (resulting from PCMU
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
57 octet 0x7F) is squashed to "plain 0", and will be re-emitted as PCMU octet
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
58 0xFF rather than 0x7F on subsequent re-encoding to G.711 PCMU.
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
59
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
60 For anyone needing a G.711 to 16-bit linear PCM decoder, the present package
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
61 provides ready-made decoding tables (following the above rules) in
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
62 dev/a2s-regen.out and dev/u2s-regen.out, generated by dev/a2s-regen.c and
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
63 dev/u2s-regen.c programs.
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
64
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
65 Now for the opposite problem: what is the most correct way to compress 16-bit
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
66 2's complement linear PCM to A-law or mu-law? In this direction the official
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
67 specs leave even more ambiguity than in the G.711 decoding direction:
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
68
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
69 * The G.711 spec itself says: "The conversion to A-law or mu-law values from
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
70 uniform PCM values corresponding to the decision values, is left to the
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
71 individual equipment specification." The specific implementation used in the
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
72 guts of G.726 ADPCM codec is referred to only as a non-normative example.
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
73
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
74 * GSM specs likewise refer to this G.726 section 4.2.8 (for compression of
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
75 13-bit speech decoder output to G.711) with language that suggests a
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
76 non-normative example.
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
77
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
78 After painstakingly comparing the C implementation of G.726 in the ITU-T G.191
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
79 STL against the language of G.726 spec itself and convincing myself that they
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
80 really do match, and then painstakingly comparing this approach against the one
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
81 implemented in the same G.191 STL for G.711 in alaw_compress() and
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
82 ulaw_compress() and against the table lookup method implemented in libgsm/toast
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
83 (my first reference, before I went down the rabbit hole of tracking down
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
84 official specs), I reached the following conclusions:
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
85
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
86 * For A-law encoding all 3 parties (G.191 STL alaw_compress() function, G.726
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
87 "compress" block and toast_alaw.c) agree on the same mapping. In this
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
88 mapping only the most significant 12 bits of the 2's complement input word
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
89 (equivalent to one sign bit and 11 bits of magnitude) are relevant, leading
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
90 to the following two interesting properties:
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
91
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
92 - the least-significant bit of GSM speech decoder output is always discarded
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
93 when converting to A-law;
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
94
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
95 - conversion can be easily implemented with a 4096-byte look-up table based
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
96 on the upper 12 bits of input, exactly as was done in toast_alaw.c in the
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
97 venerable libgsm source.
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
98
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
99 * Mu-law encoding is the real hair-raiser: if the input to the to-be-implemented
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
100 encoder has 14 or more bits (including the most practical problem of 16-bit
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
101 2's complement input), there are no less than 3 different ways to implement
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
102 this encoder!
0ee1a66c1846 doc/PCM8-conversions: beginning of document
Mychaela Falconia <falcon@freecalypso.org>
parents:
diff changeset
103
236
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
104 Let us now look at the 3 different ways of encoding a 14-bit or 16-bit 2's
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
105 complement linear PCM input to G.711 mu-law. In this analysis we shall use
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
106 14-bit notation, with 2's complement inputs contained in the domain
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
107 [-8192,8191]. The difference between the 3 identified ways of mapping from this
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
108 domain to mu-law have to do with boundaries between quantization intervals.
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
109 Tables 2a and 2b in the G.711 spec list all defined quantization intervals and
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
110 all decision values that mark boundaries between them; here is a digested form
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
111 of the beginning of the canonical quantization table for either side of zero:
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
112
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
113 Quantization interval Quantized value
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
114 (range of magnitudes) (absolute)
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
115 ---------------------------------------
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
116 0-1 0
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
117 1-3 2
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
118 3-5 4
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
119 ...
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
120 29-31 30
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
121 31-35 33
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
122 35-39 37
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
123 ...
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
124 91-95 93
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
125 95-103 99
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
126 ...
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
127
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
128 This canonical quantization table is defined in terms of absolute values, and
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
129 is therefore fully symmetric around zero. A careful look at the above table
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
130 raises a question: which quantization interval (and thus which PCMU octet
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
131 output) should be selected if the input value to the encoder has a magnitude
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
132 exactly equal to one of the threshold points, or decision values as they are
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
133 officially called? In other words, what should the encoder do if the magnitude
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
134 of the 14-bit input value equals 1, 3, 5, ..., 31, 35, 39 etc? The answer to
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
135 this question is where the 3 candidate mappings under our consideration differ:
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
136
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
137 * The "compress" function of G.726 operating in mu-law mode selects the higher
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
138 (in absolute value) quantization interval at every decision value threshold,
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
139 on both sides of zero: see Table 15/G.726. PCMU octet 0x7F (meaning -0) will
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
140 never be emitted by this version, and an input sequence of -3, -2, -1, 0, 1,
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
141 2, 3 will map to quantized values -4, -2, -2, 0, 2, 2, 4.
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
142
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
143 * The ulaw_compress() function in G.191 STL behaves like the G.726 version for
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
144 positive values, but selects the smaller-absolute-value quantization interval
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
145 for negative inputs. Given the same input sequence as above, the output will
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
146 correspond to quantized values -2, -2, -0, 0, 2, 2, 4. (Quantized value -0
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
147 is PCMU octet 0x7F.)
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
148
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
149 * The s2u[] table in toast_ulaw.c in libgsm source is flat-out wrong and should
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
150 not be used or considered further (and because those authors did not include
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
151 the source for whatever program they used to generate their broken s2u[] and
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
152 u2s[] tables, we have no way to really analyze them), but one CAN construct a
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
153 new table for the same function, using the upper 13 bits of 16-bit 2's
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
154 complement input to generate PCMU output - see our dev/s2u-regen.c program
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
155 and its output table in dev/s2u-regen.out. The resulting mapping is
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
156 "mirrored" around zero compared to G.191 STL ulaw_compress(): for the same
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
157 input sequence as in the previous two examples, the output will correspond to
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
158 quantized values -4, -2, -2, 0, 0, 2, 2. Just like the G.726 version, this
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
159 look-up table version will never emit PCMU octet 0x7F for -0.
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
160
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
161 It is important to note that all GSM speech decoders produce 2's complement
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
162 outputs that are only 13 bits wide, not 14 - therefore, when the input to the
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
163 G.711 encoder comes from the output of a GSM speech decoder, the difference
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
164 between all 3 alternatives listed above is masked, with all 3 producing
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
165 identical output.
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
166
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
167 For production software, our (Themyscira) recommendation is to use look-up
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
168 tables (dev/s2a-regen.out and dev/s2u-regen.out) for both A-law and mu-law
4c7d0dc1eecb doc/PCM8-conversions: finish encoding description
Mychaela Falconia <falcon@freecalypso.org>
parents: 235
diff changeset
169 encoding, using the upper 12 bits from 16-bit 2's complement input for A-law
237
e4a4bf11f37c doc/PCM8-conversions: document command line utilities
Mychaela Falconia <falcon@freecalypso.org>
parents: 236
diff changeset
170 encoding and the upper 13 bits for mu-law encoding. For mu-law encoding the
e4a4bf11f37c doc/PCM8-conversions: document command line utilities
Mychaela Falconia <falcon@freecalypso.org>
parents: 236
diff changeset
171 resulting mapping is different from what G.191 STL ulaw_compress() function
e4a4bf11f37c doc/PCM8-conversions: document command line utilities
Mychaela Falconia <falcon@freecalypso.org>
parents: 236
diff changeset
172 produces, and many will consider that function to be canon - but our approach
e4a4bf11f37c doc/PCM8-conversions: document command line utilities
Mychaela Falconia <falcon@freecalypso.org>
parents: 236
diff changeset
173 exhibits the same key properties, just mirrored around zero, and has the
e4a4bf11f37c doc/PCM8-conversions: document command line utilities
Mychaela Falconia <falcon@freecalypso.org>
parents: 236
diff changeset
174 advantage of needing only the upper 13 bits.
e4a4bf11f37c doc/PCM8-conversions: document command line utilities
Mychaela Falconia <falcon@freecalypso.org>
parents: 236
diff changeset
175
e4a4bf11f37c doc/PCM8-conversions: document command line utilities
Mychaela Falconia <falcon@freecalypso.org>
parents: 236
diff changeset
176 Command line utilities
e4a4bf11f37c doc/PCM8-conversions: document command line utilities
Mychaela Falconia <falcon@freecalypso.org>
parents: 236
diff changeset
177 ======================
e4a4bf11f37c doc/PCM8-conversions: document command line utilities
Mychaela Falconia <falcon@freecalypso.org>
parents: 236
diff changeset
178
e4a4bf11f37c doc/PCM8-conversions: document command line utilities
Mychaela Falconia <falcon@freecalypso.org>
parents: 236
diff changeset
179 As usual, the present Themyscira GSM codec libraries & utilities package
e4a4bf11f37c doc/PCM8-conversions: document command line utilities
Mychaela Falconia <falcon@freecalypso.org>
parents: 236
diff changeset
180 provides command line utilities for working with the subject of this article:
e4a4bf11f37c doc/PCM8-conversions: document command line utilities
Mychaela Falconia <falcon@freecalypso.org>
parents: 236
diff changeset
181 conversions between 16-bit linear PCM (the format read and written by other
e4a4bf11f37c doc/PCM8-conversions: document command line utilities
Mychaela Falconia <falcon@freecalypso.org>
parents: 236
diff changeset
182 tools in the present suite) and 8-bit PCM in G.711 A-law or mu-law. The
e4a4bf11f37c doc/PCM8-conversions: document command line utilities
Mychaela Falconia <falcon@freecalypso.org>
parents: 236
diff changeset
183 following utilities are provided:
e4a4bf11f37c doc/PCM8-conversions: document command line utilities
Mychaela Falconia <falcon@freecalypso.org>
parents: 236
diff changeset
184
e4a4bf11f37c doc/PCM8-conversions: document command line utilities
Mychaela Falconia <falcon@freecalypso.org>
parents: 236
diff changeset
185 pcm16-to-alaw These two utilities read 16-bit linear PCM in raw format (BE
e4a4bf11f37c doc/PCM8-conversions: document command line utilities
Mychaela Falconia <falcon@freecalypso.org>
parents: 236
diff changeset
186 pcm16-to-ulaw byte order by default, or LE with -l option) and convert the
e4a4bf11f37c doc/PCM8-conversions: document command line utilities
Mychaela Falconia <falcon@freecalypso.org>
parents: 236
diff changeset
187 recording into one byte per sample G.711 format, with each
e4a4bf11f37c doc/PCM8-conversions: document command line utilities
Mychaela Falconia <falcon@freecalypso.org>
parents: 236
diff changeset
188 program emitting its respective encoding law. pcm16-to-alaw
e4a4bf11f37c doc/PCM8-conversions: document command line utilities
Mychaela Falconia <falcon@freecalypso.org>
parents: 236
diff changeset
189 has only one mapping, but pcm16-to-ulaw supports two possible
e4a4bf11f37c doc/PCM8-conversions: document command line utilities
Mychaela Falconia <falcon@freecalypso.org>
parents: 236
diff changeset
190 mappings: by default it applies the mapping of G.191 STL
e4a4bf11f37c doc/PCM8-conversions: document command line utilities
Mychaela Falconia <falcon@freecalypso.org>
parents: 236
diff changeset
191 ulaw_compress(), or if use specify -t option it applies the
e4a4bf11f37c doc/PCM8-conversions: document command line utilities
Mychaela Falconia <falcon@freecalypso.org>
parents: 236
diff changeset
192 same mapping that would be produced by our recommended 13-bit
e4a4bf11f37c doc/PCM8-conversions: document command line utilities
Mychaela Falconia <falcon@freecalypso.org>
parents: 236
diff changeset
193 look-up table method.
e4a4bf11f37c doc/PCM8-conversions: document command line utilities
Mychaela Falconia <falcon@freecalypso.org>
parents: 236
diff changeset
194
e4a4bf11f37c doc/PCM8-conversions: document command line utilities
Mychaela Falconia <falcon@freecalypso.org>
parents: 236
diff changeset
195 pcm8-to-pcm16 This utility reads a G.711 8-bit PCM recording (alaw or ulaw
e4a4bf11f37c doc/PCM8-conversions: document command line utilities
Mychaela Falconia <falcon@freecalypso.org>
parents: 236
diff changeset
196 selected with a mandatory command line argument) from a "raw"
e4a4bf11f37c doc/PCM8-conversions: document command line utilities
Mychaela Falconia <falcon@freecalypso.org>
parents: 236
diff changeset
197 G.711 file and converts it to 16-bit linear PCM. The output
e4a4bf11f37c doc/PCM8-conversions: document command line utilities
Mychaela Falconia <falcon@freecalypso.org>
parents: 236
diff changeset
198 byte order is BE by default, or can be changed to LE with an
e4a4bf11f37c doc/PCM8-conversions: document command line utilities
Mychaela Falconia <falcon@freecalypso.org>
parents: 236
diff changeset
199 extra command line qualifier.