diff options
author | Igor Pashev <pashev.igor@gmail.com> | 2013-05-03 21:08:42 +0400 |
---|---|---|
committer | Igor Pashev <pashev.igor@gmail.com> | 2013-05-03 21:08:42 +0400 |
commit | 1058def8e7827e56ce4a70afb4aeacb5dc44148f (patch) | |
tree | 4495d23e7b54ab5700e3839081e797c1eafe0db9 /tutorials/sndkit/tests | |
download | oss4-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/Makefile | 11 | ||||
-rw-r--r-- | tutorials/sndkit/tests/README.1ST | 11 | ||||
-rw-r--r-- | tutorials/sndkit/tests/ioctl_test.c | 624 | ||||
-rw-r--r-- | tutorials/sndkit/tests/iosync.c | 232 | ||||
-rw-r--r-- | tutorials/sndkit/tests/multich16.c | 126 | ||||
-rw-r--r-- | tutorials/sndkit/tests/multich32.c | 126 | ||||
-rw-r--r-- | tutorials/sndkit/tests/musicin.c | 222 | ||||
-rw-r--r-- | tutorials/sndkit/tests/seltest2.c | 113 | ||||
-rw-r--r-- | tutorials/sndkit/tests/singen.inc | 38 | ||||
-rw-r--r-- | tutorials/sndkit/tests/spdif_in_debug.c | 303 | ||||
-rw-r--r-- | tutorials/sndkit/tests/sweepdown.c | 126 | ||||
-rw-r--r-- | tutorials/sndkit/tests/sweepup.c | 122 | ||||
-rw-r--r-- | tutorials/sndkit/tests/synctest.c | 96 |
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); +} |