2
* Purpose: The osstest program shipped with OSS
5
* This file contains the main parts of the {!xlink osstest} utility that is
6
* shipped with the OSS package.
8
* {!notice The sample rate converter (GRC3) required by this program
9
* is not released by 4Front Technologies. For this reason it will not be
10
* possible to compile this program. The sources have been made
11
* available just because they use some of the new OSS features such as
12
* {!nlink SNDCTL_AUDIOINFO}. However the {!nlink ossinfo.c} program might
13
* be more interesting sample source for this subject.}
15
* It's rather easy to get this program to work without GRC3 by
16
* commenting out the contents of the src_convert routine and by
17
* modifying the Makefile. However there should be no reason to do this
18
* since the precompiled program with full functionality is available for
21
* The wavedata.c and wavedata.h files contain the actual samples compressed
22
* using the MS ASPCM algorithm.
26
* This file is part of Open Sound System.
28
* Copyright (C) 4Front Technologies 1996-2008.
30
* This this source file is released under GPL v2 license (no other versions).
31
* See the COPYING file included in the main directory of this source
32
* distribution for the license terms and conditions.
46
#include <sys/ioctl.h>
47
#include <sys/utsname.h>
48
#include <soundcard.h>
56
#define CH_STEREO (CH_LEFT|CH_RIGHT)
60
#define __inline__ inline
61
#include "../../kernel/framework/audio/oss_grc3.c"
65
* uncompress_wave() is defined in wavedata.c. It expands the audio samples
66
* stored in wavedata.h and returns the lenghth of the uncompressed version
69
* The uncompressed wave data format is 16 bit (native) stereo recorded at 48000 Hz.
71
extern int uncompress_wave (short *outbuf);
73
#define SHORTER_TEST 0 /* SET THIS TO 1 if you want SHORTER TEST */
78
extern void describe_error (void); /* From ../dsp/help.c */
80
#define SAMPLE_RATE 48000
83
* Operating mode flags (set from the command line).
85
#define TF_VIRTUAL 0x00000001 /* Test virtual devices */
86
#define TF_SYSTEST 0x00000002 /* Test started by oss-install */
87
#define TF_SNDCONF 0x00000004 /* Test started by sndconf */
88
#define TF_QUICK 0x00000008 /* Shortened test */
89
#define TF_LOOP 0x00000010 /* Loop until interrupted */
91
int cardno = -1, mixerfd, num_devices_tested = 0, play_gain = 100, skip = 0;
93
static short *sample_buf;
98
if ((sample_buf = malloc (2000000)) == NULL)
100
fprintf (stderr, "Out of memory\n");
104
data_len = uncompress_wave (sample_buf);
109
* The src_convert() routine converts the wave data to the requested
113
src_convert (short *buf, short *newbuf, int count, int srate, int sz)
115
int newcount = 0, c, p = 0, np = 0;
117
grc3state_t grc1, grc2;
122
grc3_setup (&grc1, SAMPLE_RATE, srate);
123
grc3_setup (&grc2, SAMPLE_RATE, srate);
128
while (newcount < count)
131
c = count - newcount;
134
grc3_convert (&grc1, 16, 4, buf + p, newbuf + np, c / 2, 2048, 2, 0);
136
grc3_convert (&grc2, 16, 4, buf + p, newbuf + np, c / 2, 2048, 2, 1);
147
* audio_write() writes the requested audio channels of the original stereo
148
* recording(buf). This is done simply by setting the unnecessary
149
* channel (if any) to 0.
153
audio_write (int fd, short *buf, int count, int chmask)
156
int count2, l, ret, i;
158
if (chmask == CH_STEREO)
159
return write (fd, buf, count);
167
buf2 = malloc (count);
168
memcpy (buf2, buf, count);
169
for (i = 0; i < l; i++)
174
buf2 = malloc (count);
175
memcpy (buf2, buf, count);
176
for (i = 0; i < l; i++)
184
ret = write (fd, buf2, count2);
191
* The testdsp() routine checks the capabilities of a given audio device number
192
* (parameter n) and decides if the test sound needs to be played.
197
testdsp (char *devnode, int n, int flags)
200
struct timeval t1, t2;
205
int open_flags = O_WRONLY;
206
long long total_bytes = 0;
207
unsigned int tmp, caps;
209
short *test_data, *tmp_buf = NULL;
212
* Use {!nlink O_EXCL} to bypass virtual mixing and to access the actual
213
* hardware device directly. Note that we also have to use
214
* {!nlink SNDCTL_AUDIOINFO_EX} instead of usual SNDCTL_AUDIOINFO since it
215
* returns information that is valid when the device is opened with
218
* If the device is busy we will try to open it without O_EXCL.
222
* If the -V option was set then don't use O_EXCL.
224
if (!(flags & TF_VIRTUAL))
225
open_flags |= O_EXCL;
227
hd = open (devnode, open_flags, 0);
228
if (hd == -1 && errno == EBUSY)
231
* Try without O_EXCL which enables virtual mixing. In this way the device
232
* can almost certainly be opened. However the results may be different
233
* than when the device is used directly.
236
hd = open (devnode, O_WRONLY, 0);
245
printf ("Can't open the device\n");
250
if (ioctl (hd, SNDCTL_DSP_GETCAPS, &caps) == -1)
252
perror ("SNDCTL_DSP_GETCAPS");
253
printf ("Couldn't get the device capabilities\n");
258
test_bytes = ((SHORTER_TEST) ? 2000 : data_len);
261
* Setup the sample format. Since OSS will support {!nlink AFMT_S16_NE} regardless
262
* of the device we do not need to support any other formats.
266
if (ioctl (hd, SNDCTL_DSP_SETFMT, &tmp) == -1 || tmp != AFMT_S16_NE)
269
printf ("Device doesn't support the native 16 bit sample format (%x)\n",
275
* Setup the device for stereo playback. Once again we can simply assume that
276
* stereo will always work before OSS takes care of this by emulation if
280
if (ioctl (hd, SNDCTL_DSP_CHANNELS, &tmp) == -1 || tmp != 2)
283
printf ("The device doesn't support stereo (%d)\n", tmp);
288
* Set up the sample rate. Convrt the sample rate if necessary.
289
* Note that actually OSS will handle any sample rates by doing the
290
* required conversions on fly. However it's possible that some professional
291
* audio devices are configured so that the sample rate conversions are
292
* not permitted. This is unusual but we wanted the osstest utility to
293
* work OK even in these cases. This is not necessary in ordinary
298
if (ioctl (hd, SNDCTL_DSP_SPEED, &tmp) == -1)
301
perror ("Set speed");
306
if (sample_rate != SAMPLE_RATE)
310
* We need to do the sample rate conversion because the device
311
* is configured not to do it.
315
printf ("sr=%d Hz ", sample_rate);
317
a = SAMPLE_RATE / 100;
318
b = sample_rate / 100;
320
sz = ((test_bytes + 4096) * b) / a;
321
tmp_buf = test_data = malloc (sz);
322
memset (tmp_buf, 0, sz);
325
src_convert (sample_buf, test_data, test_bytes, sample_rate, sz);
327
printf ("The device doesn't support %d Hz\n", SAMPLE_RATE);
332
test_data = sample_buf;
338
/* TF_SNDCONF is used when longer messages should be printed. */
339
if (flags & TF_SNDCONF)
340
printf (" Performing left channel test on %s\n", devnode);
346
* This program will measure the real sampling rate by computing the
347
* total time required to play the sample.
349
* This is not terribly presice with short test sounds but it can be used
350
* to detect if the sampling rate badly wrong. Errors of few percents
351
* is more likely to be caused by poor accuracy of the system clock
352
* rather than problems with the sampling rate.
354
gettimeofday (&t1, NULL);
355
if (audio_write (hd, test_data, test_bytes, CH_LEFT) < 0)
357
printf ("Device returned error: %s\n", strerror (errno));
361
total_bytes = test_bytes;
362
if (flags & TF_SNDCONF)
363
printf (" Test completed OK\n");
369
if (flags & TF_SNDCONF)
370
printf (" Performing right channel test on %s\n", devnode);
374
if (audio_write (hd, test_data, test_bytes, CH_RIGHT) < 0)
376
printf ("Device returned error: %s\n", strerror (errno));
380
total_bytes += test_bytes;
381
if (flags & TF_SNDCONF)
382
printf (" Test completed OK\n");
388
if (flags & TF_SNDCONF)
389
printf (" Performing stereo test on %s\n", devnode);
391
printf ("<stereo> ");
393
if (audio_write (hd, test_data, test_bytes, CH_STEREO) < 0)
395
printf ("Device returned error: %s\n", strerror (errno));
399
total_bytes += test_bytes;
400
gettimeofday (&t2, NULL);
402
ioctl (hd, SNDCTL_DSP_GETODELAY, &delay); /* Ignore errors */
405
* Perform the time computations using milliseconds.
408
t = t2.tv_sec - t1.tv_sec;
411
t += t2.tv_usec / 1000;
412
t -= t1.tv_usec / 1000;
414
total_bytes -= delay;
420
ratio = ((float) total_bytes / (float) sample_rate) * 100.0;
421
if (flags & TF_SNDCONF)
423
(" Test completed OK.\n Sample rate was %8.2f Hz (%4.2f%%)\n",
424
(float) sample_rate * ratio / 100.0, ratio - 100.0);
426
printf ("OK <measured srate %8.2f Hz (%4.2f%%)> ",
427
(float) sample_rate * ratio / 100.0, ratio - 100.0);
431
num_devices_tested++;
440
find_num_devices (void)
445
* Find out the number of available audio devices by calling SNDCTL_SYSINFO.
448
if (ioctl (mixerfd, SNDCTL_SYSINFO, &info) == -1)
453
"OSS has not detected any supported sound hardware\n");
454
fprintf (stderr, "in your system.\n");
459
printf ("SNDCTL_SYSINFO failed: %s\n", strerror (errno));
461
("Cannot get system information. Perhaps you are not running OSS 4.x\nbut some slightly incompatible sound subsystem.\n");
465
printf ("Sound subsystem and version: %s %s (0x%08X)\n",
466
info.product, info.version, info.versionnum);
468
if (uname (&un) != -1)
469
printf ("Platform: %s/%s %s %s\n", un.sysname, un.machine, un.release,
472
return info.numaudios;
476
* The test_device() routine checks certain information about the device
477
* and calls testdsp() to play the test sound.
481
test_device (int t, int flags)
487
* Notice! We use {!nlink SNDCTL_AUDIOINFO_EX} because the device is
488
* going to be opened with {!nlink O_EXCL}. Practically all other
489
* applications should use the normal SNDCTL_AUDIOINFO call instead.
492
if (ioctl (mixerfd, SNDCTL_AUDIOINFO_EX, &ainfo) == -1)
494
perror ("SNDCTL_AUDIOINFO_EX");
498
if (ainfo.card_number != cardno) /* Switched to a new card */
500
printf ("\n*** Scanning sound adapter #%d ***\n", cardno);
503
printf ("%s (audio engine %d): %s\n", ainfo.devnode, ainfo.dev, ainfo.name);
507
printf ("- Device not present - Skipping\n");
511
if (!(ainfo.caps & PCM_CAP_OUTPUT))
513
printf ("- Skipping input only device\n");
518
* By default skip virtual devices except if we have not tested
521
if (!(flags & TF_VIRTUAL) && num_devices_tested > 0)
522
if (ainfo.caps & PCM_CAP_VIRTUAL)
524
printf ("- Skipping virtual device (use -V to force test)\n");
528
if ((ainfo.caps & DSP_CH_MASK) == DSP_CH_MULTI)
530
printf ("- Skipping multi channel device\n");
536
printf ("Note! Device is in use (by PID %d/%s) but will try anyway\n",
537
ainfo.pid, ainfo.cmd);
541
if (flags & TF_QUICK)
542
if (cardno == ainfo.card_number)
544
printf ("- card already tested\n");
548
printf ("- Performing audio playback test... ");
551
cardno = ainfo.card_number;
553
code = testdsp (ainfo.devnode, t, flags);
565
main (int argc, char *argv[])
575
* Simple command line switch handling.
578
while ((i = getopt (argc, argv, "CVflsg:")) != EOF)
598
play_gain = atoi (optarg);
601
printf ("Usage: osstest [options...] [device number]\n"
602
" -V Test virtual mixer devices as well\n"
603
" -l Loop indefinately until interrupted\n"
604
" -g gain Set playback gain (0-100). Default 100.\n"
605
" -f Faster test\n");
610
if ((optind < argc) && (sscanf (argv[optind], "%d", &dev) != 1))
612
fprintf (stderr, "Bad device number %s\n", argv[optind]);
616
if (flags & TF_SYSTEST)
618
printf ("++++ osstest results ++++\n");
622
* Open the mixer device used for calling SNDCTL_SYSINFO and
625
if ((mixerfd = open ("/dev/mixer", O_RDWR, 0)) == -1)
628
perror ("/dev/mixer");
634
prepare (); /* Prepare the wave data */
637
* Enumerate all devices and play the test sounds.
639
maxdev = find_num_devices ();
642
printf ("\n\nNOTICE! You don't have any audio devices available.\n"
643
" It looks like your audio hardware was not recognized\n"
646
" If you have installed OSS just a moment ago then it may be necessary to.\n"
647
" to rebot the system before trying to use the device(s).\n");
652
signal (SIGQUIT, skip_handler);
660
fprintf (stderr, "Bad device number %d\n", dev);
663
if (!test_device (dev, flags))
667
for (t = 0; t < maxdev; t++)
668
if (!test_device (t, flags))
671
if (!(flags & TF_SYSTEST))
674
printf ("\n*** All tests completed OK ***\n");
676
printf ("\n*** Some errors were detected during the tests ***\n");
680
} while (flags & TF_LOOP);