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