Module Name: src Committed By: isaki Date: Sat Apr 3 04:10:30 UTC 2021
Modified Files: src/sys/dev: spkr.c spkr_audio.c spkrvar.h src/sys/dev/isa: spkr_pcppi.c Log Message: Rework about the rest note in speaker(4). - Obsolete the sc_rest callback. The rest note operation can be done by the common spkr layer. This also fixes PR kern/56060. This work-in-progress patch was left in my local tree for years. :( - Improve calculations of tone and rest length. To generate a diff of this commit: cvs rdiff -u -r1.18 -r1.19 src/sys/dev/spkr.c cvs rdiff -u -r1.10 -r1.11 src/sys/dev/spkr_audio.c cvs rdiff -u -r1.9 -r1.10 src/sys/dev/spkrvar.h cvs rdiff -u -r1.12 -r1.13 src/sys/dev/isa/spkr_pcppi.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/spkr.c diff -u src/sys/dev/spkr.c:1.18 src/sys/dev/spkr.c:1.19 --- src/sys/dev/spkr.c:1.18 Sat Apr 3 03:21:53 2021 +++ src/sys/dev/spkr.c Sat Apr 3 04:10:30 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: spkr.c,v 1.18 2021/04/03 03:21:53 isaki Exp $ */ +/* $NetBSD: spkr.c,v 1.19 2021/04/03 04:10:30 isaki Exp $ */ /* * Copyright (c) 1990 Eric S. Raymond (e...@snark.thyrsus.com) @@ -43,7 +43,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: spkr.c,v 1.18 2021/04/03 03:21:53 isaki Exp $"); +__KERNEL_RCSID(0, "$NetBSD: spkr.c,v 1.19 2021/04/03 04:10:30 isaki Exp $"); #if defined(_KERNEL_OPT) #include "wsmux.h" @@ -99,12 +99,10 @@ static void playstring(struct spkr_softc * * Play string interpretation is modelled on IBM BASIC 2.0's PLAY statement; * M[LNS] are missing and the ~ synonym and octave-tracking facility is added. - * Requires spkr_tone(), spkr_rest(). String play is not interruptible - * except possibly at physical block boundaries. + * String play is not interruptible except possibly at physical block + * boundaries. */ -#define dtoi(c) ((c) - '0') - /* * Magic number avoidance... */ @@ -156,45 +154,82 @@ playinit(struct spkr_softc *sc) sc->sc_octprefix = true;/* act as though there was an initial O(n) */ } -/* play tone of proper duration for current rhythm signature */ +#define SPKRPRI (PZERO - 1) + +/* Rest for given number of ticks */ +static void +rest(struct spkr_softc *sc, int ticks) +{ + +#ifdef SPKRDEBUG + device_printf(sc->sc_dev, "%s: rest for %d ticks\n", __func__, ticks); +#endif /* SPKRDEBUG */ + KASSERT(ticks > 0); + + tsleep(sc->sc_dev, SPKRPRI | PCATCH, device_xname(sc->sc_dev), ticks); +} + +/* + * Play tone of proper duration for current rhythm signature. + * note indicates "O0C" = 0, "O0C#" = 1, "O0D" = 2, ... , and + * -1 indiacates a rest. + * val indicates the length, "L4" = 4, "L8" = 8. + * sustain indicates the number of subsequent dots that extend the sound + * by one a half. + */ static void -playtone(struct spkr_softc *sc, int pitch, int val, int sustain) +playtone(struct spkr_softc *sc, int note, int val, int sustain) { - int sound, silence, snum = 1, sdenom = 1; + int whole; + int total; + int sound; + int silence; /* this weirdness avoids floating-point arithmetic */ + whole = sc->sc_whole; for (; sustain; sustain--) { - snum *= NUM_MULT; - sdenom *= DENOM_MULT; + whole *= NUM_MULT; + val *= DENOM_MULT; } - if (pitch == -1) { - (*sc->sc_rest)(sc->sc_dev, sc->sc_whole - * snum / (val * sdenom)); + /* Total length in tick */ + total = whole / val; + + if (note == -1) { +#ifdef SPKRDEBUG + device_printf(sc->sc_dev, "%s: rest for %d ticks\n", + __func__, total); +#endif /* SPKRDEBUG */ + if (total != 0) + rest(sc, total); return; } - int fac = sc->sc_whole * (FILLTIME - sc->sc_fill); - int fval = FILLTIME * val; - sound = (sc->sc_whole * snum) / (val * sdenom) - fac / fval; - silence = fac * snum / (fval * sdenom); + /* + * Rest 1/8 (if NORMAL) or 3/8 (if STACCATO) in tick. + * silence should be rounded down. + */ + silence = total * (FILLTIME - sc->sc_fill) / FILLTIME; + sound = total - silence; #ifdef SPKRDEBUG device_printf(sc->sc_dev, - "%s: pitch %d for %d ticks, rest for %d ticks\n", __func__, - pitch, sound, silence); + "%s: note %d for %d ticks, rest for %d ticks\n", __func__, + note, sound, silence); #endif /* SPKRDEBUG */ - (*sc->sc_tone)(sc->sc_dev, pitchtab[pitch], sound); - if (sc->sc_fill != LEGATO) - (*sc->sc_rest)(sc->sc_dev, silence); + if (sound != 0) + (*sc->sc_tone)(sc->sc_dev, pitchtab[note], sound); + if (silence != 0) + rest(sc, silence); } /* interpret and play an item from a notation string */ static void playstring(struct spkr_softc *sc, const char *cp, size_t slen) { - int pitch, lastpitch = OCTAVE_NOTES * DFLT_OCTAVE; + int pitch; + int lastpitch = OCTAVE_NOTES * DFLT_OCTAVE; #define GETNUM(cp, v) \ for (v = 0; slen > 0 && isdigit((unsigned char)cp[1]); ) { \ @@ -357,16 +392,26 @@ playstring(struct spkr_softc *sc, const } } -/******************* UNIX DRIVER HOOKS BEGIN HERE ************************** - * - * This section implements driver hooks to run playstring() and the spkr_tone() - * and spkr_rest() functions defined above. - */ +/******************* UNIX DRIVER HOOKS BEGIN HERE **************************/ #define spkrenter(d) device_lookup_private(&spkr_cd, d) +/* + * Attaches spkr. Specify tone function with the following specification: + * + * void + * tone(device_t self, u_int pitch, u_int tick) + * plays a beep with specified parameters. + * The argument 'pitch' specifies the pitch of a beep in Hz. The argument + * 'tick' specifies the period of a beep in tick(9). This function waits + * to finish playing the beep and then halts it. + * If the pitch is zero, it halts all sound if any (for compatibility + * with the past confused specifications, but there should be no sound at + * this point). And it returns immediately, without waiting ticks. So + * you cannot use this as a rest. + * If the tick is zero, it returns immediately. + */ void -spkr_attach(device_t self, void (*tone)(device_t, u_int, u_int), - void (*rest)(device_t, int)) +spkr_attach(device_t self, void (*tone)(device_t, u_int, u_int)) { struct spkr_softc *sc = device_private(self); @@ -375,7 +420,6 @@ spkr_attach(device_t self, void (*tone)( #endif /* SPKRDEBUG */ sc->sc_dev = self; sc->sc_tone = tone; - sc->sc_rest = rest; sc->sc_inbuf = NULL; sc->sc_wsbelldev = NULL; @@ -492,13 +536,21 @@ spkrclose(dev_t dev, int flags, int mode return 0; } +/* + * Play tone specified by tp. + * tp->frequency is the frequency (0 means a rest). + * tp->duration is the length in tick (returns immediately if 0). + */ static void playonetone(struct spkr_softc *sc, tone_t *tp) { - if (tp->frequency == 0) - (*sc->sc_rest)(sc->sc_dev, tp->duration); - else - (*sc->sc_tone)(sc->sc_dev, tp->frequency, tp->duration); + if (tp->duration <= 0) + return; + + if (tp->frequency == 0) + rest(sc, tp->duration); + else + (*sc->sc_tone)(sc->sc_dev, tp->frequency, tp->duration); } int Index: src/sys/dev/spkr_audio.c diff -u src/sys/dev/spkr_audio.c:1.10 src/sys/dev/spkr_audio.c:1.11 --- src/sys/dev/spkr_audio.c:1.10 Sat Apr 3 03:21:53 2021 +++ src/sys/dev/spkr_audio.c Sat Apr 3 04:10:30 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: spkr_audio.c,v 1.10 2021/04/03 03:21:53 isaki Exp $ */ +/* $NetBSD: spkr_audio.c,v 1.11 2021/04/03 04:10:30 isaki Exp $ */ /*- * Copyright (c) 2016 Nathanial Sloss <nathanialsl...@yahoo.com.au> @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: spkr_audio.c,v 1.10 2021/04/03 03:21:53 isaki Exp $"); +__KERNEL_RCSID(0, "$NetBSD: spkr_audio.c,v 1.11 2021/04/03 04:10:30 isaki Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -71,21 +71,11 @@ spkr_audio_tone(device_t self, u_int xhz #ifdef SPKRDEBUG device_printf(self, "%s: %u %u\n", __func__, xhz, ticks); #endif /* SPKRDEBUG */ - audiobell(sc->sc_audiodev, xhz, hztoms(ticks), - sc->sc_spkr.sc_vol, 0); -} -static void -spkr_audio_rest(device_t self, int ticks) -{ - struct spkr_audio_softc *sc = device_private(self); - -#ifdef SPKRDEBUG - aprint_debug_dev(self, "%s: %d\n", __func__, ticks); -#endif /* SPKRDEBUG */ - if (ticks > 0) - audiobell(sc->sc_audiodev, 0, hztoms(ticks), - sc->sc_spkr.sc_vol, 0); + if (xhz == 0 || ticks == 0) + return; + + audiobell(sc->sc_audiodev, xhz, hztoms(ticks), sc->sc_spkr.sc_vol, 0); } static int @@ -113,7 +103,7 @@ spkr_audio_attach(device_t parent, devic if (!pmf_device_register(self, NULL, NULL)) aprint_error_dev(self, "couldn't establish power handler\n"); - spkr_attach(self, spkr_audio_tone, spkr_audio_rest); + spkr_attach(self, spkr_audio_tone); } static int Index: src/sys/dev/spkrvar.h diff -u src/sys/dev/spkrvar.h:1.9 src/sys/dev/spkrvar.h:1.10 --- src/sys/dev/spkrvar.h:1.9 Sun Jun 11 21:54:22 2017 +++ src/sys/dev/spkrvar.h Sat Apr 3 04:10:30 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: spkrvar.h,v 1.9 2017/06/11 21:54:22 pgoyette Exp $ */ +/* $NetBSD: spkrvar.h,v 1.10 2021/04/03 04:10:30 isaki Exp $ */ #ifndef _SYS_DEV_SPKRVAR_H #define _SYS_DEV_SPKRVAR_H @@ -18,12 +18,10 @@ struct spkr_softc { /* attachment-specific hooks */ void (*sc_tone)(device_t, u_int, u_int); - void (*sc_rest)(device_t, int); u_int sc_vol; /* volume - only for audio skpr */ }; -void spkr_attach(device_t, - void (*)(device_t, u_int, u_int), void (*)(device_t, int)); +void spkr_attach(device_t, void (*)(device_t, u_int, u_int)); int spkr_detach(device_t, int); Index: src/sys/dev/isa/spkr_pcppi.c diff -u src/sys/dev/isa/spkr_pcppi.c:1.12 src/sys/dev/isa/spkr_pcppi.c:1.13 --- src/sys/dev/isa/spkr_pcppi.c:1.12 Sat Apr 3 03:21:53 2021 +++ src/sys/dev/isa/spkr_pcppi.c Sat Apr 3 04:10:30 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: spkr_pcppi.c,v 1.12 2021/04/03 03:21:53 isaki Exp $ */ +/* $NetBSD: spkr_pcppi.c,v 1.13 2021/04/03 04:10:30 isaki Exp $ */ /* * Copyright (c) 1990 Eric S. Raymond (e...@snark.thyrsus.com) @@ -43,7 +43,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: spkr_pcppi.c,v 1.12 2021/04/03 03:21:53 isaki Exp $"); +__KERNEL_RCSID(0, "$NetBSD: spkr_pcppi.c,v 1.13 2021/04/03 04:10:30 isaki Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -79,8 +79,6 @@ CFATTACH_DECL3_NEW(spkr_pcppi, sizeof(st spkr_pcppi_probe, spkr_pcppi_attach, spkr_pcppi_detach, NULL, spkr_pcppi_rescan, spkr_pcppi_childdet, 0); -#define SPKRPRI (PZERO - 1) - /* emit tone of frequency hz for given number of ticks */ static void spkr_pcppi_tone(device_t self, u_int xhz, u_int ticks) @@ -92,22 +90,6 @@ spkr_pcppi_tone(device_t self, u_int xhz (*sc->sc_bell_func)(sc->sc_pcppicookie, xhz, ticks, PCPPI_BELL_SLEEP); } -/* rest for given number of ticks */ -static void -spkr_pcppi_rest(device_t self, int ticks) -{ - /* - * Set timeout to endrest function, then give up the timeslice. - * This is so other processes can execute while the rest is being - * waited out. - */ -#ifdef SPKRDEBUG - aprint_debug_dev(self, "%s: %d\n", __func__, ticks); -#endif /* SPKRDEBUG */ - if (ticks > 0) - tsleep(self, SPKRPRI | PCATCH, device_xname(self), ticks); -} - static int spkr_pcppi_probe(device_t parent, cfdata_t cf, void *aux) { @@ -125,7 +107,7 @@ spkr_pcppi_attach(device_t parent, devic sc->sc_pcppicookie = pa->pa_cookie; sc->sc_bell_func = pa->pa_bell_func; - spkr_attach(self, spkr_pcppi_tone, spkr_pcppi_rest); + spkr_attach(self, spkr_pcppi_tone); if (!pmf_device_register(self, NULL, NULL)) aprint_error_dev(self, "couldn't establish power handler\n"); }