home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / PASHSC11.ZIP / PLAYHSC.PAS < prev    next >
Pascal/Delphi Source File  |  1994-05-24  |  12KB  |  409 lines

  1. UNIT PLAYHSC;
  2.  
  3. (*
  4.                            HSC Player Unit V1.1
  5.                            --------------------
  6.  
  7.   Written in 1994 by GLAMOROUS RAY^RADiCAL RHYTHMS
  8.   Original code and .OBJ by CHiCKEN and ZWERG ZWACK^ELECTRONiC RATS
  9.  
  10.   This code is FREE WARE. This means that you can copy and distribute it
  11.   as you like, but you may not charge any money for its distribution. If
  12.   you intend to use this code in a commercial product then you have to
  13.   get written permission from NEO Software Produktions GmbH Austria.
  14.  
  15.  
  16.   Introduction:
  17.   -------------
  18.  
  19.   What is PLAYHSC? This unit is intended for use with the HSC tracker
  20.   written by Zwerg Zwack and Chicken on low level support from NEO
  21.   Software <g>.
  22.  
  23.   This unit supports an easy and fast to use way to play sound, so
  24.   not all general functions of the player are included. It is not
  25.   possible to do the polling - this is done by the player automatically,
  26.   it links into the timer interrupt.
  27.  
  28.  
  29.   General overview:
  30.   -----------------
  31.  
  32.   Below follows a description how to play sound files from your program,
  33.   calling this unit. There are two ways:
  34.  
  35.   1st: Play a sound file, loading from disk
  36.   2nd: Play a sound file, directly from included data.
  37.  
  38.   The first method is very easy and simple, the second one more
  39.   cool ;).
  40.  
  41.   The player is build up as an object, so it is initialized on your heap
  42.   when starting and deinstalled when finishing. Please note that the
  43.   player does _no_ check for memory. So it's up to you to check if there's
  44.   enough memory (heap) free to load the music - the player won't just do
  45.   anything in that case.
  46.  
  47.   To get the object to work, you have to declare it as a variable. This
  48.   is normally done this way:
  49.  
  50.   VAR
  51.     Music : HSC_obj;
  52.  
  53.   Now the object is declared and has to be used and called by _you_.
  54.   An object's variables and procedures a called like a record so you
  55.   can do the following:
  56.  
  57.   Music.Init(0);
  58.   Music.Done;
  59.  
  60.  
  61.   Software implementation:
  62.   ------------------------
  63.  
  64.   CONSTRUCTOR HSC_obj.Init (AdlibAddress : WORD);
  65.   -> Init the player and the object. You must supply a base address for
  66.      the adlib card. If you want to use the player's autodetection
  67.      routines, simply use 0 as the base.
  68.  
  69.   PROCEDURE HSC_Obj.Start;
  70.   -> Start music file, located at HSC_Obj.Address. The address is
  71.      set by either HSC_Obj.LoadMem or HSC_Obj.LoadFile;
  72.  
  73.   FUNCTION HSC_Obj.LoadFile (FileName):BOOLEAN;
  74.   -> Load a file from disk into memory. If the file you tend to load
  75.      is invalid or simply not there, the player won't play a single
  76.      voice. The function returns if it has loaded the music or not. If
  77.      not, there maybe was not enough memory or the file could not be
  78.      loaded (due to non-existence etc.).
  79.  
  80.   PROCEDURE HSC_Obj.LoadMem (Music_Address : Pointer);
  81.   -> "Load" music from disk. This has to be done to tell the player
  82.      that the music is _not_ loaded from disk so the memory is not freed
  83.      up when playing the next file.
  84.  
  85.   PROCEDURE HSC_Obj.GetInfo;
  86.   -> Store player information in HSC_Obj.Info. Please see section
  87.      "Player information" below for further information.
  88.  
  89.   PROCEDURE HSC_Obj.Stop;
  90.   -> Stop music (if playing). This has to be done if you want to stop
  91.      the music. If you want to unload the music, simplay call HSC_Obj.Done
  92.      as this (of course) stops the music, too!
  93.  
  94.   PROCEDURE HSC_Obj.Fade;
  95.   -> Fade out music. This takes up to 4 seconds, so be sure to wait
  96.      in you program for fade-out, otherwise you will "kill" the sound
  97.      when calling HSC_Obj.Done (this will do a very nasty "pop").
  98.  
  99.   DESTRUCTOR HSC_Obj.Done;
  100.   -> Deinit object <g>. This frees up all memory allocated and stops
  101.      the music.
  102.  
  103.  
  104.   Hints & Tips section:
  105.   ---------------------
  106.  
  107.   Make sure your program does not exit without calling the destructor
  108.   or at least stopping the music. If you don't stop the music, your
  109.   system will hang on loading a new program (This is because of the
  110.   memory usage - the player still plays while the memory is already
  111.   freed up and used by another program - "Zack!"). It is a wise idea
  112.   to put the command into the @Exitproc.
  113.  
  114.   If you want to play more than one music file - okay - do it! ;)
  115.  
  116.  
  117.   Examples:
  118.   ---------
  119.  
  120.   Please see the enclosed file TSTHSC.PAS for more information.
  121.  
  122.  
  123.   Including music into .EXE files:
  124.   --------------------------------
  125.  
  126.   All you need for doing this, is your sound file (*.HSC) and the
  127.   program BINOBJ.EXE which came with your pascal package. Run the
  128.   program like this:
  129.  
  130.   BINOBJ.EXE MUSIC.HSC MUSIC.OBJ MUSIC_DATA
  131.  
  132.   This converts the file MUSIC.HSC into MUSIC.OBJ with the public name
  133.   set to MUSIC_DATA. Now all you have to do is to declare this object
  134.   file within you program. This has to be done like this:
  135.  
  136.   {$F+}
  137.   {$L MUSIC.OBJ}
  138.   PROCEDURE MUSIC_DATA; EXTERNAL;
  139.   {$F-}
  140.  
  141.   To play this file, try:
  142.  
  143.   HSC_Obj.LoadMem (@MUSIC_DATA);
  144.  
  145.   That's it!
  146.  
  147.  
  148.   Player information:
  149.   -------------------
  150.  
  151.   The structure of the array HSC_Obj.Info is:
  152.  
  153.   offset  bytes
  154.  
  155.      0      9       current notes (1 byte per channel)
  156.      9      9       current instruments
  157.     18      9       equalizer value (ffh-0fh)
  158.     27      9       equalizer peaks (ffh = peak)
  159.  
  160.     36      1       current pattern
  161.     37      1       current track
  162.     38      1       current position
  163.     39      1       play on/off (0/1)
  164.  
  165.   Please make sure to call HSC_Obj.GetInfo before analysing the data,
  166.   otherwise, the information stored in HSC_Obj.Info is not up to date
  167.   or even wrong!
  168.  
  169.  
  170.   Last words:
  171.   -----------
  172.  
  173.   First, I'd like to comment on my code. I hope, you're able to under-
  174.   stand this mess <g>. Second, don't bother me for the way it was
  175.   written. I just know: it works. And it will work on other machines
  176.   because it is written _cleanly_. If you think, you can do better:
  177.   please do! (And send me a copy! :)) )
  178.  
  179.   Greetings go to all RADiCAL RHYTHMS members for being an amazing posse.
  180.   Last, but not least, thanks to Chicken and Zwerg Zwack for their really
  181.   neat program. A small "Knick knack!" to the D-LUSiON Crew!
  182.  
  183.   If you find any bugs, or have ideas for add-ons, please contact me:
  184.  
  185.   via modem : The UnderCover BBS - +49 2323 450 850
  186.              (9600+, 8N1)
  187.  
  188.   via fido  : Christian Bartsch@2:2445/321.49 (classic)
  189.  
  190.   via phone : +49 2323 460 525
  191.  
  192.  
  193.   May, 24th 1994 - GLAMOROUS RAY! C U in cyberspace...
  194.  
  195.  
  196.   History:
  197.   --------
  198.  
  199.   Version 1.1 - fixed little bug in HSC_Obj.LoadFile which caused to
  200.                 memory if the requested file was not found. (Music_Load
  201.                 was set to false tough!). Fixed. Fixed a bug in the
  202.                 Adlib detection routine (it always used 0 for the
  203.                 default, regardless of the address setting. So the
  204.                 autodetection was used anyway (huh, that was a nasty
  205.                 one! ;) ). Fixed.
  206.  
  207.                 Added HSC_Obj.Getinfo for people who tend to show
  208.                 more details on screen!
  209. *)
  210.  
  211. INTERFACE
  212.  
  213. TYPE
  214.   HSC_obj = OBJECT
  215.  
  216.     (* The following variables are _internal_ variables and should not be *)
  217.     (* changed from outside!                                              *)
  218.  
  219.     Address    : Pointer;
  220.     Music_Load : BOOLEAN;
  221.     Music_Size : LONGINT;
  222.     Music_Run  : BOOLEAN;
  223.     Music_Fade : BOOLEAN;
  224.  
  225.     (* The following procedures/functions are for your use. Please read  *)
  226.     (* the information above on how to use them!                         *)
  227.  
  228.     Info : ARRAY [0..39] OF BYTE; (* See "Player information" above for  *)
  229.                                   (* further information!                *)
  230.  
  231.     CONSTRUCTOR Init (AdlibAddress : WORD);
  232.     PROCEDURE Start;
  233.     PROCEDURE Stop;
  234.     PROCEDURE Fade;
  235.     PROCEDURE LoadMem (Music_Address : Pointer);
  236.     FUNCTION LoadFile (FileName : STRING):BOOLEAN;
  237.     PROCEDURE GetInfo;
  238.     DESTRUCTOR Done;
  239.  
  240.   END;
  241.  
  242. IMPLEMENTATION
  243.  
  244. USES CRT;
  245.  
  246.  
  247.  
  248. (*-------------------------------------------------------------------------*)
  249. (*                  SECTION: Sub-routines used by HSC_obj                  *)
  250. (*-------------------------------------------------------------------------*)
  251.  
  252.  
  253.  
  254. {$F+}                               (* Include                         *)
  255. {$L HSCOBJ.OBJ}                     (*        external                 *)
  256. PROCEDURE _HscPlayer; EXTERNAL;     (*                  player         *)
  257. {$F-}                               (*                          object *)
  258.  
  259. FUNCTION  DetectAdlib (SuggestedPort : WORD) : WORD; ASSEMBLER;
  260.   ASM
  261.     MOV  AH,4
  262.     MOV  BX,SuggestedPort
  263.     CALL _HscPlayer
  264.     JNC  @GoOn
  265.     MOV  AX,0FFh
  266.   @GoOn:
  267.   END;
  268.  
  269. PROCEDURE GetPlayerState (VAR Destination); ASSEMBLER;
  270.   ASM
  271.     MOV  AH,7
  272.     LES  SI,DWORD PTR Destination
  273.     CALL _HscPlayer
  274.   END;
  275.  
  276. PROCEDURE StartMusic (Song : POINTER; Polling, OldIRQ : BOOLEAN); ASSEMBLER;
  277.   ASM
  278.     MOV  AH,0
  279.     MOV  BL,Polling
  280.     MOV  BH,OldIRQ
  281.     CMP  BH,1
  282.     JE   @Invert
  283.     MOV  BH,1
  284.     JMP  @GoOn
  285.   @Invert:
  286.     XOR  BH,BH
  287.   @GoOn:
  288.     LES  SI,DWORD PTR Song
  289.     CALL _HscPlayer
  290.   END;
  291.  
  292. PROCEDURE StopMusic; ASSEMBLER;
  293.   ASM
  294.     MOV  AH,2
  295.     CALL _HscPlayer
  296.   END;
  297.  
  298.  
  299.  
  300. (*-------------------------------------------------------------------------*)
  301. (*                      SECTION: HSC_obj implementation                    *)
  302. (*-------------------------------------------------------------------------*)
  303.  
  304.  
  305.  
  306. CONSTRUCTOR HSC_obj.Init (AdlibAddress : WORD);
  307. VAR
  308.   Dummy : WORD;
  309. BEGIN
  310.   Music_Load := FALSE;
  311.   Music_Run  := FALSE;
  312.   Music_Fade := FALSE;
  313.   Address    := NIL;
  314.  
  315.   Dummy := DetectAdlib (AdlibAddress);
  316.   Delay (30);
  317. END;
  318.  
  319. PROCEDURE HSC_obj.Start;
  320. BEGIN
  321.   IF NOT Music_Run THEN BEGIN
  322.     IF Address <> NIL THEN BEGIN
  323.       StartMusic (Address,FALSE,TRUE);
  324.       Music_Run := TRUE;
  325.     END;
  326.   END;
  327. END;
  328.  
  329. PROCEDURE HSC_obj.Stop;
  330. BEGIN
  331.   IF Music_Run THEN BEGIN
  332.     StopMusic;
  333.     Music_Run := FALSE;
  334.   END;
  335. END;
  336.  
  337. PROCEDURE HSC_obj.Fade;
  338. BEGIN
  339.   IF Music_Run THEN BEGIN
  340.     ASM
  341.       MOV  AH,3
  342.       CALL _HscPlayer
  343.     END;
  344.     Music_Fade := TRUE;
  345.     Music_Run  := FALSE;
  346.   END;
  347. END;
  348.  
  349. PROCEDURE HSC_Obj.LoadMem (Music_Address : Pointer);
  350. BEGIN
  351.   IF Music_Fade or Music_Run THEN BEGIN
  352.     StopMusic;
  353.     Music_Run  := FALSE;
  354.     Music_Fade := FALSE;
  355.     IF Music_Load THEN FreeMem (Address,Music_Size);
  356.   END;
  357.   Music_Load := FALSE;
  358.   Address    := Music_Address;
  359. END;
  360.  
  361. FUNCTION HSC_Obj.LoadFile (Filename : STRING):BOOLEAN;
  362. VAR
  363.   f : FILE;
  364. BEGIN
  365.   IF FileName <> '' THEN BEGIN
  366.     Assign (F,FileName);
  367.     {$I-} RESET (F,1); {$I+}
  368.   END;
  369.  
  370.   IF (IORESULT <> 0) OR (FileName = '') THEN BEGIN
  371.     LoadFile   := FALSE;
  372.   END ELSE BEGIN
  373.     IF Music_Fade or Music_Run THEN BEGIN
  374.       StopMusic;
  375.       Music_Run  := FALSE;
  376.       Music_Fade := FALSE;
  377.       IF Music_Load THEN FreeMem (Address,Music_Size);
  378.     END;
  379.     Music_Size := FileSize (F);
  380.     IF MaxAvail < Music_Size THEN BEGIN
  381.       LoadFile   := FALSE;
  382.       Music_Load := FALSE;
  383.     END ELSE BEGIN
  384.       GetMem (Address,Music_Size);
  385.       BlockRead (f,Address^,Music_Size);
  386.       LoadFile   := TRUE;
  387.       Music_Load := TRUE;
  388.     END;
  389.   Close (f);
  390.   END;
  391. END;
  392.  
  393. PROCEDURE HSC_Obj.GetInfo;
  394. BEGIN
  395.   GetPlayerState (Info);
  396. END;
  397.  
  398. DESTRUCTOR HSC_obj.Done;
  399. BEGIN
  400.   IF Music_Run OR Music_Fade THEN StopMusic;
  401.   IF Music_Load THEN FREEMEM (Address,Music_Size);
  402. END;
  403.  
  404. END.
  405.  
  406. (*-------------------------------------------------------------------------*)
  407. (*                         SECTION: END OF FILE ;)                         *)
  408. (*-------------------------------------------------------------------------*)
  409.