summaryrefslogtreecommitdiff
path: root/tutorials/sndkit/dsp
diff options
context:
space:
mode:
Diffstat (limited to 'tutorials/sndkit/dsp')
-rw-r--r--tutorials/sndkit/dsp/Makefile31
-rw-r--r--tutorials/sndkit/dsp/Readme13
-rw-r--r--tutorials/sndkit/dsp/help.c75
-rw-r--r--tutorials/sndkit/dsp/recplay.c401
-rw-r--r--tutorials/sndkit/dsp/str/Makefile34
-rw-r--r--tutorials/sndkit/dsp/str/Readme142
-rw-r--r--tutorials/sndkit/dsp/str/str.c295
-rw-r--r--tutorials/sndkit/dsp/str/str.h74
-rw-r--r--tutorials/sndkit/dsp/str/strplay.c575
-rw-r--r--tutorials/sndkit/dsp/vplay/Makefile20
-rw-r--r--tutorials/sndkit/dsp/vplay/Readme69
-rw-r--r--tutorials/sndkit/dsp/vplay/etc.magic.vplay16
-rw-r--r--tutorials/sndkit/dsp/vplay/fmtheaders.h108
-rw-r--r--tutorials/sndkit/dsp/vplay/vplay.c1012
-rw-r--r--tutorials/sndkit/dsp/vplay_vxworks/Makefile12
-rw-r--r--tutorials/sndkit/dsp/vplay_vxworks/fmtheaders.h119
-rw-r--r--tutorials/sndkit/dsp/vplay_vxworks/vplay_vxworks.c694
17 files changed, 3690 insertions, 0 deletions
diff --git a/tutorials/sndkit/dsp/Makefile b/tutorials/sndkit/dsp/Makefile
new file mode 100644
index 0000000..1cfa1ec
--- /dev/null
+++ b/tutorials/sndkit/dsp/Makefile
@@ -0,0 +1,31 @@
+#CC = gcc
+#CFLAGS = -O6 -m486 -funroll-loops -Wall
+CFLAGS = -O -I../../../include
+#LD = gcc
+LD = cc
+#LDFLAGS = -s -N
+LDFLAGS = -s
+
+INSTALLDIR = /usr/local/bin
+
+.c.o:
+# $(CC) -c $(CFLAGS) -o $*.o $<
+ $(CC) -c $(CFLAGS) $<
+
+all: srec
+
+install: all
+ cp srec $(INSTALLDIR)
+ ln -sf $(INSTALLDIR)/srec $(INSTALLDIR)/splay
+ chown root $(INSTALLDIR)/splay $(INSTALLDIR)/srec
+ chmod 755 $(INSTALLDIR)/splay $(INSTALLDIR)/srec
+ cd str;make install
+
+srec: recplay.o help.o
+ $(LD) $(LDFLAGS) recplay.o help.o -o srec
+
+clean:
+ rm -f $(OBJS) *.o srec a.out core
+ cd str;make clean
+
+recplay.o: recplay.c
diff --git a/tutorials/sndkit/dsp/Readme b/tutorials/sndkit/dsp/Readme
new file mode 100644
index 0000000..9410464
--- /dev/null
+++ b/tutorials/sndkit/dsp/Readme
@@ -0,0 +1,13 @@
+srec and splay utilities (recplay.c)
+====================================
+
+Run "make install" to install "splay" and "srec" into /usr/local/bin.
+
+These programs support recording and playback of digitized
+voice. There is several possible parameters to these programs.
+Try "srec -h" and "splay -h" for further information.
+
+The vplay -program in the vplay directory is a improved version of
+the recplay.c.
+
+NOTE! The str program has been moved to the subdirectory ./str
diff --git a/tutorials/sndkit/dsp/help.c b/tutorials/sndkit/dsp/help.c
new file mode 100644
index 0000000..5b0156c
--- /dev/null
+++ b/tutorials/sndkit/dsp/help.c
@@ -0,0 +1,75 @@
+/*
+ * help.c
+ *
+ * Some error printing routines.
+ *
+ * Copyright by Hannu Savolainen 1993
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <stdio.h>
+#include <errno.h>
+
+void
+describe_error (void)
+{
+ switch (errno)
+ {
+ case ENODEV:
+ fprintf (stderr, "The device file was found in /dev but\n"
+ "OSS is not loaded. You need to load it by executing\n"
+ "the soundon command.\n");
+ break;
+
+ case ENXIO:
+ fprintf (stderr, "There are no sound devices available.\n"
+ "The most likely reason is that the device you have\n"
+ "is malfunctioning or it's not supported by OSS.\n"
+ "\n"
+
+ "NOTE! It may be necessary to reboot the system after installing OSS\n"
+#ifdef LICENSED_VERSION
+ "\n"
+ "If you are a licensed customer then please fill the problem report at\n"
+ "http://www.opensound.com/support.cgi\n"
+#endif
+ );
+ break;
+
+ case ENOSPC:
+ fprintf (stderr, "Your system cannot allocate memory for the device\n"
+ "buffers. Reboot your machine and try again.\n");
+ break;
+
+ case ENOENT:
+ fprintf (stderr, "The device file is missing from /dev.\n"
+ "Perhaps you have not installed and started Open Sound System yet\n");
+ break;
+
+
+ case EBUSY:
+ fprintf (stderr, "The device is busy. There is some other application\n"
+ "using it.\n");
+
+ default:;
+ }
+}
diff --git a/tutorials/sndkit/dsp/recplay.c b/tutorials/sndkit/dsp/recplay.c
new file mode 100644
index 0000000..62fdcf0
--- /dev/null
+++ b/tutorials/sndkit/dsp/recplay.c
@@ -0,0 +1,401 @@
+/*
+ * recplay.c
+ *
+ * A simple recording and playback program for OSS 4.0
+ * or later.
+ *
+ * Copyright by Hannu Savolainen 1993-2004
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer. 2.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+/* #include <getopt.h> */
+#include <fcntl.h>
+#include <string.h>
+#include <soundcard.h>
+
+#define DEFAULT_DSP_SPEED 8000
+
+#define RECORD 0
+#define PLAY 1
+#define AUDIO "/dev/dsp"
+
+int prof = APF_NORMAL;
+int timelimit = 0, dsp_speed = DEFAULT_DSP_SPEED, dsp_channels = 1;
+int samplefmt = AFMT_S16_LE;
+int quiet_mode = 0;
+int audio, abuf_size;
+int direction, omode;
+int blksize = 0;
+int fragsize = 0;
+char *audiobuf, c;
+
+char audio_name[64] = AUDIO;
+
+void recplay (char *name);
+extern void describe_error (void);
+
+typedef struct
+{
+ char *name;
+ int fmt;
+ int bits;
+} sample_fmt_t;
+
+static const sample_fmt_t formats[] = {
+ {"AFMT_MU_LAW", AFMT_MU_LAW},
+ {"AFMT_A_LAW", AFMT_A_LAW},
+ {"AFMT_IMA_ADPCM", AFMT_IMA_ADPCM},
+ {"AFMT_U8", AFMT_U8, 8},
+ {"AFMT_S16_LE", AFMT_S16_LE, 16},
+ {"AFMT_S16_BE", AFMT_S16_BE, 16},
+ {"AFMT_S8", AFMT_S8, 8},
+ {"AFMT_U16_LE", AFMT_U16_LE, 16},
+ {"AFMT_U16_BE", AFMT_U16_BE, 16},
+ {"AFMT_MPEG", AFMT_MPEG},
+ {"AFMT_AC3", AFMT_AC3},
+ {"AFMT_VORBIS", AFMT_VORBIS},
+ {"AFMT_S32_LE", AFMT_S32_LE, 32},
+ {"AFMT_S32_BE", AFMT_S32_BE, 32},
+ {"AFMT_FLOAT", AFMT_FLOAT},
+ {"AFMT_S24_LE", AFMT_S24_LE, 24},
+ {"AFMT_S24_BE", AFMT_S24_BE, 24},
+ {"AFMT_SPDIF_RAW", AFMT_SPDIF_RAW},
+ {"AFMT_S24_PACKED", AFMT_S24_PACKED, 24},
+ {NULL, 0}
+};
+
+static int
+set_samplefmt (char *fmt)
+{
+ int i;
+
+ for (i = 0; formats[i].name != NULL; i++)
+ if (strcmp (formats[i].name, fmt) == 0)
+ {
+ return formats[i].fmt;
+ }
+
+ fprintf (stderr, "Error: Unrecognized sample format '%s'\n", fmt);
+ exit (-1);
+}
+
+int
+main (int argc, char *argv[])
+{
+
+ char *command;
+ int tmp;
+ int i;
+
+ command = argv[0];
+ if (strstr (argv[0], "srec"))
+ {
+ direction = RECORD;
+ omode = O_RDONLY;
+ }
+ else if (strstr (argv[0], "splay"))
+ {
+ direction = PLAY;
+ omode = O_WRONLY;
+ }
+ else
+ {
+ fprintf (stderr,
+ "Error: command should be named either srec or splay\n");
+ exit (1);
+ }
+
+ while ((c = getopt (argc, argv, "pqs:St:b:d:B:f:F:c:")) != EOF)
+ switch (c)
+ {
+ case 'S': /* Stereo is obsolete - use -c instead */
+ dsp_channels = 2;
+ break;
+ case 'c':
+ dsp_channels = atoi (optarg);
+ break;
+ case 'q':
+ quiet_mode = 1;
+ break;
+ case 's':
+ dsp_speed = atoi (optarg);
+ if (dsp_speed < 300)
+ dsp_speed *= 1000;
+ break;
+ case 't':
+ timelimit = atoi (optarg);
+ break;
+
+ case 'b': /* Bits (obsolete) supports only 8 and 16 */
+ samplefmt = atoi (optarg);
+ break;
+
+ case 'F':
+ samplefmt = set_samplefmt (optarg);
+ break;
+
+ case 'B':
+ blksize = atoi (optarg);
+ break;
+
+ case 'd':
+ strncpy (audio_name, optarg, sizeof (audio_name) - 1);
+ break;
+
+ case 'f':
+ fragsize = atoi (optarg);
+ if (fragsize == 0)
+ {
+ fprintf (stderr, "Bad fragment size (-f %s)\n", optarg);
+ exit (-1);
+ }
+ fragsize |= 0x7fff0000;
+ break;
+
+ case 'p':
+ prof = APF_CPUINTENS;
+ break;
+
+ default:
+ fprintf (stderr,
+ "Usage: %s [-q] [-c channels] [-t secs] [-s Hz] [-b 8|12|16] [-d device] [filename]\n",
+ command);
+ exit (-1);
+ }
+
+
+ audio = open (audio_name, omode, 0);
+ if (audio == -1)
+ {
+ perror (audio_name);
+ describe_error ();
+ exit (-1);
+ }
+
+ if (fragsize != 0)
+ if (ioctl (audio, SNDCTL_DSP_SETFRAGMENT, &fragsize) == -1)
+ {
+ perror ("SETFRAGMENT");
+ exit (-1);
+ }
+
+ tmp = samplefmt;
+ ioctl (audio, SNDCTL_DSP_SETFMT, &tmp);
+ if (tmp != samplefmt)
+ {
+ fprintf (stderr, "Unable to set the requested sample format\n");
+
+ for (i = 0; formats[i].fmt != 0; i++)
+ if (formats[i].fmt == samplefmt)
+ {
+ fprintf (stderr, "The required format is %s (%08x)\n",
+ formats[i].name, formats[i].fmt);
+ break;
+ }
+
+ for (i = 0; formats[i].fmt != 0; i++)
+ if (formats[i].fmt == tmp)
+ {
+ fprintf (stderr, "The device supports %s (%08x)\n",
+ formats[i].name, formats[i].fmt);
+ break;
+ }
+ exit (-1);
+ }
+
+ ioctl (audio, SNDCTL_DSP_PROFILE, &prof);
+
+ if (ioctl (audio, SNDCTL_DSP_CHANNELS, &dsp_channels) == -1)
+ {
+ fprintf (stderr, "%s: Unable to set the number of channels\n", command);
+ perror (audio_name);
+ exit (-1);
+ }
+
+ if (ioctl (audio, SNDCTL_DSP_SPEED, &dsp_speed) == -1)
+ {
+ fprintf (stderr, "%s: Unable to set audio speed\n", command);
+ perror (audio_name);
+ exit (-1);
+ }
+ if (!quiet_mode)
+ {
+ fprintf (stderr, "Speed %d Hz ", dsp_speed);
+ fprintf (stderr, "%d channels ", dsp_channels);
+
+ for (i = 0; formats[i].fmt != 0; i++)
+ if (formats[i].fmt == samplefmt)
+ {
+ fprintf (stderr, "Sample format is %s", formats[i].name);
+ if (formats[i].bits != 0)
+ fprintf (stderr, "(%d bits)", formats[i].bits);
+ break;
+ }
+ fprintf (stderr, "\n");
+ }
+
+ if (blksize > 0)
+ abuf_size = blksize;
+ else
+ {
+#if 0
+/*
+ * There is no idea in using SNDCTL_DSP_GETBLKSIZE in applications like this.
+ * Using some fixed local buffer size will work equally well.
+ */
+ ioctl (audio, SNDCTL_DSP_GETBLKSIZE, &abuf_size);
+ if (abuf_size < 1)
+ {
+ perror ("GETBLKSIZE");
+ exit (-1);
+ }
+#else
+ abuf_size = 1024;
+#endif
+ }
+
+ if ((audiobuf = malloc (abuf_size)) == NULL)
+ {
+ fprintf (stderr, "Unable to allocate input/output buffer\n");
+ exit (-1);
+ }
+
+ if (optind > argc - 1)
+ recplay (NULL);
+ else
+ while (optind <= argc - 1)
+ {
+ recplay (argv[optind++]);
+ }
+
+ close (audio);
+ return 0;
+}
+
+void
+recplay (char *name)
+{
+ int fd, l;
+
+ int count, c;
+
+ if (!timelimit)
+ count = 0x7fffffff;
+ else
+ {
+ count = timelimit * dsp_speed * dsp_channels;
+ if (samplefmt != AFMT_U8)
+ count *= 2; /* TODO: This is bogus because just few formats are 16 bits */
+ }
+
+ if (direction == PLAY)
+ {
+ if (!name)
+ {
+ fd = 0;
+ name = "stdin";
+ }
+ else
+ {
+ if ((fd = open (name, O_RDONLY, 0)) == -1)
+ {
+ perror (name);
+ exit (-1);
+ }
+ }
+
+ while (count)
+ {
+ c = count;
+
+ if (c > abuf_size)
+ c = abuf_size;
+
+ if ((l = read (fd, audiobuf, c)) > 0)
+ {
+ if (write (audio, audiobuf, l) != l)
+ {
+ perror (audio_name);
+ exit (-1);
+ }
+ count -= l;
+ }
+ else
+ {
+ if (l == -1)
+ {
+ perror (name);
+ exit (-1);
+ }
+ count = 0; /* Stop */
+ }
+
+ } /* while (count) */
+ if (fd != 0)
+ close (fd);
+ }
+ else
+ {
+ if (!name)
+ {
+ fd = 1;
+ name = "stdout";
+ }
+ else
+ {
+ if ((fd = open (name, O_WRONLY | O_CREAT, 0666)) == -1)
+ {
+ perror (name);
+ exit (-1);
+ }
+ }
+
+ while (count)
+ {
+ c = count;
+ if (c > abuf_size)
+ c = abuf_size;
+
+ if ((l = read (audio, audiobuf, c)) > 0)
+ {
+ if (write (fd, audiobuf, l) != l)
+ {
+ perror (name);
+ exit (-1);
+ }
+ count -= l;
+ }
+
+ if (l == -1)
+ {
+ perror (audio_name);
+ exit (-1);
+ }
+ } /* While count */
+
+ if (fd != 1)
+ close (fd);
+ }
+}
diff --git a/tutorials/sndkit/dsp/str/Makefile b/tutorials/sndkit/dsp/str/Makefile
new file mode 100644
index 0000000..d0fb544
--- /dev/null
+++ b/tutorials/sndkit/dsp/str/Makefile
@@ -0,0 +1,34 @@
+#CC = gcc
+#CFLAGS = -O6 -m486 -funroll-loops -Wall
+#LD = gcc
+#LDFLAGS = -s -N
+CC = cc
+CFLAGS = -O
+LD = cc
+LDFLAGS = -s
+
+INSTALLDIR = /usr/local/bin
+
+OBJS = str.o strplay.o ../help.o
+
+.c.o:
+# $(CC) -c $(CFLAGS) -o $*.o $<
+ $(CC) -c $(CFLAGS) $<
+
+all: str
+
+install: all
+ cp str $(INSTALLDIR)
+ chown root $(INSTALLDIR)/str
+ chmod 755 $(INSTALLDIR)/str
+ ln -f $(INSTALLDIR)/str $(INSTALLDIR)/str15
+ ln -f $(INSTALLDIR)/str $(INSTALLDIR)/str32
+
+str: $(OBJS)
+ $(LD) $(LDFLAGS) $(OBJS) -o str
+
+clean:
+ rm -f $(OBJS) str a.out core
+
+str.o: str.c str.h
+strplay.o: strplay.c str.h
diff --git a/tutorials/sndkit/dsp/str/Readme b/tutorials/sndkit/dsp/str/Readme
new file mode 100644
index 0000000..1d7b28f
--- /dev/null
+++ b/tutorials/sndkit/dsp/str/Readme
@@ -0,0 +1,142 @@
+SparcTracker ver. 1.2 by Liam Corner and Marc Espie
+===================================================
+
+NOTE! This is an old and obsolete version. The latest version is
+ called tracker-3.19.
+
+#ifdef linux
+This version contains some minor modifications for Linux by Hannu Savolainen
+(hannu@voxware.pp.fi) and Leif Kornstaedt (l_kornst@informatik.uni-kl.de).
+
+Have a look at the options in the Makefile (e.g. the -m486 option) and at
+the str.h header file, in which you may configure some things.
+
+Please edit DSP_SPEED in the file str.h before compiling. The default
+setting for output frequency is 23 kHz, which may be too fast for 386/386sx
+machines. At least you have to change it if there happens to be short
+pauses in playback.
+#endif
+
+Well, here they are the first tracker module players for the Sun
+Sparcstations. There are 2 players, one for the 15 sample modules and one for
+the 32 sample ones (or should that be 31 :-). The code is not that different,
+but I could not be bothered to write an auto detection routine that worked on
+standard input.
+
+
+Usage
+-----
+
+Usage is very simple, either give the player the filename of the module, or if
+the module is compressed(frozen) you can zcat(fcat) and pipe the result into
+the player thus :
+
+ str32 -h
+ str32 [options] module ...
+ zcat module.z | str32 [options]
+ fcat module.F | str32 [options]
+
+If you have a new module and are unsure of which player (str15 or str32) to
+use then try both. If you choose the wrong one then you may get an error
+message or nothing at all will happen (except maybe a core dump :-). For
+this reason I keep my trackers in separate directories so that I know which
+player to use.
+
+Not many effects are implemented, so the result may not be exactly the same as
+an Amiga player, but it is usually OK. The sound quality of the /dev/audio is
+not too hot, so some sounds are lost, usually the bass.
+
+Options
+-------
+
+This version acceps several command line options:
+
+ -s kHz Sets the playback speed. For example
+ str32 -s 20 plays the module with
+ 22 kHz sampling frequency.
+ -S Plays the module in stereo.
+ -c Non-stop mode.
+ -q Quiet.
+ -b bits Sets the sample size (8 or 16 bits).
+ -o file Redirects output to a file or
+ another device.
+
+Errors
+------
+
+The only error not totally self-explanatory is the 'corrupt input file' one.
+This sometimes indicates that you have used the wrong player, but
+occassionally it may be that the module is too short by a few bytes. I have
+only come accross this in a couple of cases and just appending a few null
+bytes to the end usually cures this.
+
+
+The Future
+----------
+
+I may get around to combining the players into a single program and enhancing
+the error detection a bit, but then again I might not :-). If anyone else
+wants to add these functions, add more effects or correct any errors there may
+be in the current programs then please go ahead - I hope the code is
+understandable enough for you.
+
+
+Copyright Stuff
+---------------
+
+Most of the code is copyright me. The convert routine is copyright Rich
+Gopstein and was borrowed from the iff2ulaw utility. The code is freely
+distributable as long as this message and the copyright messages in the source
+are included. You are welcome to update the source code.
+
+
+ Liam Corner - University of Warwick - 1st November 1991
+
+ csubt@csv.warwick.ac.uk
+ zenith@dcs.warwick.ac.uk
+
+
+
+Version 1.2 - 3rd November 1991
+-------------------------------
+
+Thanks to Marc Espie for doing most of the first update. There is now only
+one player str15 and a link from str32 to str15, so you will still have to
+choose the correct player for a given module. There is now output showing
+module name, sample names and progress through the module as it plays. More
+effects are implemented and a bug with the sample repeat loop has been fixed.
+
+
+Patch 08/27/92 by Hannu Savolainen
+----------------------------------
+
+Modified to use integer arithmetic.
+
+
+Version 1.5 - 31st January 1993 by Leif Kornstaedt
+--------------------------------------------------
+
+- Now all standard NoiseTracker 1.0 effects should be implemented correctly,
+ as well as some bugs fixed (and the step_table calculations more accurate).
+
+- Some command line options have been added, namely:
+
+ -v verbose: the score is shown while playing
+ -z zcat is applied to the files before playing
+
+- You can now give a default path to search modules when they are not found
+ in the current working directory. E. g. using /bin/bash do
+
+$ export MODPATH=/usr/local/lib/mod/tracks15:/usr/local/lib/mod/tracks32
+
+
+TODO:
+
+- automatically determine the number of instruments instead of having
+ str15 and str32 (by testing 'M.K.' sig)
+- insert a shuffle mode: let the player play all songs in the module
+ path, but shuffled like a CD player does.
+
+
+Please let me know if you find something to ameliorate. -- L. K.
+l_kornst@informatik.uni-kl.de
diff --git a/tutorials/sndkit/dsp/str/str.c b/tutorials/sndkit/dsp/str/str.c
new file mode 100644
index 0000000..4c999ca
--- /dev/null
+++ b/tutorials/sndkit/dsp/str/str.c
@@ -0,0 +1,295 @@
+/************************************************************************/
+/* */
+/* str.c - plays sound-/noisetracker files on a SparcStation */
+/* */
+/* Authors: */
+/* Liam Corner - zenith@dcs.warwick.ac.uk */
+/* Marc Espie - espie@dmi.ens.fr */
+/* Minor modificatios for Linux by */
+/* Hannu Savolainen - hannu@voxware.pp.fi */
+/* Command-line switches added by */
+/* Muhammad Saggaf - alsaggaf@erl.mit.edu */
+/* Leif Kornstaedt - l_kornst@informatik.uni-kl.de */
+/* Relaxed program name checking */
+/* Craig Metz - cmetz@thor.tjhsst.edu */
+/* Stereo and 16 bit support by */
+/* Hannu */
+/* Some effects and minor bugfixes/ameliorations by */
+/* Leif Kornstaedt - l_kornst@informatik.uni-kl.de */
+/* */
+/* Version: 1.20 - 3 November 1991 / 31 January 1993 */
+/* 01/31/93 effects added */
+/* by Leif Kornstaedt */
+/* 08/27/92 modified to use integer arithmetic */
+/* 08/31/92 SB Pro stereo support */
+/* by Hannu Savolainen */
+/* */
+/************************************************************************/
+
+#include <stdio.h>
+#include <malloc.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+#include <sys/soundcard.h>
+#include "str.h"
+
+/* output file name or dsp device */
+char AUDIO[256] = AUDIONAME;
+
+int audio; /* file handle */
+unsigned char *audiobuf;
+int abuf_size;
+int abuf_ptr;
+
+/* for analyzing the command line: */
+char *command; /* the actual command name used (argv[0]) */
+int loop_forever = FALSE;
+int quiet_mode = FALSE, verbose_mode = FALSE;
+static int use_zcat = FALSE;
+int mute[4] = { FALSE, FALSE, FALSE, FALSE };
+int dsp_stereo = DSP_DEFAULT_STEREO;
+int dsp_samplesize = DSP_DEFAULT_SAMPLESIZE;
+long dsp_speed = DEFAULT_DSP_SPEED;
+
+FILE *fp;
+
+void play_song (void);
+extern void describe_error (void); /* from ../help.c */
+
+void
+usage (command)
+ char *command;
+{
+ fprintf (stderr, "Usage: %s [ -cqvzS1234 -b size -s kHz -o output_file ] "
+ "[ filename ... ]\n", command);
+ fprintf (stderr, "\t-c\t\tplay infinitely\n"
+ "\t-q\t\tquiet mode\n"
+ "\t-v\t\tverbose mode\n"
+ "\t-z\t\tuse zcat on file\n"
+ "\t-1234\t\tmute voices 1, 2, 3 or 4\n"
+ "\t-S\t\ttoggle stereo\n"
+ "\t-b size\t\tset sample size (8 or 16 bits)\n"
+ "\t-s kHz\t\tuse sampling speed kHz\n"
+ "\t-o file\t\tredirect output to a file\n");
+ exit (EXIT_FAILURE);
+}
+
+char *
+find_file (name)
+ char *name;
+{
+ char *dirs;
+ struct stat statbuffer;
+ static char fname[256];
+
+ strcpy (fname, name);
+ if (stat (fname, &statbuffer) != -1 && errno != ENOENT)
+ return fname;
+ else
+ {
+ dirs = getenv ("MODPATH");
+ while (dirs != NULL && strlen (dirs))
+ {
+ if (strchr (dirs, ':') != NULL)
+ {
+ strncpy (fname, dirs, strchr (dirs, ':') - dirs);
+ fname[strchr (dirs, ':') - dirs] = '\0';
+ }
+ else
+ strcpy (fname, dirs);
+ if (fname[strlen (fname) - 1] != '/')
+ strcat (fname, "/");
+ strcat (fname, name);
+ if (stat (fname, &statbuffer) != -1 && errno != ENOENT)
+ return fname;
+ if ((dirs = strchr (dirs, ':')) != NULL)
+ dirs++;
+ }
+ }
+
+ return NULL;
+}
+
+int
+main (argc, argv)
+ int argc;
+ char *argv[];
+{
+ int outdev, c;
+ struct stat statbuffer;
+ int opmode = O_WRONLY; /* mode for opening the output device */
+ char zcat_cmd[256];
+ char *currfile;
+
+ command = argv[0];
+
+ while ((c = getopt (argc, argv, "cqvz1234Sb:s:o:")) != EOF)
+ switch (c)
+ {
+ case 'c': /* play infinitely */
+ loop_forever = TRUE;
+ break;
+ case 'q': /* quiet mode */
+ quiet_mode = TRUE;
+ break;
+ case 'v': /* verbose mode */
+ verbose_mode = TRUE;
+ break;
+ case 'z': /* use zcat on file */
+ use_zcat = TRUE;
+ break;
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ mute[c - '1'] = TRUE;
+ break;
+ case 'S': /* toggle stereo */
+ dsp_stereo = !DSP_DEFAULT_STEREO;
+ break;
+ case 'b': /* sample size */
+ dsp_samplesize = atoi (optarg);
+ break;
+ case 's': /* dsp speed */
+ dsp_speed = atoi (optarg);
+ if (dsp_speed < 300)
+ dsp_speed *= 1000;
+ break;
+ case 'o': /* output file */
+ strcpy (AUDIO, optarg);
+ break;
+ default:
+ usage (command);
+ }
+
+ /* output to a character device (TRUE) or a file (FALSE)? */
+ outdev = !stat (AUDIO, &statbuffer) && S_ISCHR (statbuffer.st_mode);
+
+ if (!outdev)
+ opmode |= O_CREAT; /* file: create it */
+ if ((audio = open (AUDIO, opmode, 0)) == -1)
+ {
+ perror (AUDIO);
+ describe_error ();
+ exit (EXIT_FAILURE);
+ }
+
+
+ if (outdev)
+ { /* set dsp parameters */
+ if (ioctl (audio, SNDCTL_DSP_SETFMT, &dsp_samplesize) == -1)
+ dsp_samplesize = 8;
+ if (ioctl (audio, SNDCTL_DSP_STEREO, &dsp_stereo) == -1)
+ dsp_stereo = FALSE;
+ if (ioctl (audio, SNDCTL_DSP_SPEED, &dsp_speed) == -1)
+ {
+ fprintf (stderr, "%s: unable to set playback speed\n", command);
+ perror (AUDIO);
+ exit (EXIT_FAILURE);
+ }
+ if (!quiet_mode)
+ printf ("Playback speed %d Hz (%s) %d bits/sample.\n", dsp_speed,
+ dsp_stereo ? "stereo" : "mono", dsp_samplesize);
+ }
+
+ if (outdev)
+ { /* get the dsp buffer size */
+#if 0
+/*
+ * There is no idea in using SNDCTL_DSP_GETBLKSIZE in applications like this.
+ * Using some fixed local buffer size will work equally well.
+ */
+ ioctl (audio, SNDCTL_DSP_GETBLKSIZE, &abuf_size);
+ if (abuf_size < 1)
+ {
+ perror ("audio_size");
+ close (audio);
+ exit (EXIT_FAILURE);
+ }
+#else
+ abuf_size = 1024;
+#endif
+ }
+ else
+ { /* to a file: use block size of 1kB */
+ abuf_size = 1024;
+ loop_forever = 0;
+ }
+
+ if ((audiobuf = malloc (abuf_size)) == NULL)
+ {
+ fprintf (stderr, "%s: unable to allocate output buffer\n", command);
+ close (audio);
+ exit (EXIT_FAILURE);
+ }
+ abuf_ptr = 0;
+
+ if (optind > argc - 1)
+ {
+ if (use_zcat)
+ {
+ if ((fp = popen (ZCAT, "rb")) == NULL)
+ {
+ fprintf (stderr, "%s: can't execute " ZCAT ".\n", command);
+ return (EXIT_FAILURE);
+ }
+ }
+ else
+ fp = stdin;
+ play_song ();
+ if (use_zcat)
+ pclose (fp);
+ }
+ else
+ while (optind <= argc - 1)
+ if ((currfile = find_file (argv[optind])) == NULL)
+ {
+ fprintf (stderr, "%s: can't find file %s - skipping.\n",
+ command, argv[optind]);
+ optind++;
+ }
+ else if (use_zcat)
+ {
+ if ((fp = popen (strcat (strcpy (zcat_cmd, ZCAT " "),
+ currfile), "rb")) == NULL)
+ {
+ fprintf (stderr, "%s: can't execute " ZCAT " %s.\n",
+ command, currfile);
+ exit (EXIT_FAILURE);
+ }
+ else
+ {
+ play_song ();
+ pclose (fp);
+ if (!loop_forever)
+ optind++;
+ }
+ }
+ else
+ {
+ if ((fp = fopen (currfile, "rb")) == NULL)
+ {
+ fprintf (stderr, "%s: unable to open tune file %s.\n",
+ command, currfile);
+ exit (EXIT_FAILURE);
+ }
+ else
+ {
+ play_song ();
+ fclose (fp);
+ if (!loop_forever)
+ optind++;
+ }
+ }
+
+ if (abuf_ptr)
+ write (audio, audiobuf, abuf_ptr);
+ close (audio);
+
+ return EXIT_SUCCESS;
+}
diff --git a/tutorials/sndkit/dsp/str/str.h b/tutorials/sndkit/dsp/str/str.h
new file mode 100644
index 0000000..308d671
--- /dev/null
+++ b/tutorials/sndkit/dsp/str/str.h
@@ -0,0 +1,74 @@
+#define FALSE 0
+#define TRUE 1
+
+/* Default device for output */
+#define AUDIONAME "/dev/dsp"
+
+#define ZCAT "/usr/bin/zcat"
+
+/* Playback frequency in Hertz:
+ *
+ * 386SX -> 8000 (or 4000)
+ * 386/25 -> 12000
+ * 486/50 -> 23000
+ */
+#define DEFAULT_DSP_SPEED 44100
+
+#define DSP_DEFAULT_STEREO TRUE
+
+/* The default sample size can be 8 or 16 bits/sample */
+#define DSP_DEFAULT_SAMPLESIZE 8
+
+typedef struct
+{ /*************************************/
+ char *info; /* Sample data as a series of bytes */
+ unsigned int length; /* Length of sample in bytes */
+ int volume; /* Default volume 0-64 (min-max) */
+ unsigned int rep_start; /* Byte offset of repeat start */
+ unsigned int rep_end; /* Byte offset of repeat end */
+}
+Voice; /*************************************/
+
+typedef struct
+{ /*************************************/
+ int period[64][4]; /* Period (pitch) of note */
+ char sample[64][4]; /* Sample number to use */
+ char effect[64][4]; /* Effect number (command) */
+ unsigned char params[64][4]; /* Effect parameters */
+}
+Pattern; /*************************************/
+
+typedef struct
+{ /*************************************/
+ unsigned int pointer; /* Current position in sample */
+ unsigned int step; /* Sample offset increment */
+ int samp; /* Number of sample currently used */
+ int pitch; /* Current pitch */
+ int volume; /* Volume of current note (0-64) */
+ int doarp; /* TRUE if doing arpeggio */
+ int arp[3]; /* The three notes in the arpeggio */
+ int doslide; /* TRUE if doing slide */
+ int slide; /* Slide speed and direction */
+ int doporta; /* TRUE if doing portamento */
+ int pitchgoal; /* Pitch to reach */
+ int portarate; /* Rate at which to approach pitch */
+ int dovib; /* TRUE if doing vibrato */
+ int vibspeed; /* Speed of vibrato 0-15 << 2 */
+ int vibamp; /* Amplitude 0-15 */
+ int viboffs; /* Current offset in sine wave */
+ int doslidevol; /* TRUE if doing volume slide */
+ int volslide; /* Slide speed 0-64 */
+}
+Channel; /*************************************/
+
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+
+#define ABUF_SIZE abuf_size
+
+#ifndef EXIT_SUCCESS
+#define EXIT_SUCCESS 0
+#endif
+#ifndef EXIT_FAILURE
+#define EXIT_FAILURE 1
+#endif
diff --git a/tutorials/sndkit/dsp/str/strplay.c b/tutorials/sndkit/dsp/str/strplay.c
new file mode 100644
index 0000000..82a3cda
--- /dev/null
+++ b/tutorials/sndkit/dsp/str/strplay.c
@@ -0,0 +1,575 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#ifdef __STDC__
+#include <string.h>
+#else /* __STDC__ */
+#include <strings.h>
+#endif /* __STDC__ */
+#include <sys/types.h>
+
+#include <sys/soundcard.h>
+#include "str.h"
+
+extern int audio;
+extern unsigned char *audiobuf;
+extern int abuf_ptr;
+extern int abuf_size;
+
+extern char *command;
+extern int quiet_mode, verbose_mode;
+extern int mute[4];
+extern int dsp_stereo;
+extern int dsp_samplesize;
+extern long dsp_speed;
+
+extern FILE *fp;
+
+static int VSYNC; /* number of sample bytes to output in 1/50 sec */
+
+static int notes, channel, vsync, bytes, pat_num; /* loop variables */
+static int note, pat;
+static int end_pattern;
+
+/* song data and parameters */
+static int speed;
+static char songlength, songrepeat, tune[128];
+static int nvoices;
+static Voice voices[32];
+static char num_patterns;
+static Pattern patterns[128];
+static Channel ch[4];
+
+/* table for generating pitches */
+static int step_table[1024];
+
+/* sine wave table for the vibrato effect */
+static int sin_table[] = {
+ 0x00, 0x18, 0x31, 0x4A, 0x61, 0x78, 0x8D, 0xA1,
+ 0xB4, 0xC5, 0xD4, 0xE0, 0xEB, 0xF4, 0xFA, 0xFD,
+ 0xFF, 0xFD, 0xFA, 0xF4, 0xEB, 0xE0, 0xD4, 0xC5,
+ 0xB4, 0xA1, 0x8D, 0x78, 0x61, 0x4A, 0x31, 0x18
+};
+
+/* period table for notes C0-B2, used for arpeggio effect */
+static int periods[] = {
+ 0x358, 0x328, 0x2FA, 0x2D0, 0x2A6, 0x280,
+ 0x25C, 0x23A, 0x21A, 0x1FC, 0x1E0, 0x1C5,
+ 0x1AC, 0x194, 0x17D, 0x168, 0x153, 0x140,
+ 0x12E, 0x11D, 0x10D, 0x0FE, 0x0F0, 0x0E2,
+ 0x0D6, 0x0CA, 0x0BE, 0x0B4, 0x0AA, 0x0A0,
+ 0x097, 0x08F, 0x087, 0x07F, 0x078, 0x071
+};
+
+/* skip n bytes of file f - stdin has no fseek */
+void
+byteskip (f, n)
+ FILE *f;
+ int n;
+{
+ while (n--)
+ fgetc (f);
+}
+
+/* get string of length <len> from file f */
+char *
+getstring (f, len)
+ FILE *f;
+ int len;
+{
+ static char s[256];
+ int i;
+
+ for (i = 0; i < len; i++)
+ {
+ if ((s[i] = fgetc (f)) == '\1')
+ s[i] = '\0'; /* bug fix for some few modules */
+ if (s[i] < 32 && s[i])
+ {
+ fprintf (stderr, "This is not a string. Wrong format?\n");
+ exit (EXIT_FAILURE);
+ }
+ }
+ s[len] = '\0';
+
+ return s;
+}
+
+void
+audioput (c)
+ int c;
+{
+ audiobuf[abuf_ptr++] = c;
+ if (abuf_ptr >= ABUF_SIZE)
+ {
+#if 0
+ int count;
+
+ if (ioctl (audio, SNDCTL_DSP_GETODELAY, &count) == -1)
+ perror ("GETODELAY");
+ printf ("%6d\n", count);
+#endif
+ if (write (audio, audiobuf, abuf_ptr) == -1)
+ {
+ perror ("audio_write");
+ exit (EXIT_FAILURE);
+ }
+ abuf_ptr = 0;
+ }
+}
+
+void
+audioput16 (c)
+ int c;
+{
+ audiobuf[abuf_ptr++] = c & 0xFF;
+ audiobuf[abuf_ptr++] = c >> 8;
+ if ((abuf_ptr + 1) >= ABUF_SIZE)
+ {
+ if (write (audio, audiobuf, abuf_ptr) == -1)
+ {
+ perror ("audio_write");
+ exit (EXIT_FAILURE);
+ }
+ abuf_ptr = 0;
+ }
+}
+
+void
+play_song ()
+{
+ int i;
+
+ /* set up pitch table:
+ * 3576872 is the base clock frequency of the Amiga's Paula chip,
+ * the pitch i is the number of cycles between outputting two samples.
+ * => i / 3576872 is the delay between two bytes
+ * => our_freq * i / 3576872 is our delay.
+ * The 65536 are just there for accuracy of integer operations (<< 16).
+ */
+ step_table[0] = 0;
+ for (i = 1; i < 1024; i++)
+ step_table[i] = (int) (((3575872.0 / dsp_speed) / i) * 65536.0);
+
+ /* VSYNC is the number of bytes in 1/50 sec
+ * computed as freq * (1 / 50).
+ */
+ VSYNC = (dsp_speed + 25) / 50; /* with round */
+
+ /* read song name */
+ if (quiet_mode)
+ byteskip (fp, 20);
+ else
+ printf ("Module : %s\n\n", getstring (fp, 20));
+
+ /* determine number of voices from command name */
+ nvoices = strstr (command, "15") == NULL ? 31 : 15;
+
+ /* read in the sample information tables */
+ voices[0].length = 0;
+ for (i = 1; i <= nvoices; i++)
+ {
+ /* sample name */
+ if (quiet_mode)
+ byteskip (fp, 22);
+ else if (nvoices == 15)
+ printf ("%6d : %s\n", i, getstring (fp, 22));
+ else
+ {
+ printf ("%6d : %22s", i, getstring (fp, 22));
+ if (!(i & 1))
+ printf ("\n");
+ }
+ /* the sample length and repeat data are stored as numbers of words,
+ * we want the number of bytes << 16.
+ */
+ voices[i].length = (fgetc (fp) << 25) | (fgetc (fp) << 17);
+ fgetc (fp);
+ if ((voices[i].volume = fgetc (fp)) > 64)
+ voices[i].volume = 64;
+ voices[i].rep_start = (fgetc (fp) << 25) | (fgetc (fp) << 17);
+ voices[i].rep_end = (fgetc (fp) << 25) | (fgetc (fp) << 17);
+ if (voices[i].rep_end <= 4 << 16)
+ voices[i].rep_end = 0;
+ else
+ {
+ voices[i].rep_end += voices[i].rep_start;
+ if (voices[i].rep_end > voices[i].length)
+ voices[i].rep_end = voices[i].length;
+ }
+ }
+
+ /* read sequence data: length and repeat position */
+ songlength = fgetc (fp);
+ songrepeat = fgetc (fp);
+ if (songrepeat > songlength) /* this is often buggy in modules */
+ songrepeat = 0;
+
+ /* read in the sequence and determine the number of patterns
+ * by looking for the highest pattern number.
+ */
+ num_patterns = 0;
+ for (i = 0; i < 128; i++)
+ {
+ tune[i] = fgetc (fp);
+ if (tune[i] > num_patterns)
+ num_patterns = tune[i];
+ }
+ num_patterns++; /* pattern numbers begin at 0 */
+
+ /* skip over sig in new modules (usually M.K.).
+ * note: this sig could be used for determining whether the module
+ * is of an old type (15 samples max) or new (up to 31 samples)
+ */
+ if (nvoices == 31)
+ byteskip (fp, 4);
+
+ /* read in the patterns.
+ * Each pattern consists of 64 lines,
+ * each containing data for the four voices.
+ */
+ for (pat_num = 0; pat_num < num_patterns; pat_num++)
+ for (notes = 0; notes < 64; notes++)
+ for (channel = 0; channel < 4; channel++)
+ {
+ note = (fgetc (fp) << 8) | fgetc (fp);
+ patterns[pat_num].sample[notes][channel] = (note >> 8) & 0x10;
+ patterns[pat_num].period[notes][channel] = MIN (note & 0xFFF, 1023);
+ note = (fgetc (fp) << 8) | fgetc (fp);
+ patterns[pat_num].sample[notes][channel] |= note >> 12;
+ patterns[pat_num].effect[notes][channel] = (note >> 8) & 0xF;
+ patterns[pat_num].params[notes][channel] = note & 0xFF;
+ }
+
+ /* store each sample as an array of char */
+ for (i = 1; i <= nvoices; i++)
+ if (voices[i].length)
+ {
+ if ((voices[i].info = malloc (voices[i].length >> 16)) == NULL)
+ {
+ fprintf (stderr, "%s: can't allocate memory\n", command);
+ exit (EXIT_FAILURE);
+ }
+ fread (voices[i].info, 1, voices[i].length >> 16, fp);
+ if (voices[i].rep_end)
+ voices[i].length = voices[i].rep_end;
+ voices[i].rep_start -= voices[i].length;
+ }
+
+ /* initialize global and channel replay data */
+ speed = 6;
+ for (i = 0; i < 4; i++)
+ {
+ ch[i].pointer = 0;
+ ch[i].step = 0;
+ ch[i].volume = 0;
+ ch[i].pitch = 0;
+ }
+
+ if (!quiet_mode)
+ if (verbose_mode)
+ printf ("\n");
+ else
+ {
+ printf ("\nPosition (%d):", songlength);
+ fflush (stdout);
+ }
+
+
+ /*******************************/
+ /* Here begins the replay part */
+ /*******************************/
+
+ for (pat_num = 0; pat_num < songlength; pat_num++)
+ {
+ pat = tune[pat_num];
+
+ if (!quiet_mode)
+ if (verbose_mode)
+ printf (" --------------+--------------+--------------+-----"
+ "--------- %02X (%02X) = %02X\n", pat_num,
+ songlength, pat);
+ else
+ {
+ printf ("\r\t\t%3d", pat_num);
+ fflush (stdout);
+ }
+
+ end_pattern = FALSE;
+ for (notes = 0; notes < 64; notes++)
+ {
+ int samp, pitch, cmd, para;
+ Channel *curch;
+
+ if (!quiet_mode && verbose_mode)
+ printf ("%02X ", notes);
+
+ curch = ch;
+ for (channel = 0; channel < 4; channel++, curch++)
+ {
+ samp = patterns[pat].sample[notes][channel];
+ pitch = patterns[pat].period[notes][channel];
+ cmd = patterns[pat].effect[notes][channel];
+ para = patterns[pat].params[notes][channel];
+
+ if (verbose_mode && !quiet_mode)
+ if (pitch)
+ printf (" %03X %2X %X%02X%s", pitch, samp, cmd, para,
+ channel == 3 ? "\n" : " |");
+ else
+ printf (" --- %2X %X%02X%s", samp, cmd, para,
+ channel == 3 ? "\n" : " |");
+
+ if (mute[channel])
+ {
+ if (cmd == 0x0B || cmd == 0x0D || cmd == 0x0F)
+ switch (cmd)
+ {
+ case 0xB: /* Pattern jump */
+ end_pattern = TRUE;
+ pat_num = (para & 0xF) + (10 * (para >> 4));
+ break;
+ case 0xD: /* Pattern break */
+ end_pattern = TRUE;
+ break;
+ case 0xF: /* Set speed */
+ speed = para;
+ break;
+ }
+ continue;
+ }
+
+ /* if a sample number is given, it is loaded and the note
+ * is restarted
+ */
+ if (samp)
+ {
+ curch->samp = samp;
+ /* load new instrument */
+ curch->volume = voices[samp].volume;
+ }
+
+ if (samp || (pitch && cmd != 3))
+ {
+ if (pitch)
+ curch->pitch = curch->arp[0] = pitch;
+ curch->pointer = 0;
+ curch->viboffs = 0;
+ }
+
+ /* by default there is no effect */
+ curch->doarp = FALSE;
+ curch->doslide = FALSE;
+ curch->doporta = FALSE;
+ curch->dovib = FALSE;
+ curch->doslidevol = FALSE;
+
+ switch (cmd)
+ { /* Do effects */
+ case 0: /* Arpeggio */
+ if (para)
+ {
+ for (i = 0; i < 36 && periods[i] > curch->arp[0]; i++);
+ if (i + (para >> 4) < 36 && i + (para & 0xF) < 36)
+ {
+ curch->doarp = TRUE;
+ curch->arp[0] = periods[i];
+ curch->arp[1] = periods[i + (para >> 4)];
+ curch->arp[2] = periods[i + (para & 0xF)];
+ }
+ }
+ break;
+ case 1: /* Portamento up */
+ curch->doslide = TRUE;
+ if (para)
+ curch->slide = -para;
+ break;
+ case 2: /* Portamento down */
+ curch->doslide = TRUE;
+ if (para)
+ curch->slide = para;
+ break;
+ case 3: /* Note portamento */
+ curch->doporta = TRUE;
+ if (para)
+ curch->portarate = para;
+ if (pitch)
+ curch->pitchgoal = pitch;
+ break;
+ case 4: /* Vibrato */
+ curch->dovib = TRUE;
+ if (para)
+ {
+ curch->vibspeed = (para >> 2) & 0x3C;
+ curch->vibamp = para & 0xF;
+ }
+ break;
+ case 0xA: /* Volume slide */
+ curch->doslidevol = TRUE;
+ if (para)
+ {
+ if (!(para & 0xF0))
+ curch->volslide = -para;
+ else
+ curch->volslide = (para >> 4);
+ }
+ break;
+ case 0xB: /* Pattern jump */
+ end_pattern = TRUE;
+ pat_num = (para & 0xF) + (10 * (para >> 4));
+ break;
+ case 0xC: /* Set volume */
+ curch->volume = MIN (para, 64);
+ break;
+ case 0xD: /* Pattern break */
+ end_pattern = TRUE;
+ break;
+ case 0xF: /* Set speed */
+ speed = para;
+ break;
+ default:
+ /* printf(" [%d][%d] ", cmd, para); */
+ break;
+ }
+ }
+
+ {
+ register Channel *curch;
+ register Voice *curv;
+
+ for (vsync = 0; vsync < speed; vsync++)
+ {
+
+ ch[0].step = step_table[ch[0].pitch];
+ ch[1].step = step_table[ch[1].pitch];
+ ch[2].step = step_table[ch[2].pitch];
+ ch[3].step = step_table[ch[3].pitch];
+
+ for (bytes = 0; bytes < VSYNC; bytes++)
+ {
+ int byte[2] = { 0, 0 };
+
+ curch = ch;
+ for (channel = 0; channel < 4; channel++, curch++)
+ {
+ if (!curch->samp || mute[channel])
+ continue;
+
+ curv = &voices[(int) curch->samp];
+
+ /* test for end of sample */
+ if (curch->pointer >= curv->length)
+ if (!curv->rep_end)
+ continue;
+ else
+ curch->pointer += curv->rep_start;
+
+ /* mix samples.
+ * the sample is read and multiplied by the volume
+ */
+ if (curch->pointer < curv->length)
+ /* in stereo, channels 1 & 3 and 2 & 4 are mixed
+ * seperately
+ */
+ byte[channel & dsp_stereo] += (int)
+ ((curv->info[curch->pointer >> 16]) *
+ ((int) curch->volume << 2));
+ /* advance the sample pointer */
+ curch->pointer += curch->step;
+ }
+
+ /* output sample */
+ if (dsp_samplesize == 8)
+ {
+ if (dsp_stereo)
+ {
+ byte[0] >>= 9;
+ audioput (byte[0] + 128);
+ byte[1] >>= 9;
+ audioput (byte[1] + 128);
+ }
+ else
+ audioput ((byte[0] >> 10) + 128);
+ }
+ else
+ {
+ if (dsp_stereo)
+ {
+ audioput16 (byte[0] >> 1);
+ audioput16 (byte[1] >> 1);
+ }
+ else
+ audioput16 (byte[0] >> 2);
+ }
+ }
+
+ /* Do end of vsync */
+ if (vsync == 0)
+ continue;
+ curch = ch;
+ for (channel = 0; channel < 4; channel++, curch++)
+ {
+ if (mute[channel])
+ continue;
+ if (curch->doarp)
+ curch->pitch = curch->arp[vsync % 3];
+ else if (curch->doslide)
+ {
+ curch->arp[0] += curch->slide;
+ curch->arp[0] = MIN (curch->arp[0], 1023);
+ curch->arp[0] = MAX (curch->arp[0], 113);
+ curch->pitch = curch->arp[0];
+ }
+ else if (curch->doporta)
+ {
+ if (curch->arp[0] < curch->pitchgoal)
+ {
+ curch->arp[0] += curch->portarate;
+ if (curch->arp[0] > curch->pitchgoal)
+ curch->arp[0] = curch->pitchgoal;
+ }
+ else if (curch->arp[0] > curch->pitchgoal)
+ {
+ curch->arp[0] -= curch->portarate;
+ if (curch->arp[0] < curch->pitchgoal)
+ curch->arp[0] = curch->pitchgoal;
+ }
+ curch->pitch = curch->arp[0];
+ }
+ else if (curch->dovib)
+ {
+ if (curch->viboffs & 0x80)
+ curch->pitch = curch->arp[0] - ((sin_table
+ [(curch->
+ viboffs >> 2) &
+ 0x1F] *
+ curch->
+ vibamp) >> 6);
+ else
+ curch->pitch = curch->arp[0] + ((sin_table
+ [(curch->
+ viboffs >> 2) &
+ 0x1F] *
+ curch->
+ vibamp) >> 6);
+ curch->viboffs += curch->vibspeed;
+ }
+ else if (curch->doslidevol)
+ {
+ curch->volume += curch->volslide;
+ if (curch->volume < 0)
+ curch->volume = 0;
+ else if (curch->volume >= 64)
+ curch->volume = 64;
+ }
+ }
+ }
+ }
+ if (end_pattern == 1)
+ break;
+ }
+ }
+
+ if (!quiet_mode)
+ printf ("\n");
+}
diff --git a/tutorials/sndkit/dsp/vplay/Makefile b/tutorials/sndkit/dsp/vplay/Makefile
new file mode 100644
index 0000000..17bfd1e
--- /dev/null
+++ b/tutorials/sndkit/dsp/vplay/Makefile
@@ -0,0 +1,20 @@
+#CC=gcc
+#CFLAGS=-O6 -funroll-loops -Wall
+CC=cc
+CFLAGS=-O -Wall
+
+all: vplay vrec
+
+vplay: vplay.c fmtheaders.h
+ $(CC) $(CFLAGS) vplay.c -o vplay
+ strip vplay
+
+vrec: vplay
+ ln -s vplay vrec
+clean:
+ rm -f vplay vrec *.o core
+
+install: vplay
+ cp vplay /usr/local/bin
+ rm -f /usr/local/bin/vrec
+ ln -s /usr/local/bin/vplay /usr/local/bin/vrec
diff --git a/tutorials/sndkit/dsp/vplay/Readme b/tutorials/sndkit/dsp/vplay/Readme
new file mode 100644
index 0000000..881393d
--- /dev/null
+++ b/tutorials/sndkit/dsp/vplay/Readme
@@ -0,0 +1,69 @@
+Digitized Audio Utility for Linux ver. 0.3
+============================================
+
+This directory contains vplay.c, a modified version of recplay.c.
+
+vrec and vplay
+--------------
+
+These programs can be used for recording and playing:
+ CREATIVE LABS VOICE files
+ MICROSOFT WAVE file (old format only (new format is handled as raw data))
+ NeXT sound files (similar to Sun's .au format)
+ raw audio data.
+
+Both programs accept the same options:
+
+ vrec [-qvwrS] [-s speed] [-t seconds] -b bits [filename1 ...]
+ vplay [-qvwrS] [-s speed] [-t seconds] -b bits [filename1 ...]
+
+ -S Stereo (default is mono).
+ -s speed Sets the speed (default is 8 kHz). If the speed is
+ less than 300, it will be multiplied by 1000.
+ -t seconds Sets the recording (or playback) time in seconds.
+ (Default is no time limit).
+ -t bits Sets sample size (bits/sample). Possible values are
+ 8 and 16 (default 8).
+ -v record a CREATIVE LABS VOICE file (default)
+ -w record a MICROSOFT WAVE file
+ -r record raw data without header
+ -a record a NeXT sound file
+ -q quiet mode
+
+ The options for speed, time etc. take only effect if you playing
+ raw data files (or recording). VOC and WAVE-files include this
+ information in their headers/internal structure.
+ If no filenames are given, stdout (vrec) or stdin (vplay) is used.
+ The -t parameter applies to each files. For example
+
+ vrec -r -t 1 a b c
+
+ records one second of audio data to each of the files a, b, and c and
+
+ vplay -t 1 a b c
+
+ plays the first second of each of the files a, b and c (if its
+ raw audio).
+
+Don't use higher recording speeds than your card supports. This error is not
+always detected by the driver.
+
+vplay supports:
+ - the full CREATIVE LABS VOICE structure:
+ Silence, Repeat loops (on seekable input), Stereo, ASCII blocks,
+ blocks with different sampling rate
+ - on non-stereo cards (SB 1.0 - 2.0) 8 bit stereo files will be
+ played as mono (the first channel is used)
+ - on non-16-bit cards, 16 bit WAVE files will be played as 8 bit
+ (you can really play on a SB 1.0 a 16 bit stereo WAVE file, or
+ buy ...)
+
+unsupported:
+ - packed VOC files (because /dev/dsp can't it (yet ?))
+ - multi block WAVE files (if there exists like VOC files, my specs
+ says no but RIFF definition yes ???)
+ - not PCM coded WAVE files (because I don't know other methods)
+ - more channel WAVE files (somebody has a quadrophonic sample?)
+ - alaw- or mulaw-encoded NeXt sound files
+
+Michael Beck beck@informatik.hu-berlin.de
diff --git a/tutorials/sndkit/dsp/vplay/etc.magic.vplay b/tutorials/sndkit/dsp/vplay/etc.magic.vplay
new file mode 100644
index 0000000..a0c5c29
--- /dev/null
+++ b/tutorials/sndkit/dsp/vplay/etc.magic.vplay
@@ -0,0 +1,16 @@
+#
+# Creative Labs Voice file
+#
+0 string Creative\ Voice\ File Creative Labs Voice File
+>19 byte 0x1A
+>23 byte >0 - version %d
+>22 byte >0 \b.%d
+#
+# Microsoft WAVE format
+0 string RIFF Microsoft RIFF
+>8 string WAVE - WAVE format
+>34 short >0 %d bit
+>22 short =1 Mono
+>22 short =2 Stereo
+>22 short >2 %d Channels
+>24 long >0 %d Hz
diff --git a/tutorials/sndkit/dsp/vplay/fmtheaders.h b/tutorials/sndkit/dsp/vplay/fmtheaders.h
new file mode 100644
index 0000000..9afb0cd
--- /dev/null
+++ b/tutorials/sndkit/dsp/vplay/fmtheaders.h
@@ -0,0 +1,108 @@
+#ifndef _FMTHEADERS_H
+#define _FMTHEADERS_H 1
+
+#include <sys/types.h>
+
+/* Definitions for .VOC files */
+
+#define MAGIC_STRING "Creative Voice File\x1A"
+#define ACTUAL_VERSION 0x010A
+#define VOC_SAMPLESIZE 8
+
+#define MODE_MONO 0
+#define MODE_STEREO 1
+
+#define DATALEN(bp) ((u_long)(bp->datalen) | \
+ ((u_long)(bp->datalen_m) << 8) | \
+ ((u_long)(bp->datalen_h) << 16) )
+
+typedef struct _vocheader
+{
+ u_char magic[20]; /* must be MAGIC_STRING */
+ u_short headerlen; /* Headerlength, should be 0x1A */
+ u_short version; /* VOC-file version */
+ u_short coded_ver; /* 0x1233-version */
+}
+VocHeader;
+
+typedef struct _blocktype
+{
+ u_char type;
+ u_char datalen; /* low-byte */
+ u_char datalen_m; /* medium-byte */
+ u_char datalen_h; /* high-byte */
+}
+BlockType;
+
+typedef struct _voice_data
+{
+ u_char tc;
+ u_char pack;
+}
+Voice_data;
+
+typedef struct _ext_block
+{
+ u_short tc;
+ u_char pack;
+ u_char mode;
+}
+Ext_Block;
+
+
+/* Definitions for Microsoft WAVE format */
+
+#define RIFF 0x46464952
+#define WAVE 0x45564157
+#define FMT 0x20746D66
+#define DATA 0x61746164
+#define PCM_CODE 1
+#define WAVE_MONO 1
+#define WAVE_STEREO 2
+
+/* it's in chunks like .voc and AMIGA iff, but my source say there
+ are in only in this combination, so I combined them in one header;
+ it works on all WAVE-file I have
+*/
+typedef struct _waveheader
+{
+ u_long main_chunk; /* 'RIFF' */
+ u_long length; /* filelen */
+ u_long chunk_type; /* 'WAVE' */
+
+ u_long sub_chunk; /* 'fmt ' */
+ u_long sc_len; /* length of sub_chunk, =16 */
+ u_short format; /* should be 1 for PCM-code */
+ u_short modus; /* 1 Mono, 2 Stereo */
+ u_long sample_fq; /* frequence of sample */
+ u_long byte_p_sec;
+ u_short byte_p_spl; /* samplesize; 1 or 2 bytes */
+ u_short bit_p_spl; /* 8, 12 or 16 bit */
+
+ u_long data_chunk; /* 'data' */
+ u_long data_length; /* samplecount */
+}
+WaveHeader;
+
+typedef struct
+{
+ long magic; /* must be equal to SND_MAGIC */
+ long dataLocation; /* Offset or pointer to the raw data */
+ long dataSize; /* Number of bytes of data in the raw data */
+ long dataFormat; /* The data format code */
+ long samplingRate; /* The sampling rate */
+ long channelCount; /* The number of channels */
+}
+SndHeader;
+
+#define SND_MAGIC ((long int)0x2e736e64)
+
+#define SND_FORMAT_UNSPECIFIED (0)
+#define SND_FORMAT_MULAW_8 (1)
+#define SND_FORMAT_LINEAR_8 (2)
+#define SND_FORMAT_LINEAR_16 (3)
+#define SND_FORMAT_LINEAR_24 (4)
+#define SND_FORMAT_LINEAR_32 (5)
+#define SND_FORMAT_FLOAT (6)
+
+#endif
diff --git a/tutorials/sndkit/dsp/vplay/vplay.c b/tutorials/sndkit/dsp/vplay/vplay.c
new file mode 100644
index 0000000..afbc4d3
--- /dev/null
+++ b/tutorials/sndkit/dsp/vplay/vplay.c
@@ -0,0 +1,1012 @@
+/*
+ vplay.c - plays and records
+ CREATIVE LABS VOICE-files, Microsoft WAVE-files and raw data
+
+ Autor: Michael Beck - beck@informatik.hu-berlin.de
+*/
+
+#include <stdio.h>
+#include <malloc.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/soundcard.h>
+#include "fmtheaders.h"
+#include <netinet/in.h>
+
+#define DEFAULT_DSP_SPEED 8000
+
+#define RECORD 0
+#define PLAY 1
+#define AUDIO "/dev/dsp"
+
+#define min(a,b) ((a) <= (b) ? (a) : (b))
+#define d_printf(x) if (verbose_mode) fprintf x
+
+#define VOC_FMT 0
+#define WAVE_FMT 1
+#define RAW_DATA 2
+#define SND_FMT 3
+
+/* global data */
+
+int timelimit = 0, dsp_speed = DEFAULT_DSP_SPEED, dsp_stereo = 0;
+int samplesize = 8;
+int quiet_mode = 0;
+int verbose_mode = 0;
+int convert = 0;
+int record_type = VOC_FMT;
+u_long count;
+int audio, abuf_size, zbuf_size;
+int direction, omode;
+u_char *audiobuf, *zerobuf;
+char *command;
+int vocminor, vocmajor; /* .VOC version */
+
+/* defaults for playing raw data */
+struct
+{
+ int timelimit, dsp_speed, dsp_stereo, samplesize;
+}
+raw_info =
+{
+0, DEFAULT_DSP_SPEED, 0, 8};
+
+/* needed prototypes */
+
+void record_play (char *name);
+void start_voc (int fd, u_long count);
+void start_wave (int fd, u_long count);
+void start_snd (int fd, u_long count);
+void end_voc (int fd);
+void end_wave_raw (int fd);
+void end_snd (int fd);
+u_long calc_count ();
+
+struct fmt_record
+{
+ void (*start) (int fd, u_long count);
+ void (*end) (int fd);
+ char *what;
+}
+fmt_rec_table[] =
+{
+ {
+ start_voc, end_voc, "VOC"}
+ ,
+ {
+ start_wave, end_wave_raw, "WAVE"}
+ ,
+ {
+ NULL, end_wave_raw, "raw data"}
+ ,
+ {
+ start_snd, end_snd, "SND"}
+};
+
+int
+main (int argc, char *argv[])
+{
+ int c, n = 0;
+
+ command = argv[0];
+ if (strstr (argv[0], "vrec"))
+ {
+ direction = RECORD;
+ omode = O_RDONLY;
+ }
+ else if (strstr (argv[0], "vplay"))
+ {
+ direction = PLAY;
+ omode = O_WRONLY;
+ }
+ else
+ {
+ fprintf (stderr,
+ "Error: command should be named either vrec or vplay\n");
+ exit (1);
+ }
+
+ while ((c = getopt (argc, argv, "aqs:St:b:vrwd")) != EOF)
+ switch (c)
+ {
+ case 'S':
+ dsp_stereo = raw_info.dsp_stereo = 1;
+ break;
+ case 'q':
+ quiet_mode = 1;
+ break;
+ case 'r':
+ record_type = RAW_DATA;
+ break;
+ case 'v':
+ record_type = VOC_FMT;
+ break;
+ case 'w':
+ record_type = WAVE_FMT;
+ break;
+ case 'a':
+ record_type = SND_FMT;
+ break;
+ case 's':
+ dsp_speed = atoi (optarg);
+ if (dsp_speed < 300)
+ dsp_speed *= 1000;
+ raw_info.dsp_speed = dsp_speed;
+ break;
+ case 't':
+ timelimit = raw_info.timelimit = atoi (optarg);
+ break;
+ case 'b':
+ samplesize = raw_info.samplesize = atoi (optarg);
+ break;
+ case 'd':
+ verbose_mode = 1;
+ quiet_mode = 0;
+ break;
+ default:
+ fprintf (stderr,
+ "Usage: %s [-qvwraS] [-t secs] [-s Hz] [-b 8|12|16] [filename]\n",
+ command);
+ exit (-1);
+ }
+
+ audio = open (AUDIO, omode, 0);
+ if (audio == -1)
+ {
+ perror (AUDIO);
+ exit (-1);
+ }
+
+ if (optind > argc - 1)
+ record_play (NULL);
+ else
+ while (optind <= argc - 1)
+ {
+
+ if (n++ > 0)
+ if (ioctl (audio, SNDCTL_DSP_SYNC, NULL) < 0)
+ {
+ perror (AUDIO);
+ exit (-1);
+ }
+
+ record_play (argv[optind++]);
+ }
+ close (audio);
+ return 0;
+}
+
+/*
+ test, if it is a .VOC file and return >=0 if ok (this is the length of rest)
+ < 0 if not
+*/
+int
+test_vocfile (void *buffer)
+{
+ VocHeader *vp = buffer;
+ if (!strcmp ((const char *) vp->magic, MAGIC_STRING))
+ {
+ vocminor = vp->version & 0xFF;
+ vocmajor = vp->version / 256;
+ if (vp->version != (0x1233 - vp->coded_ver))
+ return -2; /* coded version mismatch */
+ return vp->headerlen - sizeof (VocHeader); /* 0 mostly */
+ }
+ return -1; /* magic string fail */
+}
+
+/*
+ test, if it's a .WAV file, 0 if ok (and set the speed, stereo etc.)
+ < 0 if not
+*/
+int
+test_wavefile (void *buffer)
+{
+ WaveHeader *wp = buffer;
+ if (wp->main_chunk == RIFF && wp->chunk_type == WAVE &&
+ wp->sub_chunk == FMT && wp->data_chunk == DATA)
+ {
+ if (wp->format != PCM_CODE)
+ {
+ fprintf (stderr, "%s: can't play not PCM-coded WAVE-files\n",
+ command);
+ exit (-1);
+ }
+ if (wp->modus > 2)
+ {
+ fprintf (stderr, "%s: can't play WAVE-files with %d tracks\n",
+ command, wp->modus);
+ exit (-1);
+ }
+ dsp_stereo = (wp->modus == WAVE_STEREO) ? 1 : 0;
+ samplesize = wp->bit_p_spl;
+ dsp_speed = wp->sample_fq;
+ count = wp->data_length;
+ return 0;
+ }
+ return -1;
+}
+
+/*
+* test, if it's a .SND file, 0 if ok (and set the speed, stereo etc.)
+* < 0 if not
+*/
+int
+test_sndfile (void *buffer, int fd)
+{
+ long infolen;
+ char *info;
+ SndHeader *snd = buffer;
+
+ if (snd->magic == SND_MAGIC)
+ convert = 0;
+ else
+ {
+ if (htonl (snd->magic) == SND_MAGIC)
+ {
+ convert = 1;
+ snd->dataLocation = htonl (snd->dataLocation);
+ snd->dataSize = htonl (snd->dataSize);
+ snd->dataFormat = htonl (snd->dataFormat);
+ snd->samplingRate = htonl (snd->samplingRate);
+ snd->channelCount = htonl (snd->channelCount);
+ }
+ else
+ {
+ /* No SoundFile */
+ return (-1);
+ }
+ }
+ switch (snd->dataFormat)
+ {
+ case SND_FORMAT_LINEAR_8:
+ samplesize = 8;
+ break;
+ case SND_FORMAT_LINEAR_16:
+ samplesize = 16;
+ break;
+ default:
+ fprintf (stderr, "%s: Unsupported SND_FORMAT\n", command);
+ exit (-1);
+ }
+
+ dsp_stereo = (snd->channelCount == 2) ? 1 : 0;
+ dsp_speed = snd->samplingRate;
+ count = snd->dataSize;
+
+ /* read Info-Strings */
+ infolen = snd->dataLocation - sizeof (SndHeader);
+ info = (char *) malloc (infolen);
+ read (fd, info, infolen);
+ if (!quiet_mode)
+ fprintf (stderr, "SoundFile Info: %s\n", info);
+ free (info);
+
+ return 0;
+}
+
+
+/*
+ writing zeros from the zerobuf to simulate silence,
+ perhaps it's enough to use a long var instead of zerobuf ?
+*/
+void
+write_zeros (unsigned x)
+{
+ unsigned l;
+
+ while (x)
+ {
+ l = min (x, zbuf_size);
+ if (write (audio, (char *) zerobuf, l) != l)
+ {
+ perror (AUDIO);
+ exit (-1);
+ }
+ x -= l;
+ }
+}
+
+/* if need a SYNC,
+ (is needed if we plan to change speed, stereo ... during output)
+*/
+void
+sync_dsp (void)
+{
+#if 0
+ if (ioctl (audio, SNDCTL_DSP_SYNC, NULL) < 0)
+ {
+ perror (AUDIO);
+ exit (-1);
+ }
+#endif
+}
+
+/* setting the speed for output */
+void
+set_dsp_speed (int *dsp_speed)
+{
+ if (ioctl (audio, SNDCTL_DSP_SPEED, dsp_speed) < 0)
+ {
+ fprintf (stderr, "%s: unable to set audio speed\n", command);
+ perror (AUDIO);
+ exit (-1);
+ }
+}
+
+/* if to_mono:
+ compress 8 bit stereo data 2:1, needed if we want play 'one track';
+ this is usefull, if you habe SB 1.0 - 2.0 (I have 1.0) and want
+ hear the sample (in Mono)
+ if to_8:
+ compress 16 bit to 8 by using hi-byte; wave-files use signed words,
+ so we need to convert it in "unsigned" sample (0x80 is now zero)
+
+ WARNING: this procedure can't compress 16 bit stereo to 16 bit mono,
+ because if you have a 16 (or 12) bit card you should have
+ stereo (or I'm wrong ?? )
+ */
+u_long
+one_channel (u_char * buf, u_long l, char to_mono, char to_8)
+{
+ register u_char *w = buf;
+ register u_char *w2 = buf;
+ char ofs = 0;
+ u_long incr = 0;
+ u_long c, ret;
+
+ if (to_mono)
+ ++incr;
+ if (to_8)
+ {
+ ++incr;
+ ++w2;
+ ofs = 128;
+ }
+ ret = c = l >> incr;
+ incr = incr << 1;
+
+ while (c--)
+ {
+ *w++ = *w2 + ofs;
+ w2 += incr;
+ }
+ return ret;
+}
+
+/*
+ ok, let's play a .voc file
+*/
+void
+vplay (int fd, int ofs, char *name)
+{
+ int l, real_l;
+ BlockType *bp;
+ Voice_data *vd;
+ Ext_Block *eb;
+ u_long nextblock, in_buffer;
+ u_char *data = audiobuf;
+ char was_extended = 0, output = 0;
+ u_short *sp, repeat = 0;
+ u_long silence;
+ int filepos = 0;
+ char one_chn = 0;
+
+#define COUNT(x) nextblock -= x; in_buffer -=x ;data += x
+
+ /* first SYNC the dsp */
+ sync_dsp ();
+
+ if (!quiet_mode)
+ fprintf (stderr, "Playing Creative Labs Voice file ...\n");
+
+ /* first we waste the rest of header, ugly but we don't need seek */
+ while (ofs > abuf_size)
+ {
+ read (fd, (char *) audiobuf, abuf_size);
+ ofs -= abuf_size;
+ }
+ if (ofs)
+ read (fd, audiobuf, ofs);
+
+ /* .voc files are 8 bit (now) */
+ samplesize = VOC_SAMPLESIZE;
+ ioctl (audio, SNDCTL_DSP_SETFMT, &samplesize);
+ if (samplesize != VOC_SAMPLESIZE)
+ {
+ fprintf (stderr, "%s: unable to set 8 bit sample size!\n", command);
+ exit (-1);
+ }
+ /* and there are MONO by default */
+ dsp_stereo = MODE_MONO;
+ ioctl (audio, SNDCTL_DSP_STEREO, &dsp_stereo);
+
+ in_buffer = nextblock = 0;
+ while (1)
+ {
+ Fill_the_buffer: /* need this for repeat */
+ if (in_buffer < 32)
+ {
+ /* move the rest of buffer to pos 0 and fill the audiobuf up */
+ if (in_buffer)
+ memcpy ((char *) audiobuf, data, in_buffer);
+ data = audiobuf;
+ if ((l =
+ read (fd, (char *) audiobuf + in_buffer,
+ abuf_size - in_buffer)) > 0)
+ in_buffer += l;
+ else if (!in_buffer)
+ {
+ /* the file is truncated, so simulate 'Terminator'
+ and reduce the datablock for save landing */
+ nextblock = audiobuf[0] = 0;
+ if (l == -1)
+ {
+ perror (name);
+ exit (-1);
+ }
+ }
+ }
+ while (!nextblock)
+ { /* this is a new block */
+ bp = (BlockType *) data;
+ COUNT (sizeof (BlockType));
+ nextblock = DATALEN (bp);
+ if (output && !quiet_mode)
+ fprintf (stderr, "\n"); /* write /n after ASCII-out */
+ output = 0;
+ switch (bp->type)
+ {
+ case 0:
+ d_printf ((stderr, "Terminator\n"));
+ return; /* VOC-file stop */
+ case 1:
+ vd = (Voice_data *) data;
+ COUNT (sizeof (Voice_data));
+ /* we need a SYNC, before we can set new SPEED, STEREO ... */
+ sync_dsp ();
+
+ if (!was_extended)
+ {
+ dsp_speed = (int) (vd->tc);
+ dsp_speed = 1000000 / (256 - dsp_speed);
+ d_printf ((stderr, "Voice data %d Hz\n", dsp_speed));
+ if (vd->pack)
+ { /* /dev/dsp can't it */
+ fprintf (stderr, "%s: can't play packed .voc files\n",
+ command);
+ return;
+ }
+ if (dsp_stereo)
+ { /* if we are in Stereo-Mode, switch back */
+ dsp_stereo = MODE_MONO;
+ ioctl (audio, SNDCTL_DSP_STEREO, &dsp_stereo);
+ }
+ }
+ else
+ { /* there was extended block */
+ if (one_chn) /* if one Stereo fails, why test another ? */
+ dsp_stereo = MODE_MONO;
+ else if (dsp_stereo)
+ { /* want Stereo */
+ /* shit, my MACRO dosn't work here */
+#ifdef OSS_VERSION
+ if (ioctl (audio, SNDCTL_DSP_STEREO, &dsp_stereo) < 0)
+ {
+#else
+ if (dsp_stereo !=
+ ioctl (audio, SNDCTL_DSP_STEREO, dsp_stereo))
+ {
+#endif
+ dsp_stereo = MODE_MONO;
+ fprintf (stderr,
+ "%s: can't play in Stereo; playing only one channel\n",
+ command);
+ one_chn = 1;
+ }
+ }
+ was_extended = 0;
+ }
+ set_dsp_speed (&dsp_speed);
+ break;
+ case 2: /* nothing to do, pure data */
+ d_printf ((stderr, "Voice continuation\n"));
+ break;
+ case 3: /* a silence block, no data, only a count */
+ sp = (u_short *) data;
+ COUNT (sizeof (u_short));
+ dsp_speed = (int) (*data);
+ COUNT (1);
+ dsp_speed = 1000000 / (256 - dsp_speed);
+ sync_dsp ();
+ set_dsp_speed (&dsp_speed);
+ silence = (((u_long) * sp) * 1000) / dsp_speed;
+ d_printf ((stderr, "Silence for %ld ms\n", silence));
+ write_zeros (*sp);
+ break;
+ case 4: /* a marker for syncronisation, no effect */
+ sp = (u_short *) data;
+ COUNT (sizeof (u_short));
+ d_printf ((stderr, "Marker %d\n", *sp));
+ break;
+ case 5: /* ASCII text, we copy to stderr */
+ output = 1;
+ d_printf ((stderr, "ASCII - text :\n"));
+ break;
+ case 6: /* repeat marker, says repeatcount */
+ /* my specs don't say it: maybe this can be recursive, but
+ I don't think somebody use it */
+ repeat = *(u_short *) data;
+ COUNT (sizeof (u_short));
+ d_printf ((stderr, "Repeat loop %d times\n", repeat));
+ if (filepos >= 0) /* if < 0, one seek fails, why test another */
+ if ((filepos = lseek (fd, 0, 1)) < 0)
+ {
+ fprintf (stderr,
+ "%s: can't play loops; %s isn't seekable\n",
+ command, name);
+ repeat = 0;
+ }
+ else
+ filepos -= in_buffer; /* set filepos after repeat */
+ else
+ repeat = 0;
+ break;
+ case 7: /* ok, lets repeat that be rewinding tape */
+ if (repeat)
+ {
+ if (repeat != 0xFFFF)
+ {
+ d_printf ((stderr, "Repeat loop %d\n", repeat));
+ --repeat;
+ }
+ else
+ d_printf ((stderr, "Neverending loop\n"));
+ lseek (fd, filepos, 0);
+ in_buffer = 0; /* clear the buffer */
+ goto Fill_the_buffer;
+ }
+ else
+ d_printf ((stderr, "End repeat loop\n"));
+ break;
+ case 8: /* the extension to play Stereo, I have SB 1.0 :-( */
+ was_extended = 1;
+ eb = (Ext_Block *) data;
+ COUNT (sizeof (Ext_Block));
+ dsp_speed = (int) (eb->tc);
+ dsp_speed = 256000000L / (65536 - dsp_speed);
+ dsp_stereo = eb->mode;
+ if (dsp_stereo == MODE_STEREO)
+ dsp_speed = dsp_speed >> 1;
+ if (eb->pack)
+ { /* /dev/dsp can't it */
+ fprintf (stderr, "%s: can't play packed .voc files\n",
+ command);
+ return;
+ }
+ d_printf ((stderr, "Extended block %s %d Hz\n",
+ (eb->mode ? "Stereo" : "Mono"), dsp_speed));
+ break;
+ default:
+ fprintf (stderr, "%s: unknown blocktype %d. terminate.\n",
+ command, bp->type);
+ return;
+ } /* switch (bp->type) */
+ } /* while (! nextblock) */
+ /* put nextblock data bytes to dsp */
+ l = min (in_buffer, nextblock);
+ if (l)
+ {
+ if (output && !quiet_mode)
+ write (2, data, l); /* to stderr */
+ else
+ {
+ real_l = one_chn ? one_channel (data, l, one_chn, 0) : l;
+ if (write (audio, data, real_l) != real_l)
+ {
+ perror (AUDIO);
+ exit (-1);
+ }
+ }
+ COUNT (l);
+ }
+ } /* while(1) */
+}
+
+/* that was a big one, perhaps somebody split it :-) */
+
+/* setting the globals for playing raw data */
+void
+init_raw_data (void)
+{
+ timelimit = raw_info.timelimit;
+ dsp_speed = raw_info.dsp_speed;
+ dsp_stereo = raw_info.dsp_stereo;
+ samplesize = raw_info.samplesize;
+}
+
+/* calculate the data count to read from/to dsp */
+u_long
+calc_count (void)
+{
+ u_long count;
+
+ if (!timelimit)
+ count = 0x7fffffff;
+ else
+ {
+ count = timelimit * dsp_speed;
+ if (dsp_stereo)
+ count *= 2;
+ if (samplesize != 8)
+ count *= 2;
+ }
+ return count;
+}
+
+/* write a .VOC-header */
+void
+start_voc (int fd, u_long cnt)
+{
+ VocHeader vh;
+ BlockType bt;
+ Voice_data vd;
+ Ext_Block eb;
+
+ strcpy ((char *) vh.magic, MAGIC_STRING);
+ vh.headerlen = sizeof (VocHeader);
+ vh.version = ACTUAL_VERSION;
+ vh.coded_ver = 0x1233 - ACTUAL_VERSION;
+
+ write (fd, &vh, sizeof (VocHeader));
+
+ if (dsp_stereo)
+ {
+ /* write a extended block */
+ bt.type = 8;
+ bt.datalen = 4;
+ bt.datalen_m = bt.datalen_h = 0;
+ write (fd, &bt, sizeof (BlockType));
+ eb.tc = (u_short) (65536 - 256000000L / (dsp_speed << 1));
+ eb.pack = 0;
+ eb.mode = 1;
+ write (fd, &eb, sizeof (Ext_Block));
+ }
+ bt.type = 1;
+ cnt += sizeof (Voice_data); /* Voice_data block follows */
+ bt.datalen = (u_char) (cnt & 0xFF);
+ bt.datalen_m = (u_char) ((cnt & 0xFF00) >> 8);
+ bt.datalen_h = (u_char) ((cnt & 0xFF0000) >> 16);
+ write (fd, &bt, sizeof (BlockType));
+ vd.tc = (u_char) (256 - (1000000 / dsp_speed));
+ vd.pack = 0;
+ write (fd, &vd, sizeof (Voice_data));
+}
+
+/* write a WAVE-header */
+void
+start_wave (int fd, u_long cnt)
+{
+ WaveHeader wh;
+
+ wh.main_chunk = RIFF;
+ wh.length = cnt + sizeof (WaveHeader) - 8;
+ wh.chunk_type = WAVE;
+ wh.sub_chunk = FMT;
+ wh.sc_len = 16;
+ wh.format = PCM_CODE;
+ wh.modus = dsp_stereo ? 2 : 1;
+ wh.sample_fq = dsp_speed;
+ wh.byte_p_spl = ((samplesize == 8) ? 1 : 2) * (dsp_stereo ? 2 : 1);
+ wh.byte_p_sec = dsp_speed * wh.modus * wh.byte_p_spl;
+ wh.bit_p_spl = samplesize;
+ wh.data_chunk = DATA;
+ wh.data_length = cnt;
+ write (fd, &wh, sizeof (WaveHeader));
+}
+
+/* closing .VOC */
+void
+end_voc (int fd)
+{
+ char dummy = 0; /* Write a Terminator */
+ write (fd, &dummy, 1);
+ if (fd != 1)
+ close (fd);
+}
+
+void
+end_wave_raw (int fd)
+{ /* only close output */
+ if (fd != 1)
+ close (fd);
+}
+
+void
+start_snd (int fd, u_long count)
+{
+ SndHeader snd;
+ char *sndinfo = "Recorded by vrec\000";
+
+ snd.magic = SND_MAGIC;
+ snd.dataLocation = sizeof (SndHeader) + strlen (sndinfo);
+ snd.dataSize = count;
+ switch (samplesize)
+ {
+ case 8:
+ snd.dataFormat = SND_FORMAT_LINEAR_8;
+ break;
+ case 16:
+ snd.dataFormat = SND_FORMAT_LINEAR_16;
+ break;
+ default:
+ fprintf (stderr,
+ "%d bit: unsupported sample size for NeXt sound file!\n",
+ samplesize);
+ exit (-1);
+ }
+ snd.samplingRate = dsp_speed;
+ snd.channelCount = dsp_stereo ? 2 : 1;
+
+ write (fd, &snd, sizeof (SndHeader));
+ write (fd, sndinfo, strlen (sndinfo));
+}
+
+void
+end_snd (int fd)
+{
+ if (fd != 1)
+ close (fd);
+}
+
+/* playing/recording raw data, this proc handels WAVE files and
+ recording .VOCs (as one block) */
+void
+recplay (int fd, int loaded, u_long count, int rtype, char *name)
+{
+ int l, real_l;
+ u_long c;
+ char one_chn = 0;
+ char to_8 = 0;
+ int tmps;
+
+ sync_dsp ();
+ tmps = samplesize;
+ ioctl (audio, SNDCTL_DSP_SETFMT, &tmps);
+ if (tmps != samplesize)
+ {
+ fprintf (stderr, "%s: unable to set %d bit sample size",
+ command, samplesize);
+ if (samplesize == 16)
+ {
+ samplesize = 8;
+ ioctl (audio, SNDCTL_DSP_SETFMT, &samplesize);
+ if (samplesize != 8)
+ {
+ fprintf (stderr, "%s: unable to set 8 bit sample size!\n",
+ command);
+ exit (-1);
+ }
+ fprintf (stderr, "; playing 8 bit\n");
+ to_8 = 1;
+ }
+ else
+ {
+ fprintf (stderr, "\n");
+ exit (-1);
+ }
+ }
+#ifdef OSS_VERSION
+ if (ioctl (audio, SNDCTL_DSP_STEREO, &dsp_stereo) < 0)
+ {
+#else
+ if (dsp_stereo != ioctl (audio, SNDCTL_DSP_STEREO, dsp_stereo))
+ {
+#endif
+ if (direction == PLAY)
+ {
+ fprintf (stderr,
+ "%s: can't play in Stereo; playing only one channel\n",
+ command);
+ dsp_stereo = MODE_MONO;
+ one_chn = 1;
+ }
+ else
+ {
+ fprintf (stderr, "%s: can't record in Stereo\n", command);
+ exit (-1);
+ }
+ }
+ set_dsp_speed (&dsp_speed);
+ if (!quiet_mode)
+ {
+ fprintf (stderr, "%s %s : ",
+ (direction == PLAY) ? "Playing" : "Recording",
+ fmt_rec_table[rtype].what);
+ if (samplesize != 8)
+ fprintf (stderr, "%d bit, ", samplesize);
+ fprintf (stderr, "Speed %d Hz ", dsp_speed);
+ fprintf (stderr, "%d bits ", samplesize);
+ fprintf (stderr, "%s ...\n", dsp_stereo ? "Stereo" : "Mono");
+ }
+
+ abuf_size = -1;
+#if 0
+/*
+ * There is no idea in using SNDCTL_DSP_GETBLKSIZE in applications like this.
+ * Using some fixed local buffer size will work equally well.
+ */
+ ioctl (audio, SNDCTL_DSP_GETBLKSIZE, &abuf_size);
+ if (abuf_size == -1)
+ {
+ perror (AUDIO);
+ exit (-1);
+ }
+#endif
+
+ zbuf_size = 256;
+ if ((audiobuf = (u_char *) malloc (abuf_size)) == NULL ||
+ (zerobuf = (u_char *) malloc (zbuf_size)) == NULL)
+ {
+ fprintf (stderr, "%s: unable to allocate input/output buffer\n",
+ command);
+ exit (-1);
+ }
+ memset ((char *) zerobuf, 128, zbuf_size);
+
+ if (direction == PLAY)
+ {
+ while (count)
+ {
+ c = count;
+
+ if (c > abuf_size)
+ c = abuf_size;
+
+ if ((l = read (fd, (char *) audiobuf + loaded, c - loaded)) > 0)
+ {
+ l += loaded;
+ loaded = 0; /* correct the count; ugly but ... */
+ real_l = (one_chn
+ || to_8) ? one_channel (audiobuf, l, one_chn,
+ to_8) : l;
+
+ /* change byte order if necessary */
+ if (convert && (samplesize == 16))
+ {
+ long i;
+
+ for (i = 0; i < real_l; i += 2)
+ *((short *) (audiobuf + i)) =
+ htons (*((short *) (audiobuf + i)));
+ }
+
+ if (write (audio, (char *) audiobuf, real_l) != real_l)
+ {
+ perror (AUDIO);
+ exit (-1);
+ }
+ count -= l;
+ }
+ else
+ {
+ if (l == -1)
+ {
+ perror (name);
+ exit (-1);
+ }
+ count = 0; /* Stop */
+ }
+ } /* while (count) */
+ }
+ else
+ { /* we are recording */
+
+ while (count)
+ {
+ c = count;
+ if (c > abuf_size)
+ c = abuf_size;
+
+ if ((l = read (audio, (char *) audiobuf, c)) > 0)
+ {
+ if (write (fd, (char *) audiobuf, l) != l)
+ {
+ perror (name);
+ exit (-1);
+ }
+ count -= l;
+ }
+
+ if (l == -1)
+ {
+ perror (AUDIO);
+ exit (-1);
+ }
+ } /* While count */
+ }
+}
+
+/*
+ let's play or record it (record_type says VOC/WAVE/raw)
+*/
+void
+record_play (char *name)
+{
+ int fd, ofs;
+
+ if (direction == PLAY)
+ {
+
+ if (!name)
+ {
+ fd = 0;
+ name = "stdin";
+ }
+ else if ((fd = open (name, O_RDONLY, 0)) == -1)
+ {
+ perror (name);
+ exit (-1);
+ }
+ /* Read the smallest header first, then the
+ missing bytes for the next, etc. */
+
+ /* read SND-header */
+ read (fd, (char *) audiobuf, sizeof (SndHeader));
+ if (test_sndfile (audiobuf, fd) >= 0)
+ recplay (fd, 0, count, SND_FMT, name);
+
+ else
+ {
+ /* read VOC-Header */
+ read (fd, (char *) audiobuf + sizeof (SndHeader),
+ sizeof (VocHeader) - sizeof (SndHeader));
+ if ((ofs = test_vocfile (audiobuf)) >= 0)
+ vplay (fd, ofs, name);
+
+ else
+ {
+ /* read bytes for WAVE-header */
+ read (fd, (char *) audiobuf + sizeof (VocHeader),
+ sizeof (WaveHeader) - sizeof (VocHeader));
+ if (test_wavefile (audiobuf) >= 0)
+ recplay (fd, 0, count, WAVE_FMT, name);
+ else
+ {
+ /* should be raw data */
+ init_raw_data ();
+ count = calc_count ();
+ recplay (fd, sizeof (WaveHeader), count, RAW_DATA, name);
+ }
+ }
+ }
+ if (fd != 0)
+ close (fd);
+ }
+ else
+ { /* recording ... */
+ if (!name)
+ {
+ fd = 1;
+ name = "stdout";
+ }
+ else
+ {
+ if ((fd = open (name, O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1)
+ {
+ perror (name);
+ exit (-1);
+ }
+ }
+ count = calc_count () & 0xFFFFFFFE;
+ /* WAVE-file should be even (I'm not sure), but wasting one byte
+ isn't a problem (this can only be in 8 bit mono) */
+ if (fmt_rec_table[record_type].start)
+ fmt_rec_table[record_type].start (fd, count);
+ recplay (fd, 0, count, record_type, name);
+ fmt_rec_table[record_type].end (fd);
+ }
+}
diff --git a/tutorials/sndkit/dsp/vplay_vxworks/Makefile b/tutorials/sndkit/dsp/vplay_vxworks/Makefile
new file mode 100644
index 0000000..80c0746
--- /dev/null
+++ b/tutorials/sndkit/dsp/vplay_vxworks/Makefile
@@ -0,0 +1,12 @@
+
+# Makefile for OSS/VxWorks
+#
+
+CPU = I80486
+TOOL = gnu
+
+include $(WIND_BASE)/target/h/make/defs.bsp
+include $(WIND_BASE)/target/h/make/make.$(CPU)$(TOOL)
+include $(WIND_BASE)/target/h/make/defs.$(WIND_HOST_TYPE)
+
+exe: vplay.o
diff --git a/tutorials/sndkit/dsp/vplay_vxworks/fmtheaders.h b/tutorials/sndkit/dsp/vplay_vxworks/fmtheaders.h
new file mode 100644
index 0000000..4ba1302
--- /dev/null
+++ b/tutorials/sndkit/dsp/vplay_vxworks/fmtheaders.h
@@ -0,0 +1,119 @@
+#ifndef _FMTHEADERS_H
+#define _FMTHEADERS_H 1
+/*
+ *
+ * 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 <sys/types.h>
+
+/* Definitions for .VOC files */
+
+#define MAGIC_STRING "Creative Voice File\x1A"
+#define ACTUAL_VERSION 0x010A
+#define VOC_SAMPLESIZE 8
+
+#define MODE_MONO 0
+#define MODE_STEREO 1
+
+#define DATALEN(bp) ((u_long)(bp->datalen) | \
+ ((u_long)(bp->datalen_m) << 8) | \
+ ((u_long)(bp->datalen_h) << 16) )
+
+typedef struct _vocheader
+{
+ u_char magic[20]; /* must be MAGIC_STRING */
+ u_short headerlen; /* Headerlength, should be 0x1A */
+ u_short version; /* VOC-file version */
+ u_short coded_ver; /* 0x1233-version */
+}
+VocHeader;
+
+typedef struct _blocktype
+{
+ u_char type;
+ u_char datalen; /* low-byte */
+ u_char datalen_m; /* medium-byte */
+ u_char datalen_h; /* high-byte */
+}
+BlockType;
+
+typedef struct _voice_data
+{
+ u_char tc;
+ u_char pack;
+}
+Voice_data;
+
+typedef struct _ext_block
+{
+ u_short tc;
+ u_char pack;
+ u_char mode;
+}
+Ext_Block;
+
+
+/* Definitions for Microsoft WAVE format */
+
+#define RIFF 0x46464952
+#define WAVE 0x45564157
+#define FMT 0x20746D66
+#define DATA 0x61746164
+#define PCM_CODE 1
+#define WAVE_MONO 1
+#define WAVE_STEREO 2
+
+/* it's in chunks like .voc and AMIGA iff, but my source say there
+ are in only in this combination, so I combined them in one header;
+ it works on all WAVE-file I have
+*/
+typedef struct _waveheader
+{
+ u_long main_chunk; /* 'RIFF' */
+ u_long length; /* filelen */
+ u_long chunk_type; /* 'WAVE' */
+
+ u_long sub_chunk; /* 'fmt ' */
+ u_long sc_len; /* length of sub_chunk, =16 */
+ u_short format; /* should be 1 for PCM-code */
+ u_short modus; /* 1 Mono, 2 Stereo */
+ u_long sample_fq; /* frequence of sample */
+ u_long byte_p_sec;
+ u_short byte_p_spl; /* samplesize; 1 or 2 bytes */
+ u_short bit_p_spl; /* 8, 12 or 16 bit */
+
+ u_long data_chunk; /* 'data' */
+ u_long data_length; /* samplecount */
+}
+WaveHeader;
+
+typedef struct
+{
+ long magic; /* must be equal to SND_MAGIC */
+ long dataLocation; /* Offset or pointer to the raw data */
+ long dataSize; /* Number of bytes of data in the raw data */
+ long dataFormat; /* The data format code */
+ long samplingRate; /* The sampling rate */
+ long channelCount; /* The number of channels */
+}
+SndHeader;
+
+#define SND_MAGIC ((long int)0x2e736e64)
+
+#define SND_FORMAT_UNSPECIFIED (0)
+#define SND_FORMAT_MULAW_8 (1)
+#define SND_FORMAT_LINEAR_8 (2)
+#define SND_FORMAT_LINEAR_16 (3)
+#define SND_FORMAT_LINEAR_24 (4)
+#define SND_FORMAT_LINEAR_32 (5)
+#define SND_FORMAT_FLOAT (6)
+
+#endif
diff --git a/tutorials/sndkit/dsp/vplay_vxworks/vplay_vxworks.c b/tutorials/sndkit/dsp/vplay_vxworks/vplay_vxworks.c
new file mode 100644
index 0000000..b10d35d
--- /dev/null
+++ b/tutorials/sndkit/dsp/vplay_vxworks/vplay_vxworks.c
@@ -0,0 +1,694 @@
+/*
+ vplay.c - plays
+ CREATIVE LABS VOICE-files, Microsoft WAVE-files and raw data
+
+ Autor: Michael Beck - beck@informatik.hu-berlin.de
+
+ Modified for VxWorks by 4Front Technologies
+
+ Usage: int play_wave (char *filename);
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <ioLib.h>
+#include <sys/ioctl.h>
+#include "soundcard.h" /* Edit this to contain the right location of soundcard.h */
+#include "fmtheaders.h"
+
+/*
+ * The following defines break support for .snd files. Implement these routines
+ * properly if you need to play them.
+ */
+#define htonl(x) x
+#define htons(x) x
+
+#define DEFAULT_DSP_SPEED 8000
+
+#define AUDIO "/oss/dsp"
+
+#ifndef min
+#define min(a,b) ((a) <= (b) ? (a) : (b))
+#endif
+#define d_printf(x) if (verbose_mode) fprintf x
+
+#define VOC_FMT 0
+#define WAVE_FMT 1
+#define RAW_DATA 2
+#define SND_FMT 3
+
+/* global data */
+
+static int timelimit = 0, dsp_speed = DEFAULT_DSP_SPEED, dsp_stereo = 0;
+static int samplesize = 8;
+static int quiet_mode = 0;
+static int verbose_mode = 0;
+static int convert = 0;
+static u_long count;
+static int audio, abuf_size;
+static int omode;
+static u_char audiobuf[512];
+static int vocminor, vocmajor; /* .VOC version */
+
+/* defaults for playing raw data */
+static struct
+{
+ int timelimit, dsp_speed, dsp_stereo, samplesize;
+}
+raw_info =
+{
+0, DEFAULT_DSP_SPEED, 0, 8};
+
+/* needed prototypes */
+
+static int player (char *name);
+static u_long calc_count ();
+
+int
+play_wave (char *filename)
+{
+ omode = O_WRONLY;
+
+ quiet_mode = 1;
+
+ audio = open (AUDIO, omode, 0);
+ if (audio == -1)
+ {
+ perror (AUDIO);
+ return -1;
+ }
+
+ if (player (filename) < 0)
+ return -1;
+ close (audio);
+ return 0;
+}
+
+/*
+ test, if it is a .VOC file and return >=0 if ok (this is the length of rest)
+ < 0 if not
+*/
+static int
+test_vocfile (void *buffer)
+{
+ VocHeader *vp = buffer;
+ if (!strcmp ((const char *) vp->magic, MAGIC_STRING))
+ {
+ vocminor = vp->version & 0xFF;
+ vocmajor = vp->version / 256;
+ if (vp->version != (0x1233 - vp->coded_ver))
+ return -2; /* coded version mismatch */
+ return vp->headerlen - sizeof (VocHeader); /* 0 mostly */
+ }
+ return -1; /* magic string fail */
+}
+
+/*
+ test, if it's a .WAV file, 0 if ok (and set the speed, stereo etc.)
+ < 0 if not
+*/
+static int
+test_wavefile (void *buffer)
+{
+ WaveHeader *wp = buffer;
+ if (wp->main_chunk == RIFF && wp->chunk_type == WAVE &&
+ wp->sub_chunk == FMT && wp->data_chunk == DATA)
+ {
+ if (wp->format != PCM_CODE)
+ {
+ fprintf (stderr, "Can't play non PCM-coded WAVE-files\n");
+ return -1;
+ }
+ if (wp->modus > 2)
+ {
+ fprintf (stderr, "Can't play WAVE-files with %d tracks\n",
+ wp->modus);
+ return -1;
+ }
+ dsp_stereo = (wp->modus == WAVE_STEREO) ? 1 : 0;
+ samplesize = wp->bit_p_spl;
+ dsp_speed = wp->sample_fq;
+ count = wp->data_length;
+ return 0;
+ }
+ return -1;
+}
+
+/*
+* test, if it's a .SND file, 0 if ok (and set the speed, stereo etc.)
+* < 0 if not
+*/
+static int
+test_sndfile (void *buffer, int fd)
+{
+ long infolen;
+ char *info;
+ SndHeader *snd = buffer;
+
+ if (snd->magic == SND_MAGIC)
+ convert = 0;
+ else
+ {
+ if (htonl (snd->magic) == SND_MAGIC)
+ {
+ convert = 1;
+ snd->dataLocation = htonl (snd->dataLocation);
+ snd->dataSize = htonl (snd->dataSize);
+ snd->dataFormat = htonl (snd->dataFormat);
+ snd->samplingRate = htonl (snd->samplingRate);
+ snd->channelCount = htonl (snd->channelCount);
+ }
+ else
+ {
+ /* No SoundFile */
+ return (-1);
+ }
+ }
+ switch (snd->dataFormat)
+ {
+ case SND_FORMAT_LINEAR_8:
+ samplesize = 8;
+ break;
+ case SND_FORMAT_LINEAR_16:
+ samplesize = 16;
+ break;
+ default:
+ fprintf (stderr, "Unsupported SND_FORMAT\n");
+ return -1;
+ }
+
+ dsp_stereo = (snd->channelCount == 2) ? 1 : 0;
+ dsp_speed = snd->samplingRate;
+ count = snd->dataSize;
+
+ /* read Info-Strings */
+ infolen = snd->dataLocation - sizeof (SndHeader);
+ info = (char *) malloc (infolen);
+ read (fd, info, infolen);
+ if (!quiet_mode)
+ fprintf (stderr, "SoundFile Info: %s\n", info);
+ free (info);
+
+ return 0;
+}
+
+
+/* if need a SYNC,
+ (is needed if we plan to change speed, stereo ... during output)
+*/
+static void
+sync_dsp (void)
+{
+}
+
+/* setting the speed for output */
+static int
+set_dsp_speed (int *dsp_speed)
+{
+ if (ioctl (audio, SNDCTL_DSP_SPEED, dsp_speed) < 0)
+ {
+ fprintf (stderr, "Unable to set audio speed\n");
+ perror (AUDIO);
+ return -1;
+ }
+ return 0;
+}
+
+/* if to_mono:
+ compress 8 bit stereo data 2:1, needed if we want play 'one track';
+ this is usefull, if you habe SB 1.0 - 2.0 (I have 1.0) and want
+ hear the sample (in Mono)
+ if to_8:
+ compress 16 bit to 8 by using hi-byte; wave-files use signed words,
+ so we need to convert it in "unsigned" sample (0x80 is now zero)
+
+ WARNING: this procedure can't compress 16 bit stereo to 16 bit mono,
+ because if you have a 16 (or 12) bit card you should have
+ stereo (or I'm wrong ?? )
+ */
+static u_long
+one_channel (u_char * buf, u_long l, char to_mono, char to_8)
+{
+ register u_char *w = buf;
+ register u_char *w2 = buf;
+ char ofs = 0;
+ u_long incr = 0;
+ u_long c, ret;
+
+ if (to_mono)
+ ++incr;
+ if (to_8)
+ {
+ ++incr;
+ ++w2;
+ ofs = 128;
+ }
+ ret = c = l >> incr;
+ incr = incr << 1;
+
+ while (c--)
+ {
+ *w++ = *w2 + ofs;
+ w2 += incr;
+ }
+ return ret;
+}
+
+/*
+ ok, let's play a .voc file
+*/
+static int
+vplay (int fd, int ofs, char *name)
+{
+ int l, real_l;
+ BlockType *bp;
+ Voice_data *vd;
+ Ext_Block *eb;
+ u_long nextblock, in_buffer;
+ u_char *data = audiobuf;
+ char was_extended = 0, output = 0;
+ u_short *sp, repeat = 0;
+ u_long silence;
+ int filepos = 0;
+ char one_chn = 0;
+
+#define COUNT(x) nextblock -= x; in_buffer -=x ;data += x
+
+ /* first SYNC the dsp */
+ sync_dsp ();
+
+ if (!quiet_mode)
+ fprintf (stderr, "Playing Creative Labs Voice file ...\n");
+
+ /* first we waste the rest of header, ugly but we don't need seek */
+ while (ofs > abuf_size)
+ {
+ read (fd, (char *) audiobuf, abuf_size);
+ ofs -= abuf_size;
+ }
+ if (ofs)
+ read (fd, audiobuf, ofs);
+
+ /* .voc files are 8 bit (now) */
+ samplesize = VOC_SAMPLESIZE;
+ ioctl (audio, SNDCTL_DSP_SETFMT, &samplesize);
+ if (samplesize != VOC_SAMPLESIZE)
+ {
+ fprintf (stderr, "Unable to set 8 bit sample size!\n");
+ return -1;
+ }
+ /* and there are MONO by default */
+ dsp_stereo = MODE_MONO;
+ ioctl (audio, SNDCTL_DSP_STEREO, &dsp_stereo);
+
+ in_buffer = nextblock = 0;
+ while (1)
+ {
+ Fill_the_buffer: /* need this for repeat */
+ if (in_buffer < 32)
+ {
+ /* move the rest of buffer to pos 0 and fill the audiobuf up */
+ if (in_buffer)
+ memcpy ((char *) audiobuf, data, in_buffer);
+ data = audiobuf;
+ if ((l =
+ read (fd, (char *) audiobuf + in_buffer,
+ abuf_size - in_buffer)) > 0)
+ in_buffer += l;
+ else if (!in_buffer)
+ {
+ /* the file is truncated, so simulate 'Terminator'
+ and reduce the datablock for save landing */
+ nextblock = audiobuf[0] = 0;
+ if (l == -1)
+ {
+ perror (name);
+ return -1;
+ }
+ }
+ }
+ while (!nextblock)
+ { /* this is a new block */
+ bp = (BlockType *) data;
+ COUNT (sizeof (BlockType));
+ nextblock = DATALEN (bp);
+ if (output && !quiet_mode)
+ fprintf (stderr, "\n"); /* write /n after ASCII-out */
+ output = 0;
+ switch (bp->type)
+ {
+ case 0:
+ d_printf ((stderr, "Terminator\n"));
+ return -1; /* VOC-file stop */
+ case 1:
+ vd = (Voice_data *) data;
+ COUNT (sizeof (Voice_data));
+ /* we need a SYNC, before we can set new SPEED, STEREO ... */
+ sync_dsp ();
+
+ if (!was_extended)
+ {
+ dsp_speed = (int) (vd->tc);
+ dsp_speed = 1000000 / (256 - dsp_speed);
+ d_printf ((stderr, "Voice data %d Hz\n", dsp_speed));
+ if (vd->pack)
+ { /* /dev/dsp can't it */
+ fprintf (stderr, "Can't play packed .voc files\n");
+ return -1;
+ }
+ if (dsp_stereo)
+ { /* if we are in Stereo-Mode, switch back */
+ dsp_stereo = MODE_MONO;
+ ioctl (audio, SNDCTL_DSP_STEREO, &dsp_stereo);
+ }
+ }
+ else
+ { /* there was extended block */
+ if (one_chn) /* if one Stereo fails, why test another ? */
+ dsp_stereo = MODE_MONO;
+ else if (dsp_stereo)
+ { /* want Stereo */
+ /* shit, my MACRO dosn't work here */
+#ifdef OSS_VERSION
+ if (ioctl (audio, SNDCTL_DSP_STEREO, &dsp_stereo) < 0)
+ {
+#else
+ if (dsp_stereo !=
+ ioctl (audio, SNDCTL_DSP_STEREO, dsp_stereo))
+ {
+#endif
+ dsp_stereo = MODE_MONO;
+ fprintf (stderr,
+ "Can't play in Stereo; playing only one channel\n");
+ one_chn = 1;
+ }
+ }
+ was_extended = 0;
+ }
+ if (set_dsp_speed (&dsp_speed) < 0)
+ return -1;
+ break;
+ case 2: /* nothing to do, pure data */
+ d_printf ((stderr, "Voice continuation\n"));
+ break;
+ case 3: /* a silence block, no data, only a count */
+ sp = (u_short *) data;
+ COUNT (sizeof (u_short));
+ dsp_speed = (int) (*data);
+ COUNT (1);
+ dsp_speed = 1000000 / (256 - dsp_speed);
+ sync_dsp ();
+ if (set_dsp_speed (&dsp_speed) < 0)
+ return -1;
+ silence = (((u_long) * sp) * 1000) / dsp_speed;
+ d_printf ((stderr, "Silence for %ld ms\n", silence));
+ break;
+ case 4: /* a marker for syncronisation, no effect */
+ sp = (u_short *) data;
+ COUNT (sizeof (u_short));
+ d_printf ((stderr, "Marker %d\n", *sp));
+ break;
+ case 5: /* ASCII text, we copy to stderr */
+ output = 1;
+ d_printf ((stderr, "ASCII - text :\n"));
+ break;
+ case 6: /* repeat marker, says repeatcount */
+ /* my specs don't say it: maybe this can be recursive, but
+ I don't think somebody use it */
+ repeat = *(u_short *) data;
+ COUNT (sizeof (u_short));
+ d_printf ((stderr, "Repeat loop %d times\n", repeat));
+ if (filepos >= 0) /* if < 0, one seek fails, why test another */
+ if ((filepos = lseek (fd, 0, 1)) < 0)
+ {
+ fprintf (stderr,
+ "Can't play loops; %s isn't seekable\n", name);
+ repeat = 0;
+ }
+ else
+ filepos -= in_buffer; /* set filepos after repeat */
+ else
+ repeat = 0;
+ break;
+ case 7: /* ok, lets repeat that be rewinding tape */
+ if (repeat)
+ {
+ if (repeat != 0xFFFF)
+ {
+ d_printf ((stderr, "Repeat loop %d\n", repeat));
+ --repeat;
+ }
+ else
+ d_printf ((stderr, "Neverending loop\n"));
+ lseek (fd, filepos, 0);
+ in_buffer = 0; /* clear the buffer */
+ goto Fill_the_buffer;
+ }
+ else
+ d_printf ((stderr, "End repeat loop\n"));
+ break;
+ case 8: /* the extension to play Stereo, I have SB 1.0 :-( */
+ was_extended = 1;
+ eb = (Ext_Block *) data;
+ COUNT (sizeof (Ext_Block));
+ dsp_speed = (int) (eb->tc);
+ dsp_speed = 256000000L / (65536 - dsp_speed);
+ dsp_stereo = eb->mode;
+ if (dsp_stereo == MODE_STEREO)
+ dsp_speed = dsp_speed >> 1;
+ if (eb->pack)
+ { /* /dev/dsp can't it */
+ fprintf (stderr, "Can't play packed .voc files\n");
+ return -1;
+ }
+ d_printf ((stderr, "Extended block %s %d Hz\n",
+ (eb->mode ? "Stereo" : "Mono"), dsp_speed));
+ break;
+ default:
+ fprintf (stderr, "Unknown blocktype %d. terminate.\n",
+ bp->type);
+ return -1;
+ } /* switch (bp->type) */
+ } /* while (! nextblock) */
+ /* put nextblock data bytes to dsp */
+ l = min (in_buffer, nextblock);
+ if (l)
+ {
+ if (output && !quiet_mode)
+ write (2, data, l); /* to stderr */
+ else
+ {
+ real_l = one_chn ? one_channel (data, l, one_chn, 0) : l;
+ if (write (audio, data, real_l) != real_l)
+ {
+ perror (AUDIO);
+ return -1;
+ }
+ }
+ COUNT (l);
+ }
+ } /* while(1) */
+}
+
+/* that was a big one, perhaps somebody split it :-) */
+
+/* setting the globals for playing raw data */
+static void
+init_raw_data (void)
+{
+ timelimit = raw_info.timelimit;
+ dsp_speed = raw_info.dsp_speed;
+ dsp_stereo = raw_info.dsp_stereo;
+ samplesize = raw_info.samplesize;
+}
+
+/* calculate the data count to read from/to dsp */
+static u_long
+calc_count (void)
+{
+ u_long count;
+
+ if (!timelimit)
+ count = 0x7fffffff;
+ else
+ {
+ count = timelimit * dsp_speed;
+ if (dsp_stereo)
+ count *= 2;
+ if (samplesize != 8)
+ count *= 2;
+ }
+ return count;
+}
+
+/* playing raw data, this proc handels WAVE files and
+ .VOCs (as one block) */
+static int
+do_play (int fd, int loaded, u_long count, int rtype, char *name)
+{
+ int l, real_l;
+ u_long c;
+ char one_chn = 0;
+ char to_8 = 0;
+ int tmps;
+
+ sync_dsp ();
+ tmps = samplesize;
+ ioctl (audio, SNDCTL_DSP_SETFMT, &tmps);
+ if (tmps != samplesize)
+ {
+ fprintf (stderr, "Unable to set %d bit sample size", samplesize);
+ if (samplesize == 16)
+ {
+ samplesize = 8;
+ ioctl (audio, SNDCTL_DSP_SETFMT, &samplesize);
+ if (samplesize != 8)
+ {
+ fprintf (stderr, "Unable to set 8 bit sample size!\n");
+ return -1;
+ }
+ fprintf (stderr, "; playing 8 bit\n");
+ to_8 = 1;
+ }
+ else
+ {
+ fprintf (stderr, "\n");
+ return -1;
+ }
+ }
+#ifdef OSS_VERSION
+ if (ioctl (audio, SNDCTL_DSP_STEREO, &dsp_stereo) < 0)
+ {
+#else
+ if (dsp_stereo != ioctl (audio, SNDCTL_DSP_STEREO, dsp_stereo))
+ {
+#endif
+ fprintf (stderr, "Can't play in Stereo; playing only one channel\n");
+ dsp_stereo = MODE_MONO;
+ one_chn = 1;
+ }
+ if (set_dsp_speed (&dsp_speed) < 0)
+ return -1;
+
+ abuf_size = 512;
+
+ while (count)
+ {
+ c = count;
+
+ if (c > abuf_size)
+ c = abuf_size;
+
+ if ((l = read (fd, (char *) audiobuf + loaded, c - loaded)) > 0)
+ {
+ l += loaded;
+ loaded = 0; /* correct the count; ugly but ... */
+ real_l = (one_chn
+ || to_8) ? one_channel (audiobuf, l, one_chn, to_8) : l;
+
+ /* change byte order if necessary */
+ if (convert && (samplesize == 16))
+ {
+ long i;
+
+ for (i = 0; i < real_l; i += 2)
+ *((short *) (audiobuf + i)) =
+ htons (*((short *) (audiobuf + i)));
+ }
+
+ if (write (audio, (char *) audiobuf, real_l) != real_l)
+ {
+ perror (AUDIO);
+ return -1;
+ }
+ count -= l;
+ }
+ else
+ {
+ if (l == -1)
+ {
+ perror (name);
+ return -1;
+ }
+ count = 0; /* Stop */
+ }
+ } /* while (count) */
+
+ return 0;
+}
+
+/*
+ let's play)
+*/
+static int
+player (char *name)
+{
+ int fd, ofs;
+
+ if (!name)
+ {
+ fd = 0;
+ name = "stdin";
+ }
+ else if ((fd = open (name, O_RDONLY, 0)) == -1)
+ {
+ perror (name);
+ return -1;
+ }
+ /* Read the smallest header first, then the
+ missing bytes for the next, etc. */
+
+ /* read SND-header */
+ read (fd, (char *) audiobuf, sizeof (SndHeader));
+ if (test_sndfile (audiobuf, fd) >= 0)
+ {
+ if (do_play (fd, 0, count, SND_FMT, name) < 0)
+ return -1;
+ }
+
+ else
+ {
+ /* read VOC-Header */
+ read (fd, (char *) audiobuf + sizeof (SndHeader),
+ sizeof (VocHeader) - sizeof (SndHeader));
+ if ((ofs = test_vocfile (audiobuf)) >= 0)
+ {
+ if (vplay (fd, ofs, name) < 0)
+ return -1;
+ }
+
+ else
+ {
+ /* read bytes for WAVE-header */
+ read (fd, (char *) audiobuf + sizeof (VocHeader),
+ sizeof (WaveHeader) - sizeof (VocHeader));
+ if (test_wavefile (audiobuf) >= 0)
+ {
+ if (do_play (fd, 0, count, WAVE_FMT, name) < 0)
+ return -1;
+ }
+ else
+ {
+ /* should be raw data */
+ init_raw_data ();
+ count = calc_count ();
+ if (do_play (fd, sizeof (WaveHeader), count, RAW_DATA, name) <
+ 0)
+ return -1;
+ }
+ }
+ }
+ if (fd != 0)
+ close (fd);
+ return 0;
+}
+
+#if 0
+int
+main (int agrc, char *argv[])
+{
+ exit (play_wave (argv[1]));
+}
+#endif