summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDale Rahn <drahn@cvs.openbsd.org>2005-09-27 02:53:44 +0000
committerDale Rahn <drahn@cvs.openbsd.org>2005-09-27 02:53:44 +0000
commitb175f0b94f1858b9a5a79334507588477d0488b8 (patch)
tree265fb1e68eb8cefbc0bbbed7a065b01169851c45
parentc3472f9013768c705615e3e89b073506ba3af2e6 (diff)
report time duration required to play sample then % error of sample rate.
from PR 4304. Also added support for different sample rate requests. ok jason@
-rw-r--r--regress/sys/dev/audio/autest.168
-rw-r--r--regress/sys/dev/audio/autest.c176
2 files changed, 195 insertions, 49 deletions
diff --git a/regress/sys/dev/audio/autest.1 b/regress/sys/dev/audio/autest.1
index 920d49a4b26..f25c0eb648e 100644
--- a/regress/sys/dev/audio/autest.1
+++ b/regress/sys/dev/audio/autest.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: autest.1,v 1.6 2003/06/02 19:15:38 jason Exp $
+.\" $OpenBSD: autest.1,v 1.7 2005/09/27 02:53:43 drahn Exp $
.\"
.\" Copyright (c) 2002 Jason L. Wright (jason@thought.net)
.\" All rights reserved.
@@ -33,6 +33,7 @@
.Sh SYNOPSIS
.Nm autest
.Op Fl f Ar device
+.Op Fl r Ar rate
.Sh DESCRIPTION
The
.Nm
@@ -47,17 +48,24 @@ if not specified,
and iterates through all of the encodings supported by the device playing
a 440Hz tone in the proper format.
The tone should sound almost identical in each of the formats.
+The
+.Fl r
+rate
+can be used to specify the audio rate to test, It will request the
+audio subsystem to play that Hz, however the audio device may return
+a different speed. This can be useful to test different speeds, eg 8000,
+44100, 48000.
.Pp
.Nm
can produce tones in any of the following formats and will skip other
formats if supported by the device:
.Bl -tag -width XXXXXXXXXX
.It Cm mu-law
-8bit mu-law companded
+8 bit mu-law companded
.It Cm A-law
-8bit A-law companded
-.It Cm adpcm
-4 bit adaptive differential pulse code modulation
+8 bit A-law companded
+.\" .It Cm adpcm
+.\" 4 bit adaptive differential pulse code modulation
.It Cm ulinear
8 bit unsigned linear
.It Cm ulinear_le
@@ -71,7 +79,55 @@ formats if supported by the device:
.It Cm slinear_be
16 bit signed linear big endian (twos complement)
.El
+.Sh OUTPUT
+Interpreting the output of
+.Nm
+is a little tricky.
+The output below is from an
+.Xr auich 4 .
+.Bd -literal
+ulinear:8...mono(s 44100 c 45167 e 2.4%)...stereo(s 44100 c 45162 e 2.4%)
+mulaw:8*...mono(s 44100 c 45166 e 2.4%)...stereo(s 44100 c 45157 e 2.3%)
+alaw:8*...mono[Invalid argument]...stereo[Invalid argument]
+slinear:8*...mono(s 44100 c 45171 e 2.4%)...stereo(s 44100 c 45170 e 2.4%)
+slinear_le:16...mono(s 44100 c 45171 e 2.4%)...stereo(s 44100 c 45170 e 2.4%)
+ulinear_le:16*...mono(s 44100 c 45167 e 2.4%)...stereo(s 44100 c 45168 e 2.4%)
+slinear_be:16*...mono(s 44100 c 45169 e 2.4%)...stereo(s 44100 c 45167 e 2.4%)
+ulinear_be:16*...mono(s 44100 c 45167 e 2.4%)...stereo(s 44100 c 45160 e 2.3%)
+.Ed
+.Pp
+.Nm
+loops through each mode claimed to be supported by the chip (emulated or not).
+For each emulated mode, an asterisk is appended to the mode name.
+If the tone sounds different from all the other tones for the device,
+it is likely that either the emulation is wrong, or the mode is not
+set on the device correctly.
+.Pp
+Also, for the mono and stereo versions of each mode,
+.Nm
+prints the claimed sample rate,
+.So s Bo rate Bc Sc ,
+computed sample rate,
+.So c Bo rate Bc Sc ,
+and the percent error between them,
+.So e Bo percent Bc Sc .
+If the percent error is high (greater than 10 percent or so),
+either the sample rate is not being correctly returned by
+the device, or it is not being set correctly on the device.
+.Pp
+Interestingly, when
+.Nm
+requests
+.Sq alaw
+encoding, the device driver returns
+.So Invalid argument Sc .
+This indicates that the device includes
+.Sq alaw
+in its mode enumeration, but does not support it for playback.
+This is very likely a bug in the driver.
.Sh SEE ALSO
.Xr audio 4
.Sh BUGS
-The ADPCM encoding sounds very noisy on CS4231 (it's probably incorrect).
+There is partial support for ADPCM, adaptive differential pulse code
+modulation, but it is not enabled by default
+since it does not appear to be correct.
diff --git a/regress/sys/dev/audio/autest.c b/regress/sys/dev/audio/autest.c
index 608386f68f7..171b99dbcb6 100644
--- a/regress/sys/dev/audio/autest.c
+++ b/regress/sys/dev/audio/autest.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: autest.c,v 1.10 2003/08/06 16:15:44 jason Exp $ */
+/* $OpenBSD: autest.c,v 1.11 2005/09/27 02:53:43 drahn Exp $ */
/*
* Copyright (c) 2002 Jason L. Wright (jason@thought.net)
@@ -44,18 +44,31 @@
#include "adpcm.h"
#include "law.h"
+struct ausrate {
+ struct timeval tv_begin;
+ struct timeval tv_end;
+ u_int r_rate; /* requested rate */
+ u_int s_rate; /* rate from audio layer */
+ u_int c_rate; /* computed rate */
+ int bps; /* bytes per sample */
+ int bytes; /* number of bytes played */
+ float err;
+};
+
int main(int, char **);
-void check_encoding(int, audio_encoding_t *);
-void check_encoding_mono(int, audio_encoding_t *);
-void check_encoding_stereo(int, audio_encoding_t *);
-void enc_ulaw_8(int, audio_encoding_t *, int);
-void enc_alaw_8(int, audio_encoding_t *, int);
-void enc_ulinear_8(int, audio_encoding_t *, int);
-void enc_ulinear_16(int, audio_encoding_t *, int, int);
-void enc_slinear_8(int, audio_encoding_t *, int);
-void enc_slinear_16(int, audio_encoding_t *, int, int);
-void enc_adpcm_8(int, audio_encoding_t *, int);
+void check_encoding(int, audio_encoding_t *, int);
+void check_encoding_mono(int, audio_encoding_t *, int);
+void check_encoding_stereo(int, audio_encoding_t *, int);
+void enc_ulaw_8(int, audio_encoding_t *, int, int);
+void enc_alaw_8(int, audio_encoding_t *, int, int);
+void enc_ulinear_8(int, audio_encoding_t *, int, int);
+void enc_ulinear_16(int, audio_encoding_t *, int, int, int);
+void enc_slinear_8(int, audio_encoding_t *, int, int);
+void enc_slinear_16(int, audio_encoding_t *, int, int, int);
+void enc_adpcm_8(int, audio_encoding_t *, int, int);
void audio_wait(int);
+void check_srate(struct ausrate *);
+void mark_time(struct timeval *);
#define PLAYFREQ 440.0
#define PLAYSECS 2
@@ -68,12 +81,16 @@ main(int argc, char **argv)
audio_info_t ainfo;
char *fname = NULL;
int fd, i, c;
+ int rate = 8000;
- while ((c = getopt(argc, argv, "f:")) != -1) {
+ while ((c = getopt(argc, argv, "f:r:")) != -1) {
switch (c) {
case 'f':
fname = optarg;
break;
+ case 'r':
+ rate = atoi(optarg);
+ break;
case '?':
default:
fprintf(stderr, "%s [-f device]\n", argv[0]);
@@ -98,7 +115,7 @@ main(int argc, char **argv)
enc.index = i;
if (ioctl(fd, AUDIO_GETENC, &enc) == -1)
break;
- check_encoding(fd, &enc);
+ check_encoding(fd, &enc, rate);
}
close(fd);
@@ -106,20 +123,46 @@ main(int argc, char **argv)
}
void
-check_encoding(int fd, audio_encoding_t *enc)
+check_srate(struct ausrate *rt)
+{
+ struct timeval t;
+ float tm, b, r, err;
+
+ timersub(&rt->tv_end, &rt->tv_begin, &t);
+ tm = (float)t.tv_sec + ((float)t.tv_usec / 1000000.0);
+ b = (float)rt->bytes / (float)rt->bps;
+ r = b / tm;
+
+ err = fabs((float)rt->s_rate - r);
+ err /= r * 0.01;
+ rt->err = err;
+ rt->c_rate = rintf(r);
+ printf("(s %u c %u e %3.1f%%)",
+ rt->s_rate, rt->c_rate, rt->err);
+}
+
+void
+check_encoding(int fd, audio_encoding_t *enc, int rate)
{
printf("%s:%d%s",
enc->name,
enc->precision,
(enc->flags & AUDIO_ENCODINGFLAG_EMULATED) ? "*" : "");
fflush(stdout);
- check_encoding_mono(fd, enc);
- check_encoding_stereo(fd, enc);
+ check_encoding_mono(fd, enc, rate);
+ check_encoding_stereo(fd, enc, rate);
printf("\n");
}
void
-check_encoding_mono(int fd, audio_encoding_t *enc)
+mark_time(struct timeval *tv)
+{
+ if (gettimeofday(tv, NULL) == -1)
+ err(1, "gettimeofday");
+}
+
+void
+check_encoding_mono(int fd, audio_encoding_t *enc, int rate)
{
int skipped = 0;
@@ -129,23 +172,23 @@ check_encoding_mono(int fd, audio_encoding_t *enc)
if (enc->precision == 8) {
switch (enc->encoding) {
case AUDIO_ENCODING_ULAW:
- enc_ulaw_8(fd, enc, 1);
+ enc_ulaw_8(fd, enc, 1, rate);
break;
case AUDIO_ENCODING_ALAW:
- enc_alaw_8(fd, enc, 1);
+ enc_alaw_8(fd, enc, 1, rate);
break;
case AUDIO_ENCODING_ULINEAR:
case AUDIO_ENCODING_ULINEAR_LE:
case AUDIO_ENCODING_ULINEAR_BE:
- enc_ulinear_8(fd, enc, 1);
+ enc_ulinear_8(fd, enc, 1, rate);
break;
case AUDIO_ENCODING_SLINEAR:
case AUDIO_ENCODING_SLINEAR_LE:
case AUDIO_ENCODING_SLINEAR_BE:
- enc_slinear_8(fd, enc, 1);
+ enc_slinear_8(fd, enc, 1, rate);
break;
case AUDIO_ENCODING_ADPCM:
- enc_adpcm_8(fd, enc, 1);
+ enc_adpcm_8(fd, enc, 1, rate);
break;
default:
skipped = 1;
@@ -155,16 +198,16 @@ check_encoding_mono(int fd, audio_encoding_t *enc)
if (enc->precision == 16) {
switch (enc->encoding) {
case AUDIO_ENCODING_ULINEAR_LE:
- enc_ulinear_16(fd, enc, 1, LITTLE_ENDIAN);
+ enc_ulinear_16(fd, enc, 1, LITTLE_ENDIAN, rate);
break;
case AUDIO_ENCODING_ULINEAR_BE:
- enc_ulinear_16(fd, enc, 1, BIG_ENDIAN);
+ enc_ulinear_16(fd, enc, 1, BIG_ENDIAN, rate);
break;
case AUDIO_ENCODING_SLINEAR_LE:
- enc_slinear_16(fd, enc, 1, LITTLE_ENDIAN);
+ enc_slinear_16(fd, enc, 1, LITTLE_ENDIAN, rate);
break;
case AUDIO_ENCODING_SLINEAR_BE:
- enc_slinear_16(fd, enc, 1, BIG_ENDIAN);
+ enc_slinear_16(fd, enc, 1, BIG_ENDIAN, rate);
break;
default:
skipped = 1;
@@ -176,7 +219,7 @@ check_encoding_mono(int fd, audio_encoding_t *enc)
}
void
-check_encoding_stereo(int fd, audio_encoding_t *enc)
+check_encoding_stereo(int fd, audio_encoding_t *enc, int rate)
{
int skipped = 0;
@@ -186,23 +229,23 @@ check_encoding_stereo(int fd, audio_encoding_t *enc)
if (enc->precision == 8) {
switch (enc->encoding) {
case AUDIO_ENCODING_ULAW:
- enc_ulaw_8(fd, enc, 2);
+ enc_ulaw_8(fd, enc, 2, rate);
break;
case AUDIO_ENCODING_ALAW:
- enc_alaw_8(fd, enc, 2);
+ enc_alaw_8(fd, enc, 2, rate);
break;
case AUDIO_ENCODING_ULINEAR:
case AUDIO_ENCODING_ULINEAR_LE:
case AUDIO_ENCODING_ULINEAR_BE:
- enc_ulinear_8(fd, enc, 2);
+ enc_ulinear_8(fd, enc, 2, rate);
break;
case AUDIO_ENCODING_SLINEAR:
case AUDIO_ENCODING_SLINEAR_LE:
case AUDIO_ENCODING_SLINEAR_BE:
- enc_slinear_8(fd, enc, 2);
+ enc_slinear_8(fd, enc, 2, rate);
break;
case AUDIO_ENCODING_ADPCM:
- enc_adpcm_8(fd, enc, 2);
+ enc_adpcm_8(fd, enc, 2, rate);
break;
default:
skipped = 1;
@@ -212,16 +255,16 @@ check_encoding_stereo(int fd, audio_encoding_t *enc)
if (enc->precision == 16) {
switch (enc->encoding) {
case AUDIO_ENCODING_ULINEAR_LE:
- enc_ulinear_16(fd, enc, 2, LITTLE_ENDIAN);
+ enc_ulinear_16(fd, enc, 2, LITTLE_ENDIAN, rate);
break;
case AUDIO_ENCODING_ULINEAR_BE:
- enc_ulinear_16(fd, enc, 2, BIG_ENDIAN);
+ enc_ulinear_16(fd, enc, 2, BIG_ENDIAN, rate);
break;
case AUDIO_ENCODING_SLINEAR_LE:
- enc_slinear_16(fd, enc, 2, LITTLE_ENDIAN);
+ enc_slinear_16(fd, enc, 2, LITTLE_ENDIAN, rate);
break;
case AUDIO_ENCODING_SLINEAR_BE:
- enc_slinear_16(fd, enc, 2, BIG_ENDIAN);
+ enc_slinear_16(fd, enc, 2, BIG_ENDIAN, rate);
break;
default:
skipped = 1;
@@ -233,9 +276,10 @@ check_encoding_stereo(int fd, audio_encoding_t *enc)
}
void
-enc_ulinear_8(int fd, audio_encoding_t *enc, int chans)
+enc_ulinear_8(int fd, audio_encoding_t *enc, int chans, int rate)
{
audio_info_t inf;
+ struct ausrate rt;
u_int8_t *samples = NULL, *p;
int i, j;
@@ -243,6 +287,7 @@ enc_ulinear_8(int fd, audio_encoding_t *enc, int chans)
inf.play.precision = enc->precision;
inf.play.encoding = enc->encoding;
inf.play.channels = chans;
+ inf.play.sample_rate = rate;;
if (ioctl(fd, AUDIO_SETINFO, &inf) == -1) {
printf("[%s]", strerror(errno));
@@ -253,6 +298,10 @@ enc_ulinear_8(int fd, audio_encoding_t *enc, int chans)
printf("[getinfo: %s]", strerror(errno));
goto out;
}
+ rt.r_rate = inf.play.sample_rate;
+ rt.s_rate = inf.play.sample_rate;
+ rt.bps = 1 * chans;
+ rt.bytes = inf.play.sample_rate * chans * PLAYSECS;
samples = (u_int8_t *)malloc(inf.play.sample_rate * chans);
if (samples == NULL) {
@@ -275,9 +324,12 @@ enc_ulinear_8(int fd, audio_encoding_t *enc, int chans)
}
}
+ mark_time(&rt.tv_begin);
for (i = 0; i < PLAYSECS; i++)
write(fd, samples, inf.play.sample_rate * chans);
audio_wait(fd);
+ mark_time(&rt.tv_end);
+ check_srate(&rt);
out:
if (samples != NULL)
@@ -285,9 +337,10 @@ out:
}
void
-enc_slinear_8(int fd, audio_encoding_t *enc, int chans)
+enc_slinear_8(int fd, audio_encoding_t *enc, int chans, int rate)
{
audio_info_t inf;
+ struct ausrate rt;
int8_t *samples = NULL, *p;
int i, j;
@@ -295,6 +348,7 @@ enc_slinear_8(int fd, audio_encoding_t *enc, int chans)
inf.play.precision = enc->precision;
inf.play.encoding = enc->encoding;
inf.play.channels = chans;
+ inf.play.sample_rate = rate;;
if (ioctl(fd, AUDIO_SETINFO, &inf) == -1) {
printf("[%s]", strerror(errno));
@@ -305,6 +359,10 @@ enc_slinear_8(int fd, audio_encoding_t *enc, int chans)
printf("[getinfo: %s]", strerror(errno));
goto out;
}
+ rt.r_rate = inf.play.sample_rate;
+ rt.s_rate = inf.play.sample_rate;
+ rt.bps = 1 * chans;
+ rt.bytes = inf.play.sample_rate * chans * PLAYSECS;
samples = (int8_t *)malloc(inf.play.sample_rate * chans);
if (samples == NULL) {
@@ -327,9 +385,12 @@ enc_slinear_8(int fd, audio_encoding_t *enc, int chans)
}
}
+ mark_time(&rt.tv_begin);
for (i = 0; i < PLAYSECS; i++)
write(fd, samples, inf.play.sample_rate * chans);
audio_wait(fd);
+ mark_time(&rt.tv_end);
+ check_srate(&rt);
out:
if (samples != NULL)
@@ -337,9 +398,10 @@ out:
}
void
-enc_slinear_16(int fd, audio_encoding_t *enc, int chans, int order)
+enc_slinear_16(int fd, audio_encoding_t *enc, int chans, int order, int rate)
{
audio_info_t inf;
+ struct ausrate rt;
u_int8_t *samples = NULL, *p;
int i, j;
@@ -347,6 +409,7 @@ enc_slinear_16(int fd, audio_encoding_t *enc, int chans, int order)
inf.play.precision = enc->precision;
inf.play.encoding = enc->encoding;
inf.play.channels = chans;
+ inf.play.sample_rate = rate;;
if (ioctl(fd, AUDIO_SETINFO, &inf) == -1) {
printf("[%s]", strerror(errno));
@@ -357,6 +420,10 @@ enc_slinear_16(int fd, audio_encoding_t *enc, int chans, int order)
printf("[getinfo: %s]", strerror(errno));
goto out;
}
+ rt.r_rate = inf.play.sample_rate;
+ rt.s_rate = inf.play.sample_rate;
+ rt.bps = 2 * chans;
+ rt.bytes = 2 * inf.play.sample_rate * chans * PLAYSECS;
samples = (int8_t *)malloc(inf.play.sample_rate * chans * 2);
if (samples == NULL) {
@@ -388,9 +455,12 @@ enc_slinear_16(int fd, audio_encoding_t *enc, int chans, int order)
}
}
+ mark_time(&rt.tv_begin);
for (i = 0; i < PLAYSECS; i++)
write(fd, samples, inf.play.sample_rate * chans * 2);
audio_wait(fd);
+ mark_time(&rt.tv_end);
+ check_srate(&rt);
out:
if (samples != NULL)
@@ -398,9 +468,10 @@ out:
}
void
-enc_ulinear_16(int fd, audio_encoding_t *enc, int chans, int order)
+enc_ulinear_16(int fd, audio_encoding_t *enc, int chans, int order, int rate)
{
audio_info_t inf;
+ struct ausrate rt;
u_int8_t *samples = NULL, *p;
int i, j;
@@ -408,6 +479,7 @@ enc_ulinear_16(int fd, audio_encoding_t *enc, int chans, int order)
inf.play.precision = enc->precision;
inf.play.encoding = enc->encoding;
inf.play.channels = chans;
+ inf.play.sample_rate = rate;;
if (ioctl(fd, AUDIO_SETINFO, &inf) == -1) {
printf("[%s]", strerror(errno));
@@ -424,6 +496,10 @@ enc_ulinear_16(int fd, audio_encoding_t *enc, int chans, int order)
warn("malloc");
goto out;
}
+ rt.r_rate = inf.play.sample_rate;
+ rt.s_rate = inf.play.sample_rate;
+ rt.bps = 2 * chans;
+ rt.bytes = 2 * inf.play.sample_rate * chans * PLAYSECS;
for (i = 0, p = samples; i < inf.play.sample_rate; i++) {
float d;
@@ -449,9 +525,12 @@ enc_ulinear_16(int fd, audio_encoding_t *enc, int chans, int order)
}
}
+ mark_time(&rt.tv_begin);
for (i = 0; i < PLAYSECS; i++)
write(fd, samples, inf.play.sample_rate * chans * 2);
audio_wait(fd);
+ mark_time(&rt.tv_end);
+ check_srate(&rt);
out:
if (samples != NULL)
@@ -459,7 +538,7 @@ out:
}
void
-enc_adpcm_8(int fd, audio_encoding_t *enc, int chans)
+enc_adpcm_8(int fd, audio_encoding_t *enc, int chans, int rate)
{
audio_info_t inf;
struct adpcm_state adsts;
@@ -471,6 +550,7 @@ enc_adpcm_8(int fd, audio_encoding_t *enc, int chans)
inf.play.precision = enc->precision;
inf.play.encoding = enc->encoding;
inf.play.channels = chans;
+ inf.play.sample_rate = rate;;
if (ioctl(fd, AUDIO_SETINFO, &inf) == -1) {
printf("[%s]", strerror(errno));
@@ -533,17 +613,19 @@ out:
}
void
-enc_ulaw_8(int fd, audio_encoding_t *enc, int chans)
+enc_ulaw_8(int fd, audio_encoding_t *enc, int chans, int rate)
{
audio_info_t inf;
int16_t *samples = NULL;
int i, j;
u_int8_t *outbuf = NULL, *p;
+ struct ausrate rt;
AUDIO_INITINFO(&inf);
inf.play.precision = enc->precision;
inf.play.encoding = enc->encoding;
inf.play.channels = chans;
+ inf.play.sample_rate = rate;;
if (ioctl(fd, AUDIO_SETINFO, &inf) == -1) {
printf("[%s]", strerror(errno));
@@ -554,6 +636,10 @@ enc_ulaw_8(int fd, audio_encoding_t *enc, int chans)
printf("[getinfo: %s]", strerror(errno));
goto out;
}
+ rt.r_rate = inf.play.sample_rate;
+ rt.s_rate = inf.play.sample_rate;
+ rt.bps = 1 * chans;
+ rt.bytes = inf.play.sample_rate * chans * PLAYSECS;
samples = (int16_t *)calloc(inf.play.sample_rate, sizeof(*samples));
if (samples == NULL) {
@@ -582,10 +668,13 @@ enc_ulaw_8(int fd, audio_encoding_t *enc, int chans)
}
}
+ mark_time(&rt.tv_begin);
for (i = 0; i < PLAYSECS; i++) {
write(fd, outbuf, inf.play.sample_rate * chans);
}
audio_wait(fd);
+ mark_time(&rt.tv_end);
+ check_srate(&rt);
out:
if (samples != NULL)
@@ -595,7 +684,7 @@ out:
}
void
-enc_alaw_8(int fd, audio_encoding_t *enc, int chans)
+enc_alaw_8(int fd, audio_encoding_t *enc, int chans, int rate)
{
audio_info_t inf;
int16_t *samples = NULL;
@@ -606,6 +695,7 @@ enc_alaw_8(int fd, audio_encoding_t *enc, int chans)
inf.play.precision = enc->precision;
inf.play.encoding = enc->encoding;
inf.play.channels = chans;
+ inf.play.sample_rate = rate;;
if (ioctl(fd, AUDIO_SETINFO, &inf) == -1) {
printf("[%s]", strerror(errno));