home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast.iso / pcmag / vol9n21.zip / DGSOUND.PAS < prev    next >
Pascal/Delphi Source File  |  1990-09-25  |  18KB  |  601 lines

  1. {
  2.  ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
  3.  █                                                                         █
  4.  █        TITLE :      DGSOUND.TPU                                         █
  5.  █      PURPOSE :      Sound functions and procedures.                     █
  6.  █       AUTHOR :      David Gerrold, CompuServe ID:  70307,544            █
  7.  █  _____________________________________________________________________  █
  8.  █                                                                         █
  9.  █   Written in Turbo Pascal, Version 5.5,                                 █
  10.  █   with routines from TurboPower, Object Professional.                   █
  11.  █                                                                         █
  12.  █   Turbo Pascal is a product of Borland International.                   █
  13.  █   Object Professional is a product of TurboPower Software.              █
  14.  █  _____________________________________________________________________  █
  15.  █                                                                         █
  16.  █   This is not public domain software.                                   █
  17.  █   This software is copyright 1990, by David Gerrold.                    █
  18.  █   Permission is hereby granted for personal use.                        █
  19.  █                                                                         █
  20.  █        The Brass Cannon Corporation                                     █
  21.  █        9420 Reseda Blvd., #804                                          █
  22.  █        Northridge, CA  91324-2932.                                      █
  23.  █                                                                         █
  24.  ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
  25.                                                                             }
  26. { Compiler Directives ===================================================== }
  27.  
  28. {$A-}    {Switch word alignment off, necessary for cloning}
  29. {$R-}    {Range checking off}
  30. {$B-}    {Boolean complete evaluation off}
  31. {$S-}    {Stack checking off}
  32. {$I-}    {I/O checking off}
  33. {$N+,E+} {Simulate numeric coprocessor}
  34. {$M 16384,0,327680} {stack and heap}
  35. {$V-}    {Variable range checking off}
  36.  
  37. { Name ==================================================================== }
  38.  
  39. UNIT DgSound;
  40. {
  41.   The purpose of this code is to provide a library of commonly needed
  42.   sounds and sound-managing routines.
  43. }
  44.  
  45. { Interface =============================================================== }
  46.  
  47. INTERFACE
  48.  
  49. USES
  50. { Object Professional Units }
  51.   OpCrt,
  52.   OpString,
  53.  
  54. { Dg Units }
  55.   DgBit,
  56.   DgCrt;
  57.  
  58. { Declarations ============================================================ }
  59.  
  60. CONST
  61.   SfxCues      =  1;                             { enable beeps and bonks }
  62.   SfxKeyClick  =  2;                             { enable keyclick }
  63.   SfxMusic     =  4;                             { enable music }
  64.   SfxAllSounds =  7;                             { enable all sounds }
  65.  
  66.   SfxSound    : byte = 7;                        { configurable }
  67.   SfxOptions  : byte = 7;                        { default options }
  68.   BuzzCounter : longint = 1;
  69.  
  70. TYPE
  71.   BombOb = Object
  72.     Procedure Incoming;                          { falling sound }
  73.     Procedure Boom;                              { explosion }
  74.     Procedure FlashBoom;                         { explosion with flash }
  75.     end;
  76.  
  77. VAR
  78.   Bomb : BombOb;
  79.  
  80. { Sound Managment Routines ================================================ }
  81.  
  82. FUNCTION Sfx (Option : word) : boolean;
  83. { returns true if sound effects option is set }
  84.  
  85. PROCEDURE ToggleSfxCues;
  86. { Toggle sound cues on and off. }
  87.  
  88. PROCEDURE ToggleKeyClick;
  89. { Toggle Key click on and off. }
  90.  
  91. PROCEDURE ToggleMusic;
  92. { Toggle music cues on and off. }
  93.  
  94. PROCEDURE ToggleSound;
  95. { Toggle all sounds on and off. }
  96.  
  97. PROCEDURE KeyClick;
  98.  
  99. PROCEDURE CueClick;
  100.  
  101. PROCEDURE Beep;
  102.  
  103. PROCEDURE BeepBeep;
  104.  
  105. PROCEDURE BeepBoop;
  106.  
  107. PROCEDURE BoopBeep;
  108.  
  109. PROCEDURE Bonk;
  110.  
  111. PROCEDURE Noise (Start,                          { starting frequency }
  112.                  Stop,                           { ending frequency }
  113.                  Step,                           { step size }
  114.                  TmPrStp,                        { time per step }
  115.                  Times,                          { repeats of whole sound }
  116.                  Pause                           { pause between repeats }
  117.                  : Integer);
  118.  
  119. PROCEDURE BadBuzzer;
  120.  
  121. PROCEDURE RealBadBuzzer;
  122.  
  123. PROCEDURE IncBuzzer;
  124.  
  125. PROCEDURE IndustrialSiren;
  126.  
  127. { ========================================================================= }
  128. { Implementation ========================================================== }
  129.  
  130. IMPLEMENTATION
  131.  
  132. { ========================================================================= }
  133. { Sfx ===================================================================== }
  134.  
  135. FUNCTION Sfx (Option : word) : boolean;
  136.  
  137. BEGIN
  138.   Sfx := SfxOptions and Option = Option;
  139. END;
  140.  
  141. { ToggleSfxCues =========================================================== }
  142.  
  143. {$F+} PROCEDURE ToggleSfxCues; {$F-}
  144. BEGIN
  145.   SfxOptions := ToggleBitMask (SfxOptions, SfxCues);
  146. END;
  147.  
  148. { ToggleClick ============================================================= }
  149.  
  150. {$F+} PROCEDURE ToggleKeyClick; {$F-}
  151. BEGIN
  152.   SfxOptions := ToggleBitMask (SfxOptions, SfxKeyClick);
  153. END;
  154.  
  155. { ToggleMusic ============================================================= }
  156.  
  157. {$F+} PROCEDURE ToggleMusic; {$F-}
  158. BEGIN
  159.   SfxOptions := ToggleBitMask (SfxOptions, SfxMusic);
  160. END;
  161.  
  162. { ToggleSound ============================================================= }
  163.  
  164. CONST
  165.   StoreSfxOptions : byte = 0;
  166.  
  167. {$F+} PROCEDURE ToggleSound; {$F-}
  168. BEGIN
  169.   if SfxOptions = 0 then
  170.     SfxOptions := StoreSfxOptions
  171.   else begin
  172.     StoreSfxOptions := SfxOptions;
  173.     SfxOptions := 0;
  174.     end;
  175. END;
  176.  
  177. { KeyClick ================================================================ }
  178.  
  179. PROCEDURE KeyClick;
  180. BEGIN
  181.   if not Sfx (SfxKeyClick) then exit;
  182.   Sound (55);
  183.   Delay (1);
  184.   NoSound;
  185. END;
  186.  
  187. { CueClick ================================================================ }
  188.  
  189. PROCEDURE CueClick;
  190. BEGIN
  191.   if not Sfx (SfxCues) then exit;
  192.   Sound (55);
  193.   Delay (1);
  194.   NoSound;
  195. END;
  196.  
  197. { Beep ==================================================================== }
  198.  
  199. PROCEDURE Beep;
  200. BEGIN
  201.   if not Sfx (SfxCues) then exit;
  202.   Sound (440);
  203.   Delay (25);
  204.   NoSound;
  205. END;
  206.  
  207. { BeepBeep ================================================================ }
  208.  
  209. PROCEDURE BeepBeep;
  210. BEGIN
  211.   if not Sfx (SfxCues) then exit;
  212.   Sound (1760);
  213.   Delay (50);
  214.   NoSound;
  215.   Delay (40);
  216.   Sound (1760);
  217.   Delay (50);
  218.   NoSound;
  219. END;
  220.  
  221. { BeepBoop ================================================================ }
  222.  
  223. PROCEDURE BeepBoop;
  224. BEGIN
  225.   if not Sfx (SfxCues) then exit;
  226.   Sound (440);
  227.   Delay (100);
  228.   Sound (330);
  229.   Delay (100);
  230.   NoSound;
  231. END;
  232.  
  233. { BoopBeep ================================================================ }
  234.  
  235. PROCEDURE BoopBeep;
  236. BEGIN
  237.   if not Sfx (SfxCues) then exit;
  238.   Sound (330);
  239.   Delay (100);
  240.   Sound (440);
  241.   Delay (100);
  242.   NoSound;
  243. END;
  244.  
  245. { Bonk ==================================================================== }
  246.  
  247. PROCEDURE Bonk;
  248. VAR
  249.   Loop : byte;
  250. BEGIN
  251.   if not Sfx (SfxCues) then exit;
  252.   For Loop := 1 to 65 do begin
  253.     Sound (110);
  254.     Delay (1);
  255.     Sound (55);
  256.     Delay (1);
  257.     end;
  258.   NoSound;
  259. END;
  260.  
  261. { Noise =================================================================== }
  262.  
  263. PROCEDURE Noise (Start,                          { starting frequency }
  264.                  Stop,                           { ending frequency }
  265.                  Step,                           { step size }
  266.                  TmPrStp,                        { time per step }
  267.                  Times,                          { repeats of whole sound }
  268.                  Pause                           { pause between repeats }
  269.                  : Integer);
  270. {
  271.   Code adapted from E. Kasey Kasemodel's NOISE.PAS.
  272.   Downloaded from CompuServe BPROGA forum.
  273. }
  274. VAR
  275.   Note, Diff, Loop : Integer;
  276.  
  277. BEGIN
  278.   Note := Start;
  279.   Diff := 0;
  280.   Loop := 0;
  281.   for Loop := 1 to times do begin
  282.     sound (Note); delay (TmPrStp); NoSound;      { make sound the 1st time }
  283.     repeat
  284.       if start > stop then begin                 { noise goes down }
  285.          Note := Note - Step;     { take step value away from current freq }
  286.          Diff := Note - Stop;     { check difference between freq and stop }
  287.          end
  288.        else begin                                { noise goes up }
  289.          Note := Note + Step;
  290.          Diff := Stop - Note;
  291.          end;
  292.        sound (Note); delay (TmPrStp); NoSound;   { produce updated sound }
  293.     until (Diff < 0);             { keep looping til freq goes past stop }
  294.     Note := Start;                         { start over for another loop }
  295.     delay (Pause);                               { wait between loops }
  296.     end;  {for Loop}                             { do again if necessary }
  297. END;
  298.  
  299. { IndustrialSiren ========================================================= }
  300.  
  301. PROCEDURE IndustrialSiren;
  302. VAR
  303.   Loop : byte;
  304.  
  305. BEGIN
  306.   if not Sfx (SfxCues) then exit;
  307.   for Loop := 1 to 8 do begin
  308.     Noise (1000, 2000, 15, 2, 1, 0);
  309.     Noise (2000, 1000, 15, 2, 1, 0);
  310.     end;
  311. END;
  312.  
  313. { BadBuzzer =============================================================== }
  314.  
  315. PROCEDURE BadBuzzer;
  316. BEGIN
  317.   if not Sfx (SfxCues) then exit;
  318.   Noise (1000, 2000, 500, 2, 20, 0);
  319. END;
  320.  
  321. { RealBadBuzzer =========================================================== }
  322.  
  323. PROCEDURE RealBadBuzzer;
  324. BEGIN
  325.   if not Sfx (SfxCues) then exit;
  326.   Noise (1000, 2000, 500, 2, 200, 0);
  327. END;
  328.  
  329. { IncBuzzer =============================================================== }
  330.  
  331. PROCEDURE IncBuzzer;
  332. VAR
  333.   Loop : longint;
  334. BEGIN
  335.   inc (BuzzCounter, BuzzCounter);
  336.   for Loop := 1 to BuzzCounter do
  337.     RealBadBuzzer;
  338. END;
  339.  
  340. { ========================================================================= }
  341. { BombOb.Incoming ========================================================= }
  342.  
  343. PROCEDURE BombOb.InComing;
  344. VAR Loop : word;
  345. BEGIN
  346.   for Loop := 5000 downto 1000 do begin          { falling note }
  347.     sound (Loop);
  348.     delay (1);
  349.     end;
  350.   nosound;
  351. END;
  352.  
  353. { BombOb.Boom ============================================================= }
  354.  
  355. PROCEDURE BombOb.Boom;
  356. VAR
  357.   Loop, X, Y : word;
  358. BEGIN
  359.   for Y := 1 to 5 do
  360.     for X := 80 to 100 do begin
  361.       sound (random (1000));
  362.       delay (1);
  363.       end;
  364.  
  365.   for Loop := 1 to 1500 do begin                 { crumbling sound }
  366.     sound (random (1000));
  367.     delay (1);
  368.     end;
  369.  
  370.   for Loop := 100 to 999 do begin                { the diminishing sound }
  371.     sound (random (1000 - Loop));
  372.     delay (1);
  373.     end;
  374.  
  375.   for Loop := 950 to 999 do begin                { the echo }
  376.     sound (random (1000 - Loop));
  377.     delay (1);
  378.     end;
  379.  
  380.   nosound;
  381. END;
  382.  
  383. { BombOb.FlashBoom ======================================================== }
  384.  
  385. PROCEDURE BombOb.FlashBoom;
  386. TYPE
  387.   ScreenRowArray = array [1 .. 66] of string [132];
  388.  
  389. VAR
  390.   Loop, X    : word;
  391.   ScreenRow  : ^ScreenRowArray;                  { for storing screen }
  392.   AttrStr    : string;                           { new attrs }
  393.  
  394.   R1, G1, B1 : real;                             { color components }
  395.   R2, G2, B2 : real;
  396.   Factor     : byte;
  397.  
  398.   StoreRegs  : array [1 .. 2, 1 .. 3] of byte;   { save reg values }
  399.   Bg,                                            { registers }
  400.   Fg         : byte;
  401.  
  402. BEGIN
  403.   Bg := GetEgaRegister (Black);                  { get registers }
  404.   Fg := GetEgaRegister (White);
  405.   GetVgaRegister (Fg, StoreRegs [1, 1], StoreRegs [1, 2],StoreRegs [1, 3]);
  406.   GetVgaRegister (Bg, StoreRegs [2, 1], StoreRegs [2, 2],StoreRegs [2, 3]);
  407.  
  408.   new (ScreenRow);                               { allocate memory }
  409.   for Loop := 1 to ScreenHeight do
  410.     ReadAttribute                                { read screen attrs }
  411.       (ScreenWidth, Loop, 1, ScreenRow^ [Loop]);
  412.   AttrStr := CharStr (chr (LightGray), ScreenWidth);
  413.   for Loop := 1 to ScreenHeight do               { write White text }
  414.     WriteAttribute (AttrStr, Loop, 1);
  415.  
  416.   SetVgaRegister (Fg, 63, 63, 63);               { fg turns white }
  417.   Delay (150);                                   { pause }
  418.   R1 := 63;  G1 := 63;  B1 := 63;
  419.   SetVgaRegister
  420.     (Bg, round (R1), round (G1), round(B1));     { bg turns white }
  421.   delay (150);                                   { a bright white flash }
  422.  
  423.   for Loop := 1 to 400 do begin                  { first shock wave }
  424.     sound (random (1000));
  425.     delay (1);
  426.     end;
  427.   nosound;
  428.   delay (50);
  429.  
  430.   Factor := 15;
  431.   R2 := 63;  G2 := 55;  B2 := 30;
  432.   for Loop := 1 to Factor do begin               { second shock wave }
  433.     for X := 1 to 20 do begin
  434.       sound (random (1000));
  435.       delay (1);
  436.       end;
  437.     if R1 > R2 then R1 := R1 - R1/Factor;
  438.     if G1 > G2 then G1 := G1 - G1/Factor;
  439.     if B1 > B2 then B1 := B1 - B1/Factor;
  440.     SetVgaRegister
  441.       (Bg, round (R1), round (G1), round(B1));  { black bg is white }
  442.     end;
  443.  
  444.   Factor := 5;
  445.   R2 := 63;  G2 := 50;  B2 := 0;
  446.   for Loop := 1 to Factor do begin               { second shock wave }
  447.     for X := 1 to 20 do begin
  448.       sound (random (1000));
  449.       delay (1);
  450.       end;
  451.     if R1 > R2 then R1 := R1 - R1/Factor;
  452.     if G1 > G2 then G1 := G1 - G1/Factor;
  453.     if B1 > B2 then B1 := B1 - B1/Factor;
  454.     SetVgaRegister
  455.       (Bg, round (R1), round (G1), round(B1));  { black bg is white }
  456.     end;
  457.  
  458.   Factor := 10;
  459.   R2 := 63;  G2 := 0;  B2 := 0;
  460.   for Loop := 1 to Factor do begin               { second shock wave }
  461.     for X := 1 to 20 do begin
  462.       sound (random (1000));
  463.       delay (1);
  464.       end;
  465.     if R1 > R2 then R1 := R1 - R1/Factor;
  466.     if G1 > G2 then G1 := G1 - G1/Factor;
  467.     if B1 > B2 then B1 := B1 - B1/Factor;
  468.     SetVgaRegister
  469.       (Bg, round (R1), round (G1), round(B1));  { black bg is white }
  470.     end;
  471.  
  472.   for Loop := 100 to 999 do begin                { the diminishing sound }
  473.     for x := 1 to 2 do begin
  474.       sound (random (1000 - Loop));
  475.       delay (1);
  476.       if Loop mod 30 = 0 then begin
  477.         R1 := 45 + Random (9);  G1 := 20 + Random (15);  B1 := Random (10);
  478.         SetVgaRegister (Bg, round (R1), round (G1), round (B1));
  479.         SetVgaRegister (Fg, 30 + Random (33), Random (33), Random (10));
  480.         end;
  481.       end;
  482.     end;
  483.  
  484.   Factor := 7;
  485.   R2 := 0;  G2 := 0;  B2 := 0;
  486.   for Loop := 925 to 999 do begin                { the echo }
  487.     sound (random (1000 - Loop));
  488.     delay (1);
  489.     if Loop mod 5 = 0 then begin
  490.       if R1 > R2 then R1 := R1 - R1/Factor;
  491.       if G1 > G2 then G1 := G1 - G1/Factor;
  492.       if B1 > B2 then B1 := B1 - B1/Factor;
  493.       SetVgaRegister
  494.         (Bg, round (R1), round (G1), round (B1));     { random Bg colors }
  495.       end;
  496.     end;
  497.  
  498.   SetVgaRegister (Fg, StoreRegs [1, 1], StoreRegs [1, 2],StoreRegs [1, 3]);
  499.   SetVgaRegister (Bg, StoreRegs [2, 1], StoreRegs [2, 2],StoreRegs [2, 3]);
  500.   for Loop := 1 to ScreenHeight do
  501.     WriteAttribute (ScreenRow^ [Loop], Loop, 1);
  502.   nosound;
  503.   dispose (ScreenRow);
  504. END;
  505.  
  506. { ========================================================================= }
  507. { ========================================================================= }
  508. { Initialization ========================================================== }
  509.  
  510. { No initialization needed. }
  511. END.
  512.  
  513. { ========================================================================= }
  514. { ========================================================================= }
  515.  
  516. VERSION HISTORY:
  517.   9005.05
  518.     Completely restructured for consistency with Object Professional.
  519.  
  520.   9005.07
  521.     Added sound toggles for use with DgKbd unit.  Allows procedures to
  522.     be stored in AltProcArray.
  523.  
  524.   9006.01
  525.     Added Bomb object.
  526.  
  527. { ========================================================================= }
  528.  
  529. NEED:
  530.   Chimes for hourly clock instead of beep-boop.
  531.  
  532.  
  533. { ========================================================================= }
  534.  
  535.  
  536.  
  537. (*
  538.  
  539. EXTRA NOISES
  540.   Not yet included.
  541.  
  542. { IndustrialGrindNoise ==================================================== }
  543.  
  544. PROCEDURE IndustrialGrindNoise;
  545. BEGIN
  546.   Noise (100, 50, 1, 15, 5, 100);
  547. END;
  548.  
  549. { RisingTones ============================================================= }
  550.  
  551. PROCEDURE RisingTones;
  552. BEGIN
  553.   Noise (100, 250, 10, 50, 3, 100);
  554. END;
  555.  
  556. { Boink Boink ============================================================= }
  557.  
  558. PROCEDURE BoinkBoink;
  559. BEGIN
  560.   Noise (2000, 250, 50, 5, 2, 100);
  561. END;
  562.  
  563. { BouncyNoise ============================================================= }
  564.  
  565. PROCEDURE BouncyNoise;
  566. BEGIN
  567.   Noise (50, 2500, 50, 5, 4, 50);
  568. END;
  569.  
  570. { LaserChirp ============================================================== }
  571.  
  572. PROCEDURE LaserChirp;
  573. BEGIN
  574.   Noise (4000, 1000, 150, 3, 3, 50);
  575.   Noise (1000, 4000, 150, 3, 3, 50);
  576. END;
  577.  
  578. { ChirpChirpFlammadiddle ================================================== }
  579.  
  580. PROCEDURE ChirpChirpFlammadiddle;
  581. BEGIN
  582.   Noise (1000, 6000, 100, 3, 3, 50);
  583.   Noise (4000, 250, 80, 3, 2, 75);
  584.   Noise (50, 5500, 133, 4, 2, 25);
  585.   Noise (2000, 1000, 60, 3, 3, 50);
  586. END;
  587.  
  588. { IndustrialAlarm ========================================================= }
  589.  
  590. PROCEDURE IndustrialAlarm;
  591. BEGIN
  592.   Noise (2000, 2400, 2, 2, 2, 50);
  593. END;
  594.  
  595. { ========================================================================= }
  596.  
  597. *)
  598.  
  599.  
  600.  
  601.