home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / ECO30603.ZIP / ECO30603.LZH / ECOLIBII / ECO_PLAY.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1993-03-08  |  11.1 KB  |  333 lines

  1. (*
  2.     ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  3.     ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  4.     ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  5.     ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  6.     ▓▓▓▓▓▓▓▓·──                                              ──·▓▓▓▓▓▓▓▓▓▓▓
  7.     ▓▓▓▓▓▓▓▓│                                                  │░░▓▓▓▓▓▓▓▓▓
  8.     ▓▓▓▓▓▓▓▓   Unit was conceived, designed and written         ░░▓▓▓▓▓▓▓▓▓
  9.     ▓▓▓▓▓▓▓▓   by Floor A.C. Naaijkens for                      ░░▓▓▓▓▓▓▓▓▓
  10.     ▓▓▓▓▓▓▓▓   UltiHouse Software / The ECO Group.              ░░▓▓▓▓▓▓▓▓▓
  11.     ▓▓▓▓▓▓▓▓                                                    ░░▓▓▓▓▓▓▓▓▓
  12.     ▓▓▓▓▓▓▓▓   (C) MCMXCII by EUROCON PANATIONAL CORPORATION.   ░░▓▓▓▓▓▓▓▓▓
  13.     ▓▓▓▓▓▓▓▓   All Rights Reserved for The ECO Group.           ░░▓▓▓▓▓▓▓▓▓
  14.     ▓▓▓▓▓▓▓▓                                                    ░░▓▓▓▓▓▓▓▓▓
  15.     ▓▓▓▓▓▓▓▓│                                                  │░░▓▓▓▓▓▓▓▓▓
  16.     ▓▓▓▓▓▓▓▓·──                                              ──·░░▓▓▓▓▓▓▓▓▓
  17.     ▓▓▓▓▓▓▓▓▓▓░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▓▓▓▓▓▓▓▓▓
  18.     ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  19.     ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  20.     ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  21. *)
  22. {
  23.   call: play(string)
  24.  
  25.         music_string --- the string containing the encoded music to be
  26.                          played.  the format is the same as that of the
  27.                          microsoft basic play statement.  the string
  28.                          must be <= 254 characters in length.
  29.  
  30.   calls:  sound
  31.           getint  (internal)
  32.  
  33.   remarks:  the characters accepted by this routine are:
  34.  
  35.             a - g       musical notes
  36.             # or +      following a - g note, indicates sharp
  37.             -           following a - g note, indicates flat
  38.             <           move down one octave
  39.             >           move up one octave
  40.             .           dot previous note (extend note duration by 3/2)
  41.             mn          normal duration (7/8 of interval between notes)
  42.             ms          staccato duration
  43.             ml          legato duration
  44.             ln          length of note (n=1-64; 1=whole note,4=quarter note)
  45.             pn          pause length (same n values as ln above)
  46.             tn          tempo,n=notes/minute (n=32-255,default n=120)
  47.             on          octave number (n=0-6,default n=4)
  48.             nn          play note number n (n=0-84)
  49.  
  50.             the following two commands are ignored by play:
  51.  
  52.             mf          complete note before continuing
  53.             mb          another process may begin before speaker is
  54.                         finished playing note
  55.  
  56.   important --- setdefaultnotes must have been called at least once before
  57.                 this routine is called.
  58. }
  59.  
  60. unit eco_play;
  61. interface
  62.  
  63. uses
  64.   crt
  65.  
  66.   ;
  67.  
  68. const
  69.   note_octave   : integer = 4;     { current octave for note            }
  70.   note_fraction : real    = 0.875; { fraction of duration given to note }
  71.   note_duration : integer = 0;     { duration of note     ^^semi-legato }
  72.   note_length   : real    = 0.25;  { length of note }
  73.   note_quarter  : real    = 500.0; { moderato pace (principal beat)     }
  74.  
  75.  
  76.  
  77.   procedure quitsound;
  78.   procedure startsound;
  79.   procedure errorbeep;
  80.   procedure warningbeep;
  81.   procedure smallbeep;
  82.   procedure setdefaultnotes;
  83.   procedure play(s: string);
  84.   procedure beep(h, l: word);
  85.  
  86.  
  87.  
  88. implementation
  89.  
  90.  
  91.  
  92.  
  93.   procedure quitsound;
  94.   var i: word;
  95.   begin
  96.     for i := 100 downto 1 do begin sound(i*10); delay(2) end; 
  97.     for i := 1 to 800 do begin sound(i*10); delay(2) end;  
  98.     nosound;
  99.   end;
  100.  
  101.   procedure startsound;
  102.   var i: word;
  103.   begin
  104.     for i := 100 downto 1 do begin sound(i*15); delay(2) end; 
  105.     for i := 1 to 100 do begin sound(i*15); delay(2) end; nosound;
  106.     delay(100); for i := 100 downto 1 do begin sound(i*10); delay(2) end;
  107.     nosound;
  108.   end;
  109.  
  110.  
  111.   procedure errorbeep;
  112.   begin
  113.     sound(2000); delay(75); sound(1000); delay(75); nosound;
  114.   end;
  115.  
  116.  
  117.   procedure warningbeep;
  118.   begin
  119.     sound(500); delay(500); nosound;
  120.   end;
  121.  
  122.   procedure smallbeep;
  123.   begin
  124.     sound(300); delay(50); nosound;
  125.   end;
  126.  
  127.  
  128.  
  129.  
  130.  
  131. procedure setdefaultnotes;
  132. begin
  133.    note_octave   := 4;             { default octave                      }
  134.    note_fraction := 0.875;         { default sustain is semi-legato      }
  135.    note_length   := 0.25;          { note is quarter note by default     }
  136.    note_quarter  := 500.0;         { moderato pace by default            }
  137. end;
  138.  
  139.  
  140.  
  141. procedure play(s: string);
  142. const
  143.                                       { offsets in octave of natural notes }
  144.  note_offset   : array[ 'A'..'G' ] of integer = (9,11,0,2,4,5,7);
  145.  
  146.                                       { frequencies for 7 octaves          }
  147.    note_freqs: array[ 0 .. 84 ] of integer =
  148. {
  149.       c    c#     d    d#     e     f    f#     g    g#     a    a#     b
  150. }
  151. (    0,
  152.      65,  69,  73,  78,  82,  87,  92,  98, 104, 110, 116, 123,
  153.     131, 139, 147, 156, 165, 175, 185, 196, 208, 220, 233, 247,
  154.     262, 278, 294, 312, 330, 350, 370, 392, 416, 440, 466, 494,
  155.     524, 556, 588, 624, 660, 700, 740, 784, 832, 880, 932, 988,
  156.    1048,1112,1176,1248,1320,1400,1480,1568,1664,1760,1864,1976,
  157.    2096,2224,2352,2496,2640,2800,2960,3136,3328,3520,3728,3952,
  158.    4192,4448,4704,4992,5280,5600,5920,6272,6656,7040,7456,7904 );
  159.  
  160.    quarter_note = 0.25;            { length of a quarter note }
  161.  
  162.    digits : set of '0'..'9' = ['0'..'9'];
  163.  
  164. var
  165.  
  166.    play_freq     : integer;        { frequency of note to be played }
  167.    play_duration : integer;        { duration to sound note }
  168.    rest_duration : integer;        { duration of rest after a note }
  169.    i             : integer;        { offset in music string }
  170.    c             : char;           { current character in music string }
  171.                                    { note frequencies }
  172.    freq          : array[0..6,0..11] of integer absolute note_freqs;
  173.    n             : integer;
  174.    xn            : real;
  175.    k             : integer;
  176.  
  177.   function getint : integer;
  178.   var n: integer;
  179.  
  180.   begin { getint }
  181.     n := 0;
  182.     while(s[i] in digits) do begin n := n*10+ord(s[i])-ord('0'); inc(i) end;
  183.     dec(i); getint := n;
  184.   end   { getint };
  185.  
  186. begin
  187.   s := s + ' ';                   { append blank to end of music string }
  188.   i := 1;                           { point to first character in music }
  189.   while(i < length(s)) do begin      { begin loop over music string }
  190.     c := upcase(s[i]);        { get next character in music string }
  191.     case c of                 { interpret it                       }
  192.        'A'..'G' : begin { a note }
  193.           n         := note_offset[ c ];
  194.           play_freq := freq[ note_octave ,n ];
  195.           xn := note_quarter * (note_length / quarter_note);
  196.           play_duration := trunc(xn * note_fraction);
  197.           rest_duration := trunc(xn * (1.0 - note_fraction));
  198.                                       { check for sharp/flat }
  199.           if s[i+1] in ['#','+','-' ] then
  200.              begin
  201.                 inc(i);
  202.                 case s[i] of
  203.                    '#',
  204.                    '+' : play_freq :=
  205.                             freq[ note_octave ,succ(n) ];
  206.                    '-' : play_freq :=
  207.                             freq[ note_octave ,pred(n) ];
  208.                    else  ;
  209.                 end { case };
  210.  
  211.              end;
  212.  
  213.                    { check for note length }
  214.  
  215.           if (s[i+1] in digits) then
  216.              begin
  217.  
  218.                 inc(i);
  219.                 n  := getint;
  220.                 xn := (1.0 / n) / quarter_note;
  221.  
  222.                 play_duration :=
  223.                     trunc(note_fraction * note_quarter * xn);
  224.  
  225.                 rest_duration :=
  226.                    trunc((1.0 - note_fraction) *
  227.                           xn * note_quarter);
  228.  
  229.              end;
  230.                    { check for dotting }
  231.  
  232.              if s[i+1] = '.' then
  233.                 begin
  234.  
  235.                    xn := 1.0;
  236.  
  237.                    while(s[i+1] = '.') do
  238.                       begin
  239.                          xn := xn * 1.5;
  240.                          inc(i);
  241.                       end;
  242.  
  243.                    play_duration :=
  244.                        trunc(play_duration * xn);
  245.  
  246.                 end;
  247.  
  248.                        { play the note }
  249.  
  250.           sound(play_freq);
  251.           delay(play_duration);
  252.           nosound;
  253.           delay(rest_duration);
  254.         end   { a note };
  255.  
  256.        'M' : begin { 'M' commands }
  257.          inc(i);
  258.          c := s[i];
  259.          case c of
  260.            'F' : ;
  261.            'B' : ;
  262.            'N' : note_fraction := 0.875;
  263.            'L' : note_fraction := 1.000;
  264.            'S' : note_fraction := 0.750;
  265.            else ;
  266.          end { case };
  267.        end   { 'M' commands };
  268.  
  269.        'O' : begin { set octave }
  270.          inc(i);
  271.          n := ord(s[i]) - ord('0');
  272.          if (n < 0) or (n > 6) then n := 4;
  273.          note_octave := n;
  274.        end   { set octave };
  275.  
  276.        '<' : begin { drop an octave }
  277.          if note_octave > 0 then dec(note_octave);
  278.        end   { drop an octave };
  279.  
  280.        '>' : begin { ascend an octave }
  281.          if note_octave < 6 then inc(note_octave);
  282.        end   { ascend an octave };
  283.  
  284.        'N' : begin { play note n }
  285.          inc(i); n := getint;
  286.          if (n > 0) and (n <= 84) then begin
  287.            play_freq     := note_freqs[ n ];
  288.            xn            := note_quarter * (note_length / quarter_note);
  289.            play_duration := trunc(xn * note_fraction);
  290.            rest_duration := trunc(xn * (1.0 - note_fraction));
  291.          end else if (n = 0) then begin
  292.            play_freq     := 0; play_duration := 0;
  293.            rest_duration := trunc(note_fraction * note_quarter *
  294.                                  (note_length / quarter_note));
  295.          end;
  296.          sound(play_freq); delay(play_duration); nosound;
  297.          delay(rest_duration);
  298.        end   { play note n };
  299.  
  300.        'L' : begin { set length of notes }
  301.          inc(i); n := getint;
  302.          if n > 0 then note_length := 1.0 / n;
  303.        end   { set length of notes };
  304.  
  305.        'T' : begin { # of quarter notes in a minute }
  306.          inc(i); n := getint;
  307.          note_quarter := (1092.0 / 18.2 / n) * 1000.0;
  308.        end   { # of quarter notes in a minute };
  309.  
  310.        'P' : begin { pause }
  311.          inc(i); n := getint;
  312.          if (n <  1) then n := 1 else if (n > 64) then n := 64;
  313.          play_freq := 0; play_duration := 0;
  314.          rest_duration := trunc(((1.0 / n) / quarter_note) * note_quarter);
  315.          sound(play_freq); delay(play_duration); nosound;
  316.          delay(rest_duration);
  317.        end   { pause };
  318.  
  319.        else  { ignore other stuff };
  320.     end { case };
  321.     inc(i);
  322.   end  { interpret music };
  323.   nosound;                         { make sure sound turned off when through }
  324. end;
  325.  
  326.  
  327. procedure beep(h, l: word);
  328. begin
  329.   sound(h); delay(l); nosound;
  330. end;
  331.  
  332. end. { of unit }
  333.