diff options
author | Alexandre Ratchov <ratchov@cvs.openbsd.org> | 2019-09-05 05:33:58 +0000 |
---|---|---|
committer | Alexandre Ratchov <ratchov@cvs.openbsd.org> | 2019-09-05 05:33:58 +0000 |
commit | 3e4bb613d76ad7737eee6ad5f0ad490a7afdf87a (patch) | |
tree | cf0d014dc566c21cda5bf85fe3addc432ca5d8b1 /sys/dev/audio.c | |
parent | 4b2b041ac8a7c0b6420ddab454af2762ad8194a3 (diff) |
Add the set_blksz() and set_nblks() audio driver functions.
The first sets the block size in frames, which is necessarily common
to play and recording directions no matter the number of channels. The
second sets the number of blocks per buffer for the given
direction. Together, these two functions allow audio drivers to easily
set the block size, matching both playback and recording constraints.
The round_blocksize() didn't allow to do so because it returns the
block size in *bytes*. Since the driver doesn't know if it's called
for the play or for the record block size, it's impossible to
calculate the block size in all cases if play and record number of
channels are different.
ok mpi@
Diffstat (limited to 'sys/dev/audio.c')
-rw-r--r-- | sys/dev/audio.c | 55 |
1 files changed, 50 insertions, 5 deletions
diff --git a/sys/dev/audio.c b/sys/dev/audio.c index 77c3c548b35..9aed7f978a9 100644 --- a/sys/dev/audio.c +++ b/sys/dev/audio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: audio.c,v 1.180 2019/08/17 05:04:56 ratchov Exp $ */ +/* $OpenBSD: audio.c,v 1.181 2019/09/05 05:33:57 ratchov Exp $ */ /* * Copyright (c) 2015 Alexandre Ratchov <alex@caoua.org> * @@ -193,6 +193,31 @@ audio_gcd(unsigned int a, unsigned int b) return a; } +/* + * Calculate the least block size (in frames) such that both the + * corresponding play and/or record block sizes (in bytes) are multiple + * of the given number of bytes. + */ +int +audio_blksz_bytes(int mode, + struct audio_params *p, struct audio_params *r, int bytes) +{ + unsigned int np, nr; + + if (mode & AUMODE_PLAY) { + np = bytes / audio_gcd(p->bps * p->channels, bytes); + if (!(mode & AUMODE_RECORD)) + nr = np; + } + if (mode & AUMODE_RECORD) { + nr = bytes / audio_gcd(r->bps * r->channels, bytes); + if (!(mode & AUMODE_PLAY)) + np = nr; + } + + return nr * np / audio_gcd(nr, np); +} + int audio_buf_init(struct audio_softc *sc, struct audio_buf *buf, int dir) { @@ -625,11 +650,19 @@ audio_canstart(struct audio_softc *sc) } int -audio_setpar_blksz(struct audio_softc *sc) +audio_setpar_blksz(struct audio_softc *sc, + struct audio_params *p, struct audio_params *r) { unsigned int nr, np, max, min, mult; unsigned int blk_mult, blk_max; + if (sc->ops->set_blksz) { + sc->round = sc->ops->set_blksz(sc->arg, sc->mode, + p, r, sc->round); + DPRINTF("%s: block size set to: %u\n", DEVNAME(sc), sc->round); + return 0; + } + /* * get least multiplier of the number of frames per block */ @@ -706,7 +739,8 @@ audio_setpar_blksz(struct audio_softc *sc) } int -audio_setpar_nblks(struct audio_softc *sc) +audio_setpar_nblks(struct audio_softc *sc, + struct audio_params *p, struct audio_params *r) { unsigned int max; @@ -719,6 +753,12 @@ audio_setpar_nblks(struct audio_softc *sc) sc->play.nblks = max; else if (sc->play.nblks < 2) sc->play.nblks = 2; + if (sc->ops->set_nblks) { + sc->play.nblks = sc->ops->set_nblks(sc->arg, sc->mode, + p, sc->round, sc->play.nblks); + DPRINTF("%s: play nblks -> %u\n", DEVNAME(sc), + sc->play.nblks); + } } if (sc->mode & AUMODE_RECORD) { /* @@ -727,6 +767,11 @@ audio_setpar_nblks(struct audio_softc *sc) * size of maximum reliability during xruns */ max = sc->rec.datalen / (sc->round * sc->rchan * sc->bps); + if (sc->ops->set_nblks) { + max = sc->ops->set_nblks(sc->arg, sc->mode, + r, sc->round, max); + DPRINTF("%s: rec nblks -> %u\n", DEVNAME(sc), max); + } sc->rec.nblks = max; } return 0; @@ -874,11 +919,11 @@ audio_setpar(struct audio_softc *sc) } audio_calc_sil(sc); - error = audio_setpar_blksz(sc); + error = audio_setpar_blksz(sc, &p, &r); if (error) return error; - error = audio_setpar_nblks(sc); + error = audio_setpar_nblks(sc, &p, &r); if (error) return error; |