xref: /netbsd-src/sys/dev/audio/mulaw.c (revision 82d56013d7b633d116a93943de88e08335357a7c)
1 /*	$NetBSD: mulaw.c,v 1.4 2020/09/12 06:09:16 isaki Exp $	*/
2 
3 /*
4  * Copyright (C) 2017 Tetsuya Isaki. All rights reserved.
5  * Copyright (C) 2017 Y.Sugahara (moveccr). All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 __KERNEL_RCSID(0, "$NetBSD: mulaw.c,v 1.4 2020/09/12 06:09:16 isaki Exp $");
31 
32 #include <sys/types.h>
33 #include <sys/systm.h>
34 #include <sys/device.h>
35 #include <dev/audio/audiovar.h>
36 #include <dev/audio/mulaw.h>
37 
38 /*
39  * audio_internal_to_mulaw has two implementations.
40  *
41  * 1. Use 8bit table (MULAW_LQ_ENC)
42  *  It's traditional implementation and its precision is 8bit.
43  *  It's faster but the size is larger.  And you can hear a little noise
44  *  in silent part.
45  *
46  * 2. Calculation (default)
47  *  It calculates mu-law with full spec and its precision is 14bit.
48  *  It's about 3 times slower but the size is less than a half (on m68k,
49  *  for example).
50  *
51  * mu-law is no longer a popular format.  I think size-optimized is better.
52  */
53 /* #define MULAW_LQ_ENC */
54 
55 /*
56  * About mulaw32 format.
57  *
58  * The format which I call ``mulaw32'' is only used in dev/tc/bba.c .
59  * It is 8bit mu-law but 16bit left-shifted and its containter is 32bit.
60  * Not mu-law calculated in 32bit.
61  *
62  * When MULAW32 is not defined (it's default), this file outputs
63  * audio_internal_to_mulaw() and audio_mulaw_to_internal().  When
64  * MULAW32 is defined, this file outputs audio_internal_to_mulaw32()
65  * and audio_mulaw32_to_internal() instead.
66  *
67  * Since mu-law is used as userland format and is mandatory, all audio
68  * drivers (including tc/bba) link this mulaw.c in ordinary procedure.
69  * On the other hand, only tc/bba also needs audio_internal_to_mulaw32()
70  * and audio_mulaw32_to_internal() as its hardware drivers codec, so
71  * define MULAW32 and include this file.  It's a bit tricky but I think
72  * this is the simplest way.
73  */
74 
75 #if 0
76 #define MPRINTF(fmt, ...)	printf(fmt, ## __VA_ARGS__)
77 #else
78 #define MPRINTF(fmt, ...)	/**/
79 #endif
80 
81 static const int16_t mulaw_to_slinear16[256] = {
82 	0x8284, 0x8684, 0x8a84, 0x8e84, 0x9284, 0x9684, 0x9a84, 0x9e84,
83 	0xa284, 0xa684, 0xaa84, 0xae84, 0xb284, 0xb684, 0xba84, 0xbe84,
84 	0xc184, 0xc384, 0xc584, 0xc784, 0xc984, 0xcb84, 0xcd84, 0xcf84,
85 	0xd184, 0xd384, 0xd584, 0xd784, 0xd984, 0xdb84, 0xdd84, 0xdf84,
86 	0xe104, 0xe204, 0xe304, 0xe404, 0xe504, 0xe604, 0xe704, 0xe804,
87 	0xe904, 0xea04, 0xeb04, 0xec04, 0xed04, 0xee04, 0xef04, 0xf004,
88 	0xf0c4, 0xf144, 0xf1c4, 0xf244, 0xf2c4, 0xf344, 0xf3c4, 0xf444,
89 	0xf4c4, 0xf544, 0xf5c4, 0xf644, 0xf6c4, 0xf744, 0xf7c4, 0xf844,
90 	0xf8a4, 0xf8e4, 0xf924, 0xf964, 0xf9a4, 0xf9e4, 0xfa24, 0xfa64,
91 	0xfaa4, 0xfae4, 0xfb24, 0xfb64, 0xfba4, 0xfbe4, 0xfc24, 0xfc64,
92 	0xfc94, 0xfcb4, 0xfcd4, 0xfcf4, 0xfd14, 0xfd34, 0xfd54, 0xfd74,
93 	0xfd94, 0xfdb4, 0xfdd4, 0xfdf4, 0xfe14, 0xfe34, 0xfe54, 0xfe74,
94 	0xfe8c, 0xfe9c, 0xfeac, 0xfebc, 0xfecc, 0xfedc, 0xfeec, 0xfefc,
95 	0xff0c, 0xff1c, 0xff2c, 0xff3c, 0xff4c, 0xff5c, 0xff6c, 0xff7c,
96 	0xff88, 0xff90, 0xff98, 0xffa0, 0xffa8, 0xffb0, 0xffb8, 0xffc0,
97 	0xffc8, 0xffd0, 0xffd8, 0xffe0, 0xffe8, 0xfff0, 0xfff8, 0xfffc,
98 	0x7d7c, 0x797c, 0x757c, 0x717c, 0x6d7c, 0x697c, 0x657c, 0x617c,
99 	0x5d7c, 0x597c, 0x557c, 0x517c, 0x4d7c, 0x497c, 0x457c, 0x417c,
100 	0x3e7c, 0x3c7c, 0x3a7c, 0x387c, 0x367c, 0x347c, 0x327c, 0x307c,
101 	0x2e7c, 0x2c7c, 0x2a7c, 0x287c, 0x267c, 0x247c, 0x227c, 0x207c,
102 	0x1efc, 0x1dfc, 0x1cfc, 0x1bfc, 0x1afc, 0x19fc, 0x18fc, 0x17fc,
103 	0x16fc, 0x15fc, 0x14fc, 0x13fc, 0x12fc, 0x11fc, 0x10fc, 0x0ffc,
104 	0x0f3c, 0x0ebc, 0x0e3c, 0x0dbc, 0x0d3c, 0x0cbc, 0x0c3c, 0x0bbc,
105 	0x0b3c, 0x0abc, 0x0a3c, 0x09bc, 0x093c, 0x08bc, 0x083c, 0x07bc,
106 	0x075c, 0x071c, 0x06dc, 0x069c, 0x065c, 0x061c, 0x05dc, 0x059c,
107 	0x055c, 0x051c, 0x04dc, 0x049c, 0x045c, 0x041c, 0x03dc, 0x039c,
108 	0x036c, 0x034c, 0x032c, 0x030c, 0x02ec, 0x02cc, 0x02ac, 0x028c,
109 	0x026c, 0x024c, 0x022c, 0x020c, 0x01ec, 0x01cc, 0x01ac, 0x018c,
110 	0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104,
111 	0x00f4, 0x00e4, 0x00d4, 0x00c4, 0x00b4, 0x00a4, 0x0094, 0x0084,
112 	0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040,
113 	0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000,
114 };
115 
116 #if defined(MULAW_LQ_ENC)
117 static const uint8_t slinear8_to_mulaw[256] = {
118 	0xff, 0xe7, 0xdb, 0xd3, 0xcd, 0xc9, 0xc5, 0xc1,
119 	0xbe, 0xbc, 0xba, 0xb8, 0xb6, 0xb4, 0xb2, 0xb0,
120 	0xaf, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9, 0xa8,
121 	0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1, 0xa0,
122 	0x9f, 0x9f, 0x9e, 0x9e, 0x9d, 0x9d, 0x9c, 0x9c,
123 	0x9b, 0x9b, 0x9a, 0x9a, 0x99, 0x99, 0x98, 0x98,
124 	0x97, 0x97, 0x96, 0x96, 0x95, 0x95, 0x94, 0x94,
125 	0x93, 0x93, 0x92, 0x92, 0x91, 0x91, 0x90, 0x90,
126 	0x8f, 0x8f, 0x8f, 0x8f, 0x8e, 0x8e, 0x8e, 0x8e,
127 	0x8d, 0x8d, 0x8d, 0x8d, 0x8c, 0x8c, 0x8c, 0x8c,
128 	0x8b, 0x8b, 0x8b, 0x8b, 0x8a, 0x8a, 0x8a, 0x8a,
129 	0x89, 0x89, 0x89, 0x89, 0x88, 0x88, 0x88, 0x88,
130 	0x87, 0x87, 0x87, 0x87, 0x86, 0x86, 0x86, 0x86,
131 	0x85, 0x85, 0x85, 0x85, 0x84, 0x84, 0x84, 0x84,
132 	0x83, 0x83, 0x83, 0x83, 0x82, 0x82, 0x82, 0x82,
133 	0x81, 0x81, 0x81, 0x81, 0x80, 0x80, 0x80, 0x80,
134 	0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
135 	0x01, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03,
136 	0x03, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05,
137 	0x05, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07,
138 	0x07, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09,
139 	0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b,
140 	0x0b, 0x0c, 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d,
141 	0x0d, 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f,
142 	0x0f, 0x10, 0x10, 0x11, 0x11, 0x12, 0x12, 0x13,
143 	0x13, 0x14, 0x14, 0x15, 0x15, 0x16, 0x16, 0x17,
144 	0x17, 0x18, 0x18, 0x19, 0x19, 0x1a, 0x1a, 0x1b,
145 	0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e, 0x1f,
146 	0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
147 	0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e,
148 	0x2f, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c,
149 	0x3e, 0x41, 0x45, 0x49, 0x4d, 0x53, 0x5b, 0x67,
150 };
151 #endif
152 
153 /*
154  * audio_mulaw_to_internal:
155  *	This filter performs conversion from mu-law to internal format.
156  *
157  * audio_mulaw32_to_internal:
158  *	This filter performs conversion from mulaw32 used only in tc/bba.c
159  *	to internal format.
160  */
161 void
162 #if !defined(MULAW32)
163 audio_mulaw_to_internal(audio_filter_arg_t *arg)
164 #else
165 audio_mulaw32_to_internal(audio_filter_arg_t *arg)
166 #endif
167 {
168 #if defined(MULAW32)
169 	const uint32_t *s;
170 #else
171 	const uint8_t *s;
172 #endif
173 	aint_t *d;
174 	u_int sample_count;
175 	u_int i;
176 
177 	DIAGNOSTIC_filter_arg(arg);
178 #if !defined(MULAW32)
179 	KASSERT(arg->srcfmt->encoding == AUDIO_ENCODING_ULAW);
180 	KASSERT(arg->srcfmt->stride == 8);
181 	KASSERT(arg->srcfmt->precision == 8);
182 #endif
183 	KASSERT(audio_format2_is_internal(arg->dstfmt));
184 	KASSERT(arg->srcfmt->channels == arg->dstfmt->channels);
185 
186 	s = arg->src;
187 	d = arg->dst;
188 	sample_count = arg->count * arg->srcfmt->channels;
189 
190 	for (i = 0; i < sample_count; i++) {
191 		aint_t val;
192 		uint m;
193 		m = *s++;
194 #if defined(MULAW32)
195 		/* 32bit container used only in tc/bba.c */
196 		m = (m >> 16) & 0xff;
197 #endif
198 		val = mulaw_to_slinear16[m];
199 		val <<= AUDIO_INTERNAL_BITS - 16;
200 		*d++ = val;
201 	}
202 }
203 
204 /*
205  * audio_internal_to_mulaw:
206  *	This filter performs conversion from internal format to mu-law.
207  *
208  * audio_internal_to_mulaw32:
209  *	This filter performs conversion from internal format to mulaw32
210  *	used only in tc/bba.c.
211  */
212 void
213 #if !defined(MULAW32)
214 audio_internal_to_mulaw(audio_filter_arg_t *arg)
215 #else
216 audio_internal_to_mulaw32(audio_filter_arg_t *arg)
217 #endif
218 {
219 	const aint_t *s;
220 #if defined(MULAW32)
221 	uint32_t *d;
222 #else
223 	uint8_t *d;
224 #endif
225 	u_int sample_count;
226 	u_int i;
227 
228 	DIAGNOSTIC_filter_arg(arg);
229 #if !defined(MULAW32)
230 	KASSERT(arg->dstfmt->encoding == AUDIO_ENCODING_ULAW);
231 	KASSERT(arg->dstfmt->stride == 8);
232 	KASSERT(arg->dstfmt->precision == 8);
233 #endif
234 	KASSERT(audio_format2_is_internal(arg->srcfmt));
235 	KASSERT(arg->srcfmt->channels == arg->dstfmt->channels);
236 
237 	s = arg->src;
238 	d = arg->dst;
239 	sample_count = arg->count * arg->srcfmt->channels;
240 
241 	for (i = 0; i < sample_count; i++) {
242 		uint8_t m;
243 #if defined(MULAW_LQ_ENC)
244 		/* 8bit (low quality, fast but fat) encoder */
245 		uint8_t val;
246 		val = (*s++) >> (AUDIO_INTERNAL_BITS - 8);
247 		m = slinear8_to_mulaw[val];
248 #else
249 		/* 14bit (fullspec, slow but small) encoder */
250 		uint16_t val;
251 		int c;
252 
253 		val = *s++ >> (AUDIO_INTERNAL_BITS - 16);
254 		if ((int16_t)val < 0) {
255 			m = 0;
256 		} else {
257 			val = ~val;
258 			m = 0x80;
259 		}
260 		/* limit */
261 		if ((int16_t)val < -8158 * 4)
262 			val = -8158 * 4;
263 		val -= 33 * 4;	/* bias */
264 
265 		// Before(1)         Before(2)         Before(3)
266 		// S0MMMMxx_xxxxxxxx 0MMMMxxx_xxxxxxx0 c=0,v=0MMMMxxx_xxxxxxx0
267 		// S10MMMMx_xxxxxxxx 10MMMMxx_xxxxxxx0 c=1,v=0MMMMxxx_xxxxxx00
268 		// S110MMMM_xxxxxxxx 110MMMMx_xxxxxxx0 c=2,v=0MMMMxxx_xxxxx000
269 		// :                 :                 :
270 		// S1111110_MMMMxxxx 1111110M_MMMxxxx0 c=6,v=0MMMMxxx_x0000000
271 
272 		// (1) Push out sign bit
273 		val <<= 1;
274 
275 		// (2) Find first zero (and align val to left)
276 		c = 0;
277 		if (val >= 0xf000) c += 4, val <<= 4;
278 		if (val >= 0xc000) c += 2, val <<= 2;
279 		if (val >= 0x8000) c += 1, val <<= 1;
280 
281 		// (3)
282 		m += (c << 4);
283 		m += (val >> 11) & 0x0f;
284 #endif
285 
286 #if defined(MULAW32)
287 		/* 8bit mu-law in 32bit container used only in tc/bba.c */
288 		*d++ = m << 16;
289 #else
290 		*d++ = m;
291 #endif
292 	}
293 }
294