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");
 }

Reply via email to