1 1.3 isaki /* $NetBSD: h_pad.c,v 1.3 2019/06/20 12:14:46 isaki 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.3 isaki #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.3 isaki #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.3 isaki * 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.3 isaki static const int16_t mulaw_to_slinear16[256] = { 51 1.3 isaki 0x8284, 0x8684, 0x8a84, 0x8e84, 0x9284, 0x9684, 0x9a84, 0x9e84, 52 1.3 isaki 0xa284, 0xa684, 0xaa84, 0xae84, 0xb284, 0xb684, 0xba84, 0xbe84, 53 1.3 isaki 0xc184, 0xc384, 0xc584, 0xc784, 0xc984, 0xcb84, 0xcd84, 0xcf84, 54 1.3 isaki 0xd184, 0xd384, 0xd584, 0xd784, 0xd984, 0xdb84, 0xdd84, 0xdf84, 55 1.3 isaki 0xe104, 0xe204, 0xe304, 0xe404, 0xe504, 0xe604, 0xe704, 0xe804, 56 1.3 isaki 0xe904, 0xea04, 0xeb04, 0xec04, 0xed04, 0xee04, 0xef04, 0xf004, 57 1.3 isaki 0xf0c4, 0xf144, 0xf1c4, 0xf244, 0xf2c4, 0xf344, 0xf3c4, 0xf444, 58 1.3 isaki 0xf4c4, 0xf544, 0xf5c4, 0xf644, 0xf6c4, 0xf744, 0xf7c4, 0xf844, 59 1.3 isaki 0xf8a4, 0xf8e4, 0xf924, 0xf964, 0xf9a4, 0xf9e4, 0xfa24, 0xfa64, 60 1.3 isaki 0xfaa4, 0xfae4, 0xfb24, 0xfb64, 0xfba4, 0xfbe4, 0xfc24, 0xfc64, 61 1.3 isaki 0xfc94, 0xfcb4, 0xfcd4, 0xfcf4, 0xfd14, 0xfd34, 0xfd54, 0xfd74, 62 1.3 isaki 0xfd94, 0xfdb4, 0xfdd4, 0xfdf4, 0xfe14, 0xfe34, 0xfe54, 0xfe74, 63 1.3 isaki 0xfe8c, 0xfe9c, 0xfeac, 0xfebc, 0xfecc, 0xfedc, 0xfeec, 0xfefc, 64 1.3 isaki 0xff0c, 0xff1c, 0xff2c, 0xff3c, 0xff4c, 0xff5c, 0xff6c, 0xff7c, 65 1.3 isaki 0xff88, 0xff90, 0xff98, 0xffa0, 0xffa8, 0xffb0, 0xffb8, 0xffc0, 66 1.3 isaki 0xffc8, 0xffd0, 0xffd8, 0xffe0, 0xffe8, 0xfff0, 0xfff8, 0xfffc, 67 1.3 isaki 0x7d7c, 0x797c, 0x757c, 0x717c, 0x6d7c, 0x697c, 0x657c, 0x617c, 68 1.3 isaki 0x5d7c, 0x597c, 0x557c, 0x517c, 0x4d7c, 0x497c, 0x457c, 0x417c, 69 1.3 isaki 0x3e7c, 0x3c7c, 0x3a7c, 0x387c, 0x367c, 0x347c, 0x327c, 0x307c, 70 1.3 isaki 0x2e7c, 0x2c7c, 0x2a7c, 0x287c, 0x267c, 0x247c, 0x227c, 0x207c, 71 1.3 isaki 0x1efc, 0x1dfc, 0x1cfc, 0x1bfc, 0x1afc, 0x19fc, 0x18fc, 0x17fc, 72 1.3 isaki 0x16fc, 0x15fc, 0x14fc, 0x13fc, 0x12fc, 0x11fc, 0x10fc, 0x0ffc, 73 1.3 isaki 0x0f3c, 0x0ebc, 0x0e3c, 0x0dbc, 0x0d3c, 0x0cbc, 0x0c3c, 0x0bbc, 74 1.3 isaki 0x0b3c, 0x0abc, 0x0a3c, 0x09bc, 0x093c, 0x08bc, 0x083c, 0x07bc, 75 1.3 isaki 0x075c, 0x071c, 0x06dc, 0x069c, 0x065c, 0x061c, 0x05dc, 0x059c, 76 1.3 isaki 0x055c, 0x051c, 0x04dc, 0x049c, 0x045c, 0x041c, 0x03dc, 0x039c, 77 1.3 isaki 0x036c, 0x034c, 0x032c, 0x030c, 0x02ec, 0x02cc, 0x02ac, 0x028c, 78 1.3 isaki 0x026c, 0x024c, 0x022c, 0x020c, 0x01ec, 0x01cc, 0x01ac, 0x018c, 79 1.3 isaki 0x0174, 0x0164, 0x0154, 0x0144, 0x0134, 0x0124, 0x0114, 0x0104, 80 1.3 isaki 0x00f4, 0x00e4, 0x00d4, 0x00c4, 0x00b4, 0x00a4, 0x0094, 0x0084, 81 1.3 isaki 0x0078, 0x0070, 0x0068, 0x0060, 0x0058, 0x0050, 0x0048, 0x0040, 82 1.3 isaki 0x0038, 0x0030, 0x0028, 0x0020, 0x0018, 0x0010, 0x0008, 0x0000, 83 1.3 isaki }; 84 1.3 isaki 85 1.3 isaki #define DPRINTF(n, fmt...) do { \ 86 1.3 isaki if (debug >= (n)) \ 87 1.3 isaki printf(fmt); \ 88 1.3 isaki } while (0) 89 1.3 isaki 90 1.3 isaki int debug; 91 1.3 isaki 92 1.1 pooka int 93 1.1 pooka main(int argc, char *argv[]) 94 1.1 pooka { 95 1.3 isaki struct audio_info ai; 96 1.1 pooka int padfd, audiofd; 97 1.1 pooka ssize_t n; 98 1.3 isaki int i; 99 1.3 isaki int nframe; 100 1.3 isaki int outlen; 101 1.3 isaki uint32_t *outbuf; 102 1.3 isaki uint32_t *outp; 103 1.3 isaki int inplen; 104 1.3 isaki uint32_t *inpbuf; 105 1.3 isaki uint32_t actual; 106 1.3 isaki uint32_t expected; 107 1.3 isaki int c; 108 1.3 isaki enum { 109 1.3 isaki PRE, 110 1.3 isaki BODY, 111 1.3 isaki POST, 112 1.3 isaki } phase; 113 1.3 isaki 114 1.3 isaki while ((c = getopt(argc, argv, "d")) != -1) { 115 1.3 isaki switch (c) { 116 1.3 isaki case 'd': 117 1.3 isaki debug++; 118 1.3 isaki break; 119 1.3 isaki default: 120 1.3 isaki errx(1, "unknown option"); 121 1.3 isaki } 122 1.3 isaki } 123 1.1 pooka 124 1.3 isaki /* Make input buffer (and it is also expected data). */ 125 1.3 isaki inplen = sizeof(musa) * 4; 126 1.3 isaki inpbuf = (uint32_t *)malloc(inplen); 127 1.3 isaki if (inpbuf == NULL) 128 1.3 isaki err(1, "malloc: inpbuf"); 129 1.3 isaki 130 1.3 isaki /* mulaw:mono to slinear_le16:stereo */ 131 1.3 isaki for (i = 0; i < (int)sizeof(musa); i++) { 132 1.3 isaki int16_t s = mulaw_to_slinear16[musa[i]]; 133 1.3 isaki uint32_t v = htole16((uint16_t)s); 134 1.3 isaki inpbuf[i] = (v << 16) | v; 135 1.3 isaki } 136 1.3 isaki 137 1.3 isaki outlen = BUFSIZE; 138 1.3 isaki outbuf = (uint32_t *)malloc(outlen); 139 1.3 isaki if (outbuf == NULL) 140 1.3 isaki err(1, "malloc: outbuf"); 141 1.3 isaki 142 1.3 isaki 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.3 isaki DPRINTF(1, "ioctl\n"); 153 1.3 isaki /* pad is SLINEAR_LE, 16bit, 2ch, 44100Hz. */ 154 1.3 isaki AUDIO_INITINFO(&ai); 155 1.3 isaki ai.play.encoding = AUDIO_ENCODING_SLINEAR_LE; 156 1.3 isaki ai.play.precision = 16; 157 1.3 isaki ai.play.channels = 2; 158 1.3 isaki ai.play.sample_rate = 44100; 159 1.3 isaki n = rump_sys_ioctl(audiofd, AUDIO_SETINFO, &ai); 160 1.3 isaki if (n == -1) 161 1.3 isaki err(1, "ioctl"); 162 1.3 isaki 163 1.3 isaki DPRINTF(1, "write %d\n", inplen); 164 1.3 isaki n = rump_sys_write(audiofd, inpbuf, inplen); 165 1.3 isaki if (n == -1) 166 1.1 pooka err(1, "write"); 167 1.3 isaki if (n != inplen) 168 1.3 isaki errx(1, "write: n=%zd < %d", n, inplen); 169 1.1 pooka 170 1.3 isaki phase = PRE; 171 1.3 isaki i = 0; 172 1.3 isaki nframe = 0; 173 1.3 isaki outp = NULL; 174 1.3 isaki for (;;) { 175 1.3 isaki /* Read to outbuf when it is empty. */ 176 1.3 isaki if (nframe == 0) { 177 1.3 isaki n = rump_sys_read(padfd, outbuf, outlen); 178 1.3 isaki if (n == -1) 179 1.3 isaki err(1, "read"); 180 1.3 isaki if (n == 0) 181 1.3 isaki errx(1, "read: EOF"); 182 1.3 isaki /* XXX Should I recover from this? */ 183 1.3 isaki if (n % 4 != 0) 184 1.3 isaki errx(1, "read: n=%zd", n); 185 1.3 isaki 186 1.3 isaki nframe = n / 4; 187 1.3 isaki outp = outbuf; 188 1.3 isaki } 189 1.3 isaki 190 1.3 isaki if (phase == PRE) { 191 1.3 isaki /* Skip preceding silence part. */ 192 1.3 isaki if (*outp == 0) { 193 1.3 isaki outp++; 194 1.3 isaki nframe--; 195 1.3 isaki } else { 196 1.3 isaki /* This is the first frame. */ 197 1.3 isaki phase = BODY; 198 1.3 isaki } 199 1.3 isaki } else if (phase == BODY) { 200 1.3 isaki /* Compare wavedata. */ 201 1.3 isaki expected = le32dec(outp); 202 1.3 isaki actual = le32dec(inpbuf + i); 203 1.3 isaki DPRINTF(2, "[%d] %08x %08x\n", i, actual, expected); 204 1.3 isaki if (actual != expected) { 205 1.3 isaki errx(1, "bad output [%d] %08x %08x", 206 1.3 isaki i, actual, expected); 207 1.3 isaki } 208 1.3 isaki outp++; 209 1.3 isaki nframe--; 210 1.3 isaki i++; 211 1.3 isaki if (i >= (int)sizeof(musa)) { 212 1.3 isaki phase = POST; 213 1.3 isaki i = 0; 214 1.3 isaki } 215 1.3 isaki } else if (phase == POST) { 216 1.3 isaki /* 217 1.3 isaki * There is no way to determine the end of playback. 218 1.3 isaki * Therefore it detects and terminates with some 219 1.3 isaki * continuous silence. 220 1.3 isaki */ 221 1.3 isaki actual = le32dec(outp); 222 1.3 isaki if (actual != 0) 223 1.3 isaki errx(1, "bad post output: %08x", actual); 224 1.3 isaki outp++; 225 1.3 isaki nframe--; 226 1.3 isaki i++; 227 1.3 isaki if (i >= (int)ai.play.sample_rate / 100) 228 1.3 isaki break; 229 1.3 isaki } 230 1.1 pooka } 231 1.3 isaki DPRINTF(1, "success\n"); 232 1.3 isaki return 0; 233 1.1 pooka } 234