h_pad.c revision 1.2.14.1 1 1.2.14.1 martin /* $NetBSD: h_pad.c,v 1.2.14.1 2020/04/13 08:05:22 martin Exp $ */
2 1.1 pooka
3 1.1 pooka /*
4 1.1 pooka * Copyright (c) 2010 Antti Kantee. All Rights Reserved.
5 1.1 pooka *
6 1.1 pooka * Redistribution and use in source and binary forms, with or without
7 1.1 pooka * modification, are permitted provided that the following conditions
8 1.1 pooka * are met:
9 1.1 pooka * 1. Redistributions of source code must retain the above copyright
10 1.1 pooka * notice, this list of conditions and the following disclaimer.
11 1.1 pooka * 2. Redistributions in binary form must reproduce the above copyright
12 1.1 pooka * notice, this list of conditions and the following disclaimer in the
13 1.1 pooka * documentation and/or other materials provided with the distribution.
14 1.1 pooka *
15 1.1 pooka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16 1.1 pooka * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 1.1 pooka * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 1.1 pooka * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 1.1 pooka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 1.1 pooka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 1.1 pooka * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 1.1 pooka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 1.1 pooka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 1.1 pooka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 1.1 pooka * SUCH DAMAGE.
26 1.1 pooka */
27 1.1 pooka
28 1.1 pooka #include <sys/types.h>
29 1.1 pooka
30 1.1 pooka #include <rump/rump.h>
31 1.1 pooka #include <rump/rump_syscalls.h>
32 1.1 pooka
33 1.1 pooka #include <err.h>
34 1.1 pooka #include <fcntl.h>
35 1.2.14.1 martin #include <stdbool.h>
36 1.1 pooka #include <stdio.h>
37 1.1 pooka #include <stdlib.h>
38 1.1 pooka #include <string.h>
39 1.1 pooka #include <unistd.h>
40 1.2.14.1 martin #include <sys/audioio.h>
41 1.1 pooka
42 1.1 pooka #include "h_pad_musa.c"
43 1.1 pooka
44 1.1 pooka /*
45 1.2.14.1 martin * Stuff some audio into /dev/audio, read it from /dev/pad.
46 1.1 pooka */
47 1.1 pooka
48 1.1 pooka #define BUFSIZE 1024
49 1.1 pooka
50 1.2.14.1 martin static const int16_t mulaw_to_slinear16[256] = {
51 1.2.14.1 martin 0x8284, 0x8684, 0x8a84, 0x8e84, 0x9284, 0x9684, 0x9a84, 0x9e84,
52 1.2.14.1 martin 0xa284, 0xa684, 0xaa84, 0xae84, 0xb284, 0xb684, 0xba84, 0xbe84,
53 1.2.14.1 martin 0xc184, 0xc384, 0xc584, 0xc784, 0xc984, 0xcb84, 0xcd84, 0xcf84,
54 1.2.14.1 martin 0xd184, 0xd384, 0xd584, 0xd784, 0xd984, 0xdb84, 0xdd84, 0xdf84,
55 1.2.14.1 martin 0xe104, 0xe204, 0xe304, 0xe404, 0xe504, 0xe604, 0xe704, 0xe804,
56 1.2.14.1 martin 0xe904, 0xea04, 0xeb04, 0xec04, 0xed04, 0xee04, 0xef04, 0xf004,
57 1.2.14.1 martin 0xf0c4, 0xf144, 0xf1c4, 0xf244, 0xf2c4, 0xf344, 0xf3c4, 0xf444,
58 1.2.14.1 martin 0xf4c4, 0xf544, 0xf5c4, 0xf644, 0xf6c4, 0xf744, 0xf7c4, 0xf844,
59 1.2.14.1 martin 0xf8a4, 0xf8e4, 0xf924, 0xf964, 0xf9a4, 0xf9e4, 0xfa24, 0xfa64,
60 1.2.14.1 martin 0xfaa4, 0xfae4, 0xfb24, 0xfb64, 0xfba4, 0xfbe4, 0xfc24, 0xfc64,
61 1.2.14.1 martin 0xfc94, 0xfcb4, 0xfcd4, 0xfcf4, 0xfd14, 0xfd34, 0xfd54, 0xfd74,
62 1.2.14.1 martin 0xfd94, 0xfdb4, 0xfdd4, 0xfdf4, 0xfe14, 0xfe34, 0xfe54, 0xfe74,
63 1.2.14.1 martin 0xfe8c, 0xfe9c, 0xfeac, 0xfebc, 0xfecc, 0xfedc, 0xfeec, 0xfefc,
64 1.2.14.1 martin 0xff0c, 0xff1c, 0xff2c, 0xff3c, 0xff4c, 0xff5c, 0xff6c, 0xff7c,
65 1.2.14.1 martin 0xff88, 0xff90, 0xff98, 0xffa0, 0xffa8, 0xffb0, 0xffb8, 0xffc0,
66 1.2.14.1 martin 0xffc8, 0xffd0, 0xffd8, 0xffe0, 0xffe8, 0xfff0, 0xfff8, 0xfffc,
67 1.2.14.1 martin 0x7d7c, 0x797c, 0x757c, 0x717c, 0x6d7c, 0x697c, 0x657c, 0x617c,
68 1.2.14.1 martin 0x5d7c, 0x597c, 0x557c, 0x517c, 0x4d7c, 0x497c, 0x457c, 0x417c,
69 1.2.14.1 martin 0x3e7c, 0x3c7c, 0x3a7c, 0x387c, 0x367c, 0x347c, 0x327c, 0x307c,
70 1.2.14.1 martin 0x2e7c, 0x2c7c, 0x2a7c, 0x287c, 0x267c, 0x247c, 0x227c, 0x207c,
71 1.2.14.1 martin 0x1efc, 0x1dfc, 0x1cfc, 0x1bfc, 0x1afc, 0x19fc, 0x18fc, 0x17fc,
72 1.2.14.1 martin 0x16fc, 0x15fc, 0x14fc, 0x13fc, 0x12fc, 0x11fc, 0x10fc, 0x0ffc,
73 1.2.14.1 martin 0x0f3c, 0x0ebc, 0x0e3c, 0x0dbc, 0x0d3c, 0x0cbc, 0x0c3c, 0x0bbc,
74 1.2.14.1 martin 0x0b3c, 0x0abc, 0x0a3c, 0x09bc, 0x093c, 0x08bc, 0x083c, 0x07bc,
75 1.2.14.1 martin 0x075c, 0x071c, 0x06dc, 0x069c, 0x065c, 0x061c, 0x05dc, 0x059c,
76 1.2.14.1 martin 0x055c, 0x051c, 0x04dc, 0x049c, 0x045c, 0x041c, 0x03dc, 0x039c,
77 1.2.14.1 martin 0x036c, 0x034c, 0x032c, 0x030c, 0x02ec, 0x02cc, 0x02ac, 0x028c,
78 1.2.14.1 martin 0x026c, 0x024c, 0x022c, 0x020c, 0x01ec, 0x01cc, 0x01ac, 0x018c,
79 1.2.14.1 martin 0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104,
80 1.2.14.1 martin 0x00f4, 0x00e4, 0x00d4, 0x00c4, 0x00b4, 0x00a4, 0x0094, 0x0084,
81 1.2.14.1 martin 0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040,
82 1.2.14.1 martin 0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000,
83 1.2.14.1 martin };
84 1.2.14.1 martin
85 1.2.14.1 martin #define DPRINTF(n, fmt...) do { \
86 1.2.14.1 martin if (debug >= (n)) \
87 1.2.14.1 martin printf(fmt); \
88 1.2.14.1 martin } while (0)
89 1.2.14.1 martin
90 1.2.14.1 martin int debug;
91 1.2.14.1 martin
92 1.1 pooka int
93 1.1 pooka main(int argc, char *argv[])
94 1.1 pooka {
95 1.2.14.1 martin struct audio_info ai;
96 1.1 pooka int padfd, audiofd;
97 1.1 pooka ssize_t n;
98 1.2.14.1 martin int i;
99 1.2.14.1 martin int nframe;
100 1.2.14.1 martin int outlen;
101 1.2.14.1 martin uint32_t *outbuf;
102 1.2.14.1 martin uint32_t *outp;
103 1.2.14.1 martin int inplen;
104 1.2.14.1 martin uint32_t *inpbuf;
105 1.2.14.1 martin uint32_t actual;
106 1.2.14.1 martin uint32_t expected;
107 1.2.14.1 martin int c;
108 1.2.14.1 martin enum {
109 1.2.14.1 martin PRE,
110 1.2.14.1 martin BODY,
111 1.2.14.1 martin POST,
112 1.2.14.1 martin } phase;
113 1.2.14.1 martin
114 1.2.14.1 martin while ((c = getopt(argc, argv, "d")) != -1) {
115 1.2.14.1 martin switch (c) {
116 1.2.14.1 martin case 'd':
117 1.2.14.1 martin debug++;
118 1.2.14.1 martin break;
119 1.2.14.1 martin default:
120 1.2.14.1 martin errx(1, "unknown option");
121 1.2.14.1 martin }
122 1.2.14.1 martin }
123 1.1 pooka
124 1.2.14.1 martin /* Make input buffer (and it is also expected data). */
125 1.2.14.1 martin inplen = sizeof(musa) * 4;
126 1.2.14.1 martin inpbuf = (uint32_t *)malloc(inplen);
127 1.2.14.1 martin if (inpbuf == NULL)
128 1.2.14.1 martin err(1, "malloc: inpbuf");
129 1.2.14.1 martin
130 1.2.14.1 martin /* mulaw:mono to slinear_le16:stereo */
131 1.2.14.1 martin for (i = 0; i < (int)sizeof(musa); i++) {
132 1.2.14.1 martin int16_t s = mulaw_to_slinear16[musa[i]];
133 1.2.14.1 martin uint32_t v = htole16((uint16_t)s);
134 1.2.14.1 martin inpbuf[i] = (v << 16) | v;
135 1.2.14.1 martin }
136 1.2.14.1 martin
137 1.2.14.1 martin outlen = BUFSIZE;
138 1.2.14.1 martin outbuf = (uint32_t *)malloc(outlen);
139 1.2.14.1 martin if (outbuf == NULL)
140 1.2.14.1 martin err(1, "malloc: outbuf");
141 1.2.14.1 martin
142 1.2.14.1 martin DPRINTF(1, "init\n");
143 1.1 pooka rump_init();
144 1.2 nat padfd = rump_sys_open("/dev/pad0", O_RDONLY);
145 1.2 nat if (padfd == -1)
146 1.2 nat err(1, "open pad");
147 1.2 nat
148 1.1 pooka audiofd = rump_sys_open("/dev/audio0", O_RDWR);
149 1.1 pooka if (audiofd == -1)
150 1.1 pooka err(1, "open audio");
151 1.1 pooka
152 1.2.14.1 martin DPRINTF(1, "ioctl\n");
153 1.2.14.1 martin /* pad is SLINEAR_LE, 16bit, 2ch, 44100Hz. */
154 1.2.14.1 martin AUDIO_INITINFO(&ai);
155 1.2.14.1 martin ai.play.encoding = AUDIO_ENCODING_SLINEAR_LE;
156 1.2.14.1 martin ai.play.precision = 16;
157 1.2.14.1 martin ai.play.channels = 2;
158 1.2.14.1 martin ai.play.sample_rate = 44100;
159 1.2.14.1 martin n = rump_sys_ioctl(audiofd, AUDIO_SETINFO, &ai);
160 1.2.14.1 martin if (n == -1)
161 1.2.14.1 martin err(1, "ioctl");
162 1.2.14.1 martin
163 1.2.14.1 martin DPRINTF(1, "write %d\n", inplen);
164 1.2.14.1 martin n = rump_sys_write(audiofd, inpbuf, inplen);
165 1.2.14.1 martin if (n == -1)
166 1.1 pooka err(1, "write");
167 1.2.14.1 martin if (n != inplen)
168 1.2.14.1 martin errx(1, "write: n=%zd < %d", n, inplen);
169 1.1 pooka
170 1.2.14.1 martin phase = PRE;
171 1.2.14.1 martin i = 0;
172 1.2.14.1 martin nframe = 0;
173 1.2.14.1 martin outp = NULL;
174 1.2.14.1 martin for (;;) {
175 1.2.14.1 martin /* Read to outbuf when it is empty. */
176 1.2.14.1 martin if (nframe == 0) {
177 1.2.14.1 martin n = rump_sys_read(padfd, outbuf, outlen);
178 1.2.14.1 martin if (n == -1)
179 1.2.14.1 martin err(1, "read");
180 1.2.14.1 martin if (n == 0)
181 1.2.14.1 martin errx(1, "read: EOF");
182 1.2.14.1 martin /* XXX Should I recover from this? */
183 1.2.14.1 martin if (n % 4 != 0)
184 1.2.14.1 martin errx(1, "read: n=%zd", n);
185 1.2.14.1 martin
186 1.2.14.1 martin nframe = n / 4;
187 1.2.14.1 martin outp = outbuf;
188 1.2.14.1 martin }
189 1.2.14.1 martin
190 1.2.14.1 martin if (phase == PRE) {
191 1.2.14.1 martin /* Skip preceding silence part. */
192 1.2.14.1 martin if (*outp == 0) {
193 1.2.14.1 martin outp++;
194 1.2.14.1 martin nframe--;
195 1.2.14.1 martin } else {
196 1.2.14.1 martin /* This is the first frame. */
197 1.2.14.1 martin phase = BODY;
198 1.2.14.1 martin }
199 1.2.14.1 martin } else if (phase == BODY) {
200 1.2.14.1 martin /* Compare wavedata. */
201 1.2.14.1 martin expected = le32dec(outp);
202 1.2.14.1 martin actual = le32dec(inpbuf + i);
203 1.2.14.1 martin DPRINTF(2, "[%d] %08x %08x\n", i, actual, expected);
204 1.2.14.1 martin if (actual != expected) {
205 1.2.14.1 martin errx(1, "bad output [%d] %08x %08x",
206 1.2.14.1 martin i, actual, expected);
207 1.2.14.1 martin }
208 1.2.14.1 martin outp++;
209 1.2.14.1 martin nframe--;
210 1.2.14.1 martin i++;
211 1.2.14.1 martin if (i >= (int)sizeof(musa)) {
212 1.2.14.1 martin phase = POST;
213 1.2.14.1 martin i = 0;
214 1.2.14.1 martin }
215 1.2.14.1 martin } else if (phase == POST) {
216 1.2.14.1 martin /*
217 1.2.14.1 martin * There is no way to determine the end of playback.
218 1.2.14.1 martin * Therefore it detects and terminates with some
219 1.2.14.1 martin * continuous silence.
220 1.2.14.1 martin */
221 1.2.14.1 martin actual = le32dec(outp);
222 1.2.14.1 martin if (actual != 0)
223 1.2.14.1 martin errx(1, "bad post output: %08x", actual);
224 1.2.14.1 martin outp++;
225 1.2.14.1 martin nframe--;
226 1.2.14.1 martin i++;
227 1.2.14.1 martin if (i >= (int)ai.play.sample_rate / 100)
228 1.2.14.1 martin break;
229 1.2.14.1 martin }
230 1.1 pooka }
231 1.2.14.1 martin DPRINTF(1, "success\n");
232 1.2.14.1 martin return 0;
233 1.1 pooka }
234