Fix and improve the buffer length calculation to avoid zero length
even if blk_ms is small. This fixes PR kern/56059.
This commit is contained in:
parent
1a007aec0b
commit
7a7ca36496
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: audiobell.c,v 1.3 2019/06/26 06:57:45 isaki Exp $ */
|
||||
/* $NetBSD: audiobell.c,v 1.4 2021/03/20 04:56:52 isaki Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1999 Richard Earnshaw
|
||||
@ -31,7 +31,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: audiobell.c,v 1.3 2019/06/26 06:57:45 isaki Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: audiobell.c,v 1.4 2021/03/20 04:56:52 isaki Exp $");
|
||||
|
||||
#include <sys/audioio.h>
|
||||
#include <sys/conf.h>
|
||||
@ -80,6 +80,13 @@ static const int32_t sinewave[] = {
|
||||
};
|
||||
#undef A
|
||||
|
||||
/*
|
||||
* The minimum and the maximum buffer sizes must be a multiple of 32
|
||||
* (32 = countof(sinewave) * sizeof(uint16_t)).
|
||||
*/
|
||||
#define MINBUFSIZE (1024)
|
||||
#define MAXBUFSIZE (4096)
|
||||
|
||||
/*
|
||||
* dev is a device_t for the audio device to use.
|
||||
* pitch is the pitch of the bell in Hz,
|
||||
@ -102,7 +109,7 @@ audiobell(void *dev, u_int pitch, u_int period, u_int volume, int poll)
|
||||
u_int remainbytes;
|
||||
u_int wave1count;
|
||||
u_int wave1bytes;
|
||||
u_int blkbytes;
|
||||
u_int bufbytes;
|
||||
u_int len;
|
||||
u_int step;
|
||||
u_int offset;
|
||||
@ -111,6 +118,10 @@ audiobell(void *dev, u_int pitch, u_int period, u_int volume, int poll)
|
||||
|
||||
KASSERT(volume <= 100);
|
||||
|
||||
/* Playing for 0msec does nothing. */
|
||||
if (period == 0)
|
||||
return;
|
||||
|
||||
/* The audio system isn't built for polling. */
|
||||
if (poll)
|
||||
return;
|
||||
@ -158,16 +169,23 @@ audiobell(void *dev, u_int pitch, u_int period, u_int volume, int poll)
|
||||
remainbytes = remaincount * sizeof(int16_t);
|
||||
wave1bytes = wave1count * sizeof(int16_t);
|
||||
|
||||
blkbytes = ptrack->usrbuf_blksize;
|
||||
blkbytes = rounddown(blkbytes, wave1bytes);
|
||||
blkbytes = uimin(blkbytes, remainbytes);
|
||||
buf = malloc(blkbytes, M_TEMP, M_WAITOK);
|
||||
/* Based on 3*usrbuf_blksize, but not too small or too large */
|
||||
bufbytes = ptrack->usrbuf_blksize * NBLKHW;
|
||||
if (bufbytes < MINBUFSIZE)
|
||||
bufbytes = MINBUFSIZE;
|
||||
else if (bufbytes > MAXBUFSIZE)
|
||||
bufbytes = MAXBUFSIZE;
|
||||
else
|
||||
bufbytes = roundup(bufbytes, wave1bytes);
|
||||
bufbytes = uimin(bufbytes, remainbytes);
|
||||
KASSERT(bufbytes != 0);
|
||||
buf = malloc(bufbytes, M_TEMP, M_WAITOK);
|
||||
if (buf == NULL)
|
||||
goto out;
|
||||
|
||||
/* Generate sinewave with specified volume */
|
||||
j = offset;
|
||||
for (i = 0; i < blkbytes / sizeof(int16_t); i++) {
|
||||
for (i = 0; i < bufbytes / sizeof(int16_t); i++) {
|
||||
/* XXX audio already has track volume feature though #if 0 */
|
||||
buf[i] = AUDIO_SCALEDOWN(sinewave[j] * (int)volume, 16);
|
||||
j += step;
|
||||
@ -177,7 +195,7 @@ audiobell(void *dev, u_int pitch, u_int period, u_int volume, int poll)
|
||||
/* Write while paused to avoid inserting silence. */
|
||||
ptrack->is_pause = true;
|
||||
for (; remainbytes > 0; remainbytes -= len) {
|
||||
len = uimin(remainbytes, blkbytes);
|
||||
len = uimin(remainbytes, bufbytes);
|
||||
aiov.iov_base = (void *)buf;
|
||||
aiov.iov_len = len;
|
||||
auio.uio_iov = &aiov;
|
||||
|
Loading…
Reference in New Issue
Block a user