Home | History | Annotate | Line # | Download | only in audio
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