FreeCalypso > hg > gsm-codec-lib
annotate doc/PCM8-conversions @ 285:cfa3006a66da
gsmfr-decode-r: convert to libgsmfr2
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 14 Apr 2024 06:04:32 +0000 |
parents | e4a4bf11f37c |
children |
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. |