Index: arch/x68k/dev/vs.c =================================================================== RCS file: /home/isaki/cvsroot/vs/src/sys/arch/x68k/dev/vs.c,v retrieving revision 1.1.1.1 retrieving revision 1.6 diff -u -r1.1.1.1 -r1.6 --- arch/x68k/dev/vs.c 2001/11/03 14:36:48 1.1.1.1 +++ arch/x68k/dev/vs.c 2001/11/11 12:10:52 1.6 @@ -57,12 +57,12 @@ #include #ifdef VS_DEBUG -#define DPRINTF(x) printf x +#define DPRINTF(y,x) if(vs_debug>=(y))printf x #ifdef AUDIO_DEBUG extern int audiodebug; #endif #else -#define DPRINTF(x) +#define DPRINTF(y,x) #endif static int vs_match __P((struct device *, struct cfdata *, void *)); @@ -167,6 +167,16 @@ #define NUM_RATE (sizeof(vs_l2r)/sizeof(vs_l2r[0])) +struct audio_encoding vs_encodings[] = { + {0, AudioEadpcm, AUDIO_ENCODING_ADPCM, 4, 0}, + {1, AudioEulinear, AUDIO_ENCODING_ULINEAR, 8, AUDIO_ENCODINGFLAG_EMULATED}, + {2, AudioEmulaw, AUDIO_ENCODING_ULAW, 8, AUDIO_ENCODINGFLAG_EMULATED}, +}; + +#ifdef VS_DEBUG +static int vs_debug; +#endif + static int vs_match(struct device *parent, struct cfdata *cf, void *aux) { @@ -190,9 +200,12 @@ if (ia->ia_dmaintr != VS_DMAINTR) return 0; +#ifdef VS_DEBUG + vs_debug = 1; #ifdef AUDIO_DEBUG audiodebug = 2; #endif +#endif return 1; } @@ -248,7 +261,7 @@ { struct vs_softc *sc = hdl; - DPRINTF(("vs_dmaintr\n")); + DPRINTF(2, ("vs_dmaintr\n")); if (sc->sc_pintr) { /* start next transfer */ @@ -284,7 +297,7 @@ { struct vs_softc *sc = hdl; - DPRINTF(("%s: DMA transfer error.\n", sc->sc_dev.dv_xname)); + DPRINTF(1, ("%s: DMA transfer error.\n", sc->sc_dev.dv_xname)); /* XXX */ vs_dmaintr(hdl); @@ -301,7 +314,7 @@ { struct vs_softc *sc = hdl; - DPRINTF(("%s: open: flags=%d\n", sc->sc_dev.dv_xname, flags)); + DPRINTF(1, ("vs_open: flags=%d\n", flags)); sc->sc_pintr = NULL; sc->sc_rintr = NULL; @@ -312,35 +325,18 @@ static void vs_close(void *hdl) { - DPRINTF(("vs_close\n")); + DPRINTF(1, ("vs_close\n")); } static int vs_query_encoding(void *hdl, struct audio_encoding *fp) { - DPRINTF(("vs_query_encoding\n")); - switch (fp->index) { - case 0: - strcpy(fp->name, AudioEadpcm); - fp->encoding = AUDIO_ENCODING_ADPCM; - fp->precision = 4; - fp->flags = 0; - break; - case 1: - strcpy(fp->name, AudioEulinear); - fp->encoding = AUDIO_ENCODING_ULINEAR; - fp->precision = 8; - fp->flags = AUDIO_ENCODINGFLAG_EMULATED; - break; - case 2: - strcpy(fp->name, AudioEmulaw); - fp->encoding = AUDIO_ENCODING_ULAW; - fp->precision = 8; - fp->flags = AUDIO_ENCODINGFLAG_EMULATED; - break; - default: + DPRINTF(1, ("vs_query_encoding\n")); + + if (fp->index >= sizeof(vs_encodings) / sizeof(vs_encodings[0])) return EINVAL; - } + + *fp = vs_encodings[fp->index]; return 0; } @@ -379,7 +375,7 @@ int mode; int rate; - DPRINTF(("vs_set_params: setmode=%d, usemode=%d\n", setmode, usemode)); + DPRINTF(1, ("vs_set_params: setmode=%d, usemode=%d\n", setmode, usemode)); /* set first record info, then play info */ for (mode = AUMODE_RECORD; mode != -1; @@ -395,13 +391,20 @@ rate = p->sample_rate; p->sw_code = NULL; p->factor = 1; +#ifdef AUDIO_REDUCE + p->reduce_factor = 1; +#endif + DPRINTF(1, ("vs_set_params: encoding=%d, precision=%d\n", + p->encoding, p->precision)); switch (p->encoding) { case AUDIO_ENCODING_ULAW: if (p->precision != 8) return EINVAL; if (mode == AUMODE_PLAY) { p->sw_code = msm6258_mulaw_to_adpcm; - rate = p->sample_rate * 2; +#ifdef AUDIO_REDUCE + p->reduce_factor = 2; +#endif } else { p->sw_code = msm6258_adpcm_to_mulaw; p->factor = 2; @@ -413,7 +416,9 @@ return EINVAL; if (mode == AUMODE_PLAY) { p->sw_code = msm6258_ulinear8_to_adpcm; - rate = p->sample_rate * 2; +#ifdef AUDIO_REDUCE + p->reduce_factor = 2; +#endif } else { p->sw_code = msm6258_adpcm_to_ulinear8; p->factor = 2; @@ -424,11 +429,13 @@ return EINVAL; break; default: - DPRINTF(("vs_set_params: mode=%d, encoding=%d\n", + DPRINTF(1, ("vs_set_params: mode=%d, encoding=%d\n", mode, p->encoding)); return (EINVAL); } + DPRINTF(1, ("vs_set_params: rate=%d -> ", rate)); rate = vs_round_sr(rate); + DPRINTF(1, ("%d\n", rate)); if (rate < 0) return (EINVAL); if (mode == AUMODE_PLAY) @@ -443,7 +450,7 @@ static void vs_set_sr(struct vs_softc *sc, int rate) { - DPRINTF(("setting sample rate to %d, %d\n", + DPRINTF(1, ("setting sample rate to %d, %d\n", rate, (int)vs_l2r[rate].rate)); bus_space_write_1(sc->sc_iot, sc->sc_ppi, PPI_PORTC, (bus_space_read_1 (sc->sc_iot, sc->sc_ppi, @@ -470,8 +477,8 @@ struct dmac_dma_xfer *xf; struct dmac_channel_stat *chan = sc->sc_dma_ch; - DPRINTF(("vs_trigger_output\n")); - DPRINTF(("trigger_output: start=%p, bsize=%d, intr=%p, arg=%p\n", + DPRINTF(2, ("vs_trigger_output\n")); + DPRINTF(2, ("trigger_output: start=%p, bsize=%d, intr=%p, arg=%p\n", start, bsize, intr, arg)); sc->sc_pintr = intr; @@ -519,8 +526,8 @@ struct dmac_dma_xfer *xf; struct dmac_channel_stat *chan = sc->sc_dma_ch; - DPRINTF(("vs_trigger_input\n")); - DPRINTF(("trigger_input: start=%p, bsize=%d, intr=%p, arg=%p\n", + DPRINTF(2, ("vs_trigger_input\n")); + DPRINTF(2, ("trigger_input: start=%p, bsize=%d, intr=%p, arg=%p\n", start, bsize, intr, arg)); sc->sc_rintr = intr; @@ -561,7 +568,7 @@ { struct vs_softc *sc = hdl; - DPRINTF(("vs_halt_output\n")); + DPRINTF(1, ("vs_halt_output\n")); /* stop ADPCM play */ dmac_abort_xfer(sc->sc_dma_ch->ch_softc, sc->sc_current.xfer); @@ -575,7 +582,7 @@ { struct vs_softc *sc = hdl; - DPRINTF(("vs_halt_input\n")); + DPRINTF(1, ("vs_halt_input\n")); /* stop ADPCM recoding */ dmac_abort_xfer(sc->sc_dma_ch->ch_softc, sc->sc_current.xfer); @@ -652,7 +659,7 @@ static int vs_getdev(void *hdl, struct audio_device *retp) { - DPRINTF(("vs_getdev\n")); + DPRINTF(1, ("vs_getdev\n")); *retp = vs_device; return 0; @@ -661,21 +668,21 @@ static int vs_set_port(void *hdl, mixer_ctrl_t *cp) { - DPRINTF(("vs_set_port\n")); + DPRINTF(1, ("vs_set_port\n")); return 0; } static int vs_get_port(void *hdl, mixer_ctrl_t *cp) { - DPRINTF(("vs_get_port\n")); + DPRINTF(1, ("vs_get_port\n")); return 0; } static int vs_query_devinfo(void *hdl, mixer_devinfo_t *mi) { - DPRINTF(("vs_query_devinfo\n")); + DPRINTF(1, ("vs_query_devinfo\n")); switch (mi->index) { default: return EINVAL; @@ -768,7 +775,7 @@ static int vs_get_props(void *hdl) { - DPRINTF(("vs_get_props\n")); + DPRINTF(1, ("vs_get_props\n")); return 0 /* | dependent | half duplex | no mmap */; } #endif /* NAUDIO > 0 && NVS > 0*/ Index: dev/audio.c =================================================================== RCS file: /home/isaki/cvsroot/vs/src/sys/dev/audio.c,v retrieving revision 1.1.1.2 retrieving revision 1.10 diff -u -r1.1.1.2 -r1.10 --- dev/audio.c 2001/11/03 14:36:49 1.1.1.2 +++ dev/audio.c 2001/11/11 10:29:10 1.10 @@ -283,6 +283,12 @@ audio_init_ringbuffer(&sc->sc_pr); audio_calcwater(sc); +#ifdef AUDIO_REDUCE + sc->sc_tmpbuf = malloc(65536/*XXX*/, M_DEVBUF, M_WAITOK); + if (sc->sc_tmpbuf == NULL) + return; +#endif + iclass = oclass = -1; sc->sc_inports.index = -1; sc->sc_inports.master = 0; @@ -1365,6 +1371,11 @@ struct audio_ringbuffer *cb = &sc->sc_pr; u_char *inp, *einp; int saveerror, error, s, n, cc, used; +#ifdef AUDIO_REDUCE + int *resid; + int buf_resid; + int buf_id; +#endif DPRINTFN(2,("audio_write: sc=%p count=%lu used=%d(hi=%d)\n", sc, (unsigned long)uio->uio_resid, sc->sc_pr.used, @@ -1406,8 +1417,30 @@ sc->sc_pparams.sw_code, sc->sc_pparams.factor)); error = 0; +#ifdef AUDIO_REDUCE + if (sc->sc_pparams.reduce_factor > 1) { + n = uio->uio_resid; + error = uiomove(sc->sc_tmpbuf, uio->uio_resid, uio); + if (error) + panic("audio uiomove"); + buf_resid = n - uio->uio_resid; + if (!sc->sc_pparams.sw_code) + panic("why is sw_code NULL?"); + sc->sc_pparams.sw_code(sc->hw_hdl, sc->sc_tmpbuf, buf_resid); + buf_resid /= sc->sc_pparams.reduce_factor; + buf_id = 0; + resid = &buf_resid; + } else { + resid = &uio->uio_resid; + } + while (*resid > 0 && !error ) { +#else while (uio->uio_resid > 0 && !error) { +#endif s = splaudio(); + /* + * 水位が上限を越えている間は sleep して待つ。 + */ while (cb->used >= cb->usedhigh) { DPRINTFN(2, ("audio_write: sleep used=%d lowat=%d " "hiwat=%d\n", @@ -1428,17 +1461,47 @@ inp = cb->inp; cb->copying = 1; splx(s); + /* + * cc は書き込み可能な水位までの残りバイト数。 + * n は物理バッファの終りまでの残りバイト数。 + */ cc = cb->usedhigh - used; /* maximum to write */ n = cb->end - inp; + /* + * factor > 1 ということは、sw_code 後のコードは + * 元のコードより大きくなる。 + * sw_code 前のバッファはその分縮めて考えておく必要があるため、 + * 両方の残りバイト数をともに factor で割る。 + * あとどれだけ書き込めるかを計算してるので、reduce_factor の + * 場合ここでかけ算しちゃだめ。 + */ if (sc->sc_pparams.factor != 1) { /* Compensate for software coding expansion factor. */ n /= sc->sc_pparams.factor; cc /= sc->sc_pparams.factor; } + /* + * 残り水位よりも物理バッファの方が小さければ、 + * 物理バッファあふれを防止するため、残り水位も + * 物理バッファの大きさに合わせる。 + */ if (n < cc) cc = n; /* don't write beyond end of buffer */ + /* + * ユーザランドから渡されたデータの残りが残り水位よりも + * 小さければ、それに合わせる。 + */ +#ifdef AUDIO_REDUCE + if (*resid < cc) + cc = *resid; +#else if (uio->uio_resid < cc) cc = uio->uio_resid; /* and no more than we have */ +#endif + /* + * つまりここで cc は、残り水位、残り物理バッファ、 + * ユーザから渡された残りデータのうち最も小さいものになる。 + */ #ifdef DIAGNOSTIC /* @@ -1454,14 +1517,31 @@ #endif DPRINTFN(1, ("audio_write: uiomove cc=%d inp=%p, left=%lu\n", cc, inp, (unsigned long)uio->uio_resid)); +#ifdef AUDIO_REDUCE + if (sc->sc_pparams.reduce_factor > 1){ + memcpy(inp, sc->sc_tmpbuf + buf_id, cc); + *resid -= cc; + buf_id += cc; + } else +#endif + { + /* ここで、これまでの n は捨てる */ n = uio->uio_resid; error = uiomove(inp, cc, uio); cc = n - uio->uio_resid; /* number of bytes actually moved */ + } + /* + * この時点で n は意味なし。 + * cc は実際にユーザランドから読み込んだバイト数。 + */ #ifdef AUDIO_DEBUG if (error) printf("audio_write:(1) uiomove failed %d; cc=%d " "inp=%p\n", error, cc, inp); #endif +#ifdef AUDIO_REDUCE + if (sc->sc_pparams.reduce_factor == 1) +#endif /* * Continue even if uiomove() failed because we may have * gotten a partial block. @@ -1469,10 +1549,18 @@ if (sc->sc_pparams.sw_code) { sc->sc_pparams.sw_code(sc->hw_hdl, inp, cc); /* Adjust count after the expansion. */ + /* + * cc を sw_code 通した後の長さに変える。 + */ cc *= sc->sc_pparams.factor; DPRINTFN(1, ("audio_write: expanded cc=%d\n", cc)); } + /* + * einp は次に入力されるデータの位置。 + * それが物理バッファの終り(かそれより向う)をさしていたら + * 物理バッファの最初をさすようにする。 + */ einp = cb->inp + cc; if (einp >= cb->end) einp = cb->start; @@ -1484,6 +1572,9 @@ */ sc->sc_sil_count = 0; + /* + * 入力バッファ更新。水位も更新。 + */ cb->inp = einp; cb->used += cc; /* @@ -1491,6 +1582,13 @@ * the copy did not fill the last block completely it needs to * be padded. */ + /* + * inp は読み込む前のポインタ位置。 + * 今回読み込んだのが1つのブロックに収まっているなら + * cc は読み込み終った位置からブロックの終りまでの長さ。 + * この長さは単にデバッグ用に表示するだけ。あと 0 でなければいい。 + * 今回読み込んだことでブロックをまたいだら cc = 0。 + */ if (cb->needfill && (inp - cb->start) / cb->blksize == (einp - cb->start) / cb->blksize) { @@ -1503,6 +1601,9 @@ cb->copying = 0; if (!sc->sc_pbus && !cb->pause) { saveerror = error; + /* + * ここで音を出す。 + */ error = audiostartp(sc); if (saveerror != 0) { /* Report the first error that occurred. */ @@ -1510,6 +1611,9 @@ } } splx(s); + /* + * 1つのブロックに収まっていたら残りを埋める。? + */ if (cc != 0) { DPRINTFN(1, ("audio_write: fill %d\n", cc)); audio_fill_silence(&sc->sc_pparams, einp, cc); @@ -1804,9 +1908,15 @@ sc->sc_pr.start, sc->sc_pr.used, sc->sc_pr.usedhigh, sc->sc_pr.mmapped)); + /* + * デバイスが mmap()-ed じゃない時に水位が blksize 以下なら帰る。 + */ if (!sc->sc_pr.mmapped && sc->sc_pr.used < sc->sc_pr.blksize) return 0; + /* + * trigger_out() か、なければ start_output() を呼ぶ。 + */ if (sc->hw_if->trigger_output) error = sc->hw_if->trigger_output(sc->hw_hdl, sc->sc_pr.start, sc->sc_pr.end, sc->sc_pr.blksize, @@ -1818,6 +1928,9 @@ DPRINTF(("audiostartp failed: %d\n", error)); return error; } + /* + * 再生 DMA 動作中。 + */ sc->sc_pbus = 1; return 0; } @@ -1895,10 +2008,26 @@ blksize = cb->blksize; + /* + * 出力ポインタを blksize だけ進める。 + * それが物理バッファの終り(かそれより向う)をさしていたら + * 物理バッファの先頭をさすようにする。 + */ cb->outp += blksize; if (cb->outp >= cb->end) cb->outp = cb->start; + /* + * 今回転送した (sw_code 前の) バイト数を cb->stamp に加える。 + * 今回転送したのは1ブロックサイズ分。 + * ただし factor > 1 の場合、sw_code 前はもっと小さかったので、割る。 + * ということは、reduce_factor の場合、掛ければよい? + */ +#ifdef AUDIO_REDUCE + cb->stamp += blksize * sc->sc_pparams.reduce_factor + / sc->sc_pparams.factor; +#else cb->stamp += blksize / sc->sc_pparams.factor; +#endif if (cb->mmapped) { DPRINTFN(5, ("audio_pint: mmapped outp=%p cc=%d inp=%p\n", cb->outp, blksize, cb->inp)); @@ -1939,27 +2068,53 @@ } #endif + /* 水位を1ブロック分(実際に出力した分)だけ下げる。 */ cb->used -= blksize; + /* + * 水位が1ブロックサイズ未満になったら + */ if (cb->used < blksize) { /* we don't have a full block to use */ if (cb->copying) { /* writer is in progress, don't disturb */ + /* copying=1 なら現在コピー中 */ cb->needfill = 1; DPRINTFN(1, ("audio_pint: copying in progress\n")); } else { + /* そうでなければ埋める? */ inp = cb->inp; + /* + * cc はブロック境界までの残りバイト数。 + * ccr はオリジナルの(=sw_code 前の)データ量を出したいので + * factor で割る。reduce の場合は掛けるか? + * それを各統計データに加算する。 + */ cc = blksize - (inp - cb->start) % blksize; +#ifdef AUDIO_REDUCE + ccr = cc * sc->sc_pparams.reduce_factor / sc->sc_pparams.factor; +#else ccr = cc / sc->sc_pparams.factor; +#endif if (cb->pause) cb->pdrops += ccr; else { cb->drops += ccr; sc->sc_playdrop += ccr; } + /* + * 無音で埋める? + */ audio_pint_silence(sc, cb, inp, cc); + /* + * 入力ポインタをそれだけ進める。ここでブロック境界になった。 + * 入力ポインタが物理バッファの終端なら先頭に戻す。 + */ inp += cc; if (inp >= cb->end) inp = cb->start; + /* + * inp を元に代入。水位を再び cc だけ上げる。 + */ cb->inp = inp; cb->used += cc; Index: dev/audio_if.h =================================================================== RCS file: /home/isaki/cvsroot/vs/src/sys/dev/audio_if.h,v retrieving revision 1.1.1.2 retrieving revision 1.3 diff -u -r1.1.1.2 -r1.3 --- dev/audio_if.h 2001/11/03 14:36:48 1.1.1.2 +++ dev/audio_if.h 2001/11/11 12:03:41 1.3 @@ -51,6 +51,9 @@ /* Software en/decode functions, set if SW coding required by HW */ void (*sw_code)(void *, u_char *, int); int factor; /* coding space change */ +#ifdef AUDIO_REDUCE + int reduce_factor; /* coding space change */ +#endif }; /* The default audio mode: 8 kHz mono ulaw */ Index: dev/audiovar.h =================================================================== RCS file: /home/isaki/cvsroot/vs/src/sys/dev/audiovar.h,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- dev/audiovar.h 2001/11/03 14:35:04 1.1.1.1 +++ dev/audiovar.h 2001/11/11 09:18:50 1.2 @@ -111,6 +111,9 @@ /* Ring buffers, separate for record and play. */ struct audio_ringbuffer sc_rr; /* Record ring */ struct audio_ringbuffer sc_pr; /* Play ring */ +#ifdef AUDIO_REDUCE + u_char *sc_tmpbuf; +#endif u_char sc_blkset; /* Blocksize has been set */ Index: dev/ic/msm6258.c =================================================================== RCS file: /home/isaki/cvsroot/vs/src/sys/dev/ic/msm6258.c,v retrieving revision 1.1.1.1 retrieving revision 1.2 diff -u -r1.1.1.1 -r1.2 --- dev/ic/msm6258.c 2001/11/04 13:28:49 1.1.1.1 +++ dev/ic/msm6258.c 2001/11/10 08:55:17 1.2 @@ -132,11 +132,12 @@ char *x = &(mc->mc_estim); short *y = &(mc->mc_amp); register int i; + u_char *d = p; u_char f; - for (i = 0; i < cc; i++) { - f = pcm2adpcm_step(p[i], y, x); - p[i] = f + (pcm2adpcm_step(p[i], y, x) << 4); + for (i = 0; i < cc; ) { + f = pcm2adpcm_step(p[i++], y, x); + *d++ = f + (pcm2adpcm_step(p[i++], y, x) << 4); } }