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.
This commit is contained in:
parent
74bd6922f5
commit
398f413a6e
@ -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 (esr@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(struct spkr_pcppi_softc),
|
||||
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, u_int ticks)
|
||||
(*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, device_t self, void *aux)
|
||||
|
||||
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");
|
||||
}
|
||||
|
124
sys/dev/spkr.c
124
sys/dev/spkr.c
@ -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 (esr@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 *, const char *, size_t);
|
||||
*
|
||||
* 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
|
||||
playtone(struct spkr_softc *sc, int pitch, int val, int sustain)
|
||||
rest(struct spkr_softc *sc, int ticks)
|
||||
{
|
||||
int sound, silence, snum = 1, sdenom = 1;
|
||||
|
||||
#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 note, int val, int sustain)
|
||||
{
|
||||
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 char *cp, size_t slen)
|
||||
}
|
||||
}
|
||||
|
||||
/******************* 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)(device_t, u_int, u_int),
|
||||
#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, struct lwp *l)
|
||||
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
|
||||
|
@ -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 <nathanialsloss@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, u_int ticks)
|
||||
#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, device_t self, void *aux)
|
||||
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
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user