home *** CD-ROM | disk | FTP | other *** search
/ Kids Cube / 2_Music.iso / mel / sounder.pas < prev    next >
Pascal/Delphi Source File  |  1992-07-27  |  5KB  |  143 lines

  1. {
  2. Background sound generation unit for Turbo Pascal programs
  3.  
  4.   Originally written and released to Public Domain by:
  5.  
  6.     Nels Anderson
  7.     92 Bishop Drive
  8.     Framingham, MA  01701
  9.  
  10.   Adopted for use with Melody Master by Alexei A. Efros, Jr.
  11. }
  12. unit Sounder;
  13. {
  14.       This UNIT can be used with MELODY MASTER's "TP back-gr" output
  15.       files  to  minimize  the  music development time. Please note,
  16.       however, that you may have some  problems  when  playing  high
  17.       notes.  This happens when the note's frequency is greater than
  18.       255  (byte).  To solve the problem try to lower your music: in
  19.       MELODY MASTER press F9 and then  "8  down".  Then,  output  it
  20.       again.
  21.       
  22.       To use this unit, the main program needs to do the following:
  23.                 
  24.       uses Sounder, Crt;
  25.       Begin
  26.         GetIntVec($1C,Int1CSave);  (save original interrupt vector)
  27.         SetIntVec($1C,New1CInt);   (install timer interrupt)
  28.           .
  29.           .  (body of program)
  30.           .
  31.         StartSound(@ArrayName,N,S);
  32.            (where: ArrayName is the name of the your melody,
  33.                    N is the number if repeats,
  34.                    S is the speed)
  35.           .
  36.           .  (body of program)
  37.           .
  38.         SetIntVec($1C,Int1CSave);  (restore original 1C interrupt)
  39.         NoSound;
  40.       end.
  41. }
  42.       
  43. interface
  44.  
  45. Uses
  46.   Crt;
  47.  
  48. {$I FILENAME.PAS}    { <---- Insert your music file name here! }
  49.  
  50. procedure StartSound(Notes:  POINTER; Repeats:  INTEGER; Speed:  BYTE);
  51.  
  52. { Sound Collection:
  53.  
  54.   Each sound is an array of pairs of bytes, where the first byte of each
  55.   pair is the duration in 1/18th second units and the second byte of the
  56.   pair is the note frequency in 10's of Hertz.  To use a sound, include
  57.   a command like the following in a program:
  58.  
  59.            StartSound(@PhaserSound,3,1);    {do phaser sound 3 times}
  60.  
  61. Type
  62.   ByteArray = array[1..2] of BYTE;
  63. Var
  64.   SoundSpeed:  BYTE;      {multiplier used to slow down sounds}
  65.   SoundCount:  BYTE;      {counts how long current sound has been on}
  66.   MySound: ^ByteArray;    {points to array of notes and durations}
  67.   New1CInt,{address of new interrupt}
  68.   Int1CSave:  POINTER;        {saves original $1C interrupt}
  69.   NumRepeats,            {number of times to repeat sound}
  70.   MyClock,            {general purpose timer}
  71.   SoundOff:  INTEGER;        {offset into note array}
  72.   SndFlg,            {set when sounds allowed}
  73.   MakeSound:  BOOLEAN;        {set while sound is going}
  74.  
  75. implementation
  76.  
  77. procedure StartSound(Notes:  POINTER; Repeats:  INTEGER; Speed:  BYTE);
  78. { Start generating the sound pointed to by Notes }
  79. begin
  80.   SoundSpeed := Speed;            {set speed}
  81.   SoundOff := 1;            {offset into sound array}
  82.   SoundCount := 1;            {counter for current note}
  83.   MySound := Notes;            {pointer to sound array}
  84.   MakeSound := TRUE;            {enable sounds}
  85.   NumRepeats := Repeats;        {number times to repeat sound}
  86. end; {StartSound procedure}
  87.  
  88. procedure TimerInt;
  89. interrupt;
  90. { Clock tick interrupt
  91.  
  92. BIOS interrupt $1C has been replaced with the following routine.  This
  93. interrupt occurs on each clock tick (18 per second).
  94.  
  95. The interrupt mainly handles sounds.  When the MakeSound flag is true,
  96. the pointer MySound must be pointing to a byte array containing durations
  97. and frequencies of sounds to be generated.  Sounds will be generated from
  98. the array until a duration of 0 is found.
  99.  
  100. A general purpose timer is also incremented each time the interrupt
  101. occurs.
  102. }
  103. begin
  104.   Inc(MyClock);                    {increment timer}
  105.   if not SndFlg then begin            {exit if sounds turned off}
  106.     MakeSound := FALSE;
  107.     Exit;
  108.   end;
  109.   if MakeSound then begin            {if making a sound...}
  110.     Dec(SoundCount);
  111.     if SoundCount <= 0 then begin        {if current sound done...}
  112.       NoSound;
  113.       SoundCount := SoundSpeed * MySound^[SoundOff];{get duration of next one}
  114.       if SoundCount > 0 then begin        {if there is a next one...}
  115.         Inc(SoundOff);
  116.         Sound(10*MySound^[SoundOff]);        {start it up}
  117.         Inc(SoundOff);
  118.       end
  119.       else begin                {if end of sound array...}
  120.         Dec(NumRepeats);            {decrement number of repeats}
  121.         if NumRepeats > 0 then begin        {if we must repeat...}
  122.           SoundOff := 3;            {reset offset into array}
  123.           SoundCount := MySound^[1];        {get duration of first note}
  124.           Sound(10*MySound^[2]);        {start it up}
  125.         end
  126.         else begin                {if all repeats now done...}
  127.           NoSound;                {stop all sound}
  128.           MakeSound := FALSE;            {reset flag}
  129.         end;
  130.       end;
  131.     end; {if SoundCount = 0}
  132.   end; {if making a sound}
  133. end; {TimerInt interrupt procedure}
  134.  
  135. begin
  136.  
  137.   SndFlg := TRUE;                {sounds are allowed}
  138.   MakeSound := FALSE;                {sound initially off}
  139.   MyClock := 0;                    {reset timer}
  140.   New1CInt := @TimerInt;            {get address of interrupt}
  141.  
  142. end.
  143.