xref: /openbmc/linux/drivers/isdn/mISDN/l1oip_codec.c (revision de6cc651)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 
4  * l1oip_codec.c  generic codec using lookup table
5  *  -> conversion from a-Law to u-Law
6  *  -> conversion from u-Law to a-Law
7  *  -> compression by reducing the number of sample resolution to 4
8  *
9  * NOTE: It is not compatible with any standard codec like ADPCM.
10  *
11  * Author	Andreas Eversberg (jolly@eversberg.eu)
12  *
13 
14  */
15 
16 /*
17 
18   How the codec works:
19   --------------------
20 
21   The volume is increased to increase the dynamic range of the audio signal.
22   Each sample is converted to a-LAW with only 16 steps of level resolution.
23   A pair of two samples are stored in one byte.
24 
25   The first byte is stored in the upper bits, the second byte is stored in the
26   lower bits.
27 
28   To speed up compression and decompression, two lookup tables are formed:
29 
30   - 16 bits index for two samples (law encoded) with 8 bit compressed result.
31   - 8 bits index for one compressed data with 16 bits decompressed result.
32 
33   NOTE: The bytes are handled as they are law-encoded.
34 
35 */
36 
37 #include <linux/vmalloc.h>
38 #include <linux/mISDNif.h>
39 #include <linux/in.h>
40 #include "core.h"
41 #include "l1oip.h"
42 
43 /* definitions of codec. don't use calculations, code may run slower. */
44 
45 static u8 *table_com;
46 static u16 *table_dec;
47 
48 
49 /* alaw -> ulaw */
50 static u8 alaw_to_ulaw[256] =
51 {
52 	0xab, 0x2b, 0xe3, 0x63, 0x8b, 0x0b, 0xc9, 0x49,
53 	0xba, 0x3a, 0xf6, 0x76, 0x9b, 0x1b, 0xd7, 0x57,
54 	0xa3, 0x23, 0xdd, 0x5d, 0x83, 0x03, 0xc1, 0x41,
55 	0xb2, 0x32, 0xeb, 0x6b, 0x93, 0x13, 0xcf, 0x4f,
56 	0xaf, 0x2f, 0xe7, 0x67, 0x8f, 0x0f, 0xcd, 0x4d,
57 	0xbe, 0x3e, 0xfe, 0x7e, 0x9f, 0x1f, 0xdb, 0x5b,
58 	0xa7, 0x27, 0xdf, 0x5f, 0x87, 0x07, 0xc5, 0x45,
59 	0xb6, 0x36, 0xef, 0x6f, 0x97, 0x17, 0xd3, 0x53,
60 	0xa9, 0x29, 0xe1, 0x61, 0x89, 0x09, 0xc7, 0x47,
61 	0xb8, 0x38, 0xf2, 0x72, 0x99, 0x19, 0xd5, 0x55,
62 	0xa1, 0x21, 0xdc, 0x5c, 0x81, 0x01, 0xbf, 0x3f,
63 	0xb0, 0x30, 0xe9, 0x69, 0x91, 0x11, 0xce, 0x4e,
64 	0xad, 0x2d, 0xe5, 0x65, 0x8d, 0x0d, 0xcb, 0x4b,
65 	0xbc, 0x3c, 0xfa, 0x7a, 0x9d, 0x1d, 0xd9, 0x59,
66 	0xa5, 0x25, 0xde, 0x5e, 0x85, 0x05, 0xc3, 0x43,
67 	0xb4, 0x34, 0xed, 0x6d, 0x95, 0x15, 0xd1, 0x51,
68 	0xac, 0x2c, 0xe4, 0x64, 0x8c, 0x0c, 0xca, 0x4a,
69 	0xbb, 0x3b, 0xf8, 0x78, 0x9c, 0x1c, 0xd8, 0x58,
70 	0xa4, 0x24, 0xde, 0x5e, 0x84, 0x04, 0xc2, 0x42,
71 	0xb3, 0x33, 0xec, 0x6c, 0x94, 0x14, 0xd0, 0x50,
72 	0xb0, 0x30, 0xe8, 0x68, 0x90, 0x10, 0xce, 0x4e,
73 	0xbf, 0x3f, 0xfe, 0x7e, 0xa0, 0x20, 0xdc, 0x5c,
74 	0xa8, 0x28, 0xe0, 0x60, 0x88, 0x08, 0xc6, 0x46,
75 	0xb7, 0x37, 0xf0, 0x70, 0x98, 0x18, 0xd4, 0x54,
76 	0xaa, 0x2a, 0xe2, 0x62, 0x8a, 0x0a, 0xc8, 0x48,
77 	0xb9, 0x39, 0xf4, 0x74, 0x9a, 0x1a, 0xd6, 0x56,
78 	0xa2, 0x22, 0xdd, 0x5d, 0x82, 0x02, 0xc0, 0x40,
79 	0xb1, 0x31, 0xea, 0x6a, 0x92, 0x12, 0xcf, 0x4f,
80 	0xae, 0x2e, 0xe6, 0x66, 0x8e, 0x0e, 0xcc, 0x4c,
81 	0xbd, 0x3d, 0xfc, 0x7c, 0x9e, 0x1e, 0xda, 0x5a,
82 	0xa6, 0x26, 0xdf, 0x5f, 0x86, 0x06, 0xc4, 0x44,
83 	0xb5, 0x35, 0xee, 0x6e, 0x96, 0x16, 0xd2, 0x52
84 };
85 
86 /* ulaw -> alaw */
87 static u8 ulaw_to_alaw[256] =
88 {
89 	0xab, 0x55, 0xd5, 0x15, 0x95, 0x75, 0xf5, 0x35,
90 	0xb5, 0x45, 0xc5, 0x05, 0x85, 0x65, 0xe5, 0x25,
91 	0xa5, 0x5d, 0xdd, 0x1d, 0x9d, 0x7d, 0xfd, 0x3d,
92 	0xbd, 0x4d, 0xcd, 0x0d, 0x8d, 0x6d, 0xed, 0x2d,
93 	0xad, 0x51, 0xd1, 0x11, 0x91, 0x71, 0xf1, 0x31,
94 	0xb1, 0x41, 0xc1, 0x01, 0x81, 0x61, 0xe1, 0x21,
95 	0x59, 0xd9, 0x19, 0x99, 0x79, 0xf9, 0x39, 0xb9,
96 	0x49, 0xc9, 0x09, 0x89, 0x69, 0xe9, 0x29, 0xa9,
97 	0xd7, 0x17, 0x97, 0x77, 0xf7, 0x37, 0xb7, 0x47,
98 	0xc7, 0x07, 0x87, 0x67, 0xe7, 0x27, 0xa7, 0xdf,
99 	0x9f, 0x7f, 0xff, 0x3f, 0xbf, 0x4f, 0xcf, 0x0f,
100 	0x8f, 0x6f, 0xef, 0x2f, 0x53, 0x13, 0x73, 0x33,
101 	0xb3, 0x43, 0xc3, 0x03, 0x83, 0x63, 0xe3, 0x23,
102 	0xa3, 0x5b, 0xdb, 0x1b, 0x9b, 0x7b, 0xfb, 0x3b,
103 	0xbb, 0xbb, 0x4b, 0x4b, 0xcb, 0xcb, 0x0b, 0x0b,
104 	0x8b, 0x8b, 0x6b, 0x6b, 0xeb, 0xeb, 0x2b, 0x2b,
105 	0xab, 0x54, 0xd4, 0x14, 0x94, 0x74, 0xf4, 0x34,
106 	0xb4, 0x44, 0xc4, 0x04, 0x84, 0x64, 0xe4, 0x24,
107 	0xa4, 0x5c, 0xdc, 0x1c, 0x9c, 0x7c, 0xfc, 0x3c,
108 	0xbc, 0x4c, 0xcc, 0x0c, 0x8c, 0x6c, 0xec, 0x2c,
109 	0xac, 0x50, 0xd0, 0x10, 0x90, 0x70, 0xf0, 0x30,
110 	0xb0, 0x40, 0xc0, 0x00, 0x80, 0x60, 0xe0, 0x20,
111 	0x58, 0xd8, 0x18, 0x98, 0x78, 0xf8, 0x38, 0xb8,
112 	0x48, 0xc8, 0x08, 0x88, 0x68, 0xe8, 0x28, 0xa8,
113 	0xd6, 0x16, 0x96, 0x76, 0xf6, 0x36, 0xb6, 0x46,
114 	0xc6, 0x06, 0x86, 0x66, 0xe6, 0x26, 0xa6, 0xde,
115 	0x9e, 0x7e, 0xfe, 0x3e, 0xbe, 0x4e, 0xce, 0x0e,
116 	0x8e, 0x6e, 0xee, 0x2e, 0x52, 0x12, 0x72, 0x32,
117 	0xb2, 0x42, 0xc2, 0x02, 0x82, 0x62, 0xe2, 0x22,
118 	0xa2, 0x5a, 0xda, 0x1a, 0x9a, 0x7a, 0xfa, 0x3a,
119 	0xba, 0xba, 0x4a, 0x4a, 0xca, 0xca, 0x0a, 0x0a,
120 	0x8a, 0x8a, 0x6a, 0x6a, 0xea, 0xea, 0x2a, 0x2a
121 };
122 
123 /* alaw -> 4bit compression */
124 static u8 alaw_to_4bit[256] = {
125 	0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
126 	0x0d, 0x02, 0x08, 0x07, 0x0f, 0x00, 0x0b, 0x04,
127 	0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
128 	0x0d, 0x02, 0x09, 0x06, 0x0f, 0x00, 0x0b, 0x04,
129 	0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
130 	0x0d, 0x02, 0x08, 0x07, 0x0f, 0x00, 0x0b, 0x04,
131 	0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
132 	0x0d, 0x02, 0x09, 0x06, 0x0f, 0x00, 0x0b, 0x04,
133 	0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
134 	0x0d, 0x02, 0x08, 0x07, 0x0f, 0x00, 0x0b, 0x04,
135 	0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0d, 0x02,
136 	0x0e, 0x02, 0x09, 0x06, 0x0f, 0x00, 0x0b, 0x04,
137 	0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
138 	0x0d, 0x02, 0x08, 0x07, 0x0f, 0x00, 0x0b, 0x04,
139 	0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
140 	0x0d, 0x02, 0x09, 0x06, 0x0f, 0x00, 0x0b, 0x04,
141 	0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
142 	0x0d, 0x02, 0x08, 0x07, 0x0f, 0x00, 0x0b, 0x04,
143 	0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
144 	0x0d, 0x02, 0x09, 0x06, 0x0f, 0x00, 0x0b, 0x04,
145 	0x0e, 0x02, 0x09, 0x06, 0x0f, 0x00, 0x0b, 0x04,
146 	0x0d, 0x02, 0x08, 0x07, 0x0f, 0x01, 0x0a, 0x05,
147 	0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
148 	0x0d, 0x02, 0x09, 0x07, 0x0f, 0x00, 0x0b, 0x04,
149 	0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
150 	0x0d, 0x02, 0x08, 0x07, 0x0f, 0x00, 0x0b, 0x04,
151 	0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
152 	0x0d, 0x02, 0x09, 0x06, 0x0f, 0x00, 0x0b, 0x04,
153 	0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
154 	0x0d, 0x02, 0x08, 0x07, 0x0f, 0x00, 0x0b, 0x04,
155 	0x0e, 0x01, 0x0a, 0x05, 0x0f, 0x00, 0x0c, 0x03,
156 	0x0d, 0x02, 0x09, 0x06, 0x0f, 0x00, 0x0b, 0x04,
157 };
158 
159 /* 4bit -> alaw decompression */
160 static u8 _4bit_to_alaw[16] = {
161 	0x5d, 0x51, 0xd9, 0xd7, 0x5f, 0x53, 0xa3, 0x4b,
162 	0x2a, 0x3a, 0x22, 0x2e, 0x26, 0x56, 0x20, 0x2c,
163 };
164 
165 /* ulaw -> 4bit compression */
166 static u8 ulaw_to_4bit[256] = {
167 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
168 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
169 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
170 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
171 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
172 	0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
173 	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
174 	0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
175 	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
176 	0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04,
177 	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
178 	0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
179 	0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
180 	0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
181 	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
182 	0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08,
183 	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
184 	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
185 	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
186 	0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
187 	0x0f, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
188 	0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
189 	0x0e, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d,
190 	0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d,
191 	0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
192 	0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b,
193 	0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
194 	0x0b, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x0a,
195 	0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
196 	0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
197 	0x09, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
198 	0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
199 };
200 
201 /* 4bit -> ulaw decompression */
202 static u8 _4bit_to_ulaw[16] = {
203 	0x11, 0x21, 0x31, 0x40, 0x4e, 0x5c, 0x68, 0x71,
204 	0xfe, 0xef, 0xe7, 0xdb, 0xcd, 0xbf, 0xaf, 0x9f,
205 };
206 
207 
208 /*
209  * Compresses data to the result buffer
210  * The result size must be at least half of the input buffer.
211  * The number of samples also must be even!
212  */
213 int
l1oip_law_to_4bit(u8 * data,int len,u8 * result,u32 * state)214 l1oip_law_to_4bit(u8 *data, int len, u8 *result, u32 *state)
215 {
216 	int ii, i = 0, o = 0;
217 
218 	if (!len)
219 		return 0;
220 
221 	/* send saved byte and first input byte */
222 	if (*state) {
223 		*result++ = table_com[(((*state) << 8) & 0xff00) | (*data++)];
224 		len--;
225 		o++;
226 	}
227 
228 	ii = len >> 1;
229 
230 	while (i < ii) {
231 		*result++ = table_com[(data[0]<<8) | (data[1])];
232 		data += 2;
233 		i++;
234 		o++;
235 	}
236 
237 	/* if len has an odd number, we save byte for next call */
238 	if (len & 1)
239 		*state = 0x100 + *data;
240 	else
241 		*state = 0;
242 
243 	return o;
244 }
245 
246 /* Decompress data to the result buffer
247  * The result size must be the number of sample in packet. (2 * input data)
248  * The number of samples in the result are even!
249  */
250 int
l1oip_4bit_to_law(u8 * data,int len,u8 * result)251 l1oip_4bit_to_law(u8 *data, int len, u8 *result)
252 {
253 	int i = 0;
254 	u16 r;
255 
256 	while (i < len) {
257 		r = table_dec[*data++];
258 		*result++ = r >> 8;
259 		*result++ = r;
260 		i++;
261 	}
262 
263 	return len << 1;
264 }
265 
266 
267 /*
268  * law conversion
269  */
270 int
l1oip_alaw_to_ulaw(u8 * data,int len,u8 * result)271 l1oip_alaw_to_ulaw(u8 *data, int len, u8 *result)
272 {
273 	int i = 0;
274 
275 	while (i < len) {
276 		*result++ = alaw_to_ulaw[*data++];
277 		i++;
278 	}
279 
280 	return len;
281 }
282 
283 int
l1oip_ulaw_to_alaw(u8 * data,int len,u8 * result)284 l1oip_ulaw_to_alaw(u8 *data, int len, u8 *result)
285 {
286 	int i = 0;
287 
288 	while (i < len) {
289 		*result++ = ulaw_to_alaw[*data++];
290 		i++;
291 	}
292 
293 	return len;
294 }
295 
296 
297 /*
298  * generate/free compression and decompression table
299  */
300 void
l1oip_4bit_free(void)301 l1oip_4bit_free(void)
302 {
303 	vfree(table_dec);
304 	vfree(table_com);
305 	table_com = NULL;
306 	table_dec = NULL;
307 }
308 
309 int
l1oip_4bit_alloc(int ulaw)310 l1oip_4bit_alloc(int ulaw)
311 {
312 	int i1, i2, c, sample;
313 
314 	/* in case, it is called again */
315 	if (table_dec)
316 		return 0;
317 
318 	/* alloc conversion tables */
319 	table_com = vzalloc(65536);
320 	table_dec = vzalloc(512);
321 	if (!table_com || !table_dec) {
322 		l1oip_4bit_free();
323 		return -ENOMEM;
324 	}
325 	/* generate compression table */
326 	i1 = 0;
327 	while (i1 < 256) {
328 		if (ulaw)
329 			c = ulaw_to_4bit[i1];
330 		else
331 			c = alaw_to_4bit[i1];
332 		i2 = 0;
333 		while (i2 < 256) {
334 			table_com[(i1 << 8) | i2] |= (c << 4);
335 			table_com[(i2 << 8) | i1] |= c;
336 			i2++;
337 		}
338 		i1++;
339 	}
340 
341 	/* generate decompression table */
342 	i1 = 0;
343 	while (i1 < 16) {
344 		if (ulaw)
345 			sample = _4bit_to_ulaw[i1];
346 		else
347 			sample = _4bit_to_alaw[i1];
348 		i2 = 0;
349 		while (i2 < 16) {
350 			table_dec[(i1 << 4) | i2] |= (sample << 8);
351 			table_dec[(i2 << 4) | i1] |= sample;
352 			i2++;
353 		}
354 		i1++;
355 	}
356 
357 	return 0;
358 }
359