home *** CD-ROM | disk | FTP | other *** search
/ Beijing Paradise BBS Backup / PARADISE.ISO / software / BBSDOORW / RADOOR30.ZIP / ANSIMUS.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1994-04-10  |  7.6 KB  |  270 lines

  1. {╔═════════════════════════════════════════════════════════════════════════╗
  2.  ║                                                                         ║
  3.  ║                   (c) CopyRight LiveSystems 1990, 1994                  ║
  4.  ║                                                                         ║
  5.  ║ Author    : Gerhard Hoogterp                                            ║
  6.  ║ FidoNet   : 2:282/100.5   2:283/7.33                                    ║
  7.  ║ BitNet    : GERHARD@LOIPON.WLINK.NL                                     ║
  8.  ║                                                                         ║
  9.  ║ SnailMail : Kremersmaten 108                                            ║
  10.  ║             7511 LC Enschede                                            ║
  11.  ║             The Netherlands                                             ║
  12.  ║                                                                         ║
  13.  ║        This module is part of the RADoor BBS doorwriters toolbox.       ║
  14.  ║                                                                         ║
  15.  ╚═════════════════════════════════════════════════════════════════════════╝}
  16.  
  17. { Current problems/bugs:
  18.  
  19. - Due to the streamlike nature of this AnsiMusic implementation it's not
  20.   yet possible to play music in the background.. Maybe I get a briljant
  21.   idea someday.. For now EVERYTHING is played in the foreground!
  22. }
  23.  
  24. Unit AnsiMus;
  25. Interface
  26. Uses Crt;
  27.  
  28.  
  29. { Comment: (Mon  02-04-1991, 23:02:45)
  30. |-----------------------------------------------------------------------------|
  31.   PlayAnsi accepts a string containing an ANSIMusic string. The part between
  32.   the <ESC>[M  and the #14 that is.
  33.   Controle is returned to the program as soon as the music is finished
  34. |-----------------------------------------------------------------------------|
  35. }
  36.  
  37. Procedure PlayAnsi(S : String);
  38.  
  39.  
  40. { Comment: (Mon  02-04-1991, 23:04:10)
  41. |-----------------------------------------------------------------------------|
  42.  The AnsiMusic procedure accepts a stream of characters which should only
  43.  contain legal Ansi-Music symbols.
  44.  It's up the the master-routine to detect the end of the stream..
  45.  Controle is returned after each character. See the Driver.pas file for an
  46.  example of the usage.
  47. |-----------------------------------------------------------------------------|
  48. }
  49.  
  50. Procedure AnsiMusic(C : Char);
  51.  
  52. {
  53. |-----------------------------------------------------------------------------|
  54.  Reset the ansi interpreter to it's default values!
  55. |-----------------------------------------------------------------------------|
  56. }
  57.  
  58. Procedure ResetMusic;
  59.  
  60.  
  61. Implementation
  62.  
  63. Function Str2Nr(S : String):Word;
  64. Var Temp : Word;
  65.     Err  : Word;
  66. Begin
  67. Val(S,Temp,Err);
  68. If Err<>0
  69.    Then Str2Nr:=0
  70.    Else Str2Nr:=Temp;
  71. End;
  72.  
  73. {---------------- Music routines -------------------------------------------}
  74.  
  75. Const Scale : Array[1..84] Of Word =
  76.  
  77. (
  78.  0065, 0070, 0073, 0078, 0082, 0087, 0093, 0098, 0104, 0110, 0117, 0123,
  79.  0131, 0139, 0147, 0156, 0165, 0175, 0185, 0196, 0208, 0220, 0233, 0247,
  80.  0262, 0277, 0294, 0311, 0330, 0349, 0370, 0392, 0415, 0440, 0466, 0494,
  81.  0523, 0554, 0587, 0622, 0659, 0698, 0740, 0784, 0831, 0880, 0932, 0987,
  82.  1047, 1109, 1175, 1245, 1329, 1397, 1480, 1568, 1661, 1760, 1865, 1976,
  83.  2093, 2217, 2349, 2489, 2637, 2794, 2960, 3136, 3322, 3520, 3729, 3951,
  84.  4186, 4435, 4699, 4978, 5274, 5588, 5920, 6272, 6645, 7040, 7459, 7902
  85. );
  86.  
  87.  
  88. Type StatusType = (None,Note,NoteLen,Music,Octave,Tempo);
  89.      BufType    = String[10];
  90.  
  91. Var Status     : StatusType;
  92.     Buf        : BufType;
  93.  
  94.     DefLength  : Word;
  95.     DefOctave  : Word;
  96.     DefTempo   : Word;
  97.     Timing     : Real;
  98.     Fraktion   : Real;
  99.  
  100.  
  101. Procedure DoNote(S : BufType);
  102. Var UseNote : Byte;
  103.     NoteLen : Byte;
  104.  
  105.     TTime,
  106.     PTime,
  107.     ITime,
  108.     DTime   : LongInt;
  109.  
  110.     Len     : String[5];
  111.     Count   : Byte;
  112.     Error   : Integer;
  113.  
  114. Begin
  115. UseNote:=Pos(S[1],'CcDdEFfGgAaB');
  116.  
  117. DTime:=1000;
  118. If Length(S)>1
  119.    Then Begin
  120.         If S[2] In ['+','#','-']
  121.            Then Begin
  122.                 Case S[2] Of
  123.                  '+','#' : Inc(UseNote);
  124.                  '-'     : Dec(UseNote);
  125.                 End;
  126.                 Count:=3;
  127.                 End
  128.            Else Count:=2;
  129.         Len:='';
  130.  
  131.         While (Count<=Length(S)) And (S[Count] In ['0'..'9']) Do
  132.            Begin
  133.            Len:=Len+S[Count];
  134.            Inc(Count);
  135.            End;
  136.         Val(Len,NoteLen,Error);
  137.  
  138.         If NoteLen=0
  139.            Then NoteLen:=DefLength;
  140.  
  141.         If Length(S)>(Count-1)
  142.            Then Begin
  143.                 While Count<=Length(S) Do
  144.                  Begin
  145.                  If S[Count]='.'
  146.                     Then DTime:=DTime+DTime Div 2;
  147.                  Inc(Count);
  148.                  End;
  149.                 End;
  150.         End
  151.    Else NoteLen:=DefLength;
  152.  
  153.  
  154. TTime := Round(DTime/DefTempo/NoteLen*240);
  155. PTime := Round(TTime*Fraktion/8);
  156. ITime := TTime-PTime;
  157.  
  158.  
  159. If S[1]<>'P'
  160.    Then Sound(Scale[UseNote + DefOctave * 12 ]);
  161.  
  162. Delay(PTime);
  163. If ITime<>0
  164.    Then Begin
  165.         NoSound;
  166.         Delay(ITime);
  167.         End;
  168. End;
  169.  
  170. Procedure AnsiMusic(C : Char);
  171. Var Buffed : Boolean;
  172.     Mem    : Char;
  173. Begin
  174. Buffed:=False;
  175. Repeat
  176.  If Buffed
  177.     Then Begin
  178.          C:=Mem;
  179.          Buffed:=False;
  180.          End;
  181.  
  182.  Case Status Of
  183.   None      : Begin
  184.               Buf:=C;
  185.               Case C Of
  186.                'A'..'G',
  187.                'P'      : Status:=Note;
  188.                'L'      : Status:=NoteLen;
  189.                'M'      : Status:=Music;
  190.                'O'      : Status:=Octave;
  191.                'T'      : Status:=Tempo;
  192.                '>'      : If DefOctave<8
  193.                              Then Inc(DefOctave);
  194.                '<'      : If DefOctave>0
  195.                              Then Dec(DefOctave);
  196.               End;{Case}
  197.               End;
  198.   Note      : Begin
  199.               If C In ['A'..'G','P','M','L','O','T','P']
  200.                  Then Begin
  201.                       Status:=None;
  202.                       Mem:=C;
  203.                       Buffed:=True;
  204.                       End
  205.                  Else Buf:=Buf+C;
  206.               If Status=None
  207.                  Then DoNote(Buf);
  208.               End;
  209.   NoteLen   : Begin
  210.               If Not (C In ['0'..'9'])
  211.                  Then Begin
  212.                       Status:=None;
  213.                       Mem:=C;
  214.                       Buffed:=True;
  215.                       End
  216.                  Else Buf:=Buf+C;
  217.               If Status=None
  218.                  Then DefLength:=Str2Nr(Copy(Buf,2,Length(Buf)-1));
  219.               End;
  220.   Music     : Begin
  221.               Case C Of
  222.                'B','F' : ;
  223.                'S'     : Fraktion:=6;
  224.                'N'     : Fraktion:=7;
  225.                'L'     : Fraktion:=8;
  226.               End;
  227.               Status:=None;
  228.               End;
  229.   Octave    : Begin
  230.               DefOctave:=Ord(C)-$30;
  231.               Status:=None;
  232.               End;
  233.   Tempo     : Begin
  234.               If Not (C In ['0'..'9'])
  235.                  Then Begin
  236.                       Status:=None;
  237.                       Mem:=C;
  238.                       Buffed:=True;
  239.                       End
  240.                  Else Buf:=Buf+C;
  241.               If Status=None
  242.                  Then DefTempo:=Str2Nr(Copy(Buf,2,Length(Buf)-1));
  243.               End;
  244.  End; {Status}
  245. Until Not Buffed;
  246. End;
  247.  
  248. Procedure PlayAnsi(S : String);
  249. Var Count : Byte;
  250. Begin
  251. For Count:=1 To Length(S) Do
  252.   AnsiMusic(Upcase(S[Count]));
  253. End;
  254.  
  255.  
  256. Procedure ResetMusic;
  257. Begin
  258. DefOctave:=3;
  259. DefTempo:=120;
  260. DefLength:=4;
  261. Status:=None;
  262. End;
  263.  
  264. Begin
  265. DefOctave:=3;
  266. DefTempo:=120;
  267. DefLength:=4;
  268. Status:=None;
  269. End.
  270.