285 lines
5.8 KiB
Text
285 lines
5.8 KiB
Text
$NetBSD: patch-bb,v 1.2 1998/08/07 10:36:06 agc Exp $
|
|
|
|
*** /dev/null Fri Mar 6 05:54:22 1998
|
|
--- dacio-netbsd.c Fri Mar 6 06:51:04 1998
|
|
***************
|
|
*** 0 ****
|
|
--- 1,278 ----
|
|
+ #include <stdio.h> /*(perror)*/
|
|
+ #include <fcntl.h> /*O_WRONLY*/
|
|
+ #include <sys/ioctl.h> /*(ioctl)*/
|
|
+ #include <string.h> /*(memset)*/
|
|
+ #include <unistd.h> /*(write)*/
|
|
+ #include <sys/audioio.h> /*SNDCTL_XXX*/
|
|
+ #include <errno.h> /*EINTR*/
|
|
+ #include "defs.h" /*u8,u16*/
|
|
+ #include "dacio.h" /*(dacioXXX)*/
|
|
+ #include "mem.h" /*(memPerm)*/
|
|
+
|
|
+ #if 0
|
|
+ #define LIM_SIZE (32 * 256) /* 32ch * 8bit */
|
|
+
|
|
+ static u8 *lim;
|
|
+
|
|
+ static void
|
|
+ makeLim(void)
|
|
+ {
|
|
+ u8 *p;
|
|
+ i15x i;
|
|
+
|
|
+ lim = (u8 *)memPerm(LIM_SIZE) + LIM_SIZE/2;
|
|
+ p = lim-128;
|
|
+ for (i = 0; i < 256; i++, p++) *p = i;
|
|
+ for (; p < lim + LIM_SIZE/2; p++) *p = 255;
|
|
+ }
|
|
+ #endif
|
|
+
|
|
+ static int fd;
|
|
+
|
|
+ #ifndef DAC_DEV
|
|
+ #define DAC_DEV "/dev/audio"
|
|
+ #endif
|
|
+
|
|
+ void
|
|
+ dacioInit(void)
|
|
+ {
|
|
+ fd = open(DAC_DEV, O_WRONLY);
|
|
+ if (fd < 0) {
|
|
+ perror("dacioInit");
|
|
+ exit(1);
|
|
+ }
|
|
+ /*makeLim();*/
|
|
+ }
|
|
+
|
|
+ static struct {
|
|
+ union {
|
|
+ u8 *p8;
|
|
+ i15 *p16;
|
|
+ } p;
|
|
+ u8 *top;
|
|
+ u8 *bot;
|
|
+ int size;
|
|
+ int shift;
|
|
+ } buf;
|
|
+
|
|
+ #define bufRest() ((buf.bot - buf.p.p8) >> buf.shift)
|
|
+
|
|
+ static DacioConfInfo dci;
|
|
+
|
|
+ void
|
|
+ dacioConf(DacioConfInfo *dcp)
|
|
+ {
|
|
+ audio_info_t info;
|
|
+
|
|
+ #if 0
|
|
+ if (ioctl(fd, AUDIO_FLUSH, 0) < 0) {
|
|
+ perror("dacioConf");
|
|
+ exit(1);
|
|
+ }
|
|
+ #endif
|
|
+ AUDIO_INITINFO(&info);
|
|
+ info.play.encoding = AUDIO_ENCODING_LINEAR;
|
|
+ info.play.precision = dcp->bits;
|
|
+ info.play.channels = dcp->stereo ? 2 : 1;
|
|
+ info.play.sample_rate = dcp->speed;
|
|
+ if (ioctl(fd, AUDIO_SETINFO, &info) < 0) {
|
|
+ perror("dacioConf");
|
|
+ exit(1);
|
|
+ }
|
|
+ /*fprintf(stderr, "fmt = 0x%x\n", tmp);*/
|
|
+
|
|
+ if (ioctl(fd, AUDIO_GETINFO, &info) < 0) {
|
|
+ perror("dacioConf");
|
|
+ exit(1);
|
|
+ }
|
|
+ buf.size = info.play.buffer_size;
|
|
+ /*fprintf(stderr, "buffer size = 0x%x\n", buf.size);*/
|
|
+ dci = *dcp;
|
|
+ /*if (buf.top != NULL) free(buf.top);*/
|
|
+ buf.top = memPerm(buf.size);
|
|
+ buf.p.p8 = buf.top;
|
|
+ buf.bot = buf.top + buf.size;
|
|
+ buf.shift = dci.stereo + ffs(dci.bits / 8) - 1;
|
|
+ }
|
|
+
|
|
+ void
|
|
+ dacioSync(void)
|
|
+ {
|
|
+ if (ioctl(fd, AUDIO_DRAIN, 0) < 0) {
|
|
+ perror("dacioSync");
|
|
+ exit(1);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* OS independent part (?) */
|
|
+
|
|
+ void
|
|
+ dacioFlush(void)
|
|
+ {
|
|
+ i15x n;
|
|
+ u8 *u8p;
|
|
+ i15 *i15p;
|
|
+ int s;
|
|
+
|
|
+ if (buf.p.p8 <= buf.top) return;
|
|
+
|
|
+ n = bufRest() << dci.stereo;
|
|
+ switch (dci.bits) {
|
|
+ case 8:
|
|
+ u8p = buf.p.p8;
|
|
+ for (; n > 0; n--)
|
|
+ *u8p++ = 128;
|
|
+ buf.p.p8 = u8p;
|
|
+ break;
|
|
+ case 16:
|
|
+ i15p = buf.p.p16;
|
|
+ for (; n > 0; n--)
|
|
+ *i15p++ = 0;
|
|
+ buf.p.p16 = i15p;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ RETRY:
|
|
+ s = write(fd, buf.top, buf.size);
|
|
+ if (s < buf.size) {
|
|
+ if (s < 0) {
|
|
+ if (errno == EINTR) goto RETRY;
|
|
+ perror("dacioFlush");
|
|
+ } else fprintf(stderr, "wrote only %d bytes\n", s);
|
|
+ exit(1);
|
|
+ }
|
|
+ buf.p.p8 = buf.top;
|
|
+ }
|
|
+
|
|
+ static struct {
|
|
+ const i31 *p0;
|
|
+ const i31 *p;
|
|
+ i15x len;
|
|
+ } inbuf;
|
|
+
|
|
+ void
|
|
+ dacioIncomingBuf(const i31 *bp)
|
|
+ {
|
|
+ inbuf.p0 = bp;
|
|
+ }
|
|
+
|
|
+ void
|
|
+ dacioIncomingBufLen(i15x len)
|
|
+ {
|
|
+ inbuf.len = len;
|
|
+ }
|
|
+
|
|
+ static i15x gv = 0x40*0x40; /* default g.v = m.v = 64 */
|
|
+
|
|
+ /* gv = 0(min)..64*128(max) */
|
|
+ void
|
|
+ dacioGlobalVol(i15x v)
|
|
+ {
|
|
+ gv = v;
|
|
+ }
|
|
+
|
|
+ #define VOL_MAX (64*64*128) /* vol max * g.v max * m.v max */
|
|
+ #define VOL_MAX_LOG ( 6+ 6+ 7) /* 1 << VOL_MAX_LOG == VOL_MAX */
|
|
+ #define LEV_MAX (128*VOL_MAX)
|
|
+
|
|
+ #if 0
|
|
+ #define to8bit(x, /*i31x*/tmpvar) \
|
|
+ ( tmpvar = (x) * gv, \
|
|
+ (tmpvar >= LEV_MAX) ? 255 : \
|
|
+ (tmpvar < -LEV_MAX) ? 0 : \
|
|
+ (u32x)tmpvar/VOL_MAX ^ 128 )
|
|
+ /* ^^^^^^ see asm output w/o this */
|
|
+ #define to8bit(x, /*i31x*/tmpvar) \
|
|
+ ( tmpvar = (x) * gv + LEV_MAX, \
|
|
+ (tmpvar & ~(LEV_MAX*2-1)) ? \
|
|
+ ((tmpvar < 0)? 0 : 255) : \
|
|
+ (u32x)tmpvar/VOL_MAX)
|
|
+ #define to8bit(x, /*i31x*/tmpvar) lim[(x) * gv >> VOL_MAX_LOG]
|
|
+ #else
|
|
+ /* almost the same CPU usage as lim[] table mathod */
|
|
+ #define to8bit(x, /*i31x*/tmpvar) \
|
|
+ ( tmpvar = ((x) * gv + LEV_MAX) >> VOL_MAX_LOG, \
|
|
+ (tmpvar & ~255)? ~tmpvar >> 16 : tmpvar ) /* 16 will be OK */
|
|
+ /* ~(tmpvar >> 16) makes longer asm */
|
|
+ #endif
|
|
+ #define to16bit(x) \
|
|
+ ( ((x) * gv) >> 12 )
|
|
+
|
|
+ /* stereo */
|
|
+ static void
|
|
+ dacioOutHirevS(i15x n)
|
|
+ {
|
|
+ const i31 *inbufp = inbuf.p;
|
|
+ u8 *u8p;
|
|
+ i15 *i15p;
|
|
+
|
|
+ switch (dci.bits) {
|
|
+ case 8:
|
|
+ u8p = buf.p.p8;
|
|
+ for (; n > 0; n--) {
|
|
+ i31x tmp;
|
|
+ *u8p++ = to8bit(*inbufp++, tmp); /* L */
|
|
+ *u8p++ = to8bit(*inbufp++, tmp); /* R */
|
|
+ }
|
|
+ buf.p.p8 = u8p;
|
|
+ break;
|
|
+ case 16:
|
|
+ i15p = buf.p.p16;
|
|
+ for (; n > 0; n--) {
|
|
+ *i15p++ = to16bit(*inbufp++); /* L */
|
|
+ *i15p++ = to16bit(*inbufp++); /* R */
|
|
+ }
|
|
+ buf.p.p16 = i15p;
|
|
+ break;
|
|
+ }
|
|
+ inbuf.p = inbufp;
|
|
+ }
|
|
+
|
|
+ /* mono */
|
|
+ static void
|
|
+ dacioOutHirevM(i15x n)
|
|
+ {
|
|
+ const i31 *inbufp = inbuf.p;
|
|
+ u8 *u8p;
|
|
+ i15 *i15p;
|
|
+
|
|
+ switch (dci.bits) {
|
|
+ case 8:
|
|
+ u8p = buf.p.p8;
|
|
+ for (; n > 0; n--) {
|
|
+ i31x tmp;
|
|
+ *u8p++ = to8bit(*inbufp, tmp);
|
|
+ inbufp += 2;
|
|
+ }
|
|
+ buf.p.p8 = u8p;
|
|
+ break;
|
|
+ case 16:
|
|
+ i15p = buf.p.p16;
|
|
+ for (; n > 0; n--) {
|
|
+ *i15p++ = to16bit(*inbufp);
|
|
+ inbufp += 2;
|
|
+ }
|
|
+ buf.p.p16 = i15p;
|
|
+ break;
|
|
+ }
|
|
+ inbuf.p = inbufp;
|
|
+ }
|
|
+
|
|
+ #define dacioOutHirev(x) \
|
|
+ if (dci.stereo) dacioOutHirevS(x); else dacioOutHirevM(x)
|
|
+
|
|
+ void
|
|
+ dacioOut(void)
|
|
+ {
|
|
+ i31x iLen;
|
|
+ i31x oLen;
|
|
+
|
|
+ inbuf.p = inbuf.p0;
|
|
+ iLen = inbuf.len;
|
|
+ while ((oLen = bufRest()) <= iLen) {
|
|
+ iLen -= oLen;
|
|
+ dacioOutHirev(oLen);
|
|
+ dacioFlush();
|
|
+ }
|
|
+ dacioOutHirev(iLen);
|
|
+ }
|