1 /* $NetBSD: alaw.c,v 1.4 2021/07/21 06:35:44 skrll Exp $ */
2
3 /*
4 * Copyright (C) 2018 Tetsuya Isaki. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
20 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
22 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 #include <sys/cdefs.h>
29 __KERNEL_RCSID(0, "$NetBSD: alaw.c,v 1.4 2021/07/21 06:35:44 skrll Exp $");
30
31 #include <sys/param.h>
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 static const uint16_t alaw_to_slinear16[256] = {
39 0xea80, 0xeb80, 0xe880, 0xe980, 0xee80, 0xef80, 0xec80, 0xed80,
40 0xe280, 0xe380, 0xe080, 0xe180, 0xe680, 0xe780, 0xe480, 0xe580,
41 0xf540, 0xf5c0, 0xf440, 0xf4c0, 0xf740, 0xf7c0, 0xf640, 0xf6c0,
42 0xf140, 0xf1c0, 0xf040, 0xf0c0, 0xf340, 0xf3c0, 0xf240, 0xf2c0,
43 0xaa00, 0xae00, 0xa200, 0xa600, 0xba00, 0xbe00, 0xb200, 0xb600,
44 0x8a00, 0x8e00, 0x8200, 0x8600, 0x9a00, 0x9e00, 0x9200, 0x9600,
45 0xd500, 0xd700, 0xd100, 0xd300, 0xdd00, 0xdf00, 0xd900, 0xdb00,
46 0xc500, 0xc700, 0xc100, 0xc300, 0xcd00, 0xcf00, 0xc900, 0xcb00,
47 0xfea8, 0xfeb8, 0xfe88, 0xfe98, 0xfee8, 0xfef8, 0xfec8, 0xfed8,
48 0xfe28, 0xfe38, 0xfe08, 0xfe18, 0xfe68, 0xfe78, 0xfe48, 0xfe58,
49 0xffa8, 0xffb8, 0xff88, 0xff98, 0xffe8, 0xfff8, 0xffc8, 0xffd8,
50 0xff28, 0xff38, 0xff08, 0xff18, 0xff68, 0xff78, 0xff48, 0xff58,
51 0xfaa0, 0xfae0, 0xfa20, 0xfa60, 0xfba0, 0xfbe0, 0xfb20, 0xfb60,
52 0xf8a0, 0xf8e0, 0xf820, 0xf860, 0xf9a0, 0xf9e0, 0xf920, 0xf960,
53 0xfd50, 0xfd70, 0xfd10, 0xfd30, 0xfdd0, 0xfdf0, 0xfd90, 0xfdb0,
54 0xfc50, 0xfc70, 0xfc10, 0xfc30, 0xfcd0, 0xfcf0, 0xfc90, 0xfcb0,
55 0x1580, 0x1480, 0x1780, 0x1680, 0x1180, 0x1080, 0x1380, 0x1280,
56 0x1d80, 0x1c80, 0x1f80, 0x1e80, 0x1980, 0x1880, 0x1b80, 0x1a80,
57 0x0ac0, 0x0a40, 0x0bc0, 0x0b40, 0x08c0, 0x0840, 0x09c0, 0x0940,
58 0x0ec0, 0x0e40, 0x0fc0, 0x0f40, 0x0cc0, 0x0c40, 0x0dc0, 0x0d40,
59 0x5600, 0x5200, 0x5e00, 0x5a00, 0x4600, 0x4200, 0x4e00, 0x4a00,
60 0x7600, 0x7200, 0x7e00, 0x7a00, 0x6600, 0x6200, 0x6e00, 0x6a00,
61 0x2b00, 0x2900, 0x2f00, 0x2d00, 0x2300, 0x2100, 0x2700, 0x2500,
62 0x3b00, 0x3900, 0x3f00, 0x3d00, 0x3300, 0x3100, 0x3700, 0x3500,
63 0x0158, 0x0148, 0x0178, 0x0168, 0x0118, 0x0108, 0x0138, 0x0128,
64 0x01d8, 0x01c8, 0x01f8, 0x01e8, 0x0198, 0x0188, 0x01b8, 0x01a8,
65 0x0058, 0x0048, 0x0078, 0x0068, 0x0018, 0x0008, 0x0038, 0x0028,
66 0x00d8, 0x00c8, 0x00f8, 0x00e8, 0x0098, 0x0088, 0x00b8, 0x00a8,
67 0x0560, 0x0520, 0x05e0, 0x05a0, 0x0460, 0x0420, 0x04e0, 0x04a0,
68 0x0760, 0x0720, 0x07e0, 0x07a0, 0x0660, 0x0620, 0x06e0, 0x06a0,
69 0x02b0, 0x0290, 0x02f0, 0x02d0, 0x0230, 0x0210, 0x0270, 0x0250,
70 0x03b0, 0x0390, 0x03f0, 0x03d0, 0x0330, 0x0310, 0x0370, 0x0350,
71 };
72
73 static const uint8_t slinear8_to_alaw[256] = {
74 0xd5, 0xc5, 0xf5, 0xfd, 0xe5, 0xe1, 0xed, 0xe9,
75 0x95, 0x97, 0x91, 0x93, 0x9d, 0x9f, 0x99, 0x9b,
76 0x85, 0x84, 0x87, 0x86, 0x81, 0x80, 0x83, 0x82,
77 0x8d, 0x8c, 0x8f, 0x8e, 0x89, 0x88, 0x8b, 0x8a,
78 0xb5, 0xb5, 0xb4, 0xb4, 0xb7, 0xb7, 0xb6, 0xb6,
79 0xb1, 0xb1, 0xb0, 0xb0, 0xb3, 0xb3, 0xb2, 0xb2,
80 0xbd, 0xbd, 0xbc, 0xbc, 0xbf, 0xbf, 0xbe, 0xbe,
81 0xb9, 0xb9, 0xb8, 0xb8, 0xbb, 0xbb, 0xba, 0xba,
82 0xa5, 0xa5, 0xa5, 0xa5, 0xa4, 0xa4, 0xa4, 0xa4,
83 0xa7, 0xa7, 0xa7, 0xa7, 0xa6, 0xa6, 0xa6, 0xa6,
84 0xa1, 0xa1, 0xa1, 0xa1, 0xa0, 0xa0, 0xa0, 0xa0,
85 0xa3, 0xa3, 0xa3, 0xa3, 0xa2, 0xa2, 0xa2, 0xa2,
86 0xad, 0xad, 0xad, 0xad, 0xac, 0xac, 0xac, 0xac,
87 0xaf, 0xaf, 0xaf, 0xaf, 0xae, 0xae, 0xae, 0xae,
88 0xa9, 0xa9, 0xa9, 0xa9, 0xa8, 0xa8, 0xa8, 0xa8,
89 0xab, 0xab, 0xab, 0xab, 0xaa, 0xaa, 0xaa, 0xaa,
90 0x2a, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2b,
91 0x28, 0x28, 0x28, 0x28, 0x29, 0x29, 0x29, 0x29,
92 0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x2f,
93 0x2c, 0x2c, 0x2c, 0x2c, 0x2d, 0x2d, 0x2d, 0x2d,
94 0x22, 0x22, 0x22, 0x22, 0x23, 0x23, 0x23, 0x23,
95 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21, 0x21,
96 0x26, 0x26, 0x26, 0x26, 0x27, 0x27, 0x27, 0x27,
97 0x24, 0x24, 0x24, 0x24, 0x25, 0x25, 0x25, 0x25,
98 0x3a, 0x3a, 0x3b, 0x3b, 0x38, 0x38, 0x39, 0x39,
99 0x3e, 0x3e, 0x3f, 0x3f, 0x3c, 0x3c, 0x3d, 0x3d,
100 0x32, 0x32, 0x33, 0x33, 0x30, 0x30, 0x31, 0x31,
101 0x36, 0x36, 0x37, 0x37, 0x34, 0x34, 0x35, 0x35,
102 0x0a, 0x0b, 0x08, 0x09, 0x0e, 0x0f, 0x0c, 0x0d,
103 0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05,
104 0x1a, 0x18, 0x1e, 0x1c, 0x12, 0x10, 0x16, 0x14,
105 0x6a, 0x6e, 0x62, 0x66, 0x7a, 0x72, 0x4a, 0x5a,
106 };
107
108 /*
109 * audio_alaw_to_internal:
110 * This filter performs conversion from A-law to internal format.
111 */
112 void
audio_alaw_to_internal(audio_filter_arg_t * arg)113 audio_alaw_to_internal(audio_filter_arg_t *arg)
114 {
115 const uint8_t *s;
116 aint_t *d;
117 u_int sample_count;
118 u_int i;
119
120 DIAGNOSTIC_filter_arg(arg);
121 KASSERT(arg->srcfmt->encoding == AUDIO_ENCODING_ALAW);
122 KASSERT(arg->srcfmt->stride == 8);
123 KASSERT(arg->srcfmt->precision == 8);
124 KASSERT(audio_format2_is_internal(arg->dstfmt));
125 KASSERT(arg->srcfmt->channels == arg->dstfmt->channels);
126
127 s = arg->src;
128 d = arg->dst;
129 sample_count = arg->count * arg->srcfmt->channels;
130
131 for (i = 0; i < sample_count; i++) {
132 aint_t val;
133 val = alaw_to_slinear16[*s++];
134 val <<= AUDIO_INTERNAL_BITS - 16;
135 *d++ = val;
136 }
137 }
138
139 /*
140 * audio_internal_to_alaw:
141 * This filter performs conversion from internal format to A-law.
142 */
143 void
audio_internal_to_alaw(audio_filter_arg_t * arg)144 audio_internal_to_alaw(audio_filter_arg_t *arg)
145 {
146 const aint_t *s;
147 uint8_t *d;
148 u_int sample_count;
149 u_int i;
150
151 DIAGNOSTIC_filter_arg(arg);
152 KASSERT(arg->dstfmt->encoding == AUDIO_ENCODING_ALAW);
153 KASSERT(arg->dstfmt->stride == 8);
154 KASSERT(arg->dstfmt->precision == 8);
155 KASSERT(audio_format2_is_internal(arg->srcfmt));
156 KASSERT(arg->srcfmt->channels == arg->dstfmt->channels);
157
158 s = arg->src;
159 d = arg->dst;
160 sample_count = arg->count * arg->srcfmt->channels;
161
162 for (i = 0; i < sample_count; i++) {
163 uint8_t val;
164 val = (*s++) >> (AUDIO_INTERNAL_BITS - 8);
165 *d++ = slinear8_to_alaw[val];
166 }
167 }
168