FreeCalypso > hg > gsm-codec-lib
annotate doc/PCM8-conversions @ 555:62943a1ad64e
doc/FR1-Rx-DTX-detail: grammar fix
| author | Mychaela Falconia <falcon@freecalypso.org> | 
|---|---|
| date | Fri, 11 Oct 2024 00:22:47 +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: 
235diff
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: 
235diff
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: 
235diff
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: 
235diff
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: 
235diff
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: 
235diff
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: 
235diff
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: 
235diff
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: 
235diff
changeset | 112 | 
| 
4c7d0dc1eecb
doc/PCM8-conversions: finish encoding description
 Mychaela Falconia <falcon@freecalypso.org> parents: 
235diff
changeset | 113 Quantization interval Quantized value | 
| 
4c7d0dc1eecb
doc/PCM8-conversions: finish encoding description
 Mychaela Falconia <falcon@freecalypso.org> parents: 
235diff
changeset | 114 (range of magnitudes) (absolute) | 
| 
4c7d0dc1eecb
doc/PCM8-conversions: finish encoding description
 Mychaela Falconia <falcon@freecalypso.org> parents: 
235diff
changeset | 115 --------------------------------------- | 
| 
4c7d0dc1eecb
doc/PCM8-conversions: finish encoding description
 Mychaela Falconia <falcon@freecalypso.org> parents: 
235diff
changeset | 116 0-1 0 | 
| 
4c7d0dc1eecb
doc/PCM8-conversions: finish encoding description
 Mychaela Falconia <falcon@freecalypso.org> parents: 
235diff
changeset | 117 1-3 2 | 
| 
4c7d0dc1eecb
doc/PCM8-conversions: finish encoding description
 Mychaela Falconia <falcon@freecalypso.org> parents: 
235diff
changeset | 118 3-5 4 | 
| 
4c7d0dc1eecb
doc/PCM8-conversions: finish encoding description
 Mychaela Falconia <falcon@freecalypso.org> parents: 
235diff
changeset | 119 ... | 
| 
4c7d0dc1eecb
doc/PCM8-conversions: finish encoding description
 Mychaela Falconia <falcon@freecalypso.org> parents: 
235diff
changeset | 120 29-31 30 | 
| 
4c7d0dc1eecb
doc/PCM8-conversions: finish encoding description
 Mychaela Falconia <falcon@freecalypso.org> parents: 
235diff
changeset | 121 31-35 33 | 
| 
4c7d0dc1eecb
doc/PCM8-conversions: finish encoding description
 Mychaela Falconia <falcon@freecalypso.org> parents: 
235diff
changeset | 122 35-39 37 | 
| 
4c7d0dc1eecb
doc/PCM8-conversions: finish encoding description
 Mychaela Falconia <falcon@freecalypso.org> parents: 
235diff
changeset | 123 ... | 
| 
4c7d0dc1eecb
doc/PCM8-conversions: finish encoding description
 Mychaela Falconia <falcon@freecalypso.org> parents: 
235diff
changeset | 124 91-95 93 | 
| 
4c7d0dc1eecb
doc/PCM8-conversions: finish encoding description
 Mychaela Falconia <falcon@freecalypso.org> parents: 
235diff
changeset | 125 95-103 99 | 
| 
4c7d0dc1eecb
doc/PCM8-conversions: finish encoding description
 Mychaela Falconia <falcon@freecalypso.org> parents: 
235diff
changeset | 126 ... | 
| 
4c7d0dc1eecb
doc/PCM8-conversions: finish encoding description
 Mychaela Falconia <falcon@freecalypso.org> parents: 
235diff
changeset | 127 | 
| 
4c7d0dc1eecb
doc/PCM8-conversions: finish encoding description
 Mychaela Falconia <falcon@freecalypso.org> parents: 
235diff
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: 
235diff
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: 
235diff
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: 
235diff
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: 
235diff
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: 
235diff
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: 
235diff
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: 
235diff
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: 
235diff
changeset | 136 | 
| 
4c7d0dc1eecb
doc/PCM8-conversions: finish encoding description
 Mychaela Falconia <falcon@freecalypso.org> parents: 
