home *** CD-ROM | disk | FTP | other *** search
/ Black Art of 3D Game Programming / Black_Art_of_3D_Game_Programming.iso / source / borland / chap_6 / black6.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-20  |  10.4 KB  |  444 lines

  1.  
  2. // BLACK6.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.  
  18. #include "black6.h"
  19.  
  20. // G L O B A L S  ////////////////////////////////////////////////////////////
  21.  
  22.  
  23.  
  24. // F U N C T I O N S /////////////////////////////////////////////////////////
  25.  
  26. int Sound_Load(char *filename, _sound_ptr the_sound,int translate)
  27. {
  28. // this function will load a sound from disk into memory and pre-format
  29. // it in preparation to be played
  30.  
  31. unsigned char far *temp_ptr;   // temporary pointer used to load sound
  32. unsigned char far *sound_ptr;  // pointer to sound data
  33.  
  34. unsigned int segment,          // segment of sound data memory
  35.              paragraphs,       // number of 16 byte paragraphs sound takes up
  36.              bytes_read,       // used to track numbr of bytes read by DOS
  37.              size_of_file,     // the total size of the VOC file in bytes
  38.              header_length;    // the length of the header portion of VOC file
  39.  
  40. int sound_handle;              // DOS file handle
  41.  
  42.  
  43. // open the sound file, use DOS file and memory allocation to make sure
  44. // memory is on a 16 byte or paragraph boundary
  45.  
  46. if (_dos_open(filename, O_RDONLY, &sound_handle)!=0)
  47.    {
  48.    printf("\nSound System - Couldn't open %s",filename);
  49.    return(0);
  50.  
  51.    } // end if file not found
  52.  
  53. // compute number of paragraphs that sound file needs
  54.  
  55. size_of_file = filelength(sound_handle);
  56.  
  57. paragraphs = 1 + (size_of_file)/16;
  58.  
  59. // allocate the memory on a paragraph boundary
  60.  
  61. _dos_allocmem(paragraphs,&segment);
  62.  
  63. // point data pointer to allocated data area
  64.  
  65. FP_SEG(sound_ptr) = segment;
  66. FP_OFF(sound_ptr) = 0;
  67.  
  68. // alias pointer to memory storage area
  69.  
  70. temp_ptr = sound_ptr;
  71.  
  72. // read in blocks of 16k until file is loaded
  73.  
  74. do
  75.  {
  76.  // load next block
  77.  
  78.  _dos_read(sound_handle,temp_ptr, 0x4000, &bytes_read);
  79.  
  80.  // adjust pointer
  81.  
  82.  temp_ptr += bytes_read;
  83.  
  84.  } while(bytes_read==0x4000);
  85.  
  86. // close the file
  87.  
  88. _dos_close(sound_handle);
  89.  
  90. // make sure it's a voc file, test for "Creative"
  91.  
  92. if ((sound_ptr[0] != 'C') || (sound_ptr[1] != 'r'))
  93.     {
  94.  
  95.    printf("\n%s is not a VOC file!",filename);
  96.  
  97.     // de-allocate the memory
  98.  
  99.    _dos_freemem(FP_SEG(sound_ptr));
  100.  
  101.    // return failure
  102.  
  103.    return(0);
  104.  
  105.    } // end if voc file
  106.  
  107.    // compute start of sound data;
  108.  
  109.    header_length = (unsigned int)sound_ptr[20];
  110.  
  111.     // point buffer pointer to start of VOC file in memory
  112.  
  113.     the_sound->buffer       = sound_ptr;
  114.  
  115.     // set up the SNDSTRUC for DIGIPAK
  116.  
  117.     the_sound->SS.sound     = (unsigned char far*)(sound_ptr+header_length+4);
  118.  
  119.     the_sound->SS.sndlen    = (unsigned short)(size_of_file - header_length);
  120.  
  121.    the_sound->SS.IsPlaying = (short far *)&the_sound->status;
  122.  
  123.     the_sound->SS.frequency = (short)((long)(-1000000) /
  124.                                 ((int)sound_ptr[header_length+4]-256));
  125.  
  126.    // now format data for sound card if requested
  127.  
  128.    if (translate)
  129.        Sound_Translate(the_sound);
  130.  
  131. // return success
  132.  
  133. return(1);
  134.  
  135. } // end Sound_Load
  136.  
  137. //////////////////////////////////////////////////////////////////////////////
  138.  
  139. void Sound_Unload(_sound_ptr the_sound)
  140. {
  141.  
  142. // this functions deletes the sound from memory
  143.  
  144. _dos_freemem(FP_SEG(the_sound->buffer));
  145.  
  146. the_sound->buffer=NULL;
  147.  
  148. } // end Sound_Unload
  149.  
  150. //////////////////////////////////////////////////////////////////////////////
  151.  
  152. void Sound_Translate(_sound_ptr the_sound)
  153. {
  154. // this function calls the DIGIPAK function massage audio to translate
  155. // the raw audio data into the proper format for the sound card that
  156. // the sound system is running on.
  157.  
  158. unsigned char far *buffer;
  159.  
  160. buffer = (unsigned char far*)&the_sound->SS;
  161.  
  162. _asm   {
  163.     push ds         // save DS and SI on stack
  164.     push si
  165.     mov ax, 068Ah   // function 3: MassageAudio
  166.     lds si, buffer  // move address of sound in DS:SI
  167.     int 66h         // call DIGIPAK
  168.     pop si          // restore DS and SI from stack
  169.     pop ds
  170.  
  171.     } // end inline assembly
  172.  
  173. } // end Sound_Translate
  174.  
  175. ///////////////////////////////////////////////////////////////////////////////
  176.  
  177. void Sound_Play(_sound_ptr the_sound)
  178. {
  179. // ths function will the sound pointed to in the sent sound structure
  180.  
  181. unsigned char far *buffer;
  182.  
  183. buffer = (unsigned char far*)&the_sound->SS;
  184.  
  185. _asm    {
  186.     push ds         // save DS and SI on stack
  187.     push si
  188.     mov ax, 068Bh   // function 4: DigPlay2
  189.     lds si, buffer  // move address of sound in DS:SI
  190.     int 66h         // call DIGIPAK
  191.     pop si          // restore DS and SI from stack
  192.     pop ds
  193.  
  194.    } // end inline assembly
  195.  
  196. } // end Sound_Play
  197.  
  198. //////////////////////////////////////////////////////////////////////////////
  199.  
  200. int Sound_Status(void)
  201. {
  202. // this function will return the status of DIGIPAK i.e. is a sound playing
  203. // or not
  204.  
  205. _asm    {
  206.     mov ax, 0689h   // function 2: SoundStatus
  207.     int 66h         // call DIGIPAK
  208.  
  209.     } // end inline assembly
  210.  
  211. // on exit AX will be used as the return value, if 1 then a sound is playing
  212. // 0 if a sound is not playing
  213.  
  214. } // end Sound_Status
  215.  
  216. //////////////////////////////////////////////////////////////////////////////
  217.  
  218. void Sound_Stop(void)
  219. {
  220. // this function will stop a currently playing sound
  221.  
  222. _asm    {
  223.     mov ax, 068Fh   // function 8: StopSound
  224.     int 66h         // call DIGIPAK
  225.  
  226.     } // end inline assembly
  227.  
  228. } // end Sound_Stop
  229.  
  230. //////////////////////////////////////////////////////////////////////////////
  231.  
  232. int Music_Load(char *filename, music_ptr the_music)
  233. {
  234. // this function will load a xmidi file from disk into memory and register it
  235.  
  236. unsigned char far *temp_ptr;   // temporary pointer used to load music
  237. unsigned char far *xmidi_ptr;   // pointer to xmidi data
  238.  
  239. unsigned int segment,          // segment of music data memory
  240.                  paragraphs,       // number of 16 byte paragraphs music takes up
  241.              bytes_read;       // used to track numbr of bytes read by DOS
  242.  
  243. long         size_of_file;     // the total size of the xmidi file in bytes
  244.  
  245. int xmidi_handle;              // DOS file handle
  246.  
  247. // open the extended xmidi file, use DOS file and memory allocation to make sure
  248. // memory is on a 16 byte or paragraph boundary
  249.  
  250. if (_dos_open(filename, O_RDONLY, &xmidi_handle)!=0)
  251.    {
  252.    printf("\nMusic System - Couldn't open %s",filename);
  253.     return(0);
  254.  
  255.    } // end if file not found
  256.  
  257. // compute number of paragraphs that sound file needs
  258.  
  259. size_of_file = filelength(xmidi_handle);
  260.  
  261. paragraphs = 1 + (size_of_file)/16;
  262.  
  263. // allocate the memory on a paragraph boundary
  264.  
  265. _dos_allocmem(paragraphs,&segment);
  266.  
  267. // point data pointer to allocated data area
  268.  
  269. FP_SEG(xmidi_ptr) = segment;
  270. FP_OFF(xmidi_ptr) = 0;
  271.  
  272. // alias pointer to memory storage area
  273.  
  274. temp_ptr = xmidi_ptr;
  275.  
  276. // read in blocks of 16k until file is loaded
  277.  
  278. do
  279.  {
  280.  // load next block
  281.  
  282.  _dos_read(xmidi_handle,temp_ptr, 0x4000, &bytes_read);
  283.  
  284.  // adjust pointer
  285.  
  286.  temp_ptr += bytes_read;
  287.  
  288.  } while(bytes_read==0x4000);
  289.  
  290. // close the file
  291.  
  292. _dos_close(xmidi_handle);
  293.  
  294. // set up the music structure
  295.  
  296. the_music->buffer = xmidi_ptr;
  297. the_music->size   = size_of_file;
  298. the_music->status = 0;
  299.  
  300. // now register the xmidi file with MIDIPAK
  301.  
  302. if ((the_music->register_info = Music_Register(the_music))==XMIDI_UNREGISTERED)
  303.    {
  304.    // delete the memory
  305.  
  306.    Music_Unload(the_music);
  307.  
  308.     // return an error
  309.  
  310.    return(0);
  311.  
  312.     } // end if couldn't register xmidi file
  313.  
  314. // else return success
  315.  
  316. return(1);
  317.  
  318. } // end Music_Load
  319.  
  320. /////////////////////////////////////////////////////////////////////////////
  321.  
  322. void Music_Unload(music_ptr the_music)
  323. {
  324.  
  325. // this functions deletes the xmidi file data from memory
  326.  
  327. _dos_freemem(FP_SEG(the_music->buffer));
  328.  
  329. the_music->buffer=NULL;
  330.  
  331. } // end Music_Unload
  332.  
  333. ///////////////////////////////////////////////////////////////////////////////
  334.  
  335. int Music_Register(music_ptr the_music)
  336. {
  337.  
  338. // this function registers the xmidi music with MIDIPAK, so that it can be
  339. // played
  340.  
  341. unsigned int xmid_off,   // offset and segment of midi file
  342.              xmid_seg,
  343.              length_low, // length of midi file in bytes
  344.                  length_hi;
  345.  
  346. // extract segment and offset of music buffer
  347.  
  348. xmid_off = FP_OFF((the_music->buffer));
  349. xmid_seg = FP_SEG((the_music->buffer));
  350.  
  351. // extract the low word and high word of xmidi file length
  352.  
  353. length_low = the_music->size;
  354. length_hi  = (the_music->size) >> 16;
  355.  
  356. // call MIDIPAK
  357.  
  358. _asm   {
  359.     push si           // save si and di
  360.     push di
  361.  
  362.     mov ax,704h       // function #5: RegisterXmidi
  363.  
  364.     mov bx,xmid_off   // offset of xmidi data
  365.  
  366.     mov cx,xmid_seg   // segment of xmidi data
  367.  
  368.     mov si,length_low // low word of xmidi length
  369.     mov di,length_hi  // hi word of xmidi length
  370.  
  371.     int 66h           // call MIDIPAK
  372.     pop di            // restore si and di
  373.     pop si
  374.  
  375.    } // end inline assembly
  376.  
  377. // return value will be in AX
  378.  
  379. } // end Music_Register
  380.  
  381. ///////////////////////////////////////////////////////////////////////////////
  382.  
  383. void Music_Stop(void)
  384. {
  385. // this function will stop the song currently playing
  386.  
  387. _asm    {
  388.     mov ax,705h    // function #6: MidiStop
  389.     int 66h        // call MIDIPAK
  390.  
  391.     } // end inline assembly
  392.  
  393. } // end Music_Stop
  394.  
  395. ///////////////////////////////////////////////////////////////////////////////
  396.  
  397. int Music_Play(music_ptr the_music,int sequence)
  398. {
  399. // this function plays a xmidi file from memory
  400.  
  401. _asm     {
  402.     mov ax,702h        // function #3: PlaySequence
  403.     mov bx, sequence   // which sequence to play 0,1,2....
  404.     int 66h            // call MIDIPAK
  405.  
  406.    } // end inline assembly
  407.  
  408. // return value is in AX, 1 success, 0 sequence not available
  409.  
  410. } // end Music_Play
  411.  
  412. ///////////////////////////////////////////////////////////////////////////////
  413.  
  414. void Music_Resume(void)
  415. {
  416. // this function resumes a previously stopped xmidi sequence
  417.  
  418. _asm    {
  419.     mov ax,70Bh        // function #12: ResumePlaying
  420.     int 66h            // call MIDIPAK
  421.  
  422.     } // end inline assembly
  423.  
  424. } // end Music_Resume
  425.  
  426. ///////////////////////////////////////////////////////////////////////////////
  427.  
  428. int Music_Status(void)
  429. {
  430. // this function returns the status of a playing sequence
  431.  
  432. _asm    {
  433.     mov ax,70Ch        // function #13: SequenceStatus
  434.     int 66h            // call MIDIPAK
  435.  
  436.     } // end inline assembly
  437.  
  438. // return value is in AX
  439.  
  440. } // end Music_Status
  441.  
  442. ///////////////////////////////////////////////////////////////////////////////
  443.  
  444.