FreeCalypso > hg > gsm-codec-lib
annotate doc/PCM8-conversions @ 242:f081a6850fb5
libgsmfrp: new refined implementation
The previous implementation exhibited the following defects,
which are now fixed:
1) The last received valid SID was cached forever for the purpose of
handling future invalid SIDs - we could have received some valid
SID ages ago, then lots of speech or NO_DATA, and if we then get
an invalid SID, we would resurrect the last valid SID from ancient
history - a bad design. In our new design, we handle invalid SID
based on the current state, much like BFI.
2) GSM 06.11 spec says clearly that after the second lost SID
(received BFI=1 && TAF=1 in CN state) we need to gradually decrease
the output level, rather than jump directly to emitting silence
frames - we previously failed to implement such logic.
3) Per GSM 06.12 section 5.2, Xmaxc should be the same in all 4 subframes
in a SID frame. What should we do if we receive an otherwise valid
SID frame with different Xmaxc? Our previous approach would
replicate this Xmaxc oddity in every subsequent generated CN frame,
which is rather bad. In our new design, the very first CN frame
(which can be seen as a transformation of the SID frame itself)
retains the original 4 distinct Xmaxc, but all subsequent CN frames
are based on the Xmaxc from the last subframe of the most recent SID.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Tue, 09 May 2023 05:16:31 +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. |