home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.ee.lbl.gov
/
2014.05.ftp.ee.lbl.gov.tar
/
ftp.ee.lbl.gov
/
sst.tar.Z
/
sst.tar
/
sst
/
tune.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-01-10
|
4KB
|
208 lines
/* tune.c - play simple tunes on the speaker
**
** Based on tones.c, Copyright (C) 1989 by Jef Poskanzer.
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted, provided
** that the above copyright notice appear in all copies and that both that
** copyright notice and this permission notice appear in supporting
** documentation. This software is provided "as is" without express or
** implied warranty.
*/
/*
Here's the tune language:
when argc is 1 the program reads its tune string from stdin;
when argc is 2 it uses argv[1] for a tune
the tune can begin with a number, which is beats/minute (default is 150)
A..G span middle C
a trailing # is a sharp; a trailing b is a flat
a trailing ^ raises a note an octave; a v lowers it an octave
a space is a rest
a - holds the preceeding note another beat
a note followed by a slash gets half the beats it would otherwise get
two slashes mean a quarter of the default, etc.
a note followed by a dot gets an extra 50% of time
a note followed by two dots gets an extra 75%, etc.
newlines, commas, and vertical bars between notes are ignored
the highest playable note is B^^^
for the future:
a pair of notes in square brackets is a two-note chord
(all the chip supports)
< (between notes) is a crescendo -- it ups the volume one notch
> is a decrescendo -- it lowers the volume a notch
*/
#include <stdio.h>
#include <fcntl.h>
#include <signal.h>
#include "libsst.h"
#define DEFAULT_TEMPO 150 /* beats per minute */
int any (c, s)
char c, *s;
{
while (*s) {
if (c == *s++) return 1;
}
return 0;
}
int pitch[] = {
/* Ab */ 208,
/* A */ 220,
/* A# */ 233,
/* Bb */ 233,
/* B */ 247,
/* B# */ 262,
/* Cb */ 247,
/* C */ 262,
/* C# */ 277,
/* Db */ 277,
/* D */ 294,
/* D# */ 311,
/* Eb */ 311,
/* E */ 330,
/* E# */ 349,
/* Fb */ 330,
/* F */ 349,
/* F# */ 370,
/* Gb */ 370,
/* G */ 392,
/* G# */ 415,
0
};
int notes[] = {
/* A */ 1,
/* B */ 4,
/* C */ 7,
/* D */ 10,
/* E */ 13,
/* F */ 16,
/* G */ 19,
0
};
int read_stdin = 0;
char c;
char *tune;
void next ()
{
if (read_stdin) {
int i = getchar();
c = (i == EOF) ? '\0' : i;
} else {
c = *tune;
++tune;
}
}
int sst_fd;
void cleanup ()
{
sst_close( sst_fd );
exit( 0 );
}
main( argc, argv )
int argc;
char *argv[];
{
int tempo = DEFAULT_TEMPO; /* beats per minute */
if ( argc == 1 ) {
read_stdin = 1;
} else {
tune = argv[1];
if ( argc != 2 ) {
fprintf( stderr, "usage: %s string\n", argv[0] );
exit( 1 );
}
}
signal (SIGINT, cleanup);
signal (SIGQUIT, cleanup);
sst_fd = sst_open( );
next ();
if (any (c, "0123456789")) {
tempo = 0;
while (any (c, "0123456789")) {
tempo *= 10;
tempo += (c - '0');
next ();
}
}
while (1) {
int Hz;
double beats, dot_value;
int usec;
int index;
while (any (c, ",|\n")) next ();
if (!c) break;
if (! any (c, "ABCDEFG ")) {
int count = 0;
fprintf (stderr, "bad tune. right context: ");
while (c) {
putc (c, stderr);
next ();
if (++count > 40) break;
}
putc ('\n', stderr);
sst_close( sst_fd );
exit (1);
}
if (c == ' ') {
Hz = 0;
next ();
} else {
index = notes[c - 'A'];
next ();
if (c == '#') {
++index;
next ();
}
else if (c == 'b') {
--index;
next ();
}
Hz = pitch[index];
while (any (c, "^v")) {
if (c == '^') Hz <<= 1;
if (c == 'v') Hz >>= 1;
next ();
}
}
beats = 1.0;
while (c == '-') {
beats += 1.0;
next ();
}
while (c == '/') {
beats /= 2.0;
next ();
}
dot_value = 1.0;
while (c == '.') {
dot_value /= 2.0;
next ();
}
beats *= 2.0 - dot_value;
usec = (int) (60*1000000*beats/tempo);
sst_tones( sst_fd, Hz, 0, 0, 0, usec );
/* printf ("%d Hz, %d msec\n", Hz, usec/1000); */
}
cleanup ();
}