summaryrefslogtreecommitdiff
path: root/tutorials/sndkit/tests
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2013-05-03 21:08:42 +0400
committerIgor Pashev <pashev.igor@gmail.com>2013-05-03 21:08:42 +0400
commit1058def8e7827e56ce4a70afb4aeacb5dc44148f (patch)
tree4495d23e7b54ab5700e3839081e797c1eafe0db9 /tutorials/sndkit/tests
downloadoss4-upstream/4.2-build2006.tar.gz
Imported Upstream version 4.2-build2006upstream/4.2-build2006upstream
Diffstat (limited to 'tutorials/sndkit/tests')
-rw-r--r--tutorials/sndkit/tests/Makefile11
-rw-r--r--tutorials/sndkit/tests/README.1ST11
-rw-r--r--tutorials/sndkit/tests/ioctl_test.c624
-rw-r--r--tutorials/sndkit/tests/iosync.c232
-rw-r--r--tutorials/sndkit/tests/multich16.c126
-rw-r--r--tutorials/sndkit/tests/multich32.c126
-rw-r--r--tutorials/sndkit/tests/musicin.c222
-rw-r--r--tutorials/sndkit/tests/seltest2.c113
-rw-r--r--tutorials/sndkit/tests/singen.inc38
-rw-r--r--tutorials/sndkit/tests/spdif_in_debug.c303
-rw-r--r--tutorials/sndkit/tests/sweepdown.c126
-rw-r--r--tutorials/sndkit/tests/sweepup.c122
-rw-r--r--tutorials/sndkit/tests/synctest.c96
13 files changed, 2150 insertions, 0 deletions
diff --git a/tutorials/sndkit/tests/Makefile b/tutorials/sndkit/tests/Makefile
new file mode 100644
index 0000000..e3fb129
--- /dev/null
+++ b/tutorials/sndkit/tests/Makefile
@@ -0,0 +1,11 @@
+TARGETS=iosync multich16 multich32 musicin seltest2 spdif_in_debug sweepdown sweepup synctest ioctl_test
+
+CFLAGS=-I../../../include
+
+all: ${TARGETS}
+
+sweepup:
+ $(CC) ${CFLAGS} $(LDFLAGS) -lm -o sweepup sweepup.c
+
+clean:
+ rm -f ${TARGETS} *.o x y z *~
diff --git a/tutorials/sndkit/tests/README.1ST b/tutorials/sndkit/tests/README.1ST
new file mode 100644
index 0000000..8a69f0f
--- /dev/null
+++ b/tutorials/sndkit/tests/README.1ST
@@ -0,0 +1,11 @@
+Important warning
+=================
+
+Many prongrams in this directory are in no way sample programs. Most of them
+intentionally misuse the OSS API to force the drivers to fail if there are
+any bugs in them. Using this kind of stupid methods in ordinary applications
+is asking for troubles.
+
+However some of the programs demonstrate how to use certain new features
+of OSS. In such cases the program name is mentioned somewhere else in the
+OSS documentation.
diff --git a/tutorials/sndkit/tests/ioctl_test.c b/tutorials/sndkit/tests/ioctl_test.c
new file mode 100644
index 0000000..ea0e4b9
--- /dev/null
+++ b/tutorials/sndkit/tests/ioctl_test.c
@@ -0,0 +1,624 @@
+/*
+ * Purpose: This program has been used to verify that some of the ioctl calls work
+ *
+ * Description:
+ * This program can be used to debug some of the most common OSS audio ioctl calls (use the -m option to select):
+ *
+ * Output tests:
+ * -m0 : SNDCTL_DSP_GETOSPTR - The output buffer pointer
+ * -m1 : SNDCTL_DSP_GETODELAY - The output delay
+ * -m2 : SNDCTL_DSP_GETOSPACE - Space available in the output buffer
+ *
+ * Input tests:
+ * -m20 : SNDCTL_DSP_GETISPTR - The input buffer pointer
+ * -m21 : SNDCTL_DSP_GETISPACE - Data available in the input buffer
+ *
+ * CAUTION!
+ *
+ * This program is not an automated test that tells if the device/driver is working correctly or not.
+ * It simply displays the value returned by the ioctl call and gives some visual indication of the
+ * result. You will see a '*' walking left or right on some kind of bar display.
+ *
+ * Tho use this program you should have very detailed knowledge about the internals of OSS. Otherwise
+ * the results will not make any sense to you.
+ *
+ * NOTE!
+ *
+ * Output of this program is supposed to be redirected to a disk file that is to be examined after the
+ * test is finished. Output to a terminal will delay the program too much which gives wrong results.
+ *
+ * How it works:
+ *
+ * There are different tests in this program. All they write audio data to the audio device (no sound will be produced).
+ * After each write call the program will display the information specific to that test. The times displayed are derived
+ * from the number of bytes written to the device so far. It is important to understand that they are not real time. As
+ * long as the device buffer is not completely filled the time difference between two subsequent writes will be zero
+ * (unless the -D option is used).
+ *
+ * Device setup:
+ *
+ * Use the following command line options to select the setup parameters for the device:
+ *
+ * -s NNN Selects the sampling rate (in Hz or kHz)
+ * -c NNN Selects the number of channels (1, 2, ..., N)
+ * -b NNN Selects the number of bits (8, 16 or 32)
+ *
+ * -f NNN Selects the fragment size (fs = 2**NNN)
+ * -n NNN Selects the number of fragments (2 to N)
+ * -d NNN Selects the output device to use (/dev/dsp by default)
+ *
+ * -r Disables automatic format conversions performed by OSS
+ * -B Open the physical device directly (bypassing virtual mixer (vmix))
+ *
+ * -w NNN Selects the number of bytes written during each loop. By default this is
+ * equal to the fragment size.
+ * -D NNN Delay NNN milliseconds after each write/read (before displaying the test output).
+ * This emulates the processing done by an application. Using too long
+ * delay times will cause buffer underruns. Use delays that are shorter than the fragment time
+ * reported by the program. Note that granularity of the system timer is about 10 ms in typical
+ * systems (HZ=100). This means that the delay time will always be rounded up to the nearest
+ * system timer tick aftere the requested time. Using -D1 may result in up to 10-20 milliseconds of
+ * delay.
+ */
+/*
+ *
+ * This file is part of Open Sound System.
+ *
+ * Copyright (C) 4Front Technologies 1996-2008.
+ *
+ * This this source file is released under GPL v2 license (no other versions).
+ * See the COPYING file included in the main directory of this source
+ * distribution for the license terms and conditions.
+ *
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <string.h>
+#include <soundcard.h>
+#ifdef _AIX
+#include <sys/select.h>
+#endif
+
+typedef void (*measure_f_t) (int fd);
+
+measure_f_t measure_f = NULL, run_test = NULL;
+
+char *name = "Unknown";
+
+char *dspdev = "/dev/dsp";
+int mode = 0;
+int fd = -1;
+int speed = 48000;
+int bits = 16;
+int fmt = AFMT_S16_LE;
+int channels = 2;
+unsigned char silence = 0;
+int fragsize = 0; /* Use default */
+int fragcount = 0x7fff; /* Unlimited */
+int write_size = 0;
+int write_byte = 0;
+int raw_mode = 0;
+int loop_delay = 0;
+
+long long prev_time = 0;
+
+int data_rate, buffer_size;
+
+static long long
+get_usecs(void)
+{
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+
+ return (long long)tv.tv_sec * 1000000LL + (long long)tv.tv_usec;
+}
+
+static void
+player (int fd)
+{
+ char *buffer;
+
+ if ((buffer = malloc (write_size)) == NULL)
+ {
+ fprintf (stderr, "Out of memory\n");
+ exit (EXIT_FAILURE);
+ }
+
+ memset (buffer, silence, write_size);
+
+ while (1)
+ {
+ long long t, d;
+
+ t = get_usecs ();
+
+ d = t - prev_time;
+ prev_time = t;
+
+ printf("d=%2lld.%03lldms ", d / 1000LL, d % 1000LL);
+
+ if (write (fd, buffer, write_size) != write_size)
+ {
+ perror ("write");
+ exit (EXIT_FAILURE);
+ }
+
+ if (loop_delay > 0)
+ usleep (loop_delay * 1000);
+
+ measure_f (fd);
+
+ write_byte += write_size;
+ }
+}
+
+static void
+recorder (int fd)
+{
+ char *buffer;
+
+ if ((buffer = malloc (write_size)) == NULL)
+ {
+ fprintf (stderr, "Out of memory\n");
+ exit (EXIT_FAILURE);
+ }
+
+ while (1)
+ {
+ long long t, d;
+
+ t = get_usecs ();
+
+ d = t - prev_time;
+ prev_time = t;
+
+ printf("d=%2lld.%03lldms ", d / 1000LL, d % 1000LL);
+
+ if (read (fd, buffer, write_size) != write_size)
+ {
+ perror ("read");
+ exit (EXIT_FAILURE);
+ }
+
+ if (loop_delay > 0)
+ usleep (loop_delay * 1000);
+
+ measure_f (fd);
+
+ write_byte += write_size;
+ }
+}
+
+static void
+print_spacing (int i)
+{
+ if ((i % 10) == 0)
+ {
+ printf ("%d", (i / 10) % 10);
+ return;
+ }
+
+ if ((i % 5) == 0)
+ {
+ printf(",");
+ return;
+ }
+
+ printf (".");
+}
+
+static void
+error_check (int fd)
+{
+ audio_errinfo err;
+
+ if (ioctl (fd, SNDCTL_DSP_GETERROR, &err) == -1)
+ return;
+
+ if (err.play_underruns > 0)
+ printf (" %d underruns\n", err.play_underruns);
+
+ if (err.rec_overruns > 0)
+ printf (" %d overruns\n", err.rec_overruns);
+}
+
+static void
+measure_getoptr (int fd)
+{
+ count_info ci;
+ int i, n;
+
+ if (ioctl (fd, SNDCTL_DSP_GETOPTR, &ci) == -1)
+ {
+ perror ("SNDCTL_DSP_GETOPTR");
+ exit (EXIT_FAILURE);
+ }
+
+ n = (100 * ci.ptr + buffer_size / 2) / buffer_size;
+
+ printf ("b=%8d, t=%8d ms, p=%6d : ", write_byte,
+ (1000 * write_byte + data_rate / 2) / data_rate, ci.ptr);
+
+ for (i = 0; i < n; i++)
+ print_spacing (i);
+ printf ("*");
+
+ if (n < 100)
+ {
+ for (i = n + 1; i < 100; i++)
+ print_spacing (i);
+ printf ("%%");
+ }
+
+ error_check (fd);
+ printf ("\n");
+ fflush (stdout);
+}
+
+static void
+measure_getiptr (int fd)
+{
+ count_info ci;
+ int i, n;
+
+ if (ioctl (fd, SNDCTL_DSP_GETIPTR, &ci) == -1)
+ {
+ perror ("SNDCTL_DSP_GETIPTR");
+ exit (EXIT_FAILURE);
+ }
+
+ n = (100 * ci.ptr + buffer_size / 2) / buffer_size;
+
+ printf ("b=%8d, t=%8d ms, p=%6d : ", write_byte,
+ (1000 * write_byte + data_rate / 2) / data_rate, ci.ptr);
+
+ for (i = 0; i < n; i++)
+ print_spacing (i);
+ printf ("*");
+
+ if (n < 100)
+ {
+ for (i = n + 1; i < 100; i++)
+ print_spacing (i);
+ printf ("%%");
+ }
+
+ error_check (fd);
+ printf ("\n");
+ fflush (stdout);
+}
+
+static void
+measure_getospace (int fd)
+{
+ audio_buf_info bi;
+ int i, n;
+
+ if (ioctl (fd, SNDCTL_DSP_GETOSPACE, &bi) == -1)
+ {
+ perror ("SNDCTL_DSP_GETOSPACE");
+ exit (EXIT_FAILURE);
+ }
+
+ n = (100 * bi.bytes + buffer_size / 2) / buffer_size;
+
+ printf ("b=%8d, t=%8d ms, p=%6d : ", write_byte,
+ (1000 * write_byte + data_rate / 2) / data_rate, bi.bytes);
+
+ for (i = 0; i < n; i++)
+ print_spacing (i);
+ printf ("*");
+
+ if (n < 100)
+ {
+ for (i = n + 1; i < 100; i++)
+ print_spacing (i);
+ printf ("%%");
+ }
+
+ error_check (fd);
+ printf ("\n");
+ fflush (stdout);
+}
+
+static void
+measure_getispace (int fd)
+{
+ audio_buf_info bi;
+ int i, n;
+
+ if (ioctl (fd, SNDCTL_DSP_GETISPACE, &bi) == -1)
+ {
+ perror ("SNDCTL_DSP_GETISPACE");
+ exit (EXIT_FAILURE);
+ }
+
+ n = (100 * bi.bytes + buffer_size / 2) / buffer_size;
+
+ printf ("b=%8d, t=%8d ms, p=%6d : ", write_byte,
+ (1000 * write_byte + data_rate / 2) / data_rate, bi.bytes);
+
+ for (i = 0; i < n; i++)
+ print_spacing (i);
+ printf ("*");
+
+ if (n < 100)
+ {
+ for (i = n + 1; i < 100; i++)
+ print_spacing (i);
+ printf ("%%");
+ }
+
+ error_check (fd);
+ printf ("\n");
+ fflush (stdout);
+}
+
+static void
+measure_getodelay (int fd)
+{
+ int d, i, n;
+
+ if (ioctl (fd, SNDCTL_DSP_GETODELAY, &d) == -1)
+ {
+ perror ("SNDCTL_DSP_GETODELAY");
+ exit (EXIT_FAILURE);
+ }
+
+ n = (100 * d + buffer_size / 2) / buffer_size;
+
+ printf ("b=%8d, t=%8d ms, d=%6d : ", write_byte,
+ (1000 * write_byte + data_rate / 2) / data_rate, d);
+
+ for (i = 0; i < n; i++)
+ print_spacing (i);
+ printf ("*");
+
+ if (n < 100)
+ {
+ for (i = n + 1; i < 100; i++)
+ print_spacing (i);
+ printf ("%%");
+ }
+
+ error_check (fd);
+ printf ("\n");
+ fflush (stdout);
+}
+
+int
+main (int argc, char *argv[])
+{
+ int i;
+ int tmp;
+ int is_input = 0;
+ audio_buf_info bi;
+
+ int open_mode = 0;
+
+ measure_f = measure_getospace;
+
+ while ((i = getopt (argc, argv, "rBd:m:s:c:b:f:n:w:D:")) != EOF)
+ switch (i)
+ {
+ case 'd':
+ dspdev = optarg;
+ break;
+
+ case 'm':
+ mode = atoi (optarg);
+ break;
+
+ case 's':
+ speed = atoi (optarg);
+ if (speed < 200)
+ speed *= 1000;
+ break;
+
+ case 'c':
+ channels = atoi (optarg);
+ break;
+
+ case 'b':
+ bits = atoi (optarg);
+ break;
+
+ case 'f':
+ fragsize = atoi (optarg);
+ break;
+
+ case 'n':
+ fragcount = atoi (optarg);
+ break;
+
+ case 'w':
+ write_size = atoi (optarg);
+ break;
+
+ case 'D':
+ loop_delay = atoi (optarg);
+ break;
+
+ case 'r':
+ raw_mode = 1;
+ break;
+
+ case 'B':
+ open_mode |= O_EXCL;
+ break;
+ }
+
+ switch (bits)
+ {
+ case 8:
+ bits = AFMT_U8;
+ silence = 0x80;
+ break;
+ case 16:
+ bits = AFMT_S16_NE;
+ break;
+ case 32:
+ bits = AFMT_S32_LE;
+ break;
+ default:
+ fprintf (stderr, "Bad numer of bits %d\n", bits);
+ exit (EXIT_FAILURE);
+ }
+
+ switch (mode)
+ {
+ case 0:
+ measure_f = measure_getoptr;
+ name = "Getoptr";
+ run_test = player;
+ open_mode |= O_WRONLY;
+ break;
+
+ case 1:
+ measure_f = measure_getodelay;
+ name = "Getodelay";
+ run_test = player;
+ open_mode |= O_WRONLY;
+ break;
+
+ case 2:
+ measure_f = measure_getospace;
+ name = "Getospace";
+ run_test = player;
+ open_mode |= O_WRONLY;
+ break;
+
+ case 20:
+ measure_f = measure_getiptr;
+ name = "Getiptr";
+ run_test = recorder;
+ open_mode |= O_RDONLY;
+ is_input = 1;
+ break;
+
+ case 21:
+ measure_f = measure_getispace;
+ name = "Getispace";
+ run_test = recorder;
+ open_mode |= O_RDONLY;
+ is_input = 1;
+ break;
+
+ default:
+ fprintf (stderr, "Bad mode -m %d\n", mode);
+ exit (EXIT_FAILURE);
+ }
+
+ if ((fd = open (dspdev, open_mode, 0)) == -1)
+ {
+ perror (dspdev);
+ exit (EXIT_FAILURE);
+ }
+
+ if (raw_mode)
+ {
+ tmp = 0;
+ ioctl (fd, SNDCTL_DSP_COOKEDMODE, &tmp); /* Ignore errors */
+ }
+
+ if (fragsize != 0)
+ {
+ fragsize = (fragsize & 0xffff) | ((fragcount & 0x7fff) << 16);
+ ioctl (fd, SNDCTL_DSP_SETFRAGMENT, &fragsize); /* Ignore errors */
+ }
+
+ tmp = fmt;
+ if (ioctl (fd, SNDCTL_DSP_SETFMT, &tmp) == -1)
+ {
+ perror ("SNDCTL_DSP_SETFMT");
+ exit (EXIT_FAILURE);
+ }
+
+ if (tmp != fmt)
+ {
+ fprintf (stderr,
+ "Failed to select the requested sample format (%x, %x)\n", fmt,
+ tmp);
+ exit (EXIT_FAILURE);
+ }
+
+ tmp = channels;
+ if (ioctl (fd, SNDCTL_DSP_CHANNELS, &tmp) == -1)
+ {
+ perror ("SNDCTL_DSP_CHANNELS");
+ exit (EXIT_FAILURE);
+ }
+
+ if (tmp != channels)
+ {
+ fprintf (stderr, "Failed to select the requested #channels (%d, %d)\n",
+ channels, tmp);
+ exit (EXIT_FAILURE);
+ }
+
+ tmp = speed;
+ if (ioctl (fd, SNDCTL_DSP_SPEED, &tmp) == -1)
+ {
+ perror ("SNDCTL_DSP_SPEED");
+ exit (EXIT_FAILURE);
+ }
+
+ if (tmp != speed)
+ {
+ fprintf (stderr, "Failed to select the requested rate (%d, %d)\n",
+ speed, tmp);
+ exit (EXIT_FAILURE);
+ }
+
+ if (is_input)
+ {
+ if (ioctl (fd, SNDCTL_DSP_GETISPACE, &bi) == -1)
+ {
+ perror ("SNDCTL_DSP_GETISPACE");
+ exit (EXIT_FAILURE);
+ }
+ }
+ else
+ {
+ if (ioctl (fd, SNDCTL_DSP_GETOSPACE, &bi) == -1)
+ {
+ perror ("SNDCTL_DSP_GETOSPACE");
+ exit (EXIT_FAILURE);
+ }
+ }
+
+ buffer_size = bi.fragsize * bi.fragstotal;
+
+ data_rate = speed * channels * (bits / 8);
+
+ printf ("fragsize %d, nfrags %d, total buffer %d (bytes)\n", bi.fragsize,
+ bi.fragstotal, buffer_size);
+
+ if (write_size == 0)
+ write_size = bi.fragsize;
+
+ printf ("Sample rate rate %d Hz, channels %d, bits %d\n", speed, channels,
+ bits);
+ printf ("Data rate %d bytes / second\n", data_rate);
+ printf ("Fragment time %d ms\n",
+ (1000 * bi.fragsize + data_rate / 2) / data_rate);
+ printf ("Buffer time %d ms\n",
+ (1000 * buffer_size + data_rate / 2) / data_rate);
+ printf ("Write size %d bytes, write time %d ms\n", write_size,
+ (1000 * write_size + data_rate / 2) / data_rate);
+
+ printf ("\n");
+ printf ("*** Starting test %d (%s)\n", mode, name);
+ printf ("\n");
+
+ prev_time = get_usecs();
+
+ run_test (fd);
+ exit (0);
+}
diff --git a/tutorials/sndkit/tests/iosync.c b/tutorials/sndkit/tests/iosync.c
new file mode 100644
index 0000000..fc9aa52
--- /dev/null
+++ b/tutorials/sndkit/tests/iosync.c
@@ -0,0 +1,232 @@
+/*
+ * Purpose: Measuring the hardware level latencies.
+ * Copyright (C) 4Front Technologies, 2002-2004. Released under GPLv2/CDDL.
+ *
+ * Description:
+ * This simple program was once used to measure internal latencies of some
+ * sound cards. It was written in great hurry so don't use it as a program
+ * template. Error checking is completely inadequate.
+ *
+ * This program requires that the output of the sound card is connected
+ * to the line in of the same card.
+ *
+ * The program will play a short spike and then measure how many "silent "
+ * samples there are in the input before the spike is seen. You can
+ * get the delay in seconds by dividing this sample count by the
+ * sample rate.
+ *
+ * This is the total delay value that includes both the output and input
+ * delays. There is no way to estimate how large part of it is caused by
+ * input or output.
+ */
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <soundcard.h>
+#ifdef _AIX
+#include <sys/select.h>
+#endif
+
+int frag_size = 0;
+static int pos = 0;
+
+static int
+open_device (char *name, int mode)
+{
+ int tmp, fd;
+
+ int frag = 0x0020000b; /* 32 fragments of 2^11=2048 bytes */
+
+ if ((fd = open (name, mode, 0)) == -1)
+ {
+ perror (name);
+ exit (-1);
+ }
+
+/*
+ * WARNING!!!!!!!!!!!
+ *
+ * The following code makes ioctl calls without verifying that the
+ * result was OK. Don't do this at home.
+ */
+ if (ioctl (fd, SNDCTL_DSP_SETFRAGMENT, &frag) == -1)
+ perror ("SNDCTL_DSP_SETFRAGMENT");
+
+ tmp = 1;
+ if (ioctl (fd, SNDCTL_DSP_CHANNELS, &tmp) == -1)
+ perror ("SNDCTL_DSP_CHANNELS");
+
+ tmp = AFMT_S16_NE;
+ if (ioctl (fd, SNDCTL_DSP_SETFMT, &tmp) == -1)
+ perror ("SNDCTL_DSP_SETFMT");
+
+ tmp = 48000;
+ if (ioctl (fd, SNDCTL_DSP_SPEED, &tmp) == -1) /* And #channels & #bits if required */
+ perror ("SNDCTL_DSP_SPEED");
+
+ if (ioctl (fd, SNDCTL_DSP_GETBLKSIZE, &frag_size) == -1)
+ perror ("SNDCTL_DSP_GETBLKSIZE");
+
+ tmp = 0;
+ if (ioctl (fd, SNDCTL_DSP_SETTRIGGER, &tmp) == -1)
+ perror ("SNDCTL_DSP_SETTRIGGER");
+/*
+ * WARNING!!!!!!!!!!!
+ *
+ * The above code makes ioctl calls without verifying that the
+ * result was OK. Don't do this at home.
+ */
+
+ return fd;
+}
+
+static void
+gen_spike (short *buf)
+{
+ int i, p;
+
+ for (i = 0; i < 30; i++)
+ {
+ p = (i / 4) % 3;
+ buf[i] = (p - 1) * 8 * 1024;
+ }
+}
+
+static void
+check_buf (short *buf, int l)
+{
+ int i;
+
+ for (i = 0; i < l; i++)
+ {
+ int v;
+
+ v = buf[i];
+ if (v < 0)
+ v = -v;
+ if (v > 4096)
+ printf ("%d = %d\n", pos, v);
+ pos++;
+ }
+}
+
+int
+main (int argc, char *argv[])
+{
+ int fd_in, fd_out;
+ char *name_in = "/dev/dsp", *name_out = NULL;
+
+ int tmp;
+ int have_data = 0;
+
+ char buf[128 * 1024];
+
+ int n, l;
+
+ fd_set reads, writes;
+
+ if (argc > 1)
+ name_in = argv[1];
+ if (argc > 2)
+ name_out = argv[2];
+
+ if (name_out != NULL)
+ {
+ fd_in = open_device (name_in, O_RDONLY);
+ fd_out = open_device (name_out, O_WRONLY);
+ }
+ else
+ {
+ fd_in = fd_out == open_device (name_in, O_RDWR);
+ }
+
+ memset (buf, 0, frag_size);
+ gen_spike ((short *) buf);
+ write (fd_out, buf, frag_size);
+
+ if (fd_out != fd_in)
+ {
+ tmp = PCM_ENABLE_INPUT;
+ ioctl (fd_in, SNDCTL_DSP_SETTRIGGER, &tmp);
+ tmp = PCM_ENABLE_OUTPUT;
+ ioctl (fd_out, SNDCTL_DSP_SETTRIGGER, &tmp);
+ }
+ else
+ {
+ tmp = PCM_ENABLE_INPUT | PCM_ENABLE_OUTPUT;
+ ioctl (fd_in, SNDCTL_DSP_SETTRIGGER, &tmp);
+ }
+
+ while (1)
+ {
+ struct timeval time;
+
+ FD_ZERO (&reads);
+ FD_ZERO (&writes);
+
+ FD_SET (fd_out, &writes);
+ FD_SET (fd_in, &reads);
+
+ time.tv_sec = 0;
+ time.tv_usec = 100000;
+ if ((l = select (fd_out + 1, &reads, &writes, NULL, &time)) == -1)
+ {
+ perror ("select");
+ exit (-1);
+ }
+ if (l == 0)
+ printf ("Timeout ");
+
+ if (FD_ISSET (fd_in, &reads))
+ {
+ struct audio_buf_info info;
+
+ if (ioctl (fd_in, SNDCTL_DSP_GETISPACE, &info) == -1)
+ {
+ perror ("select");
+ exit (-1);
+ }
+
+ n = info.bytes;
+ if (n <= 0)
+ {
+ printf ("Error: NREAD=%d\n", n);
+ exit (-1);
+ }
+
+ l = read (fd_in, buf, n);
+ if (l > 0)
+ have_data = 1;
+ else
+ perror ("read");
+ check_buf ((short *) buf, l / 2);
+ }
+
+ if (FD_ISSET (fd_out, &writes))
+ {
+ int i;
+
+ struct audio_buf_info info;
+
+ if (ioctl (fd_out, SNDCTL_DSP_GETOSPACE, &info) == -1)
+ {
+ perror ("select");
+ exit (-1);
+ }
+
+ n = info.bytes;
+
+ /* printf("Write %d", l); */
+ l = n;
+ memset (buf, 0, l);
+ if (write (fd_out, buf, l) == l);
+ have_data = 0;
+ }
+ }
+
+ exit (0);
+}
diff --git a/tutorials/sndkit/tests/multich16.c b/tutorials/sndkit/tests/multich16.c
new file mode 100644
index 0000000..b575a02
--- /dev/null
+++ b/tutorials/sndkit/tests/multich16.c
@@ -0,0 +1,126 @@
+/*
+ * Multi channel audio test.
+ *
+ * This program is intended to test playback of 16 bit samples using 4 or more
+ * channels at 48000 Hz. The program plays sine wave pulses sequentially on
+ * channels 0 to N-1.
+ *
+ * Arguments:
+ *
+ * 1: Number of channelts (default is 8).
+ * 2: Audio device (/dev/dsp by default).
+ * 3-N: Options
+ * -b Bypass virtual mixer
+ * -r Raw mode (disables automatic sample rate/format conversions)
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <soundcard.h>
+
+static int sinedata[48] = {
+
+ 0, 4276, 8480, 12539, 16383, 19947, 23169, 25995,
+ 28377, 30272, 31650, 32486, 32767, 32486, 31650, 30272,
+ 28377, 25995, 23169, 19947, 16383, 12539, 8480, 4276,
+ 0, -4276, -8480, -12539, -16383, -19947, -23169, -25995,
+ -28377, -30272, -31650, -32486, -32767, -32486, -31650, -30272,
+ -28377, -25995, -23169, -19947, -16383, -12539, -8480, -4276
+};
+
+int
+main (int argc, char *argv[])
+{
+ char *dev = "/dev/dsp";
+ int fd, l, i, n = 0, ch, p = 0, phase = 0, arg, channels, srate, thisch = 0;
+ int tick = 0;
+ int nch = 8;
+ int bypass_vmix=0;
+ int disable_format_conversions=0;
+
+ short buf[1024];
+
+ if (argc > 1)
+ if (sscanf (argv[1], "%d", &nch) != 1)
+ nch = 2;
+
+ if (argc > 2)
+ dev = argv[2];
+
+ for (i=3;i<argc;i++)
+ if (argv[i][0]=='-')
+ switch (argv[i][1])
+ {
+ case 'b': /* Bypass virtual mixer */
+ bypass_vmix = O_EXCL;
+ break;
+
+ case 'r': /* Use raw mode (disable automatic format conversions) */
+ disable_format_conversions=1;
+ break;
+ }
+
+ if ((fd = open (dev, O_WRONLY|bypass_vmix, 0)) == -1)
+ {
+ perror (dev);
+ exit (-1);
+ }
+
+ if (disable_format_conversions)
+ {
+ arg=0;
+ ioctl(fd, SNDCTL_DSP_COOKEDMODE, &arg);
+ }
+
+ arg = nch;
+ if (ioctl (fd, SNDCTL_DSP_CHANNELS, &arg) == -1)
+ perror ("SNDCTL_DSP_CHANNELS");
+ channels = arg;
+ fprintf (stderr, "Channels %d\n", arg);
+
+ arg = AFMT_S16_NE;
+ if (ioctl (fd, SNDCTL_DSP_SETFMT, &arg) == -1)
+ perror ("SNDCTL_DSP_SETFMT");
+ fprintf (stderr, "Format %x\n", arg);
+
+ arg = 48000;
+ if (ioctl (fd, SNDCTL_DSP_SPEED, &arg) == -1)
+ perror ("SNDCTL_DSP_SPEED");
+ printf ("Using sampling rate %d\n", arg);
+ srate = arg;
+
+ while (1)
+ {
+ for (ch = 0; ch < channels; ch++)
+ {
+ if (ch == thisch)
+ {
+ buf[p] = sinedata[phase];
+ phase = (phase + 1 + (ch / 2)) % 48;
+ if (phase == 0 && tick > 10 * channels)
+ {
+ thisch = (thisch + 1) % channels;
+ tick = 0;
+ }
+ }
+ else
+ buf[p] = 0;
+
+ p++;
+
+ if (p >= sizeof (buf) / 2)
+ {
+ if (write (fd, buf, p * 2) != p * 2)
+ perror ("write");
+ p = 0;
+ tick++;
+
+ }
+ }
+ n++;
+ }
+
+ exit (0);
+}
diff --git a/tutorials/sndkit/tests/multich32.c b/tutorials/sndkit/tests/multich32.c
new file mode 100644
index 0000000..ab39297
--- /dev/null
+++ b/tutorials/sndkit/tests/multich32.c
@@ -0,0 +1,126 @@
+/*
+ * Multi channel audio test.
+ *
+ * This program is intended to test playback of 16 bit samples using 4 or more
+ * channels at 48000 Hz. The program plays sine wave pulses sequentially on
+ * channels 0 to N-1.
+ *
+ * Arguments:
+ *
+ * 1: Number of channelts (default is 8).
+ * 2: Audio device (/dev/dsp by default).
+ * 3-N: Options
+ * -b Bypass virtual mixer
+ * -r Raw mode (disables automatic sample rate/format conversions)
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <soundcard.h>
+
+static int sinedata[48] = {
+
+ 0, 4276, 8480, 12539, 16383, 19947, 23169, 25995,
+ 28377, 30272, 31650, 32486, 32767, 32486, 31650, 30272,
+ 28377, 25995, 23169, 19947, 16383, 12539, 8480, 4276,
+ 0, -4276, -8480, -12539, -16383, -19947, -23169, -25995,
+ -28377, -30272, -31650, -32486, -32767, -32486, -31650, -30272,
+ -28377, -25995, -23169, -19947, -16383, -12539, -8480, -4276
+};
+
+int
+main (int argc, char *argv[])
+{
+ char *dev = "/dev/dsp";
+ int fd, l, i, n = 0, ch, p = 0, phase = 0, arg, channels, srate, thisch = 0;
+ int tick = 0;
+ int nch = 8;
+ int bypass_vmix=0;
+ int disable_format_conversions=0;
+
+ int buf[32*1024];
+
+ if (argc > 1)
+ if (sscanf (argv[1], "%d", &nch) != 1)
+ nch = 2;
+
+ if (argc > 2)
+ dev = argv[2];
+
+ for (i=3;i<argc;i++)
+ if (argv[i][0]=='-')
+ switch (argv[i][1])
+ {
+ case 'b': /* Bypass virtual mixer */
+ bypass_vmix = O_EXCL;
+ break;
+
+ case 'r': /* Use raw mode (disable automatic format conversions) */
+ disable_format_conversions=1;
+ break;
+ }
+
+ if ((fd = open (dev, O_WRONLY|bypass_vmix, 0)) == -1)
+ {
+ perror (dev);
+ exit (-1);
+ }
+
+ if (disable_format_conversions)
+ {
+ arg=0;
+ ioctl(fd, SNDCTL_DSP_COOKEDMODE, &arg);
+ }
+
+ arg = nch;
+ if (ioctl (fd, SNDCTL_DSP_CHANNELS, &arg) == -1)
+ perror ("SNDCTL_DSP_CHANNELS");
+ channels = arg;
+ fprintf (stderr, "Channels %d\n", arg);
+
+ arg = AFMT_S32_NE;
+ if (ioctl (fd, SNDCTL_DSP_SETFMT, &arg) == -1)
+ perror ("SNDCTL_DSP_SETFMT");
+ fprintf (stderr, "Format %x\n", arg);
+
+ arg = 48000;
+ if (ioctl (fd, SNDCTL_DSP_SPEED, &arg) == -1)
+ perror ("SNDCTL_DSP_SPEED");
+ printf ("Using sampling rate %d\n", arg);
+ srate = arg;
+
+ while (1)
+ {
+ for (ch = 0; ch < channels; ch++)
+ {
+ if (ch == thisch)
+ {
+ buf[p] = sinedata[phase]<<16;
+ phase = (phase + 1 + (ch / 2)) % 48;
+ if (phase == 0 && tick > 10 * channels)
+ {
+ thisch = (thisch + 1) % channels;
+ tick = 0;
+ }
+ }
+ else
+ buf[p] = 0;
+
+ p++;
+
+ if (p >= sizeof (buf) / 4)
+ {
+ if (write (fd, buf, p * 4) != p * 4)
+ perror ("write");
+ p = 0;
+ tick++;
+
+ }
+ }
+ n++;
+ }
+
+ exit (0);
+}
diff --git a/tutorials/sndkit/tests/musicin.c b/tutorials/sndkit/tests/musicin.c
new file mode 100644
index 0000000..651e27a
--- /dev/null
+++ b/tutorials/sndkit/tests/musicin.c
@@ -0,0 +1,222 @@
+/*
+ * Purpose: A program that demonstrates MIDI input with /dev/music (obsolete)
+ * Copyright (C) 4Front Technologies, 2002-2004. Released under GPLv2/CDDL.
+ *
+ * Description:
+ * This program was supposed to be a sample program for doing MIDI input
+ * with the /dev/music interface. However it has not much use since the
+ * /dev/music interface is now obsoleted.
+ *
+ * The /dev/midi interface is recommended in the new applications. Please
+ * see the "{!link MIDI}" section of the OSS Developer's manual.
+ */
+#include <soundcard.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+void
+decode_event (unsigned char *ev)
+{
+ int i;
+
+ for (i = 0; i < 8; i++)
+ {
+ printf ("%02x ", ev[i]);
+ }
+
+ printf (": ");
+
+ switch (ev[0])
+ {
+ case EV_CHN_VOICE:
+ printf ("EV_CHN_VOICE(%d)\t| ", ev[1]);
+ switch (ev[2])
+ {
+ case MIDI_NOTEON:
+ printf ("Note On ch%d note%d vel%d", ev[3], ev[4], ev[5]);
+ break;
+
+ case MIDI_NOTEOFF:
+ printf ("Note Off ch%d note%d vel%d", ev[3], ev[4], ev[5]);
+ break;
+
+ case MIDI_KEY_PRESSURE:
+ printf ("KPressure ch%d note%d vel%d", ev[3], ev[4], ev[5]);
+ break;
+
+ default:
+ printf ("*** Unknown ***");
+ }
+ break;
+
+ case EV_CHN_COMMON:
+ printf ("EV_CHN_COMMON\tdev%d\t| ", ev[1]);
+ switch (ev[2])
+ {
+ case MIDI_CHN_PRESSURE:
+ printf ("MIDI_CHN_PRESSURE ch%d %d", ev[3], ev[4]);
+ break;
+ case MIDI_PGM_CHANGE:
+ printf ("MIDI_PGM_CHANGE ch%d %d", ev[3], ev[4]);
+ break;
+ case MIDI_CTL_CHANGE:
+ printf ("MIDI_CTL_CHANGE ch%d %d,%d", ev[3], ev[4],
+ *(short *) &ev[6]);
+ break;
+ case MIDI_PITCH_BEND:
+ printf ("MIDI_CTL_CHANGE ch%d %d", ev[3], *(short *) &ev[6]);
+ break;
+ default:
+ printf ("*** Unknown ***");
+ }
+ break;
+
+ case EV_SYSEX:
+ printf ("EV_SYSEX\tdev%d: ", ev[1]);
+ for (i = 2; i < 8; i++)
+ printf ("%02x ", ev[i]);
+ break;
+
+ case EV_TIMING:
+ printf ("EV_TIMING\t\t| ");
+ switch (ev[1])
+ {
+ case TMR_START:
+ printf ("TMR_START\t");
+ break;
+ case TMR_STOP:
+ printf ("TMR_STOP\t");
+ break;
+ case TMR_CONTINUE:
+ printf ("TMR_CONTINUE\t");
+ break;
+ case TMR_WAIT_ABS:
+ printf ("TMR_WAIT_ABS\t%10u", *(unsigned int *) &ev[4]);
+ break;
+ case TMR_WAIT_REL:
+ printf ("TMR_WAIT_REL\t%10u", *(unsigned int *) &ev[4]);
+ break;
+ case TMR_ECHO:
+ printf ("TMR_ECHO\t%10u", *(unsigned int *) &ev[4]);
+ break;
+ case TMR_TEMPO:
+ printf ("TMR_TEMPO\t%10u", *(unsigned int *) &ev[4]);
+ break;
+ case TMR_SPP:
+ printf ("TMR_SPP\t%10u", *(unsigned int *) &ev[4]);
+ break;
+ case TMR_TIMESIG:
+ printf ("TMR_TIMESIG\t%10u", *(unsigned int *) &ev[4]);
+ break;
+ }
+ break;
+
+ case EV_SEQ_LOCAL:
+ printf ("EV_SEQ_LOCAL\t*** Should not happen ***");
+ break;
+
+ case EV_SYSTEM:
+ printf ("EV_SYSTEM(%d)\t\t| ", ev[1]);
+ switch (ev[2])
+ {
+ case 0xf0:
+ printf ("SysEx *** Should not happen ***");
+ break;
+
+ case 0xf1:
+ printf ("MTC Qframe %02x", ev[3]);
+ break;
+
+ case 0xf2:
+ printf ("Songpos ptr %02x,%02x", ev[3], ev[4]);
+ break;
+
+ case 0xf3:
+ printf ("Song select %02x", ev[3]);
+ break;
+
+ case 0xf4:
+ case 0xf5:
+ printf ("*** Undefined ***");
+ break;
+
+ case 0xf6:
+ printf ("Tune request");
+ break;
+
+ case 0xf7:
+ printf ("EOX");
+ break;
+ case 0xf8:
+ printf ("Timing clock");
+ break;
+ case 0xf9:
+ printf ("** Undefined ***");
+ break;
+ case 0xfa:
+ printf ("Start");
+ break;
+ case 0xfb:
+ printf ("Continue");
+ break;
+ case 0xfc:
+ printf ("Stop");
+ break;
+ case 0xfd:
+ printf ("** Undefined ***");
+ break;
+ case 0xfe:
+ printf ("Active sensing");
+ break;
+ case 0xff:
+ printf ("SYSTEM RESET");
+ break;
+ }
+ break;
+
+ default:
+ printf ("*** Unknown event type ***");
+ }
+ printf ("\n");
+}
+
+int
+main (int argc, int *argv[])
+{
+ int fd, l, i;
+ unsigned char buf[4096];
+
+ if ((fd = open ("/dev/music", O_RDONLY, 0)) == -1)
+ {
+ perror ("/dev/music");
+ exit (-1);
+ }
+
+ if (ioctl (fd, SNDCTL_SEQ_ACTSENSE_ENABLE, 0) == -1)
+ {
+ perror ("/dev/music ACTSENSE_ENABLE");
+ exit (-1);
+ }
+
+ if (ioctl (fd, SNDCTL_SEQ_TIMING_ENABLE, 0) == -1)
+ {
+ perror ("/dev/music TIMING_ENABLE");
+ exit (-1);
+ }
+
+ if (ioctl (fd, SNDCTL_SEQ_RT_ENABLE, 0) == -1)
+ {
+ perror ("/dev/music RT_ENABLE");
+ exit (-1);
+ }
+
+ while ((l = read (fd, buf, sizeof (buf))) != -1)
+ {
+ for (i = 0; i < l; i += 8)
+ {
+ decode_event (&buf[i]);
+ }
+ }
+}
diff --git a/tutorials/sndkit/tests/seltest2.c b/tutorials/sndkit/tests/seltest2.c
new file mode 100644
index 0000000..d4e3ab8
--- /dev/null
+++ b/tutorials/sndkit/tests/seltest2.c
@@ -0,0 +1,113 @@
+/*
+ Purpose: This program has been used to verify that the select() call works
+ * Copyright (C) 4Front Technologies, 2002-2004. Released under GPLv2/CDDL.
+ *
+ * Description:
+ * This program opens an audio device and then just
+ * copies input to output. Select is used for flow control.
+ */
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <soundcard.h>
+#ifdef _AIX
+#include <sys/select.h>
+#endif
+
+int
+main (int agrc, char *argv[])
+{
+ int fd;
+
+ int tmp;
+
+ char buf[128 * 1024];
+
+ int have_data = 0;
+ int n, l;
+
+ int frag = 0x00200008; /* 32 fragments of 2^8=256 bytes */
+
+ fd_set reads, writes;
+
+ close (0);
+
+ if ((fd = open ("/dev/dsp", O_RDWR, 0)) == -1)
+ {
+ perror ("/dev/dsp open");
+ exit (-1);
+ }
+
+ ioctl (fd, SNDCTL_DSP_SETFRAGMENT, &frag);
+
+/*
+ * Set just the sampling tahe. Use the default format. We do not do any
+ * error checking (maybe not so good idea) because we don't care what
+ * the sampling rate really is.
+ */
+ tmp = 48000;
+ ioctl (fd, SNDCTL_DSP_SPEED, &tmp);
+
+ while (1)
+ {
+ struct timeval time;
+
+ FD_ZERO (&reads);
+ FD_ZERO (&writes);
+
+ if (have_data)
+ FD_SET (fd, &writes);
+ else
+ FD_SET (fd, &reads);
+
+ time.tv_sec = 1;
+ time.tv_usec = 0;
+ if (select (fd + 1, &reads, &writes, NULL, &time) == -1)
+ {
+ perror ("select");
+ exit (-1);
+ }
+
+ if (FD_ISSET (fd, &reads))
+ {
+ struct audio_buf_info info;
+
+ if (ioctl (fd, SNDCTL_DSP_GETISPACE, &info) == -1)
+ {
+ perror ("select");
+ exit (-1);
+ }
+
+ n = info.bytes;
+
+ l = read (fd, buf, n);
+ if (l > 0)
+ have_data = 1;
+ }
+
+ if (FD_ISSET (fd, &writes))
+ {
+ int i;
+
+ struct audio_buf_info info;
+
+ if (ioctl (fd, SNDCTL_DSP_GETOSPACE, &info) == -1)
+ {
+ perror ("select");
+ exit (-1);
+ }
+
+ n = info.bytes;
+
+ printf ("Write %d\n", l);
+ write (fd, buf, l);
+ printf ("OK");
+ have_data = 0;
+ }
+ }
+
+ exit (0);
+}
diff --git a/tutorials/sndkit/tests/singen.inc b/tutorials/sndkit/tests/singen.inc
new file mode 100644
index 0000000..8e2af93
--- /dev/null
+++ b/tutorials/sndkit/tests/singen.inc
@@ -0,0 +1,38 @@
+#if 0
+/*
+ *
+ * This file is part of Open Sound System.
+ *
+ * Copyright (C) 4Front Technologies 1996-2008.
+ *
+ * This this source file is released under GPL v2 license (no other versions).
+ * See the COPYING file included in the main directory of this source
+ * distribution for the license terms and conditions.
+ *
+ */
+{
+ static unsigned int p[10] = { 0 };
+ int *pp;
+ int i;
+
+ static int sinebuf[48] = {
+
+ 0, 4276, 8480, 12539, 16383, 19947, 23169, 25995,
+ 28377, 30272, 31650, 32486, 32767, 32486, 31650, 30272,
+ 28377, 25995, 23169, 19947, 16383, 12539, 8480, 4276,
+ 0, -4276, -8480, -12539, -16383, -19947, -23169, -25995,
+ -28377, -30272, -31650, -32486, -32767, -32486, -31650, -30272,
+ -28377, -25995, -23169, -19947, -16383, -12539, -8480, -4276
+ };
+
+ for (i = 0; i < dmap->grc3state[ch].outsz; i++)
+ {
+ if (0 * ctr)
+ {
+ *((unsigned int *) (p2) + i * channels + ch) =
+ sinebuf[p[ch] % 48] * 64 * 0;
+ p[ch]++;
+ }
+ }
+}
+#endif
diff --git a/tutorials/sndkit/tests/spdif_in_debug.c b/tutorials/sndkit/tests/spdif_in_debug.c
new file mode 100644
index 0000000..20963eb
--- /dev/null
+++ b/tutorials/sndkit/tests/spdif_in_debug.c
@@ -0,0 +1,303 @@
+/*
+ * Purpose: A program that prints the S/PDIF receiver status.
+ * Copyright (C) 4Front Technologies, 2002-2004. Released under GPLv2/CDDL.
+ *
+ * Description:
+ * This program demonstrates use of the {!nlink SNDCTL_DSP_READCTL}
+ * call. It's actually a low cost digital (S/PDIF) input analyzer.
+ *
+ * {!notice This program will work just with a bunch of sound cards because
+ * most devices are not able to return this information. AT this moment the
+ * only card that is verified is M Audio Audiophile 2496. It's possible that
+ * some other M Audio Delta models work too. It's almost certain that
+ * "ordinary" sound cards will never have a digital receiver chip capable to
+ * return this information.}
+ *
+ * Please read the "{!link spdif_control}" section of the OSS Developer's
+ * manual for more info.
+ */
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <time.h>
+#include <soundcard.h>
+
+#undef SHOW_DATA
+#define SHOW_STATUS
+
+#define RATE 48000
+#define CHANNELS 2
+#define BUFSZ (CHANNELS*RATE)
+
+#ifdef SHOW_STATUS
+static int
+xbits (unsigned char b, int first, int last)
+{
+ int v, i;
+
+ v = 0;
+
+ for (i = first; i <= last; i++)
+ {
+ v <<= 1;
+ if (b & (1 << i))
+ v |= 1;
+ }
+
+ return v;
+}
+
+static void
+decode_pro_mode (unsigned char *bits)
+{
+ printf ("Professional mode (PRO=1)\n");
+}
+
+static void
+decode_consumer_mode (unsigned char *bits)
+{
+ int tmp, tmp2, tmp3;
+
+ printf ("Consumer mode (PRO=0)\n");
+
+ printf ("Byte 00=%02x: ", bits[0]);
+ if (bits[0] & 0x02)
+ printf ("Data (not audio) ");
+ else
+ printf ("Audio (not data) ");
+ if (bits[0] & 0x04)
+ printf ("Copy permitted ");
+ else
+ printf ("Copy inhibited ");
+
+ tmp = xbits (bits[0], 3, 5);
+ if (bits[0] & 0x02)
+ printf ("Non-audio=0x%x ", tmp);
+ else
+ printf ("Pre-emph=0x%x ", tmp);
+
+ tmp = xbits (bits[0], 6, 7);
+ printf ("Mode=0x%x ", tmp);
+ printf ("\n");
+
+ printf ("Byte 01=%02x: ", bits[1]);
+ tmp = xbits (bits[1], 0, 2);
+ tmp2 = xbits (bits[1], 3, 6);
+ tmp3 = xbits (bits[1], 7, 7);
+
+ printf ("Category code = %x:%x, L=%d ", tmp, tmp2, tmp3);
+ printf ("\n");
+
+ printf ("Byte 02=%02x: ", bits[2]);
+ tmp = xbits (bits[2], 0, 3);
+ tmp2 = xbits (bits[2], 4, 7);
+
+ printf ("Source number=0x%x Channel number=0x%x ", tmp, tmp2);
+ printf ("\n");
+
+ printf ("Byte 03=%02x: ", bits[3]);
+ tmp = xbits (bits[3], 0, 3);
+ tmp2 = xbits (bits[3], 4, 5);
+
+ printf ("Sample rate=0x%x Clock accuracy=0x%x ", tmp, tmp2);
+ printf ("\n");
+
+}
+#endif
+
+int
+main (int argc, char *argv[])
+{
+ char *devname = "/dev/dsp";
+ unsigned short buf[BUFSZ], expected = 0;
+ int fd, parm, l, i;
+ int bcount = 0;
+
+ if (argc > 1)
+ devname = argv[1];
+
+ if ((fd = open (devname, O_RDONLY, 0)) == -1)
+ {
+ perror (devname);
+ exit (-1);
+ }
+
+ parm = AFMT_S16_NE;
+ if (ioctl (fd, SNDCTL_DSP_SETFMT, &parm) == -1)
+ {
+ perror ("SETFMT");
+ close (fd);
+ exit (-1);
+ }
+
+ if (parm != AFMT_S16_NE)
+ {
+ printf
+ ("Error: 16 bit sample format is not supported by the device\n");
+ printf ("%08x/%08x\n", parm, AFMT_S16_LE);
+ close (fd);
+ exit (-1);
+ }
+
+ parm = CHANNELS;
+ if (ioctl (fd, SNDCTL_DSP_CHANNELS, &parm) == -1)
+ {
+ perror ("CHANNELS");
+ close (fd);
+ exit (-1);
+ }
+
+ parm = RATE;
+ if (ioctl (fd, SNDCTL_DSP_SPEED, &parm) == -1)
+ {
+ perror ("SPEED");
+ close (fd);
+ exit (-1);
+ }
+
+ if (parm != RATE)
+ {
+ printf
+ ("Warning: %d Hz sampling rate is not supported by the device. Will use %d)\n",
+ RATE, parm);
+ }
+
+#ifdef SHOW_DATA
+ while ((l = read (fd, buf, sizeof (buf))) > 0)
+#else
+ while (1)
+#endif
+ {
+#ifdef SHOW_STATUS
+ time_t t;
+ oss_digital_control c;
+
+ c.valid = VAL_CBITIN | VAL_ISTATUS;
+
+ if (ioctl (fd, SNDCTL_DSP_READCTL, &c) == -1)
+ {
+ perror ("SNDCTL_DSP_READCTL");
+ exit (-1);
+ }
+
+ time (&t);
+ printf ("\n%s\n", ctime (&t));
+
+ if (c.valid & VAL_ISTATUS)
+ {
+ switch (c.in_locked)
+ {
+ case LOCK_NOT_INDICATED:
+ printf ("Receiver locked: Status unknown\n");
+ break;
+ case LOCK_UNLOCKED:
+ printf ("receiver locked: *** NOT LOCKED ***\n");
+ break;
+ case LOCK_LOCKED:
+ printf ("receiver locked: Locked OK\n");
+ break;
+ }
+
+ switch (c.in_quality)
+ {
+ case IN_QUAL_NOT_INDICATED:
+ printf ("Signal quality: Unknown\n");
+ break;
+ case IN_QUAL_POOR:
+ printf ("Signal quality: *** POOR ***\n");
+ break;
+ case IN_QUAL_GOOD:
+ printf ("Signal quality: Good\n");
+ break;
+ }
+
+ switch (c.in_vbit)
+ {
+ case VBIT_NOT_INDICATED:
+ printf ("V-bit: Unknown\n");
+ break;
+ case VBIT_ON:
+ printf ("V-bit: On (not valid audio)\n");
+ break;
+ case VBIT_OFF:
+ printf ("V-bit: Off (valid audio signal)\n");
+ break;
+ }
+
+ switch (c.in_data)
+ {
+ case IND_UNKNOWN:
+ printf ("Audio/data: Unknown\n");
+ break;
+ case IND_AUDIO:
+ printf ("Audio/data: Audio\n");
+ break;
+ case IND_DATA:
+ printf ("Audio/data: Data\n");
+ break;
+ }
+
+ printf ("Errors: ");
+ if (c.in_errors & INERR_CRC)
+ printf ("CRC ");
+ if (c.in_errors & INERR_QCODE_CRC)
+ printf ("QCODE_CRC ");
+ if (c.in_errors & INERR_PARITY)
+ printf ("PARITY ");
+ if (c.in_errors & INERR_BIPHASE)
+ printf ("BIPHASE ");
+ printf ("\n");
+ }
+ else
+ printf ("No input status information available\n");
+
+ if (c.valid & VAL_CBITIN && c.in_locked != LOCK_UNLOCKED)
+ {
+ printf ("\n");
+ printf ("Control bits: ");
+ for (i = 0; i < 24; i++)
+ printf ("%02x ", c.cbitin[i]);
+ printf ("\n");
+
+ if (c.cbitin[0] & 0x01)
+ decode_pro_mode (c.cbitin);
+ else
+ decode_consumer_mode (c.cbitin);
+ }
+ else
+ printf ("No incoming control bit information available\n");
+#endif
+
+#ifdef SHOW_DATA
+# ifdef SHOW_STATUS
+ if (c.in_locked != LOCK_UNLOCKED)
+# endif
+ {
+ for (i = 0; i < l / 2; i++)
+ {
+ if (buf[i] == expected)
+ {
+ printf ("%04x\n", buf[i]);
+ }
+ else
+ {
+ printf ("Error %04x != %04x (%4x), c=%d/%x\n", buf[i],
+ expected, buf[i] ^ expected, bcount, bcount);
+ }
+ expected = buf[i] + 1;
+ bcount++;
+ }
+ }
+
+#else
+ sleep (1);
+#endif
+ }
+
+ perror (devname);
+
+ exit (-1);
+}
diff --git a/tutorials/sndkit/tests/sweepdown.c b/tutorials/sndkit/tests/sweepdown.c
new file mode 100644
index 0000000..8006053
--- /dev/null
+++ b/tutorials/sndkit/tests/sweepdown.c
@@ -0,0 +1,126 @@
+/*
+ * Purpose: Plays a funny synthetic engine stop sound
+ * Copyright (C) 4Front Technologies, 2002-2004. Released under GPLv2/CDDL.
+ *
+ * Description:
+ * This program was supposed to do a frequency sweep down from sample_rate/2
+ * to 0 Hz. However due to some arithmetic problem the result was much more
+ * interesting.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <soundcard.h>
+
+char *dspname = "/dev/dsp";
+
+int fd;
+
+#define SIN_STEPS 48
+static short sinebuf[48] = {
+ 0, 4276, 8480, 12539, 16383, 19947, 23169, 25995,
+ 28377, 30272, 31650, 32486, 32767, 32486, 31650, 30272,
+ 28377, 25995, 23169, 19947, 16383, 12539, 8480, 4276,
+ 0, -4276, -8480, -12539, -16383, -19947, -23169, -25995,
+ -28377, -30272, -31650, -32486, -32767, -32486, -31650, -30272,
+ -28377, -25995, -23169, -19947, -16383, -12539, -8480, -4276
+};
+
+#define F_SCALE (1000000)
+
+int phase = 0, freq = F_SCALE / 2;
+
+static void
+sweeper (int speed, int channels, int fragsize)
+{
+ short buf[4096], *p = buf;
+ int c, i, n, v, x;
+
+ fragsize /= 2 * channels;
+ speed /= 100;
+
+ for (i = 0; i < fragsize; i++)
+ {
+ x = (phase + F_SCALE / 2) / F_SCALE;
+ if (x < 0) x = 0;
+ v = sinebuf[x % SIN_STEPS] / 4;
+
+ phase = phase + freq * 480 / speed;
+
+ if (freq > 1000)
+ freq -= 3 * 480 / speed;
+ else
+ freq -= 1;
+
+ for (c = 0; c < channels; c++)
+ *p++ = v;
+
+ if (freq <= 0)
+ break;
+ }
+
+ write (fd, buf, i * 2 * channels);
+}
+
+int
+main (int argc, char *argv[])
+{
+ int bits, channels, speed, tmp;
+ int i, l;
+
+ if (argc == 2)
+ dspname = argv[1];
+
+
+ if ((fd = open (dspname, O_WRONLY, 0)) == -1)
+ {
+ perror (dspname);
+ exit (-1);
+ }
+
+ speed = 96000;
+ channels = 2;
+ bits = AFMT_S16_NE;
+
+ if (ioctl (fd, SNDCTL_DSP_CHANNELS, &channels) == -1)
+ {
+ perror ("SNDCTL_DSP_CHANNELS");
+ exit (-1);
+ }
+
+ if (ioctl (fd, SNDCTL_DSP_SETFMT, &bits) == -1)
+ {
+ perror ("SNDCTL_DSP_SETFMT");
+ exit (-1);
+ }
+
+ if (bits != AFMT_S16_NE)
+ {
+ fprintf (stderr,
+ "Device %s doesn't support 16 bit (native endian) format\n",
+ dspname);
+ exit (-1);
+ }
+
+ if (ioctl (fd, SNDCTL_DSP_SPEED, &speed) == -1)
+ {
+ perror ("SNDCTL_DSP_SPEED");
+ exit (-1);
+ }
+
+ if (ioctl (fd, SNDCTL_DSP_GETBLKSIZE, &tmp) == -1)
+ {
+ perror ("SNDCTL_DSP_GETBLKSIZE");
+ exit (-1);
+ }
+
+ printf ("Outputting sweep at %d Hz, %d channels, 16 bits\n", speed,
+ channels);
+ printf ("Fragment size is %d\n", tmp);
+
+ while (freq > 0)
+ sweeper (speed, channels, tmp);
+
+ exit (0);
+}
diff --git a/tutorials/sndkit/tests/sweepup.c b/tutorials/sndkit/tests/sweepup.c
new file mode 100644
index 0000000..de4c421
--- /dev/null
+++ b/tutorials/sndkit/tests/sweepup.c
@@ -0,0 +1,122 @@
+/*
+ * Purpose: A simple program that plays frequency sweep from 10 Hz to fs/2.
+ * Copyright (C) 4Front Technologies, 2002-2004. Released under GPLv2/CDDL.
+ *
+ * Description:
+ * This program plays a frequency seep up starting from 10 Hz and
+ * goes up to sample_rate/2.
+ */
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <soundcard.h>
+
+char *dspname = "/dev/dsp";
+
+int fd;
+
+int
+main (int argc, char *argv[])
+{
+ int bits, channels, speed, tmp;
+ int i, l, n;
+#define BUFFSIZE (64*1024)
+ short buf[BUFFSIZE];
+ int p, t;
+ double freq = 10.0 /* Hz */ , phase = 0.0;
+ int delay = 0;
+
+ if (argc > 1)
+ dspname = argv[1];
+
+ if (argc > 2)
+ delay = atoi (argv[2]);
+
+ if ((fd = open (dspname, O_WRONLY, 0)) == -1)
+ {
+ perror (dspname);
+ exit (-1);
+ }
+
+ speed = 48000;
+ channels = 2;
+ bits = AFMT_S16_NE;
+
+ if (ioctl (fd, SNDCTL_DSP_CHANNELS, &channels) == -1)
+ {
+ perror ("SNDCTL_DSP_CHANNELS");
+ exit (-1);
+ }
+
+ if (ioctl (fd, SNDCTL_DSP_SETFMT, &bits) == -1)
+ {
+ perror ("SNDCTL_DSP_SETFMT");
+ exit (-1);
+ }
+
+ if (bits != AFMT_S16_NE)
+ {
+ fprintf (stderr,
+ "Device %s doesn't support 16 bit (native endian) format\n",
+ dspname);
+ exit (-1);
+ }
+
+ if (ioctl (fd, SNDCTL_DSP_SPEED, &speed) == -1)
+ {
+ perror ("SNDCTL_DSP_SPEED");
+ exit (-1);
+ }
+
+ fprintf (stderr, "Outputting sweep at %d Hz, %d channels, 16 bits\n", speed,
+ channels);
+
+ n = 0;
+ p = 0;
+
+ while (1) /* Infinite loop */
+ {
+ int v;
+ double step;
+
+ v = sin (phase) * 16483.0;
+
+ for (i = 0; i < channels; i++)
+ {
+ buf[p++] = v;
+
+ if (p >= BUFFSIZE)
+ {
+// write (1, buf, p * 2);
+
+ if (write (fd, buf, p * 2) != p * 2)
+ {
+ perror ("write");
+ exit (-1);
+ }
+ if (delay > 0)
+ usleep (delay * 1000);
+ fprintf (stderr, "\r%d ", (int) (freq));
+ fflush (stderr);
+ p = 0;
+ }
+ }
+
+ step = 2.0 * M_PI * freq / (double) speed;
+
+ phase += step;
+
+ if (freq < (double) speed / 2.1)
+ freq *= 1.000002;
+ else
+ break;
+ }
+
+ fprintf (stderr, "\n");
+ if (p > 0)
+ write (fd, buf, p * 2);
+
+ exit (0);
+}
diff --git a/tutorials/sndkit/tests/synctest.c b/tutorials/sndkit/tests/synctest.c
new file mode 100644
index 0000000..d2ed77b
--- /dev/null
+++ b/tutorials/sndkit/tests/synctest.c
@@ -0,0 +1,96 @@
+/*
+ * Purpose: A program that demonstrates use of syncronization groups.
+ * Copyright (C) 4Front Technologies, 2002-2004. Released under GPLv2/CDDL.
+ *
+ * Description:
+ * This program opens three audio devices (hard coded in the program)
+ * and creates a syncronization group using {!nlink SNDCTL_DSP_SYNCGROUP}.
+ *
+ * Next it starts all the devices joined in the group simultaneously
+ * by calling {!nlink SNDCTL_DSP_SYNCSTART}. Finally it will keep copying
+ * audio input from the 3rd device to the other two ones.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <soundcard.h>
+
+#define MAX_DEV 10
+
+int
+main (int argc, char *argv[])
+{
+ int i, id, fd[MAX_DEV], ndevs = 0;
+ char buf[32768] = { 0 };
+
+ oss_syncgroup group;
+
+ group.id = 0;
+ group.mode = PCM_ENABLE_OUTPUT;
+
+/*
+ * Open the devices listed on command line
+ */
+ if (argc < 2)
+ exit (-1);
+
+ for (i = 1; i < argc; i++)
+ {
+ if ((fd[ndevs] = open (argv[i], O_WRONLY, 0)) == -1)
+ {
+ perror (argv[i]);
+ exit (-1);
+ }
+
+ if (ioctl (fd[ndevs], SNDCTL_DSP_SYNCGROUP, &group) == -1)
+ {
+ perror ("SNDCTL_DSP_SYNCGROUP");
+ exit (-1);
+ }
+/*
+ * Note! It is very important to write some data to all output devices
+ * between calling SNDCTL_DSP_SYNCGROUP and SNDCTL_DSP_SYNCSTART. Otherwise
+ * playback will not start properly. However do not write more data than
+ * there is room in device's DMA buffer. Recommended amount of prteload data
+ * is one full fragment.
+ *
+ * In applications that record audio, process it and then play back it's
+ * necessary to write two fragments of silence to the output device(s) before
+ * starting the group. Otherwise output device(s) will run out of data before
+ * the first read from the input device returns.
+ */
+
+ if (write (fd[ndevs], buf, sizeof (buf)) != sizeof (buf))
+ {
+ perror ("write");
+ exit (-1);
+ }
+
+ ndevs++;
+ }
+
+ printf ("Sync group %x created with %d devices\n", group.id, ndevs);
+
+
+ id = group.id;
+
+ if (ioctl (fd[0], SNDCTL_DSP_SYNCSTART, &id) == -1)
+ {
+ perror ("SNDCTL_DSP_SYNCSTART");
+ exit (-1);
+ }
+
+ while (1)
+ {
+ for (i = 0; i < ndevs; i++)
+ if (write (fd[i], buf, sizeof (buf)) != sizeof (buf))
+ {
+ perror ("write2");
+ exit (-1);
+ }
+ }
+
+ exit (0);
+}