235diff
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: 
235diff
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: 
235diff
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: 
235diff
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: 
235diff
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: 
235diff
changeset | 142 | 
| 
4c7d0dc1eecb
doc/PCM8-conversions: finish encoding description
 Mychaela Falconia <falcon@freecalypso.org> parents: 
235diff
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: 
235diff
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: 
235diff
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: 
235diff
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: 
235diff
changeset | 147 is PCMU octet 0x7F.) | 
| 
4c7d0dc1eecb
doc/PCM8-conversions: finish encoding description
 Mychaela Falconia <falcon@freecalypso.org> parents: 
235diff
changeset | 148 | 
| 
4c7d0dc1eecb
doc/PCM8-conversions: finish encoding description
 Mychaela Falconia <falcon@freecalypso.org> parents: 
235diff
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: 
235diff
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: 
235diff
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: 
235diff
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: 
235diff
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: 
235diff
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: 
235diff
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: 
235diff
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: 
235diff
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: 
235diff
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: 
235diff
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: 
235diff
changeset | 160 | 
| 
4c7d0dc1eecb
doc/PCM8-conversions: finish encoding description
 Mychaela Falconia <falcon@freecalypso.org> parents: 
235diff
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: 
235diff
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: 
235diff
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: 
235diff
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: 
235diff
changeset | 165 identical output. | 
| 
4c7d0dc1eecb
doc/PCM8-conversions: finish encoding description
 Mychaela Falconia <falcon@freecalypso.org> parents: 
235diff
changeset | 166 | 
| 
4c7d0dc1eecb
doc/PCM8-conversions: finish encoding description
 Mychaela Falconia <falcon@freecalypso.org> parents: 
235diff
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: 
235diff
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: 
235diff
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: 
236diff
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: 
236diff
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: 
236diff
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: 
236diff
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: 
236diff
changeset | 174 advantage of needing only the upper 13 bits. | 
| 
e4a4bf11f37c
doc/PCM8-conversions: document command line utilities
 Mychaela Falconia <falcon@freecalypso.org> parents: 
236diff
changeset | 175 | 
| 
e4a4bf11f37c
doc/PCM8-conversions: document command line utilities
 Mychaela Falconia <falcon@freecalypso.org> parents: 
236diff
changeset | 176 Command line utilities | 
| 
e4a4bf11f37c
doc/PCM8-conversions: document command line utilities
 Mychaela Falconia <falcon@freecalypso.org> parents: 
236diff
changeset | 177 ====================== | 
| 
e4a4bf11f37c
doc/PCM8-conversions: document command line utilities
 Mychaela Falconia <falcon@freecalypso.org> parents: 
236diff
changeset | 178 | 
| 
e4a4bf11f37c
doc/PCM8-conversions: document command line utilities
 Mychaela Falconia <falcon@freecalypso.org> parents: 
236diff
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: 
236diff
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: 
236diff
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: 
236diff
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: 
236diff
changeset | 183 following utilities are provided: | 
| 
e4a4bf11f37c
doc/PCM8-conversions: document command line utilities
 Mychaela Falconia <falcon@freecalypso.org> parents: 
236diff
changeset | 184 | 
| 
e4a4bf11f37c
doc/PCM8-conversions: document command line utilities
 Mychaela Falconia <falcon@freecalypso.org> parents: 
236diff
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: 
236diff
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: 
236diff
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: 
236diff
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: 
236diff
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: 
236diff
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: 
236diff
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: 
236diff
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: 
236diff
changeset | 193 look-up table method. | 
| 
e4a4bf11f37c
doc/PCM8-conversions: document command line utilities
 Mychaela Falconia <falcon@freecalypso.org> parents: 
236diff
changeset | 194 | 
| 
e4a4bf11f37c
doc/PCM8-conversions: document command line utilities
 Mychaela Falconia <falcon@freecalypso.org> parents: 
236diff
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: 
236diff
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: 
236diff
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: 
236diff
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: 
236diff
changeset | 199 extra command line qualifier. | 
