home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Programmierung / SOURCE.mdf / programm / msdos / c / src_cpp / src / sndfile.cpp < prev   
Encoding:
C/C++ Source or Header  |  1993-08-14  |  6.3 KB  |  269 lines

  1. // Copyright 1993, Mark T. Pflaging
  2. // Implementation for class SB_SoundFile.
  3. // Reads a .WAV file (instead a "raw" file).
  4. // Also maps in sections of EMM for use when playing a sound,
  5. // and handles "named" sounds with a simple look-up table.
  6. //
  7. // Got the format of a .WAV file from:
  8. // "PRO-16 MULTIMEDIA SYSTEM'S
  9. //  MOST COMMONLY-ASKED
  10. //  QUESTIONS AND ANSWERS
  11. //   July 13, 1992"
  12. // provided by Media Vision of Fremont, CA.
  13. //
  14. // Portions were borrowed from Jeff Bird's (cejjb@marlin.jcu.edu.au)
  15. // Sound Blaster Freedom routines dated    12 Feb 92
  16. //
  17. // -MTP  6/10/93
  18. #include "sb.hpp"
  19. #include "sndfile.hpp"
  20.  
  21. //#include <stdio.h>
  22. #include <fstream.h>
  23. #include <io.h>
  24. #include <string.h>
  25.  
  26. strSnd SB_SoundFile::sndRefs[MAXSOUNDS];
  27. int SB_SoundFile::currentSnds = 0;
  28.  
  29. log_to_phys_map SB_SoundFile::quadphys[4];
  30.  
  31. SB_SoundFile * SB_SoundFile::Find(char * ref)
  32. {
  33.     for (int i = 0; i < currentSnds; i ++) {
  34.         if (!strcmp(ref, sndRefs[i].name)) {
  35.             return sndRefs[i].sound;
  36.         }
  37.     }
  38.     return NULL;
  39. }
  40.  
  41. void SB_SoundFile::KillAllSounds()
  42. {
  43.     for (int i = 0; i < currentSnds; i ++) {
  44.         delete sndRefs[i].name;
  45.         delete sndRefs[i].sound;
  46.     }
  47. }
  48.  
  49. SB_SoundFile * SB_SoundFile::current_file = NULL;
  50. extern int DMA_complete;
  51.  
  52. int SB_SoundFile::current_page;
  53. int SB_SoundFile::pages_left;
  54. int SB_SoundFile::is_not_maptime;
  55. unsigned long SB_SoundFile::bytes_left;
  56. SoundBlaster * SB_SoundFile::device;
  57.  
  58. // Interrupt handler for DMA complete IRQ from Soundblaster
  59. void far interrupt SBHandler(...)
  60. {
  61.     disable();
  62.  
  63.     // Acknowledge the interrupt
  64.     inportb(DSP_DATA_AVAIL);
  65.     outportb(0x20,0x20);
  66.     if (SB_SoundFile::nextDMAtransfer()) {
  67.         DMA_complete = 1;
  68.     }
  69.     enable();
  70. }
  71.  
  72. int min(int v1, int v2)
  73. {
  74.     return ((v1 < v2) ? v1 : v2);
  75. }
  76.  
  77. Boolean SB_SoundFile::NextDMASegment()
  78. {
  79.     if (!pages_left) return True;    // Done!!
  80.     int temp;
  81.     if (pages_left > 1) {
  82.         sl = 16383;
  83.         bytes_left -= long(sl);
  84.         temp = 1;
  85.     }
  86.     else {
  87.         temp = pages_left;
  88.         sl = (unsigned int)bytes_left;    // Should be < 16383!
  89.     }
  90.  
  91.     if (!is_not_maptime)
  92.         MapInSound(current_page, min(4, pages_left));
  93.     pages_left -= temp;
  94.     current_page += temp;
  95.  
  96.     unsigned IOaddr = device->getIOaddr();
  97.     // Setup device
  98.     device->Reset();
  99.     device->Sample_Rate(sr);
  100.     device->Voice(True);
  101.  
  102.     sl --;
  103.     // Setup DMA
  104.     dma_reset(device->getDMAchan());
  105.     dma_setup(device->getDMAchan(), getPageFrame() + (is_not_maptime * 16384), sl, 1);
  106.     is_not_maptime ++;
  107.     is_not_maptime %= 4;
  108.  
  109.     // Turn on stereo output
  110.     if(stereo && (device->getType() == SBPro)) writemixer(0x0e,0x13);
  111.  
  112.     // Setup Soundblaster for transfer
  113.     // Would be nice to allow 16 bit files!
  114.     writedac(DMA_8_BIT_DAC);
  115.  
  116.     // Write length
  117.     writedac(sl & 0xff);
  118.     writedac(sl >> 8);
  119.  
  120.     return False;        // Continue...
  121. }
  122.  
  123. /********************************WAV FILE FORMAT***********************************
  124. 4 bytes     'RIFF'
  125. 4 bytes     <length>
  126. 4 bytes     'WAVE'
  127. 4 bytes     'fmt '
  128. 4 bytes     <length>        ; 10h - length of 'data' block
  129. 2 bytes     01                ; format tag
  130. 2 bytes     01                ; channels (1=mono, 2=stereo)
  131. 4 bytes     xxxx            ; samples per second
  132. 4 bytes     xxxx            ; average samples per second
  133. 2 bytes     01                ; block alignment
  134. 2 bytes     08                ; bits per sample
  135. 4 bytes     'data'
  136. 4 bytes     <length>
  137.    bytes     <sample data>
  138. **********************************************************************************/
  139.  
  140. Boolean SB_SoundFile::ReadHeader(int fd)
  141. {
  142.     struct wav_header header;
  143.     if (_read(fd, &header, sizeof(struct wav_header)) != sizeof(struct wav_header))
  144.         return False;
  145.     if (strncmp(header.id1, "RIFF", 4)) return False;
  146.  
  147.     if (strncmp(header.id2, "WAVEfmt ", 8)) return False;
  148.     if (header.blklen != 0x10) return False;
  149.     if (header.indicator != 1) return False;
  150.     switch(header.stereoval) {
  151.     case 1:
  152.         setStereo(False);
  153.         break;
  154.     case 2:
  155.         setStereo(True);
  156.         break;
  157.     default:
  158.         return False;
  159.     }
  160.     sr = header.sr;
  161.  
  162.     // I'm not really sure what to do with these numbers at
  163.     // present.  They really just seem to be a restatement of
  164.     // the sample rate, but maybe I'm missing something...
  165.     if ((header.blkpersec / header.blkspersamp) != sr) return False;
  166.  
  167.     // Sound Blaster can only handle 8 bit samples....
  168.     if (header.bits_per_sample != 8) return False;
  169.  
  170.     if (strncmp(header.id3, "data", 4)) return False;
  171.     sample_len = header.sample_len;
  172.     // Whew!  Success.
  173.     return True;
  174. }
  175.  
  176. #include <fcntl.h>
  177. #include <sys\stat.h>
  178. void SB_SoundFile::Init(char * refname, char * filenm)
  179. {
  180.     InitRef(refname);
  181.  
  182.     int fd = open(filenm, O_RDONLY | O_BINARY);
  183.     if (fd == -1) {
  184.         cerr << "Could not open sample file " << filenm << endl;
  185.         exit(1);
  186.     }
  187.  
  188.  
  189.     if (!ReadHeader(fd)) {
  190.         close(fd);
  191.         cerr << "Some sort of problem with sample file " << filenm << endl;
  192.         return;
  193.     }
  194.  
  195.  
  196. #ifdef OLD_WAY
  197.     if (sample_len > 64000)
  198.         sl = 64000;
  199.     else
  200.         sl = (unsigned)sample_len;
  201.     raw = (signed char far *)farmalloc((unsigned long)sl + 65535L);
  202.     unsigned long physical = ((unsigned long)FP_OFF(raw)) + (((unsigned long)FP_SEG(raw)) << 4);
  203.     unsigned long aligned_physical = physical+0x0FFFFL;
  204.     aligned_physical &= 0xF0000L;
  205.     aligned=(char *)MK_FP((unsigned )((aligned_physical >> 4) & 0xFFFF),0);
  206.     _read(fd, aligned, sl);
  207. #else
  208.     unsigned long left = sample_len;
  209.     pages = 0;
  210.     Boolean done = False;
  211.     first_page = CurrentlyAllocated();    // zero-relative
  212.     int temp;
  213.     last_page = first_page;
  214.  
  215.     while (!done) {
  216.         if (left > 16383) {
  217.             sl = 16363;
  218.             left -= 16383L;
  219.             temp = 1;
  220.         }
  221.         else {
  222.             sl = (unsigned int) left;
  223.             temp = 1;
  224.             done = True;
  225.         }
  226.         pages += temp;
  227.         Allocate(temp);
  228.         MapInSound(last_page, temp);
  229.         _read(fd, getPageFrame(), sl);
  230.         last_page += temp;
  231.     }
  232. #endif
  233.     close(fd);
  234. }
  235.  
  236. #ifndef OLD_WAY
  237. void SB_SoundFile::MapInSound(int first, int howmany)
  238. {
  239.     for (int i = 0; i < howmany; i ++) {
  240.         quadphys[i].log_page_number = i + first;
  241.         quadphys[i].phys_page_number = i;
  242.     }
  243.     MapMultiple(quadphys, howmany);
  244. }
  245. #endif
  246.  
  247. void SB_SoundFile::OutVoice_DMA(SoundBlaster & device_arg)
  248. {
  249.     device = &device_arg;
  250.     bytes_left = sample_len;
  251.     current_page = first_page;
  252.     pages_left = pages;
  253.     is_not_maptime = 0;
  254.     current_file = this;
  255.  
  256.     unsigned char im, tm;
  257.     device_arg.reset_DMA_Complete();
  258.  
  259.     // Enable interrupts on PIC
  260.     disable();
  261.     im = inportb(0x21);
  262.     tm = ~(1 << device_arg.getIRQ());
  263.     outportb(0x21,im & tm);
  264.     enable();
  265.  
  266.     NextDMASegment();
  267. }
  268.  
  269.