1 /*-------------- Telecommunications & Signal Processing Lab ---------------
2 McGill University
3
4 Routine:
5 int AFfWrAlaw (AFILE *AFp, const float Dbuff[], int Nval)
6
7 Purpose:
8 Write 8-bit A-law data to an audio file (float input values)
9
10 Description:
11 This routine writes a specified number of 8-bit A-law samples to an audio
12 file. The input to this routine is a buffer of float values.
13
14 Parameters:
15 <- int AFfWrAlaw
16 Number of samples written. If this value is less than Nval, an error
17 has occurred.
18 -> AFILE *AFp
19 Audio file pointer for an audio file opened by AFopnWrite
20 -> const float Dbuff[]
21 Array of floats with the samples to be written
22 -> int Nval
23 Number of samples to be written
24
25 Author / revision:
26 P. Kabal Copyright (C) 2003
27 $Revision: 1.2 $ $Date: 2003/05/09 01:11:34 $
28
29 -------------------------------------------------------------------------*/
30
31 #include <libtsp.h>
32 #include <libtsp/AFdataio.h>
33 #include <libtsp/AFpar.h>
34 #include <libtsp/UTtypes.h>
35
36 #define LW FDL_ALAW8
37 #define MINV(a, b) (((a) < (b)) ? (a) : (b))
38 #define NBBUF 8192
39 #define NLEV 256
40 #define AMAX 32768 /* Xq[NLEV-1] + (Xq[NLEV-1] - Xq[NLEV-2]) */
41
42 #define FWRITE(buf,size,nv,fp) (int) fwrite ((const char *) buf, \
43 (size_t) size, (size_t) nv, fp)
44
45 /* ITU-T Recommendation G.711
46 Conversion to A-law is carried out using a quantization operation. Given
47 an array of (ordered) decision levels, the interval containing the input
48 value is determined. However, there is an ambiguity at the quantizer
49 decision levels themselves. G.711 allows the output value corresponding to
50 the decision levels to go either up or down. The decision levels themselves
51 are symmetric with respect to zero. The ITU-T Software Tool Library (STL)
52 (Recommendation G.191) has a reference implementation for which positive
53 values on the decision levels move upward (away from zero) and negative
54 values on the decision levels also move upward (towards zero).
55
56 The present implementation uses a direct quantization. For the quantization
57 routine SPfQuantL, the intervals are defined as Xq[i-1] <= x < Xq[i], and
58 so input values which lie at the decision level move upward. For integer
59 valued inputs, the results match exactly the results of the STL96 G.711
60 reference routine.
61
62 A-law data is stored in sign-magnitude alternate-bit-complemented format.
63 The sign bit is 1 for positive data. The uncomplemented byte is in
64 sign-segment-mantissa format.
65
66 bin no. signal value bit pattern complement
67 0-15 1, ... , 31 1 000 xxxx 1 101 xyxy
68 16-31 33, ... , 63 1 001 xxxx 1 100 xyxy
69 32-47 66, ... , 126 1 010 xxxx 1 111 xyxy
70 48-63 132, ... , 252 1 011 xxxx 1 110 xyxy
71 64-79 264, ... , 504 1 100 xxxx 1 001 xyxy
72 80-95 528, ... , 1008 1 101 xxxx 1 000 xyxy
73 96-111 1056, ... , 2016 1 110 xxxx 1 011 xyxy
74 112-127 2112, ... , 4032 1 111 xxxx 1 010 xyxy
75
76 AFquant is used to find a quantization region for the input value. The
77 A-law value is determined from this region index by table lookup. The
78 table includes the effect of complementing the bit pattern. The decision
79 levels are scaled by 8, corresponding to quantized values from -32256 to
80 +32256 (for AFp->ScaleF = 1).
81 */
82
83 static const double Xq[NLEV-1] = {
84 -31744, -30720, -29696, -28672, -27648, -26624, -25600,
85 -24576, -23552, -22528, -21504, -20480, -19456, -18432, -17408,
86 -16384, -15872, -15360, -14848, -14336, -13824, -13312, -12800,
87 -12288, -11776, -11264, -10752, -10240, -9728, -9216, -8704,
88 -8192, -7936, -7680, -7424, -7168, -6912, -6656, -6400,
89 -6144, -5888, -5632, -5376, -5120, -4864, -4608, -4352,
90 -4096, -3968, -3840, -3712, -3584, -3456, -3328, -3200,
91 -3072, -2944, -2816, -2688, -2560, -2432, -2304, -2176,
92 -2048, -1984, -1920, -1856, -1792, -1728, -1664, -1600,
93 -1536, -1472, -1408, -1344, -1280, -1216, -1152, -1088,
94 -1024, -992, -960, -928, -896, -864, -832, -800,
95 -768, -736, -704, -672, -640, -608, -576, -544,
96 -512, -496, -480, -464, -448, -432, -416, -400,
97 -384, -368, -352, -336, -320, -304, -288, -272,
98 -256, -240, -224, -208, -192, -176, -160, -144,
99 -128, -112, -96, -80, -64, -48, -32, -16,
100 0,
101 16, 32, 48, 64, 80, 96, 112, 128,
102 144, 160, 176, 192, 208, 224, 240, 256,
103 272, 288, 304, 320, 336, 352, 368, 384,
104 400, 416, 432, 448, 464, 480, 496, 512,
105 544, 576, 608, 640, 672, 704, 736, 768,
106 800, 832, 864, 896, 928, 960, 992, 1024,
107 1088, 1152, 1216, 1280, 1344, 1408, 1472, 1536,
108 1600, 1664, 1728, 1792, 1856, 1920, 1984, 2048,
109 2176, 2304, 2432, 2560, 2688, 2816, 2944, 3072,
110 3200, 3328, 3456, 3584, 3712, 3840, 3968, 4096,
111 4352, 4608, 4864, 5120, 5376, 5632, 5888, 6144,
112 6400, 6656, 6912, 7168, 7424, 7680, 7936, 8192,
113 8704, 9216, 9728, 10240, 10752, 11264, 11776, 12288,
114 12800, 13312, 13824, 14336, 14848, 15360, 15872, 16384,
115 17408, 18432, 19456, 20480, 21504, 22528, 23552, 24576,
116 25600, 26624, 27648, 28672, 29696, 30720, 31744
117 };
118 static const uint1_t Yq[NLEV] = {
119 0x2A, 0x2B, 0x28, 0x29, 0x2E, 0x2F, 0x2C, 0x2D,
120 0x22, 0x23, 0x20, 0x21, 0x26, 0x27, 0x24, 0x25,
121 0x3A, 0x3B, 0x38, 0x39, 0x3E, 0x3F, 0x3C, 0x3D,
122 0x32, 0x33, 0x30, 0x31, 0x36, 0x37, 0x34, 0x35,
123 0x0A, 0x0B, 0x08, 0x09, 0x0E, 0x0F, 0x0C, 0x0D,
124 0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05,
125 0x1A, 0x1B, 0x18, 0x19, 0x1E, 0x1F, 0x1C, 0x1D,
126 0x12, 0x13, 0x10, 0x11, 0x16, 0x17, 0x14, 0x15,
127 0x6A, 0x6B, 0x68, 0x69, 0x6E, 0x6F, 0x6C, 0x6D,
128 0x62, 0x63, 0x60, 0x61, 0x66, 0x67, 0x64, 0x65,
129 0x7A, 0x7B, 0x78, 0x79, 0x7E, 0x7F, 0x7C, 0x7D,
130 0x72, 0x73, 0x70, 0x71, 0x76, 0x77, 0x74, 0x75,
131 0x4A, 0x4B, 0x48, 0x49, 0x4E, 0x4F, 0x4C, 0x4D,
132 0x42, 0x43, 0x40, 0x41, 0x46, 0x47, 0x44, 0x45,
133 0x5A, 0x5B, 0x58, 0x59, 0x5E, 0x5F, 0x5C, 0x5D,
134 0x52, 0x53, 0x50, 0x51, 0x56, 0x57, 0x54, 0x55,
135 0xD5, 0xD4, 0xD7, 0xD6, 0xD1, 0xD0, 0xD3, 0xD2,
136 0xDD, 0xDC, 0xDF, 0xDE, 0xD9, 0xD8, 0xDB, 0xDA,
137 0xC5, 0xC4, 0xC7, 0xC6, 0xC1, 0xC0, 0xC3, 0xC2,
138 0xCD, 0xCC, 0xCF, 0xCE, 0xC9, 0xC8, 0xCB, 0xCA,
139 0xF5, 0xF4, 0xF7, 0xF6, 0xF1, 0xF0, 0xF3, 0xF2,
140 0xFD, 0xFC, 0xFF, 0xFE, 0xF9, 0xF8, 0xFB, 0xFA,
141 0xE5, 0xE4, 0xE7, 0xE6, 0xE1, 0xE0, 0xE3, 0xE2,
142 0xED, 0xEC, 0xEF, 0xEE, 0xE9, 0xE8, 0xEB, 0xEA,
143 0x95, 0x94, 0x97, 0x96, 0x91, 0x90, 0x93, 0x92,
144 0x9D, 0x9C, 0x9F, 0x9E, 0x99, 0x98, 0x9B, 0x9A,
145 0x85, 0x84, 0x87, 0x86, 0x81, 0x80, 0x83, 0x82,
146 0x8D, 0x8C, 0x8F, 0x8E, 0x89, 0x88, 0x8B, 0x8A,
147 0xB5, 0xB4, 0xB7, 0xB6, 0xB1, 0xB0, 0xB3, 0xB2,
148 0xBD, 0xBC, 0xBF, 0xBE, 0xB9, 0xB8, 0xBB, 0xBA,
149 0xA5, 0xA4, 0xA7, 0xA6, 0xA1, 0xA0, 0xA3, 0xA2,
150 0xAD, 0xAC, 0xAF, 0xAE, 0xA9, 0xA8, 0xAB, 0xAA
151 };
152
153
154 int
AFfWrAlaw(AFILE * AFp,const float Dbuff[],int Nval)155 AFfWrAlaw (AFILE *AFp, const float Dbuff[], int Nval)
156
157 {
158 int is, N, Nw, i;
159 uint1_t Buf[NBBUF/LW];
160 double g, Dv;
161
162 /* Write data to the audio file */
163 is = 0;
164 g = AFp->ScaleF;
165 while (is < Nval) {
166 N = MINV (NBBUF / LW, Nval - is);
167 for (i = 0; i < N; ++i) {
168 Dv = g * Dbuff[i+is];
169 if (Dv > AMAX || Dv < -AMAX)
170 ++AFp->Novld;
171 Buf[i] = Yq[SPdQuantL (Dv, Xq, NLEV)];
172 }
173 Nw = FWRITE (Buf, LW, N, AFp->fp);
174 is += Nw;
175 if (Nw < N)
176 break;
177 }
178
179 return is;
180 }
181