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 >
C/C++ Source or Header  |  1990-01-10  |  4KB  |  208 lines

  1. /* tune.c - play simple tunes on the speaker
  2. **
  3. ** Based on tones.c, Copyright (C) 1989 by Jef Poskanzer.
  4. **
  5. ** Permission to use, copy, modify, and distribute this software and its
  6. ** documentation for any purpose and without fee is hereby granted, provided
  7. ** that the above copyright notice appear in all copies and that both that
  8. ** copyright notice and this permission notice appear in supporting
  9. ** documentation.  This software is provided "as is" without express or
  10. ** implied warranty.
  11. */
  12.  
  13. /*
  14.     Here's the tune language:
  15.     when argc is 1 the program reads its tune string from stdin;
  16.     when argc is 2 it uses argv[1] for a tune
  17.     the tune can begin with a number, which is beats/minute (default is 150)
  18.     A..G span middle C
  19.     a trailing # is a sharp; a trailing b is a flat
  20.     a trailing ^ raises a note an octave; a v lowers it an octave
  21.     a space is a rest
  22.     a - holds the preceeding note another beat
  23.     a note followed by a slash gets half the beats it would otherwise get
  24.         two slashes mean a quarter of the default, etc.
  25.     a note followed by a dot gets an extra 50% of time
  26.         a note followed by two dots gets an extra 75%, etc.
  27.     newlines, commas, and vertical bars between notes are ignored
  28.     the highest playable note is B^^^
  29.  
  30.     for the future:
  31.         a pair of notes in square brackets is a two-note chord
  32.             (all the chip supports)
  33.         < (between notes) is a crescendo -- it ups the volume one notch
  34.         > is a decrescendo -- it lowers the volume a notch
  35. */
  36.  
  37. #include <stdio.h>
  38. #include <fcntl.h>
  39. #include <signal.h>
  40. #include "libsst.h"
  41.  
  42. #define DEFAULT_TEMPO 150        /* beats per minute */
  43.  
  44. int any (c, s)
  45. char c, *s;
  46. {
  47.     while (*s) {
  48.         if (c == *s++) return 1;
  49.     }
  50.     return 0;
  51. }
  52.  
  53. int pitch[] = {
  54.     /* Ab */ 208,
  55.     /* A  */ 220,
  56.     /* A# */ 233,
  57.     /* Bb */ 233,
  58.     /* B  */ 247,
  59.     /* B# */ 262,
  60.     /* Cb */ 247,
  61.     /* C  */ 262,
  62.     /* C# */ 277,
  63.     /* Db */ 277,
  64.     /* D  */ 294,
  65.     /* D# */ 311,
  66.     /* Eb */ 311,
  67.     /* E  */ 330,
  68.     /* E# */ 349,
  69.     /* Fb */ 330,
  70.     /* F  */ 349,
  71.     /* F# */ 370,
  72.     /* Gb */ 370,
  73.     /* G  */ 392,
  74.     /* G# */ 415,
  75.     0
  76. };
  77. int notes[] = {
  78.     /* A */ 1,
  79.     /* B */ 4,
  80.     /* C */ 7,
  81.     /* D */ 10,
  82.     /* E */ 13,
  83.     /* F */ 16,
  84.     /* G */ 19,
  85.     0
  86. };
  87.  
  88. int read_stdin = 0;
  89. char c;
  90. char *tune;
  91.  
  92. void next ()
  93. {
  94.     if (read_stdin) {
  95.         int i = getchar();
  96.         c = (i == EOF) ? '\0' : i;
  97.     } else {
  98.         c = *tune;
  99.         ++tune;
  100.     }
  101. }
  102.  
  103. int sst_fd;
  104.  
  105. void cleanup ()
  106. {
  107.     sst_close( sst_fd );
  108.     exit( 0 );
  109. }
  110.  
  111. main( argc, argv )
  112. int argc;
  113. char *argv[];
  114. {
  115.     int tempo = DEFAULT_TEMPO;    /* beats per minute */
  116.  
  117.     if ( argc == 1 ) {
  118.         read_stdin = 1;
  119.     } else {
  120.         tune = argv[1];
  121.         if ( argc != 2 ) {
  122.             fprintf( stderr, "usage:  %s string\n", argv[0] );
  123.             exit( 1 );
  124.         }
  125.     }
  126.  
  127.     signal (SIGINT, cleanup);
  128.     signal (SIGQUIT, cleanup);
  129.     sst_fd = sst_open( );
  130.  
  131.     next ();
  132.     if (any (c, "0123456789")) {
  133.         tempo = 0;
  134.         while (any (c, "0123456789")) {
  135.             tempo *= 10;
  136.             tempo += (c - '0');
  137.             next ();
  138.         }
  139.     }
  140.  
  141.     while (1) {
  142.         int Hz;
  143.         double beats, dot_value;
  144.         int usec;
  145.         int index;
  146.  
  147.         while (any (c, ",|\n")) next ();
  148.  
  149.     if (!c) break;
  150.  
  151.         if (! any (c, "ABCDEFG ")) {
  152.             int count = 0;
  153.             fprintf (stderr, "bad tune.  right context: ");
  154.             while (c) {
  155.                 putc (c, stderr);
  156.                 next ();
  157.                 if (++count > 40) break;
  158.             }
  159.             putc ('\n', stderr);
  160.             sst_close( sst_fd );
  161.             exit (1);
  162.         }
  163.         if (c == ' ') {
  164.             Hz = 0;
  165.             next ();
  166.         } else {
  167.             index = notes[c - 'A'];
  168.             next ();
  169.             if (c == '#') {
  170.                 ++index;
  171.                 next ();
  172.             }
  173.             else if (c == 'b') {
  174.                 --index;
  175.                 next ();
  176.             }
  177.             Hz = pitch[index];
  178.  
  179.             while (any (c, "^v")) {
  180.                 if (c == '^') Hz <<= 1;
  181.                 if (c == 'v') Hz >>= 1;
  182.                 next ();
  183.             }
  184.         }
  185.         beats = 1.0;
  186.         while (c == '-') {
  187.             beats += 1.0;
  188.             next ();
  189.         }
  190.         while (c == '/') {
  191.             beats /= 2.0;
  192.             next ();
  193.         }
  194.         dot_value = 1.0;
  195.         while (c == '.') {
  196.             dot_value /= 2.0;
  197.             next ();
  198.         }
  199.         beats *= 2.0 - dot_value;
  200.         usec = (int) (60*1000000*beats/tempo);
  201.  
  202.         sst_tones( sst_fd, Hz, 0, 0, 0, usec );
  203. /*        printf ("%d Hz, %d msec\n", Hz, usec/1000); */
  204.     }
  205.  
  206.     cleanup ();
  207. }
  208.