*** /dev/null Fri Mar 6 05:54:22 1998 --- dacio-netbsd.c Fri Mar 6 06:51:04 1998 *************** *** 0 **** --- 1,278 ---- + #include /*(perror)*/ + #include /*O_WRONLY*/ + #include /*(ioctl)*/ + #include /*(memset)*/ + #include /*(write)*/ + #include /*SNDCTL_XXX*/ + #include /*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); + }