1/* $NetBSD: mulaw.c,v 1.28 2011/11/23 23:07:31 jmcneill Exp $ */
2
3/*
4 * Copyright (c) 1991-1993 Regents of the University of California.
5 * 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 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by the Computer Systems
18 * Engineering Group at Lawrence Berkeley Laboratory.
19 * 4. Neither the name of the University nor of the Laboratory may be used
20 * to endorse or promote products derived from this software without
21 * specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 */
36
37#include <sys/cdefs.h>
38__KERNEL_RCSID(0, "$NetBSD: mulaw.c,v 1.28 2011/11/23 23:07:31 jmcneill Exp $");
39
40#include <sys/types.h>
41#include <sys/systm.h>
42#include <sys/device.h>
43#include <dev/auconv.h>
44#include <dev/mulaw.h>
45
46/* #define MULAW_DEBUG */
47#ifdef MULAW_DEBUG
48# define DPRINTF(x) printf x
49#else
50# define DPRINTF(x)
51#endif
52
53/*
54 * This table converts a (8 bit) mu-law value to a 16 bit value.
55 * The 16 bits are represented as an array of two bytes for easier access
56 * to the individual bytes.
57 */
58static const uint8_t mulawtolin16[256][2] = {
59 {0x02,0x84}, {0x06,0x84}, {0x0a,0x84}, {0x0e,0x84},
60 {0x12,0x84}, {0x16,0x84}, {0x1a,0x84}, {0x1e,0x84},
61 {0x22,0x84}, {0x26,0x84}, {0x2a,0x84}, {0x2e,0x84},
62 {0x32,0x84}, {0x36,0x84}, {0x3a,0x84}, {0x3e,0x84},
63 {0x41,0x84}, {0x43,0x84}, {0x45,0x84}, {0x47,0x84},
64 {0x49,0x84}, {0x4b,0x84}, {0x4d,0x84}, {0x4f,0x84},
65 {0x51,0x84}, {0x53,0x84}, {0x55,0x84}, {0x57,0x84},
66 {0x59,0x84}, {0x5b,0x84}, {0x5d,0x84}, {0x5f,0x84},
67 {0x61,0x04}, {0x62,0x04}, {0x63,0x04}, {0x64,0x04},
68 {0x65,0x04}, {0x66,0x04}, {0x67,0x04}, {0x68,0x04},
69 {0x69,0x04}, {0x6a,0x04}, {0x6b,0x04}, {0x6c,0x04},
70 {0x6d,0x04}, {0x6e,0x04}, {0x6f,0x04}, {0x70,0x04},
71 {0x70,0xc4}, {0x71,0x44}, {0x71,0xc4}, {0x72,0x44},
72 {0x72,0xc4}, {0x73,0x44}, {0x73,0xc4}, {0x74,0x44},
73 {0x74,0xc4}, {0x75,0x44}, {0x75,0xc4}, {0x76,0x44},
74 {0x76,0xc4}, {0x77,0x44}, {0x77,0xc4}, {0x78,0x44},
75 {0x78,0xa4}, {0x78,0xe4}, {0x79,0x24}, {0x79,0x64},
76 {0x79,0xa4}, {0x79,0xe4}, {0x7a,0x24}, {0x7a,0x64},
77 {0x7a,0xa4}, {0x7a,0xe4}, {0x7b,0x24}, {0x7b,0x64},
78 {0x7b,0xa4}, {0x7b,0xe4}, {0x7c,0x24}, {0x7c,0x64},
79 {0x7c,0x94}, {0x7c,0xb4}, {0x7c,0xd4}, {0x7c,0xf4},
80 {0x7d,0x14}, {0x7d,0x34}, {0x7d,0x54}, {0x7d,0x74},
81 {0x7d,0x94}, {0x7d,0xb4}, {0x7d,0xd4}, {0x7d,0xf4},
82 {0x7e,0x14}, {0x7e,0x34}, {0x7e,0x54}, {0x7e,0x74},
83 {0x7e,0x8c}, {0x7e,0x9c}, {0x7e,0xac}, {0x7e,0xbc},
84 {0x7e,0xcc}, {0x7e,0xdc}, {0x7e,0xec}, {0x7e,0xfc},
85 {0x7f,0x0c}, {0x7f,0x1c}, {0x7f,0x2c}, {0x7f,0x3c},
86 {0x7f,0x4c}, {0x7f,0x5c}, {0x7f,0x6c}, {0x7f,0x7c},
87 {0x7f,0x88}, {0x7f,0x90}, {0x7f,0x98}, {0x7f,0xa0},
88 {0x7f,0xa8}, {0x7f,0xb0}, {0x7f,0xb8}, {0x7f,0xc0},
89 {0x7f,0xc8}, {0x7f,0xd0}, {0x7f,0xd8}, {0x7f,0xe0},
90 {0x7f,0xe8}, {0x7f,0xf0}, {0x7f,0xf8}, {0x80,0x00},
91 {0xfd,0x7c}, {0xf9,0x7c}, {0xf5,0x7c}, {0xf1,0x7c},
92 {0xed,0x7c}, {0xe9,0x7c}, {0xe5,0x7c}, {0xe1,0x7c},
93 {0xdd,0x7c}, {0xd9,0x7c}, {0xd5,0x7c}, {0xd1,0x7c},
94 {0xcd,0x7c}, {0xc9,0x7c}, {0xc5,0x7c}, {0xc1,0x7c},
95 {0xbe,0x7c}, {0xbc,0x7c}, {0xba,0x7c}, {0xb8,0x7c},
96 {0xb6,0x7c}, {0xb4,0x7c}, {0xb2,0x7c}, {0xb0,0x7c},
97 {0xae,0x7c}, {0xac,0x7c}, {0xaa,0x7c}, {0xa8,0x7c},
98 {0xa6,0x7c}, {0xa4,0x7c}, {0xa2,0x7c}, {0xa0,0x7c},
99 {0x9e,0xfc}, {0x9d,0xfc}, {0x9c,0xfc}, {0x9b,0xfc},
100 {0x9a,0xfc}, {0x99,0xfc}, {0x98,0xfc}, {0x97,0xfc},
101 {0x96,0xfc}, {0x95,0xfc}, {0x94,0xfc}, {0x93,0xfc},
102 {0x92,0xfc}, {0x91,0xfc}, {0x90,0xfc}, {0x8f,0xfc},
103 {0x8f,0x3c}, {0x8e,0xbc}, {0x8e,0x3c}, {0x8d,0xbc},
104 {0x8d,0x3c}, {0x8c,0xbc}, {0x8c,0x3c}, {0x8b,0xbc},
105 {0x8b,0x3c}, {0x8a,0xbc}, {0x8a,0x3c}, {0x89,0xbc},
106 {0x89,0x3c}, {0x88,0xbc}, {0x88,0x3c}, {0x87,0xbc},
107 {0x87,0x5c}, {0x87,0x1c}, {0x86,0xdc}, {0x86,0x9c},
108 {0x86,0x5c}, {0x86,0x1c}, {0x85,0xdc}, {0x85,0x9c},
109 {0x85,0x5c}, {0x85,0x1c}, {0x84,0xdc}, {0x84,0x9c},
110 {0x84,0x5c}, {0x84,0x1c}, {0x83,0xdc}, {0x83,0x9c},
111 {0x83,0x6c}, {0x83,0x4c}, {0x83,0x2c}, {0x83,0x0c},
112 {0x82,0xec}, {0x82,0xcc}, {0x82,0xac}, {0x82,0x8c},
113 {0x82,0x6c}, {0x82,0x4c}, {0x82,0x2c}, {0x82,0x0c},
114 {0x81,0xec}, {0x81,0xcc}, {0x81,0xac}, {0x81,0x8c},
115 {0x81,0x74}, {0x81,0x64}, {0x81,0x54}, {0x81,0x44},
116 {0x81,0x34}, {0x81,0x24}, {0x81,0x14}, {0x81,0x04},
117 {0x80,0xf4}, {0x80,0xe4}, {0x80,0xd4}, {0x80,0xc4},
118 {0x80,0xb4}, {0x80,0xa4}, {0x80,0x94}, {0x80,0x84},
119 {0x80,0x78}, {0x80,0x70}, {0x80,0x68}, {0x80,0x60},
120 {0x80,0x58}, {0x80,0x50}, {0x80,0x48}, {0x80,0x40},
121 {0x80,0x38}, {0x80,0x30}, {0x80,0x28}, {0x80,0x20},
122 {0x80,0x18}, {0x80,0x10}, {0x80,0x08}, {0x80,0x00},
123};
124
125static const uint8_t lintomulaw[256] = {
126 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
127 0x01, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03,
128 0x03, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05,
129 0x05, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07,
130 0x07, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09,
131 0x09, 0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b,
132 0x0b, 0x0c, 0x0c, 0x0c, 0x0c, 0x0d, 0x0d, 0x0d,
133 0x0d, 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f,
134 0x0f, 0x10, 0x10, 0x11, 0x11, 0x12, 0x12, 0x13,
135 0x13, 0x14, 0x14, 0x15, 0x15, 0x16, 0x16, 0x17,
136 0x17, 0x18, 0x18, 0x19, 0x19, 0x1a, 0x1a, 0x1b,
137 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e, 0x1f,
138 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26,
139 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e,
140 0x2f, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c,
141 0x3e, 0x41, 0x45, 0x49, 0x4d, 0x53, 0x5b, 0x67,
142 0xff, 0xe7, 0xdb, 0xd3, 0xcd, 0xc9, 0xc5, 0xc1,
143 0xbe, 0xbc, 0xba, 0xb8, 0xb6, 0xb4, 0xb2, 0xb0,
144 0xaf, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9, 0xa8,
145 0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1, 0xa0,
146 0x9f, 0x9f, 0x9e, 0x9e, 0x9d, 0x9d, 0x9c, 0x9c,
147 0x9b, 0x9b, 0x9a, 0x9a, 0x99, 0x99, 0x98, 0x98,
148 0x97, 0x97, 0x96, 0x96, 0x95, 0x95, 0x94, 0x94,
149 0x93, 0x93, 0x92, 0x92, 0x91, 0x91, 0x90, 0x90,
150 0x8f, 0x8f, 0x8f, 0x8f, 0x8e, 0x8e, 0x8e, 0x8e,
151 0x8d, 0x8d, 0x8d, 0x8d, 0x8c, 0x8c, 0x8c, 0x8c,
152 0x8b, 0x8b, 0x8b, 0x8b, 0x8a, 0x8a, 0x8a, 0x8a,
153 0x89, 0x89, 0x89, 0x89, 0x88, 0x88, 0x88, 0x88,
154 0x87, 0x87, 0x87, 0x87, 0x86, 0x86, 0x86, 0x86,
155 0x85, 0x85, 0x85, 0x85, 0x84, 0x84, 0x84, 0x84,
156 0x83, 0x83, 0x83, 0x83, 0x82, 0x82, 0x82, 0x82,
157 0x81, 0x81, 0x81, 0x81, 0x80, 0x80, 0x80, 0x80,
158};
159
160static const uint8_t alawtolin16[256][2] = {
161 {0x6a,0x80}, {0x6b,0x80}, {0x68,0x80}, {0x69,0x80},
162 {0x6e,0x80}, {0x6f,0x80}, {0x6c,0x80}, {0x6d,0x80},
163 {0x62,0x80}, {0x63,0x80}, {0x60,0x80}, {0x61,0x80},
164 {0x66,0x80}, {0x67,0x80}, {0x64,0x80}, {0x65,0x80},
165 {0x75,0x40}, {0x75,0xc0}, {0x74,0x40}, {0x74,0xc0},
166 {0x77,0x40}, {0x77,0xc0}, {0x76,0x40}, {0x76,0xc0},
167 {0x71,0x40}, {0x71,0xc0}, {0x70,0x40}, {0x70,0xc0},
168 {0x73,0x40}, {0x73,0xc0}, {0x72,0x40}, {0x72,0xc0},
169 {0x2a,0x00}, {0x2e,0x00}, {0x22,0x00}, {0x26,0x00},
170 {0x3a,0x00}, {0x3e,0x00}, {0x32,0x00}, {0x36,0x00},
171 {0x0a,0x00}, {0x0e,0x00}, {0x02,0x00}, {0x06,0x00},
172 {0x1a,0x00}, {0x1e,0x00}, {0x12,0x00}, {0x16,0x00},
173 {0x55,0x00}, {0x57,0x00}, {0x51,0x00}, {0x53,0x00},
174 {0x5d,0x00}, {0x5f,0x00}, {0x59,0x00}, {0x5b,0x00},
175 {0x45,0x00}, {0x47,0x00}, {0x41,0x00}, {0x43,0x00},
176 {0x4d,0x00}, {0x4f,0x00}, {0x49,0x00}, {0x4b,0x00},
177 {0x7e,0xa8}, {0x7e,0xb8}, {0x7e,0x88}, {0x7e,0x98},
178 {0x7e,0xe8}, {0x7e,0xf8}, {0x7e,0xc8}, {0x7e,0xd8},
179 {0x7e,0x28}, {0x7e,0x38}, {0x7e,0x08}, {0x7e,0x18},
180 {0x7e,0x68}, {0x7e,0x78}, {0x7e,0x48}, {0x7e,0x58},
181 {0x7f,0xa8}, {0x7f,0xb8}, {0x7f,0x88}, {0x7f,0x98},
182 {0x7f,0xe8}, {0x7f,0xf8}, {0x7f,0xc8}, {0x7f,0xd8},
183 {0x7f,0x28}, {0x7f,0x38}, {0x7f,0x08}, {0x7f,0x18},
184 {0x7f,0x68}, {0x7f,0x78}, {0x7f,0x48}, {0x7f,0x58},
185 {0x7a,0xa0}, {0x7a,0xe0}, {0x7a,0x20}, {0x7a,0x60},
186 {0x7b,0xa0}, {0x7b,0xe0}, {0x7b,0x20}, {0x7b,0x60},
187 {0x78,0xa0}, {0x78,0xe0}, {0x78,0x20}, {0x78,0x60},
188 {0x79,0xa0}, {0x79,0xe0}, {0x79,0x20}, {0x79,0x60},
189 {0x7d,0x50}, {0x7d,0x70}, {0x7d,0x10}, {0x7d,0x30},
190 {0x7d,0xd0}, {0x7d,0xf0}, {0x7d,0x90}, {0x7d,0xb0},
191 {0x7c,0x50}, {0x7c,0x70}, {0x7c,0x10}, {0x7c,0x30},
192 {0x7c,0xd0}, {0x7c,0xf0}, {0x7c,0x90}, {0x7c,0xb0},
193 {0x95,0x80}, {0x94,0x80}, {0x97,0x80}, {0x96,0x80},
194 {0x91,0x80}, {0x90,0x80}, {0x93,0x80}, {0x92,0x80},
195 {0x9d,0x80}, {0x9c,0x80}, {0x9f,0x80}, {0x9e,0x80},
196 {0x99,0x80}, {0x98,0x80}, {0x9b,0x80}, {0x9a,0x80},
197 {0x8a,0xc0}, {0x8a,0x40}, {0x8b,0xc0}, {0x8b,0x40},
198 {0x88,0xc0}, {0x88,0x40}, {0x89,0xc0}, {0x89,0x40},
199 {0x8e,0xc0}, {0x8e,0x40}, {0x8f,0xc0}, {0x8f,0x40},
200 {0x8c,0xc0}, {0x8c,0x40}, {0x8d,0xc0}, {0x8d,0x40},
201 {0xd6,0x00}, {0xd2,0x00}, {0xde,0x00}, {0xda,0x00},
202 {0xc6,0x00}, {0xc2,0x00}, {0xce,0x00}, {0xca,0x00},
203 {0xf6,0x00}, {0xf2,0x00}, {0xfe,0x00}, {0xfa,0x00},
204 {0xe6,0x00}, {0xe2,0x00}, {0xee,0x00}, {0xea,0x00},
205 {0xab,0x00}, {0xa9,0x00}, {0xaf,0x00}, {0xad,0x00},
206 {0xa3,0x00}, {0xa1,0x00}, {0xa7,0x00}, {0xa5,0x00},
207 {0xbb,0x00}, {0xb9,0x00}, {0xbf,0x00}, {0xbd,0x00},
208 {0xb3,0x00}, {0xb1,0x00}, {0xb7,0x00}, {0xb5,0x00},
209 {0x81,0x58}, {0x81,0x48}, {0x81,0x78}, {0x81,0x68},
210 {0x81,0x18}, {0x81,0x08}, {0x81,0x38}, {0x81,0x28},
211 {0x81,0xd8}, {0x81,0xc8}, {0x81,0xf8}, {0x81,0xe8},
212 {0x81,0x98}, {0x81,0x88}, {0x81,0xb8}, {0x81,0xa8},
213 {0x80,0x58}, {0x80,0x48}, {0x80,0x78}, {0x80,0x68},
214 {0x80,0x18}, {0x80,0x08}, {0x80,0x38}, {0x80,0x28},
215 {0x80,0xd8}, {0x80,0xc8}, {0x80,0xf8}, {0x80,0xe8},
216 {0x80,0x98}, {0x80,0x88}, {0x80,0xb8}, {0x80,0xa8},
217 {0x85,0x60}, {0x85,0x20}, {0x85,0xe0}, {0x85,0xa0},
218 {0x84,0x60}, {0x84,0x20}, {0x84,0xe0}, {0x84,0xa0},
219 {0x87,0x60}, {0x87,0x20}, {0x87,0xe0}, {0x87,0xa0},
220 {0x86,0x60}, {0x86,0x20}, {0x86,0xe0}, {0x86,0xa0},
221 {0x82,0xb0}, {0x82,0x90}, {0x82,0xf0}, {0x82,0xd0},
222 {0x82,0x30}, {0x82,0x10}, {0x82,0x70}, {0x82,0x50},
223 {0x83,0xb0}, {0x83,0x90}, {0x83,0xf0}, {0x83,0xd0},
224 {0x83,0x30}, {0x83,0x10}, {0x83,0x70}, {0x83,0x50},
225};
226
227static const uint8_t lintoalaw[256] = {
228 0x2a, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2b,
229 0x28, 0x28, 0x28, 0x28, 0x29, 0x29, 0x29, 0x29,
230 0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x2f,
231 0x2c, 0x2c, 0x2c, 0x2c, 0x2d, 0x2d, 0x2d, 0x2d,
232 0x22, 0x22, 0x22, 0x22, 0x23, 0x23, 0x23, 0x23,
233 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21, 0x21,
234 0x26, 0x26, 0x26, 0x26, 0x27, 0x27, 0x27, 0x27,
235 0x24, 0x24, 0x24, 0x24, 0x25, 0x25, 0x25, 0x25,
236 0x3a, 0x3a, 0x3b, 0x3b, 0x38, 0x38, 0x39, 0x39,
237 0x3e, 0x3e, 0x3f, 0x3f, 0x3c, 0x3c, 0x3d, 0x3d,
238 0x32, 0x32, 0x33, 0x33, 0x30, 0x30, 0x31, 0x31,
239 0x36, 0x36, 0x37, 0x37, 0x34, 0x34, 0x35, 0x35,
240 0x0a, 0x0b, 0x08, 0x09, 0x0e, 0x0f, 0x0c, 0x0d,
241 0x02, 0x03, 0x00, 0x01, 0x06, 0x07, 0x04, 0x05,
242 0x1a, 0x18, 0x1e, 0x1c, 0x12, 0x10, 0x16, 0x14,
243 0x6a, 0x6e, 0x62, 0x66, 0x7a, 0x72, 0x4a, 0x5a,
244 0xd5, 0xc5, 0xf5, 0xfd, 0xe5, 0xe1, 0xed, 0xe9,
245 0x95, 0x97, 0x91, 0x93, 0x9d, 0x9f, 0x99, 0x9b,
246 0x85, 0x84, 0x87, 0x86, 0x81, 0x80, 0x83, 0x82,
247 0x8d, 0x8c, 0x8f, 0x8e, 0x89, 0x88, 0x8b, 0x8a,
248 0xb5, 0xb5, 0xb4, 0xb4, 0xb7, 0xb7, 0xb6, 0xb6,
249 0xb1, 0xb1, 0xb0, 0xb0, 0xb3, 0xb3, 0xb2, 0xb2,
250 0xbd, 0xbd, 0xbc, 0xbc, 0xbf, 0xbf, 0xbe, 0xbe,
251 0xb9, 0xb9, 0xb8, 0xb8, 0xbb, 0xbb, 0xba, 0xba,
252 0xa5, 0xa5, 0xa5, 0xa5, 0xa4, 0xa4, 0xa4, 0xa4,
253 0xa7, 0xa7, 0xa7, 0xa7, 0xa6, 0xa6, 0xa6, 0xa6,
254 0xa1, 0xa1, 0xa1, 0xa1, 0xa0, 0xa0, 0xa0, 0xa0,
255 0xa3, 0xa3, 0xa3, 0xa3, 0xa2, 0xa2, 0xa2, 0xa2,
256 0xad, 0xad, 0xad, 0xad, 0xac, 0xac, 0xac, 0xac,
257 0xaf, 0xaf, 0xaf, 0xaf, 0xae, 0xae, 0xae, 0xae,
258 0xa9, 0xa9, 0xa9, 0xa9, 0xa8, 0xa8, 0xa8, 0xa8,
259 0xab, 0xab, 0xab, 0xab, 0xaa, 0xaa, 0xaa, 0xaa,
260};
261
262#define DEFINE_FILTER(name) \
263static int \
264name##_fetch_to(struct audio_softc *, stream_fetcher_t *, audio_stream_t *, int); \
265stream_filter_t * \
266name(struct audio_softc *sc, const audio_params_t *from, \
267 const audio_params_t *to) \
268{ \
269 DPRINTF(("Construct '%s' filter.\n", __func__)); \
270 return auconv_nocontext_filter_factory(name##_fetch_to); \
271} \
272static int \
273name##_fetch_to(struct audio_softc *sc, stream_fetcher_t *self, \
274 audio_stream_t *dst, int max_used)
275
276DEFINE_FILTER(mulaw_to_linear8)
277{
278 stream_filter_t *this;
279 int m, err;
280
281 this = (stream_filter_t *)self;
282 if ((err = this->prev->fetch_to(sc, this->prev, this->src, max_used)))
283 return err;
284 m = dst->end - dst->start;
285 m = min(m, max_used);
286 if (dst->param.encoding == AUDIO_ENCODING_ULINEAR_LE) {
287 FILTER_LOOP_PROLOGUE(this->src, 1, dst, 1, m) {
288 *d = mulawtolin16[*s][0];
289 } FILTER_LOOP_EPILOGUE(this->src, dst);
290 } else {
291 FILTER_LOOP_PROLOGUE(this->src, 1, dst, 1, m) {
292 *d = mulawtolin16[*s][0] ^ 0x80;
293 } FILTER_LOOP_EPILOGUE(this->src, dst);
294 }
295 return 0;
296}
297
298DEFINE_FILTER(mulaw_to_linear16)
299{
300 stream_filter_t *this;
301 int m, err;
302
303 this = (stream_filter_t *)self;
304 max_used = (max_used + 1) & ~1; /* round up to even */
305 if ((err = this->prev->fetch_to(sc, this->prev, this->src, max_used / 2)))
306 return err;
307 m = (dst->end - dst->start) & ~1;
308 m = min(m, max_used);
309 switch (dst->param.encoding) {
310 case AUDIO_ENCODING_ULINEAR_LE:
311 FILTER_LOOP_PROLOGUE(this->src, 1, dst, 2, m) {
312 d[0] = mulawtolin16[s[0]][1];
313 d[1] = mulawtolin16[s[0]][0];
314 } FILTER_LOOP_EPILOGUE(this->src, dst);
315 break;
316 case AUDIO_ENCODING_ULINEAR_BE:
317 FILTER_LOOP_PROLOGUE(this->src, 1, dst, 2, m) {
318 d[0] = mulawtolin16[s[0]][0];
319 d[1] = mulawtolin16[s[0]][1];
320 } FILTER_LOOP_EPILOGUE(this->src, dst);
321 break;
322 case AUDIO_ENCODING_SLINEAR_LE:
323 FILTER_LOOP_PROLOGUE(this->src, 1, dst, 2, m) {
324 d[0] = mulawtolin16[s[0]][1];
325 d[1] = mulawtolin16[s[0]][0] ^ 0x80;
326 } FILTER_LOOP_EPILOGUE(this->src, dst);
327 break;
328 case AUDIO_ENCODING_SLINEAR_BE:
329 FILTER_LOOP_PROLOGUE(this->src, 1, dst, 2, m) {
330 d[0] = mulawtolin16[s[0]][0] ^ 0x80;
331 d[1] = mulawtolin16[s[0]][1];
332 } FILTER_LOOP_EPILOGUE(this->src, dst);
333 break;
334 }
335 return 0;
336}
337
338DEFINE_FILTER(linear16_to_mulaw)
339{
340 stream_filter_t *this;
341 int m, err;
342
343 this = (stream_filter_t *)self;
344 if ((err = this->prev->fetch_to(sc, this->prev, this->src, max_used * 2)))
345 return err;
346 m = dst->end - dst->start;
347 m = min(m, max_used);
348 switch (this->src->param.encoding) {
349 case AUDIO_ENCODING_SLINEAR_LE:
350 FILTER_LOOP_PROLOGUE(this->src, 2, dst, 1, m) {
351 d[0] = lintomulaw[s[1] ^ 0x80];
352 } FILTER_LOOP_EPILOGUE(this->src, dst);
353 break;
354 case AUDIO_ENCODING_SLINEAR_BE:
355 FILTER_LOOP_PROLOGUE(this->src, 2, dst, 1, m) {
356 d[0] = lintomulaw[s[0] ^ 0x80];
357 } FILTER_LOOP_EPILOGUE(this->src, dst);
358 break;
359 case AUDIO_ENCODING_ULINEAR_LE:
360 FILTER_LOOP_PROLOGUE(this->src, 2, dst, 1, m) {
361 d[0] = lintomulaw[s[1]];
362 } FILTER_LOOP_EPILOGUE(this->src, dst);
363 break;
364 case AUDIO_ENCODING_ULINEAR_BE:
365 FILTER_LOOP_PROLOGUE(this->src, 2, dst, 1, m) {
366 d[0] = lintomulaw[s[0]];
367 } FILTER_LOOP_EPILOGUE(this->src, dst);
368 break;
369 }
370 return 0;
371}
372
373DEFINE_FILTER(linear8_to_mulaw)
374{
375 stream_filter_t *this;
376 int m, err;
377
378 this = (stream_filter_t *)self;
379 if ((err = this->prev->fetch_to(sc, this->prev, this->src, max_used)))
380 return err;
381 m = dst->end - dst->start;
382 m = min(m, max_used);
383 if (this->src->param.encoding == AUDIO_ENCODING_ULINEAR_LE) {
384 FILTER_LOOP_PROLOGUE(this->src, 1, dst, 1, m) {
385 *d = lintomulaw[*s];
386 } FILTER_LOOP_EPILOGUE(this->src, dst);
387 } else { /* SLINEAR_LE */
388 FILTER_LOOP_PROLOGUE(this->src, 1, dst, 1, m) {
389 *d = lintomulaw[*s ^ 0x80];
390 } FILTER_LOOP_EPILOGUE(this->src, dst);
391 }
392 return 0;
393}
394
395DEFINE_FILTER(alaw_to_linear8)
396{
397 stream_filter_t *this;
398 int m, err;
399
400 this = (stream_filter_t *)self;
401 if ((err = this->prev->fetch_to(sc, this->prev, this->src, max_used)))
402 return err;
403 m = dst->end - dst->start;
404 m = min(m, max_used);
405 if (dst->param.encoding == AUDIO_ENCODING_ULINEAR_LE) {
406 FILTER_LOOP_PROLOGUE(this->src, 1, dst, 1, m) {
407 *d = alawtolin16[*s][0];
408 } FILTER_LOOP_EPILOGUE(this->src, dst);
409 } else { /* SLINEAR */
410 FILTER_LOOP_PROLOGUE(this->src, 1, dst, 1, m) {
411 *d = alawtolin16[*s][0] ^ 0x80;
412 } FILTER_LOOP_EPILOGUE(this->src, dst);
413 }
414 return 0;
415}
416
417DEFINE_FILTER(alaw_to_linear16)
418{
419 stream_filter_t *this;
420 int m, err;
421
422 this = (stream_filter_t *)self;
423 max_used = (max_used + 1) & ~1; /* round up to even */
424 if ((err = this->prev->fetch_to(sc, this->prev, this->src, max_used / 2)))
425 return err;
426 m = (dst->end - dst->start) & ~1;
427 m = min(m, max_used);
428 switch (dst->param.encoding) {
429 case AUDIO_ENCODING_ULINEAR_LE:
430 FILTER_LOOP_PROLOGUE(this->src, 1, dst, 2, m) {
431 d[0] = alawtolin16[s[0]][1];
432 d[1] = alawtolin16[s[0]][0];
433 } FILTER_LOOP_EPILOGUE(this->src, dst);
434 break;
435 case AUDIO_ENCODING_ULINEAR_BE:
436 FILTER_LOOP_PROLOGUE(this->src, 1, dst, 2, m) {
437 d[0] = alawtolin16[s[0]][0];
438 d[1] = alawtolin16[s[0]][1];
439 } FILTER_LOOP_EPILOGUE(this->src, dst);
440 break;
441 case AUDIO_ENCODING_SLINEAR_LE:
442 FILTER_LOOP_PROLOGUE(this->src, 1, dst, 2, m) {
443 d[0] = alawtolin16[s[0]][1];
444 d[1] = alawtolin16[s[0]][0] ^ 0x80;
445 } FILTER_LOOP_EPILOGUE(this->src, dst);
446 break;
447 case AUDIO_ENCODING_SLINEAR_BE:
448 FILTER_LOOP_PROLOGUE(this->src, 1, dst, 2, m) {
449 d[0] = alawtolin16[s[0]][0] ^ 0x80;
450 d[1] = alawtolin16[s[0]][1];
451 } FILTER_LOOP_EPILOGUE(this->src, dst);
452 break;
453 }
454 return 0;
455}
456
457DEFINE_FILTER(linear8_to_alaw)
458{
459 stream_filter_t *this;
460 int m, err;
461
462 this = (stream_filter_t *)self;
463 if ((err = this->prev->fetch_to(sc, this->prev, this->src, max_used)))
464 return err;
465 m = dst->end - dst->start;
466 m = min(m, max_used);
467 if (this->src->param.encoding == AUDIO_ENCODING_ULINEAR_LE) {
468 FILTER_LOOP_PROLOGUE(this->src, 1, dst, 1, m) {
469 *d = lintoalaw[*s];
470 } FILTER_LOOP_EPILOGUE(this->src, dst);
471 } else { /* SLINEAR_LE */
472 FILTER_LOOP_PROLOGUE(this->src, 1, dst, 1, m) {
473 *d = lintoalaw[*s ^ 0x80];
474 } FILTER_LOOP_EPILOGUE(this->src, dst);
475 }
476 return 0;
477}
478
479DEFINE_FILTER(linear16_to_alaw)
480{
481 stream_filter_t *this;
482 int m, err;
483
484 this = (stream_filter_t *)self;
485 if ((err = this->prev->fetch_to(sc, this->prev, this->src, max_used * 2)))
486 return err;
487 m = dst->end - dst->start;
488 m = min(m, max_used);
489 switch (this->src->param.encoding) {
490 case AUDIO_ENCODING_SLINEAR_LE:
491 FILTER_LOOP_PROLOGUE(this->src, 2, dst, 1, m) {
492 d[0] = lintoalaw[s[1] ^ 0x80];
493 } FILTER_LOOP_EPILOGUE(this->src, dst);
494 break;
495 case AUDIO_ENCODING_SLINEAR_BE:
496 FILTER_LOOP_PROLOGUE(this->src, 2, dst, 1, m) {
497 d[0] = lintoalaw[s[0] ^ 0x80];
498 } FILTER_LOOP_EPILOGUE(this->src, dst);
499 break;
500 case AUDIO_ENCODING_ULINEAR_LE:
501 FILTER_LOOP_PROLOGUE(this->src, 2, dst, 1, m) {
502 d[0] = lintoalaw[s[1]];
503 } FILTER_LOOP_EPILOGUE(this->src, dst);
504 break;
505 case AUDIO_ENCODING_ULINEAR_BE:
506 FILTER_LOOP_PROLOGUE(this->src, 2, dst, 1, m) {
507 d[0] = lintoalaw[s[0]];
508 } FILTER_LOOP_EPILOGUE(this->src, dst);
509 break;
510 }
511 return 0;
512}
513