summaryrefslogtreecommitdiff
path: root/tutorials/sndkit/dsp/str/str.c
diff options
context:
space:
mode:
Diffstat (limited to 'tutorials/sndkit/dsp/str/str.c')
-rw-r--r--tutorials/sndkit/dsp/str/str.c295
1 files changed, 295 insertions, 0 deletions
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;
+}