home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / BATTLE.ZIP / INSTALL.ZIP / SOUND.C < prev    next >
C/C++ Source or Header  |  1996-05-02  |  13KB  |  604 lines

  1.  
  2. // SOUND.C - Library Module
  3.  
  4. // I N C L U D E S ///////////////////////////////////////////////////////////
  5.  
  6. #include <io.h>
  7. #include <conio.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <dos.h>
  11. #include <bios.h>
  12. #include <fcntl.h>
  13. #include <memory.h>
  14. #include <malloc.h>
  15. #include <math.h>
  16. #include <string.h>
  17. #include <share.h>
  18.  
  19. #include "sound.h"
  20.  
  21.  
  22.  
  23. // F U N C T I O N S /////////////////////////////////////////////////////////
  24. /*
  25. void Time_Delay(int clicks)
  26. {
  27. // this function uses the internal timer to wait a specified number of "clicks"
  28. // the actual amount of real time is the number of clicks * (time per click)
  29. // usually the time per click is set to 1/18th of a second or 55ms
  30.  
  31. long far *clock = (long far *)0x0000046CL; // address of timer
  32.  
  33. long start_time; // starting time
  34.  
  35. // get current time
  36.  
  37. start_time = *clock;
  38.  
  39. // when the current time minus the starting time >= the requested delay then
  40. // the function can exit
  41.  
  42. while(labs(*clock - start_time) < (long)clicks){}
  43.  
  44. } // end Time_Delay
  45. */
  46.  
  47. ///////////////
  48.  
  49. int Sound_Load(char *filename, sound_ptr the_sound, int translate)
  50. {
  51. // this function will load a sound from disk into memory and pre-format
  52. // it in preparation to be played
  53.  
  54. unsigned char far *temp_ptr;   // temporary pointer used to load sound
  55. unsigned char far *sound_ptr;  // pointer to sound data
  56.  
  57. unsigned short segment,          // segment of sound data memory
  58.              paragraphs,       // number of 16 byte paragraphs sound takes up
  59.              size_of_file,     // the total size of the VOC file in bytes
  60.              header_length;    // the length of the header portion of VOC file
  61.              
  62. unsigned bytes_read;      // used to track numbr of bytes read by DOS
  63.  
  64.  
  65. int sound_handle;              // DOS file handle
  66.  
  67.  
  68. // open the sound file, use DOS file and memory allocation to make sure
  69. // memory is on a 16 byte or paragraph boundary
  70.  
  71. if (_dos_open(filename, _O_RDONLY, &sound_handle)!=0)
  72.    {
  73.    printf("\nSound System - Couldn't open %s",filename);
  74.    return(0);
  75.  
  76.    } // end if file not found
  77.  
  78. // compute number of paragraphs that sound file needs
  79.  
  80. size_of_file = filelength(sound_handle);
  81.  
  82. paragraphs = 1 + (size_of_file)/16;
  83.  
  84. // allocate the memory on a paragraph boundary
  85.  
  86. _dos_allocmem(paragraphs,&segment);
  87.  
  88. // point data pointer to allocated data area
  89. sound_ptr = (unsigned char far *) MK_FP (segment, 0x0);
  90. /*
  91. FP_SEG(sound_ptr) = segment;
  92. FP_OFF(sound_ptr) = 0;
  93. */
  94. // alias pointer to memory storage area
  95.  
  96. temp_ptr = sound_ptr;
  97.  
  98. // read in blocks of 16k until file is loaded
  99.  
  100. do
  101.  {
  102.  // load next block
  103.  
  104.  _dos_read(sound_handle, temp_ptr, 0x4000, &bytes_read);
  105.  
  106.  // adjust pointer
  107.  
  108.  temp_ptr += bytes_read;
  109.  
  110.  } while(bytes_read==0x4000);
  111.  
  112. // close the file
  113.  
  114. _dos_close(sound_handle);
  115.  
  116. // make sure it's a voc file, test for "Creative"
  117.  
  118. if ((sound_ptr[0] != 'C') || (sound_ptr[1] != 'r'))
  119.    {
  120.  
  121.    printf("\n%s is not a VOC file!",filename);
  122.  
  123.    // de-allocate the memory
  124.  
  125.    _dos_freemem(FP_SEG(sound_ptr));
  126.  
  127.    // return failure
  128.  
  129.    return(0);
  130.  
  131.    } // end if voc file
  132.  
  133.    // compute start of sound data;
  134.  
  135.    header_length = (unsigned int)sound_ptr[20];
  136.  
  137.    // point buffer pointer to start of VOC file in memory
  138.  
  139.    the_sound->buffer       = sound_ptr;
  140.  
  141.    // set up the SNDSTRUC for DIGIPAK
  142.  
  143.    the_sound->SS.sound     = (unsigned char far*)(sound_ptr+header_length+4);
  144.  
  145.    the_sound->SS.sndlen    = (unsigned short)(size_of_file - header_length);
  146.  
  147.    the_sound->SS.IsPlaying = (short far *)&the_sound->status;
  148.  
  149.    the_sound->SS.frequency = (short)((long)(-1000000) /
  150.                                 ((int)sound_ptr[header_length+4]-256));
  151.  
  152.    // now format data for sound card if requested
  153.  
  154.    if (translate)
  155.        Sound_Translate(the_sound);
  156.  
  157. // return success
  158.  
  159. return(1);
  160.  
  161. } // end Sound_Load
  162.  
  163. //////////////////////////////////////////////////////////////////////////////
  164.  
  165. void Sound_Unload(sound_ptr the_sound)
  166. {
  167.  
  168. // this functions deletes the sound from memory
  169.  
  170. _dos_freemem(FP_SEG(the_sound->buffer));
  171.  
  172. the_sound->buffer=NULL;
  173.  
  174. } // end Sound_Unload
  175.  
  176. //////////////////////////////////////////////////////////////////////////////
  177.  
  178. void Sound_Translate(sound_ptr the_sound)
  179. {
  180. // this function calls the DIGIPAK function massage audio to translate
  181. // the raw audio data into the proper format for the sound card that
  182. // the sound system is running on.
  183.  
  184. static unsigned char far *buffer;
  185.  
  186. #pragma aux call_DIGIPAK = \
  187.    "push ds"  \
  188.    "push si"  \
  189.    "mov ax, 068Ah" \
  190.    "lds si, buffer" \
  191.    "int 66h" \
  192.    "pop si" \
  193.    "pop ds"  \
  194.    modify [ax];
  195.  
  196. buffer = (unsigned char far*) &the_sound->SS;
  197.  
  198. call_DIGIPAK();
  199.  
  200.  
  201. ///// CALL DIGIPAK PRAGMA //////////////////
  202.  
  203. }
  204.  
  205. /*_asm
  206.    {
  207.    push ds         ; save DS and SI on stack
  208.    push si
  209.    mov ax, 068Ah   ; function 3: MassageAudio
  210.    lds si, buffer  ; move address of sound in DS:SI
  211.    int 66h         ; call DIGIPAK
  212.    pop si          ; restore DS and SI from stack
  213.    pop ds
  214.  
  215.    } // end inline assembly
  216.  
  217. } // end Sound_Translate
  218. */
  219. ///////////////////////////////////////////////////////////////////////////////
  220.  
  221. void Sound_Play(sound_ptr the_sound)
  222. {
  223. // ths function will the sound pointed to in the sent sound structure
  224.  
  225. unsigned char far *buffer;
  226.  
  227. #pragma aux call_DIGIPAK2 = \
  228.    "push ds"  \
  229.    "push si"  \
  230.    "mov ax, 068Bh" \
  231.    "lds si, buffer" \
  232.    "int 66h" \
  233.    "pop si"  \
  234.    "pop ds"  \
  235.    modify [ax];
  236.  
  237. buffer = (unsigned char far*)&the_sound->SS;
  238.  
  239. call_DIGIPAK2();
  240.  
  241. ///// CALL DIGIPAK PRAGMA //////////////////
  242.  
  243.  
  244. }
  245. /*
  246. _asm
  247.    {
  248.    push ds         ; save DS and SI on stack
  249.    push si
  250.    mov ax, 068Bh   ; function 4: DigPlay2
  251.    lds si, buffer  ; move address of sound in DS:SI
  252.    int 66h         ; call DIGIPAK
  253.    pop si          ; restore DS and SI from stack
  254.    pop ds
  255.  
  256.    } // end inline assembly
  257.  
  258. } // end Sound_Play
  259. */
  260. //////////////////////////////////////////////////////////////////////////////
  261.  
  262.  
  263.  
  264.  
  265. int Sound_Status(void)
  266. {
  267. // this function will return the status of DIGIPAK i.e. is a sound playing
  268. // or not
  269.  
  270. int return_value; //this gets the return value from the pragma
  271.  
  272. #pragma aux da_sound_status = \
  273.    "mov ax, 0689h"   \
  274.    "int 66h"    \
  275.    value [ax]  \
  276.    modify [ax];
  277.  
  278. return_value = da_sound_status();
  279.  
  280. /*_asm
  281.    {
  282.    mov ax, 0689h   ; function 2: SoundStatus
  283.    int 66h         ; call DIGIPAK
  284.  
  285.    } // end inline assembly
  286.  
  287. // on exit AX will be used as the return value, if 1 then a sound is playing
  288. // 0 if a sound is not playing
  289. */
  290. return return_value;
  291. } // end Sound_Status
  292.  
  293. //////////////////////////////////////////////////////////////////////////////
  294.  
  295. void Sound_Stop(void)
  296. {
  297.  
  298. #pragma aux stoppit_pleeez = \
  299.    "mov ax, 068Fh"   \
  300.    "int 66h"    \
  301.    modify [ax];
  302.  
  303. stoppit_pleeez();
  304. }
  305. /*
  306. {
  307. // this function will stop a currently playing sound
  308.  
  309. _asm
  310.    {
  311.    mov ax, 068Fh   ; function 8: StopSound
  312.    int 66h         ; call DIGIPAK
  313.  
  314.    } // end inline assembly
  315.  
  316. } // end Sound_Stop
  317. */
  318. //////////////////////////////////////////////////////////////////////////////
  319.  
  320. int Music_Load(char *filename, music_ptr the_music)
  321. {
  322. // this function will load a xmidi file from disk into memory and register it
  323.  
  324. unsigned char far *temp_ptr;   // temporary pointer used to load music
  325. unsigned char far *xmidi_ptr;   // pointer to xmidi data
  326.  
  327. unsigned int paragraphs,       // number of 16 byte paragraphs music takes up
  328.              bytes_read;       // used to track numbr of bytes read by DOS
  329.  
  330. unsigned short segment;          // segment of music data memory
  331.                            
  332. long         size_of_file;     // the total size of the xmidi file in bytes
  333.  
  334. int xmidi_handle;              // DOS file handle
  335.  
  336. // open the extended xmidi file, use DOS file and memory allocation to make sure
  337. // memory is on a 16 byte or paragraph boundary
  338.  
  339. if (_dos_open(filename, _O_RDONLY, &xmidi_handle)!=0)
  340.    {
  341.    printf("\nMusic System - Couldn't open %s",filename);
  342.    return(0);
  343.  
  344.    } // end if file not found
  345.  
  346. // compute number of paragraphs that sound file needs
  347.  
  348. size_of_file = filelength(xmidi_handle);
  349.  
  350. paragraphs = 1 + (size_of_file)/16;
  351.  
  352. // allocate the memory on a paragraph boundary
  353.  
  354. _dos_allocmem(paragraphs, &segment);
  355.  
  356. // point data pointer to allocated data area
  357. xmidi_ptr = (unsigned char far *) MK_FP (segment, 0x0);
  358. /*
  359. FP_SEG(xmidi_ptr) = segment;
  360. FP_OFF(xmidi_ptr) = 0;
  361. */
  362. // alias pointer to memory storage area
  363.  
  364. temp_ptr = xmidi_ptr;
  365.  
  366. // read in blocks of 16k until file is loaded
  367.  
  368. do
  369.  {
  370.  // load next block
  371.  
  372.  _dos_read(xmidi_handle,temp_ptr, 0x4000, &bytes_read);
  373.  
  374.  // adjust pointer
  375.  
  376.  temp_ptr += bytes_read;
  377.  
  378.  } while(bytes_read==0x4000);
  379.  
  380. // close the file
  381.  
  382. _dos_close(xmidi_handle);
  383.  
  384. // set up the music structure
  385.  
  386. the_music->buffer = xmidi_ptr;
  387. the_music->size   = size_of_file;
  388. the_music->status = 0;
  389.  
  390. // now register the xmidi file with MIDIPAK
  391.  
  392. if ((the_music->register_info = Music_Register(the_music))==XMIDI_UNREGISTERED)
  393.    {
  394.    // delete the memory
  395.  
  396.    Music_Unload(the_music);
  397.  
  398.    // return an error
  399.  
  400.    return(0);
  401.  
  402.    } // end if couldn't register xmidi file
  403.  
  404. // else return success
  405.  
  406. return(1);
  407.  
  408. } // end Music_Load
  409.  
  410. /////////////////////////////////////////////////////////////////////////////
  411.  
  412. void Music_Unload(music_ptr the_music)
  413. {
  414.  
  415. // this functions deletes the xmidi file data from memory
  416.  
  417. _dos_freemem(FP_SEG(the_music->buffer));
  418.  
  419. the_music->buffer=NULL;
  420.  
  421. } // end Music_Unload
  422.  
  423. ///////////////////////////////////////////////////////////////////////////////
  424.  
  425. int Music_Register(music_ptr the_music)
  426. {
  427.  
  428. // this function registers the xmidi music with MIDIPAK, so that it can be
  429. // played
  430. int register_info;
  431.  
  432. static unsigned int xmid_off,   // offset and segment of midi file
  433.              xmid_seg,
  434.              length_low, // length of midi file in bytes
  435.              length_hi;
  436.  
  437.  
  438. #pragma aux call_MIDIPAK = \
  439.    "push di"  \
  440.    "push si"  \
  441.    "mov ax, 704h" \
  442.    "mov bx, xmid_off" \
  443.    "mov cx, xmid_seg"  \
  444.    "mov si, length_low"  \
  445.    "mov di, length_hi" \
  446.    "int 66h"  \
  447.    "pop si"  \
  448.    "pop di"  \
  449.    value [ax]  \
  450.    modify [ax bx cx];
  451.  
  452. // extract segment and offset of music buffer
  453.  
  454. xmid_off = FP_OFF((the_music->buffer));
  455. xmid_seg = FP_SEG((the_music->buffer));
  456.  
  457. // extract the low word and high word of xmidi file length
  458.  
  459. length_low = the_music->size;
  460. length_hi  = (the_music->size) >> 16;
  461.  
  462. register_info = call_MIDIPAK();
  463.  
  464. // call MIDIPAK
  465.  
  466. /*
  467. _asm
  468.    {
  469.    push si           ; save si and di
  470.    push di
  471.  
  472.    mov ax,704h       ; function #5: RegisterXmidi
  473.  
  474.    mov bx,xmid_off   ; offset of xmidi data
  475.  
  476.    mov cx,xmid_seg   ; segment of xmidi data
  477.  
  478.    mov si,length_low ; low word of xmidi length
  479.    mov di,length_hi  ; hi word of xmidi length
  480.  
  481.    int 66h           ; call MIDIPAK
  482.    pop di            ; restore si and di
  483.    pop si
  484.  
  485.    } // end inline assembly
  486.  
  487. // return value will be in AX
  488.  
  489. } // end Music_Register
  490. */
  491.  
  492. return register_info;
  493. }
  494. ///////////////////////////////////////////////////////////////////////////////
  495.  
  496. void Music_Stop(void)
  497. {
  498.  
  499.  
  500. #pragma aux stop_da_music = \
  501.         "mov ax, 705h"  \
  502.         "int 66h"  \
  503.         modify [ax];
  504.  
  505. stop_da_music();
  506. // this function will stop the song currently playing
  507. /*
  508. _asm
  509.    {
  510.    mov ax,705h    ; function #6: MidiStop
  511.    int 66h        ; call MIDIPAK
  512.  
  513.    } // end inline assembly
  514.  
  515. } // end Music_Stop
  516. */
  517. }
  518. ///////////////////////////////////////////////////////////////////////////////
  519.  
  520. int Music_Play(music_ptr the_music, int sequence)
  521. {
  522. int playing;
  523.  
  524. int tmp_sequence;
  525.  
  526. #pragma aux play_da_music =  \
  527.         "mov ax, 702h"  \
  528.         "mov bx, tmp_sequence"  \
  529.         "int 66h"  \
  530.         value [ax]  \
  531.         modify [ax bx];
  532.  
  533. tmp_sequence = sequence;
  534.  
  535. playing = play_da_music();
  536. // this function plays a xmidi file from memory
  537. /*
  538. _asm
  539.    {
  540.    mov ax,702h        ; function #3: PlaySequence
  541.    mov bx, sequence   ; which sequence to play 0,1,2....
  542.    int 66h            ; call MIDIPAK
  543.  
  544.    } // end inline assembly
  545.  
  546. // return value is in AX, 1 success, 0 sequence not available
  547. */
  548.  
  549. return playing;
  550. } // end Music_Play
  551.  
  552. ///////////////////////////////////////////////////////////////////////////////
  553.  
  554. void Music_Resume(void)
  555. {
  556.  
  557. #pragma aux resume_da_music =  \
  558.         "mov ax, 70Bh"  \
  559.         "int 66h"  \
  560.         modify [ax];
  561.  
  562. resume_da_music();
  563. // this function resumes a previously stopped xmidi sequence
  564. /*
  565. _asm
  566.    {
  567.    mov ax,70Bh        ; function #12: ResumePlaying
  568.    int 66h            ; call MIDIPAK
  569.  
  570.    } // end inline assembly
  571. */
  572.  
  573. } // end Music_Resume
  574.  
  575. ///////////////////////////////////////////////////////////////////////////////
  576.  
  577. int Music_Status(void)
  578. {
  579.  
  580. int saywhat;
  581.  
  582. #pragma aux what_da_music = \
  583.         "mov ax, 70Ch"  \
  584.         "int 66h" \
  585.         value [ax]  \
  586.         modify [ax];
  587.  
  588. saywhat = what_da_music();
  589. // this function returns the status of a playing sequence
  590. /*
  591. _asm
  592.    {
  593.    mov ax,70Ch        ; function #13: SequenceStatus
  594.    int 66h            ; call MIDIPAK
  595.  
  596.    } // end inline assembly
  597.  
  598. // return value is in AX
  599. */
  600. return saywhat;
  601. } // end Music_Status
  602.  
  603.  
  604.