linear.c revision 1.4 1 1.4 skrll /* $NetBSD: linear.c,v 1.4 2021/07/21 06:35:44 skrll Exp $ */
2 1.2 isaki
3 1.2 isaki /*
4 1.2 isaki * Copyright (C) 2017 Tetsuya Isaki. All rights reserved.
5 1.2 isaki * Copyright (C) 2017 Y.Sugahara (moveccr). All rights reserved.
6 1.2 isaki *
7 1.2 isaki * Redistribution and use in source and binary forms, with or without
8 1.2 isaki * modification, are permitted provided that the following conditions
9 1.2 isaki * are met:
10 1.2 isaki * 1. Redistributions of source code must retain the above copyright
11 1.2 isaki * notice, this list of conditions and the following disclaimer.
12 1.2 isaki * 2. Redistributions in binary form must reproduce the above copyright
13 1.2 isaki * notice, this list of conditions and the following disclaimer in the
14 1.2 isaki * documentation and/or other materials provided with the distribution.
15 1.2 isaki *
16 1.2 isaki * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 1.2 isaki * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 1.2 isaki * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 1.2 isaki * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 1.2 isaki * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 1.2 isaki * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 1.2 isaki * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 1.2 isaki * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 1.2 isaki * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 1.2 isaki * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 1.2 isaki * SUCH DAMAGE.
27 1.2 isaki */
28 1.2 isaki
29 1.2 isaki #include <sys/cdefs.h>
30 1.4 skrll __KERNEL_RCSID(0, "$NetBSD: linear.c,v 1.4 2021/07/21 06:35:44 skrll Exp $");
31 1.2 isaki
32 1.4 skrll #include <sys/param.h>
33 1.2 isaki #include <sys/types.h>
34 1.2 isaki #include <sys/systm.h>
35 1.2 isaki #include <sys/device.h>
36 1.2 isaki #include <dev/audio/audiovar.h>
37 1.2 isaki #include <dev/audio/linear.h>
38 1.2 isaki
39 1.2 isaki /*
40 1.2 isaki * audio_linear8_to_internal:
41 1.2 isaki * This filter performs conversion from [US]LINEAR8 to internal format.
42 1.2 isaki */
43 1.2 isaki void
44 1.2 isaki audio_linear8_to_internal(audio_filter_arg_t *arg)
45 1.2 isaki {
46 1.2 isaki const uint8_t *s;
47 1.2 isaki aint_t *d;
48 1.2 isaki uint8_t xor;
49 1.2 isaki u_int sample_count;
50 1.2 isaki u_int i;
51 1.2 isaki
52 1.2 isaki DIAGNOSTIC_filter_arg(arg);
53 1.2 isaki KASSERT(audio_format2_is_linear(arg->srcfmt));
54 1.2 isaki KASSERT(arg->srcfmt->precision == 8);
55 1.2 isaki KASSERT(arg->srcfmt->stride == 8);
56 1.2 isaki KASSERT(audio_format2_is_internal(arg->dstfmt));
57 1.2 isaki KASSERT(arg->srcfmt->channels == arg->dstfmt->channels);
58 1.2 isaki
59 1.2 isaki s = arg->src;
60 1.2 isaki d = arg->dst;
61 1.2 isaki sample_count = arg->count * arg->srcfmt->channels;
62 1.2 isaki xor = audio_format2_is_signed(arg->srcfmt) ? 0 : 0x80;
63 1.2 isaki
64 1.2 isaki for (i = 0; i < sample_count; i++) {
65 1.2 isaki uint8_t val;
66 1.2 isaki val = *s++;
67 1.2 isaki val ^= xor;
68 1.2 isaki *d++ = (auint_t)val << (AUDIO_INTERNAL_BITS - 8);
69 1.2 isaki }
70 1.2 isaki }
71 1.2 isaki
72 1.2 isaki /*
73 1.2 isaki * audio_internal_to_linear8:
74 1.2 isaki * This filter performs conversion from internal format to [US]LINEAR8.
75 1.2 isaki */
76 1.2 isaki void
77 1.2 isaki audio_internal_to_linear8(audio_filter_arg_t *arg)
78 1.2 isaki {
79 1.2 isaki const aint_t *s;
80 1.2 isaki uint8_t *d;
81 1.2 isaki uint8_t xor;
82 1.2 isaki u_int sample_count;
83 1.2 isaki u_int i;
84 1.2 isaki
85 1.2 isaki DIAGNOSTIC_filter_arg(arg);
86 1.2 isaki KASSERT(audio_format2_is_linear(arg->dstfmt));
87 1.2 isaki KASSERT(arg->dstfmt->precision == 8);
88 1.2 isaki KASSERT(arg->dstfmt->stride == 8);
89 1.2 isaki KASSERT(audio_format2_is_internal(arg->srcfmt));
90 1.2 isaki KASSERT(arg->srcfmt->channels == arg->dstfmt->channels);
91 1.2 isaki
92 1.2 isaki s = arg->src;
93 1.2 isaki d = arg->dst;
94 1.2 isaki sample_count = arg->count * arg->srcfmt->channels;
95 1.2 isaki xor = audio_format2_is_signed(arg->dstfmt) ? 0 : 0x80;
96 1.2 isaki
97 1.2 isaki for (i = 0; i < sample_count; i++) {
98 1.2 isaki uint8_t val;
99 1.2 isaki val = (*s++) >> (AUDIO_INTERNAL_BITS - 8);
100 1.2 isaki val ^= xor;
101 1.2 isaki *d++ = val;
102 1.2 isaki }
103 1.2 isaki }
104 1.2 isaki
105 1.2 isaki /*
106 1.2 isaki * audio_linear16_to_internal:
107 1.2 isaki * This filter performs conversion from [US]LINEAR16{LE,BE} to internal
108 1.2 isaki * format.
109 1.2 isaki */
110 1.2 isaki void
111 1.2 isaki audio_linear16_to_internal(audio_filter_arg_t *arg)
112 1.2 isaki {
113 1.2 isaki const uint16_t *s;
114 1.2 isaki aint_t *d;
115 1.2 isaki uint16_t xor;
116 1.2 isaki u_int sample_count;
117 1.2 isaki u_int shift;
118 1.2 isaki u_int i;
119 1.2 isaki bool is_src_NE;
120 1.2 isaki
121 1.2 isaki DIAGNOSTIC_filter_arg(arg);
122 1.2 isaki KASSERT(audio_format2_is_linear(arg->srcfmt));
123 1.2 isaki KASSERT(arg->srcfmt->precision == 16);
124 1.2 isaki KASSERT(arg->srcfmt->stride == 16);
125 1.2 isaki KASSERT(audio_format2_is_internal(arg->dstfmt));
126 1.2 isaki KASSERT(arg->srcfmt->channels == arg->dstfmt->channels);
127 1.2 isaki
128 1.2 isaki s = arg->src;
129 1.2 isaki d = arg->dst;
130 1.2 isaki sample_count = arg->count * arg->srcfmt->channels;
131 1.2 isaki
132 1.2 isaki shift = AUDIO_INTERNAL_BITS - 16;
133 1.2 isaki xor = audio_format2_is_signed(arg->srcfmt) ? 0 : 0x8000;
134 1.2 isaki is_src_NE = (audio_format2_endian(arg->srcfmt) == BYTE_ORDER);
135 1.2 isaki
136 1.2 isaki /*
137 1.2 isaki * Since slinear16_OppositeEndian to slinear_NativeEndian is used
138 1.2 isaki * so much especially on big endian machines, so it's expanded.
139 1.2 isaki * Other conversions are rarely used, so they are compressed.
140 1.2 isaki */
141 1.2 isaki if (__predict_true(xor == 0) && is_src_NE == false) {
142 1.2 isaki /* slinear16_OE to slinear<AI>_NE */
143 1.2 isaki for (i = 0; i < sample_count; i++) {
144 1.2 isaki uint16_t val;
145 1.2 isaki val = *s++;
146 1.2 isaki val = bswap16(val);
147 1.2 isaki *d++ = (auint_t)val << shift;
148 1.2 isaki }
149 1.2 isaki } else {
150 1.2 isaki /* slinear16_NE to slinear<AI>_NE */
151 1.2 isaki /* ulinear16_{NE,OE} to slinear<AI>_NE */
152 1.2 isaki for (i = 0; i < sample_count; i++) {
153 1.2 isaki uint16_t val;
154 1.2 isaki val = *s++;
155 1.2 isaki if (!is_src_NE)
156 1.2 isaki val = bswap16(val);
157 1.2 isaki val ^= xor;
158 1.2 isaki *d++ = (auint_t)val << shift;
159 1.2 isaki }
160 1.2 isaki }
161 1.2 isaki }
162 1.2 isaki
163 1.2 isaki /*
164 1.2 isaki * audio_internal_to_linear16:
165 1.2 isaki * This filter performs conversion from internal format to
166 1.2 isaki * [US]LINEAR16{LE,BE}.
167 1.2 isaki */
168 1.2 isaki void
169 1.2 isaki audio_internal_to_linear16(audio_filter_arg_t *arg)
170 1.2 isaki {
171 1.2 isaki const aint_t *s;
172 1.2 isaki uint16_t *d;
173 1.2 isaki uint16_t xor;
174 1.2 isaki u_int sample_count;
175 1.2 isaki u_int shift;
176 1.2 isaki u_int i;
177 1.2 isaki bool is_dst_NE;
178 1.2 isaki
179 1.2 isaki DIAGNOSTIC_filter_arg(arg);
180 1.2 isaki KASSERT(audio_format2_is_linear(arg->dstfmt));
181 1.2 isaki KASSERT(arg->dstfmt->precision == 16);
182 1.2 isaki KASSERT(arg->dstfmt->stride == 16);
183 1.2 isaki KASSERT(audio_format2_is_internal(arg->srcfmt));
184 1.2 isaki KASSERT(arg->srcfmt->channels == arg->dstfmt->channels);
185 1.2 isaki
186 1.2 isaki s = arg->src;
187 1.2 isaki d = arg->dst;
188 1.2 isaki sample_count = arg->count * arg->srcfmt->channels;
189 1.2 isaki
190 1.2 isaki shift = AUDIO_INTERNAL_BITS - 16;
191 1.2 isaki xor = audio_format2_is_signed(arg->dstfmt) ? 0 : 0x8000;
192 1.2 isaki is_dst_NE = (audio_format2_endian(arg->dstfmt) == BYTE_ORDER);
193 1.2 isaki
194 1.2 isaki /*
195 1.2 isaki * Since slinear_NativeEndian to slinear16_OppositeEndian is used
196 1.2 isaki * so much especially on big endian machines, so it's expanded.
197 1.2 isaki * Other conversions are rarely used, so they are compressed.
198 1.2 isaki */
199 1.2 isaki if (__predict_true(xor == 0) && is_dst_NE == false) {
200 1.2 isaki /* slinear<AI>_NE -> slinear16_OE */
201 1.2 isaki for (i = 0; i < sample_count; i++) {
202 1.2 isaki uint16_t val;
203 1.2 isaki val = (*s++) >> shift;
204 1.2 isaki val = bswap16(val);
205 1.2 isaki *d++ = val;
206 1.2 isaki }
207 1.2 isaki } else {
208 1.2 isaki /* slinear<AI>_NE -> slinear16_NE */
209 1.2 isaki /* slinear<AI>_NE -> ulinear16_{NE,OE} */
210 1.2 isaki for (i = 0; i < sample_count; i++) {
211 1.2 isaki uint16_t val;
212 1.2 isaki val = (*s++) >> shift;
213 1.2 isaki val ^= xor;
214 1.2 isaki if (!is_dst_NE)
215 1.2 isaki val = bswap16(val);
216 1.2 isaki *d++ = val;
217 1.2 isaki }
218 1.2 isaki }
219 1.2 isaki }
220 1.2 isaki
221 1.2 isaki #if defined(AUDIO_SUPPORT_LINEAR24)
222 1.2 isaki /*
223 1.2 isaki * audio_linear24_to_internal:
224 1.2 isaki * This filter performs conversion from [US]LINEAR24/24{LE,BE} to
225 1.2 isaki * internal format. Since it's rerely used, it's size optimized.
226 1.2 isaki */
227 1.2 isaki void
228 1.2 isaki audio_linear24_to_internal(audio_filter_arg_t *arg)
229 1.2 isaki {
230 1.2 isaki const uint8_t *s;
231 1.2 isaki aint_t *d;
232 1.2 isaki auint_t xor;
233 1.2 isaki u_int sample_count;
234 1.2 isaki u_int i;
235 1.2 isaki bool is_src_LE;
236 1.2 isaki
237 1.2 isaki DIAGNOSTIC_filter_arg(arg);
238 1.2 isaki KASSERT(audio_format2_is_linear(arg->srcfmt));
239 1.2 isaki KASSERT(arg->srcfmt->precision == 24);
240 1.2 isaki KASSERT(arg->srcfmt->stride == 24);
241 1.2 isaki KASSERT(audio_format2_is_internal(arg->dstfmt));
242 1.2 isaki KASSERT(arg->srcfmt->channels == arg->dstfmt->channels);
243 1.2 isaki
244 1.2 isaki s = arg->src;
245 1.2 isaki d = arg->dst;
246 1.2 isaki sample_count = arg->count * arg->srcfmt->channels;
247 1.2 isaki xor = audio_format2_is_signed(arg->srcfmt)
248 1.2 isaki ? 0 : (1 << (AUDIO_INTERNAL_BITS - 1));
249 1.2 isaki is_src_LE = (audio_format2_endian(arg->srcfmt) == LITTLE_ENDIAN);
250 1.2 isaki
251 1.2 isaki for (i = 0; i < sample_count; i++) {
252 1.2 isaki uint32_t val;
253 1.2 isaki if (is_src_LE) {
254 1.2 isaki val = s[0] | (s[1] << 8) | (s[2] << 16);
255 1.2 isaki } else {
256 1.2 isaki val = (s[0] << 16) | (s[1] << 8) | s[2];
257 1.2 isaki }
258 1.2 isaki s += 3;
259 1.2 isaki
260 1.2 isaki #if AUDIO_INTERNAL_BITS < 24
261 1.2 isaki val >>= 24 - AUDIO_INTERNAL_BITS;
262 1.2 isaki #else
263 1.2 isaki val <<= AUDIO_INTERNAL_BITS - 24;
264 1.2 isaki #endif
265 1.2 isaki val ^= xor;
266 1.2 isaki *d++ = val;
267 1.2 isaki }
268 1.2 isaki }
269 1.2 isaki
270 1.2 isaki /*
271 1.2 isaki * audio_internal_to_linear24:
272 1.2 isaki * This filter performs conversion from internal format to
273 1.2 isaki * [US]LINEAR24/24{LE,BE}. Since it's rarely used, it's size optimized.
274 1.2 isaki */
275 1.2 isaki void
276 1.2 isaki audio_internal_to_linear24(audio_filter_arg_t *arg)
277 1.2 isaki {
278 1.2 isaki const aint_t *s;
279 1.2 isaki uint8_t *d;
280 1.2 isaki auint_t xor;
281 1.2 isaki u_int sample_count;
282 1.2 isaki u_int i;
283 1.2 isaki bool is_dst_LE;
284 1.2 isaki
285 1.2 isaki DIAGNOSTIC_filter_arg(arg);
286 1.2 isaki KASSERT(audio_format2_is_linear(arg->dstfmt));
287 1.2 isaki KASSERT(arg->dstfmt->precision == 24);
288 1.2 isaki KASSERT(arg->dstfmt->stride == 24);
289 1.2 isaki KASSERT(audio_format2_is_internal(arg->srcfmt));
290 1.2 isaki KASSERT(arg->srcfmt->channels == arg->dstfmt->channels);
291 1.2 isaki
292 1.2 isaki s = arg->src;
293 1.2 isaki d = arg->dst;
294 1.2 isaki sample_count = arg->count * arg->srcfmt->channels;
295 1.2 isaki xor = audio_format2_is_signed(arg->dstfmt)
296 1.2 isaki ? 0 : (1 << (AUDIO_INTERNAL_BITS - 1));
297 1.2 isaki is_dst_LE = (audio_format2_endian(arg->dstfmt) == LITTLE_ENDIAN);
298 1.2 isaki
299 1.2 isaki for (i = 0; i < sample_count; i++) {
300 1.2 isaki uint32_t val;
301 1.2 isaki val = *s++;
302 1.2 isaki val ^= xor;
303 1.2 isaki #if AUDIO_INTERNAL_BITS < 24
304 1.2 isaki val <<= 24 - AUDIO_INTERNAL_BITS;
305 1.2 isaki #else
306 1.2 isaki val >>= AUDIO_INTERNAL_BITS - 24;
307 1.2 isaki #endif
308 1.2 isaki if (is_dst_LE) {
309 1.2 isaki d[0] = val & 0xff;
310 1.2 isaki d[1] = (val >> 8) & 0xff;
311 1.2 isaki d[2] = (val >> 16) & 0xff;
312 1.2 isaki } else {
313 1.2 isaki d[0] = (val >> 16) & 0xff;
314 1.2 isaki d[1] = (val >> 8) & 0xff;
315 1.2 isaki d[2] = val & 0xff;
316 1.2 isaki }
317 1.2 isaki d += 3;
318 1.2 isaki }
319 1.2 isaki }
320 1.2 isaki #endif /* AUDIO_SUPPORT_LINEAR24 */
321 1.2 isaki
322 1.2 isaki /*
323 1.2 isaki * audio_linear32_to_internal:
324 1.2 isaki * This filter performs conversion from [US]LINEAR32{LE,BE} to internal
325 1.2 isaki * format. Since it's rarely used, it's size optimized.
326 1.2 isaki */
327 1.2 isaki void
328 1.2 isaki audio_linear32_to_internal(audio_filter_arg_t *arg)
329 1.2 isaki {
330 1.2 isaki const uint32_t *s;
331 1.2 isaki aint_t *d;
332 1.2 isaki auint_t xor;
333 1.2 isaki u_int sample_count;
334 1.2 isaki u_int i;
335 1.2 isaki bool is_src_NE;
336 1.2 isaki
337 1.2 isaki DIAGNOSTIC_filter_arg(arg);
338 1.2 isaki KASSERT(audio_format2_is_linear(arg->srcfmt));
339 1.2 isaki KASSERT(arg->srcfmt->precision == 32);
340 1.2 isaki KASSERT(arg->srcfmt->stride == 32);
341 1.2 isaki KASSERT(audio_format2_is_internal(arg->dstfmt));
342 1.2 isaki KASSERT(arg->srcfmt->channels == arg->dstfmt->channels);
343 1.2 isaki
344 1.2 isaki s = arg->src;
345 1.2 isaki d = arg->dst;
346 1.2 isaki sample_count = arg->count * arg->srcfmt->channels;
347 1.2 isaki xor = audio_format2_is_signed(arg->srcfmt)
348 1.2 isaki ? 0 : (1 << (AUDIO_INTERNAL_BITS - 1));
349 1.2 isaki is_src_NE = (audio_format2_endian(arg->srcfmt) == BYTE_ORDER);
350 1.2 isaki
351 1.2 isaki for (i = 0; i < sample_count; i++) {
352 1.2 isaki uint32_t val;
353 1.2 isaki val = *s++;
354 1.2 isaki if (!is_src_NE)
355 1.2 isaki val = bswap32(val);
356 1.2 isaki val >>= 32 - AUDIO_INTERNAL_BITS;
357 1.2 isaki val ^= xor;
358 1.2 isaki *d++ = val;
359 1.2 isaki }
360 1.2 isaki }
361 1.2 isaki
362 1.2 isaki /*
363 1.2 isaki * audio_internal_to_linear32:
364 1.2 isaki * This filter performs conversion from internal format to
365 1.2 isaki * [US]LINEAR32{LE,BE}. Since it's rarely used, it's size optimized.
366 1.2 isaki */
367 1.2 isaki void
368 1.2 isaki audio_internal_to_linear32(audio_filter_arg_t *arg)
369 1.2 isaki {
370 1.2 isaki const aint_t *s;
371 1.2 isaki uint32_t *d;
372 1.2 isaki auint_t xor;
373 1.2 isaki u_int sample_count;
374 1.2 isaki u_int i;
375 1.2 isaki bool is_dst_NE;
376 1.2 isaki
377 1.2 isaki DIAGNOSTIC_filter_arg(arg);
378 1.2 isaki KASSERT(audio_format2_is_linear(arg->dstfmt));
379 1.2 isaki KASSERT(arg->dstfmt->precision == 32);
380 1.2 isaki KASSERT(arg->dstfmt->stride == 32);
381 1.2 isaki KASSERT(audio_format2_is_internal(arg->srcfmt));
382 1.2 isaki KASSERT(arg->srcfmt->channels == arg->dstfmt->channels);
383 1.2 isaki
384 1.2 isaki s = arg->src;
385 1.2 isaki d = arg->dst;
386 1.2 isaki sample_count = arg->count * arg->srcfmt->channels;
387 1.2 isaki xor = audio_format2_is_signed(arg->dstfmt)
388 1.2 isaki ? 0 : (1 << (AUDIO_INTERNAL_BITS - 1));
389 1.2 isaki is_dst_NE = (audio_format2_endian(arg->dstfmt) == BYTE_ORDER);
390 1.2 isaki
391 1.2 isaki for (i = 0; i < sample_count; i++) {
392 1.2 isaki uint32_t val;
393 1.2 isaki val = *s++;
394 1.2 isaki val ^= xor;
395 1.2 isaki val <<= 32 - AUDIO_INTERNAL_BITS;
396 1.2 isaki if (!is_dst_NE)
397 1.2 isaki val = bswap32(val);
398 1.2 isaki *d++ = val;
399 1.2 isaki }
400 1.2 isaki }
401