home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 200-299 / ff216.lzh / Wanderer / src / ami-sounds.c < prev    next >
C/C++ Source or Header  |  1989-06-02  |  11KB  |  379 lines

  1. #ifdef AMIGA
  2.  
  3. /****************************   Sound.c   *********************************
  4.  
  5.     Sound is copyright (c) 1988 by Richard Lee Stockton, 21305 60th Ave W.,
  6. Mountlake Terrace, Washington 98043, 206/776-1253(voice), but may be freely
  7. distributed as long as no profit is made from its distribution or sale
  8. without my written permission. I call this concept 'FreeWare', you can
  9. call it whatcha want.
  10.  
  11. Hacked to death by Alan Bland, bears little resemblance to the original
  12. sound.c.
  13.  
  14. **************************************************************************/
  15.  
  16. #include <exec/types.h>
  17. #include <exec/memory.h>
  18. #include <libraries/dosextens.h>
  19. #include <devices/audio.h>
  20. #include <string.h>
  21. #include "sounds.h"
  22.  
  23. /* We'll need 4 buffers in CHIP memory, all else in FAST, if ya got it */
  24.  
  25. #define  BUFSIZE  1024L
  26.  
  27. /* This array defines all the possible sounds */
  28.  
  29. struct SoundData {
  30.     long    sps;
  31.     BOOL    stereo;
  32.     long    sactual;
  33.     char    *sbuffer;
  34. } sdata[MAX_SOUNDS];
  35.  
  36. struct IOAudio    *sound[4]={NULL,NULL,NULL,NULL};
  37. UBYTE    sunit[4]={12,10,5,3};
  38. long    templength;
  39. char    *tempbuffer=NULL, *cbuf[4]={NULL,NULL,NULL,NULL};
  40.  
  41. /*********** quit, give-up, go home, finish... Neatness counts! ******/
  42.  
  43. void freeSounds(string)
  44. char    *string;
  45. {
  46.    short   k;
  47.  
  48.    if(sound[0])      /* This cleans up the audio device stuff */
  49.    {
  50.       for(k=3;k>(-1);k--)    if(sound[k]) AbortIO(sound[k]);
  51.       if(sound[0]->ioa_Request.io_Device) CloseDevice(sound[0]);
  52.       for(k=3;k>(-1);k--)
  53.       {
  54.          if(sound[k]->ioa_Request.io_Message.mn_ReplyPort)
  55.             DeletePort(sound[k]->ioa_Request.io_Message.mn_ReplyPort);
  56.       }
  57.       for(k=3;k>(-1);k--)
  58.       {
  59.          if(sound[k]) FreeMem(sound[k],(long)sizeof(struct IOAudio));
  60.          if(cbuf[k])  FreeMem(cbuf[k],BUFSIZE);
  61.       }
  62.       sound[0]=NULL;
  63.    }
  64.  
  65.   if (string != NULL)
  66.   {
  67.     fatal(string);
  68.   }
  69.  
  70. /* Get rid of all the sound data */
  71.    for(k=0; k<MAX_SOUNDS; k++)
  72.    {
  73.     if (sdata[k].sbuffer)
  74.         FreeMem(sdata[k].sbuffer, sdata[k].sactual);
  75.    }
  76.  
  77. /* Clean up everything else */
  78.  
  79.    if(tempbuffer)          FreeMem(tempbuffer,templength);
  80.  
  81. /* and return, caller will exit */
  82. }
  83.  
  84.  
  85. /*  Don't Allocate if Low Mem - by Bryce Nesbitt  */
  86. /* Aberations by RLS. 4096 should be fudge enough */
  87.  
  88. char *SafeAllocMem(size,flags)
  89. long size, flags;
  90. {
  91.    register char *p;
  92.    
  93.    if(p=(char *)AllocMem(size,flags))
  94.       if(AvailMem(MEMF_CHIP)<4096L)
  95.          { FreeMem(p,size);  return(NULL); }
  96.    return(p);
  97. }
  98.  
  99.  
  100. /******** Load SoundFile 'sPath' ********/
  101.  
  102. void loadSound(sPath, sd)
  103. char    *sPath;
  104. struct SoundData *sd;
  105. {
  106.    struct FileHandle    *sFile=NULL;
  107.    struct FileInfoBlock *finfo=NULL;
  108.    struct FileLock      *lock=NULL;
  109.           long          i, j, sstart;
  110.           char          string[5];
  111.  
  112. /* Set defaults if not found in IFF file */
  113.    sd->stereo = FALSE;
  114.    sd->sactual = 0L;
  115.  
  116. /* Allocate 256 bytes as work memory */
  117.  
  118.    if(!(tempbuffer=SafeAllocMem(256L,MEMF_CLEAR|MEMF_PUBLIC)))
  119.         freeSounds("No Work Memory!");
  120.  
  121. /* Check for and parse IFF data in first 256 bytes of file */
  122.  
  123.    if(!(sFile=(struct FileHandle *)Open(sPath,MODE_OLDFILE)))
  124.    {
  125. /*
  126.       char errmsg[80];
  127.       templength=256L;
  128.       strcpy(errmsg, "Can't open ");
  129.       strcat(errmsg, sPath);
  130.       freeSounds(errmsg);
  131. */
  132.       /* ignore if sound file not found */
  133.       sd->sbuffer = NULL;
  134.       FreeMem(tempbuffer,256L); tempbuffer=NULL;
  135.       return;
  136.    }
  137.    Read(sFile,tempbuffer,256L);              /* load the 1st 256 bytes */
  138.    for(sstart=0L, sd->sps=0L, i=0L; i<252L; i+=4L)
  139.    {
  140.       strncpy(string,tempbuffer+i,4);   string[4]=NULL;
  141.       if(!(strcmp(string,"VHDR")))        /* get samples per second */
  142.       {
  143.          for(j=0;j<(long)((UBYTE)tempbuffer[i+20]);j++) sd->sps+=256L;
  144.          sd->sps += ((UBYTE)tempbuffer[i+21L]);
  145.       }
  146.       if(!(strcmp(string,"CHAN")))            /* Channel Assignment */
  147.       {
  148.          if((tempbuffer[i+7]==6)||(tempbuffer[i+11]==6)) sd->stereo=TRUE;
  149.       }
  150.       if(!(strcmp(string,"BODY")))        /* get size of sound data */
  151.       {
  152.          for(j=0;j<4;j++) sd->sactual+=(((UBYTE)tempbuffer[i+7L-j])<<(8*j));
  153.          sstart = i+8L; i=252L;
  154.       }
  155.    }
  156.  
  157. /* if not in IFF format, get filesize from FileInfoBlock */
  158.  
  159.    if(!sd->sactual)
  160.    {
  161.  
  162. /* Allocate a file info block, get size from it, and de-allocate */
  163.  
  164.       if((!(finfo=(struct FileInfoBlock *)
  165.          SafeAllocMem((long)sizeof(struct FileInfoBlock),MEMF_CLEAR)))
  166.        ||(!(lock=(struct FileLock *)Lock(sPath,ACCESS_READ)))||(!(Examine(lock,finfo))) )
  167.                     freeSounds("FileInfoBlock Problem!");
  168.       sd->sactual = finfo->fib_Size;      if(lock) UnLock(lock);
  169.       if(finfo) FreeMem(finfo,(long)sizeof(struct FileInfoBlock));
  170.  
  171. /* default for non-IFF sample */
  172.       sd->sps = 20000L;
  173.    }
  174.  
  175. /* clean up work area */
  176.  
  177.    FreeMem(tempbuffer,256L); tempbuffer=NULL;
  178.  
  179. /* Allocate _contiguous_ memory for SOUND data. */
  180. /* We'll transfer in BUFSIZE chunks to CHIP memory a little later. */
  181. /* We have to do the contiguity(?) check since AllocMem() does not. */
  182.  
  183.    if((AvailMem(MEMF_LARGEST) < sd->sactual) ||
  184.      (!(sd->sbuffer=SafeAllocMem(sd->sactual,MEMF_CLEAR|MEMF_PUBLIC))))
  185.         { Close(sFile); freeSounds("Need Contiguous Memory!"); }
  186.  
  187. /* Load the data into sbuffer */
  188.  
  189.    Seek(sFile,sstart,OFFSET_BEGINNING);
  190.    if((Read(sFile,sd->sbuffer,sd->sactual)) == -1L)
  191.       { Close(sFile); freeSounds("Read Error!");}
  192.    Close(sFile);
  193. }
  194.  
  195. void initSoundMem()
  196. {
  197.     short  k;
  198.  
  199. /* Allocate sound data buffers from CHIP memory. Ports and */
  200. /* Audio Request Structures do NOT require CHIP memory */
  201.  
  202.    for(k=0;k<4;k++)
  203.    {
  204.      if(!(cbuf[k]=SafeAllocMem(BUFSIZE,
  205.            MEMF_CHIP|MEMF_CLEAR|MEMF_PUBLIC))) freeSounds("No CHIP Memory!");
  206.      if(!(sound[k]=(struct IOAudio *)SafeAllocMem((long)sizeof(struct IOAudio),
  207.                      MEMF_CLEAR|MEMF_PUBLIC))) freeSounds("No IOA Memory!");
  208.    }
  209.    if( (!(sound[0]->ioa_Request.io_Message.mn_ReplyPort =
  210.            (struct MsgPort *) CreatePort("Sound0",0L))) ||
  211.        (!(sound[1]->ioa_Request.io_Message.mn_ReplyPort =
  212.            (struct MsgPort *) CreatePort("Sound1",0L))) ||
  213.        (!(sound[2]->ioa_Request.io_Message.mn_ReplyPort =
  214.            (struct MsgPort *) CreatePort("Sound2",0L))) ||
  215.        (!(sound[3]->ioa_Request.io_Message.mn_ReplyPort =
  216.            (struct MsgPort *) CreatePort("Sound3",0L))) )
  217.         freeSounds("No Port Memory!");
  218.    
  219.  
  220. /* Open Audio using the first IOAudio as the 'initializer' request */
  221.  
  222.    sound[0]->ioa_Request.io_Message.mn_Node.ln_Pri = 20;
  223.    sound[0]->ioa_Data   = &sunit[0];
  224.    sound[0]->ioa_Length = 4L;
  225.    if((OpenDevice(AUDIONAME,0L,sound[0],0L))!=NULL)
  226.       freeSounds("No Audio Device!");
  227.  
  228. /* Set all IOAudios. */
  229.  
  230.    for(k=0;k<4;k++)
  231.    {
  232.       sound[k]->ioa_Request.io_Message.mn_Node.ln_Pri = 20;
  233.       sound[k]->ioa_Request.io_Command = CMD_WRITE;
  234.       sound[k]->ioa_Request.io_Flags   = ADIOF_PERVOL;
  235.  
  236. /* Note copies of Device & AllocKey from initializer. */
  237.  
  238.       sound[k]->ioa_Request.io_Device  = sound[0]->ioa_Request.io_Device;
  239.       sound[k]->ioa_AllocKey  = sound[0]->ioa_AllocKey;
  240.  
  241. /* Each IOAudio has its own CHIP buffer, Port, and Unit (left/right) */
  242.  
  243.       sound[k]->ioa_Data   = (UBYTE *)cbuf[k];
  244.  
  245. /* One time through this BUFSIZE (or smaller) part of the whole */
  246.  
  247.       sound[k]->ioa_Cycles = 1L;
  248.    }
  249.  
  250. /* The compiler wants 'Unit' to be a structure, we just want to mask */
  251. /* into the allocated left/right channels. left=1 or 8, right=2 or 4 */
  252. /*        ...zap! You're a Unit structure! Feel any different?       */
  253.  
  254.    for(k=2;k>(-1);k-=2)
  255.    {
  256.       sound[k+1]->ioa_Request.io_Unit = (struct Unit *)
  257.                       ((ULONG)(sound[0]->ioa_Request.io_Unit)&6L);
  258.       sound[k]->ioa_Request.io_Unit  = (struct Unit *)
  259.                       ((ULONG)(sound[0]->ioa_Request.io_Unit)&9L);
  260.    }
  261.  
  262. }
  263.  
  264. /*****************  make a noise ******************/
  265.  
  266. void playSound(snum)
  267. int snum;
  268. {
  269.     LONG    dactual, dlength, remaining;
  270.     USHORT  count;
  271.     short   k;
  272.     long    cycles = 1;
  273.  
  274. /* don't do sound if not loaded */
  275.     if (sdata[snum].sbuffer == NULL) return;
  276.  
  277.     for (k=0; k<4; k++)
  278.     {
  279.  
  280. /* 3579547 divided by 55 = 65083, nearly the maximum Period (65535) */
  281.  
  282.       sound[k]->ioa_Period = 3579547L/sdata[snum].sps;
  283.  
  284. /* As LOUD as possible. Use your monitor/stereo volume. Rock 'n Roll! */
  285.  
  286.       sound[k]->ioa_Volume = 64L;
  287.     }
  288.  
  289. /* If in STEREO, split file. If in MONO, 'b' buffers use 'a' data */
  290.  
  291.    if(sdata[snum].stereo) remaining=(sdata[snum].sactual/2L)-(sdata[snum].sactual&1L);
  292.    else
  293.    {
  294.       remaining=sdata[snum].sactual;
  295.       sound[1]->ioa_Data   = (UBYTE *)cbuf[0];
  296.       sound[3]->ioa_Data   = (UBYTE *)cbuf[2];
  297.    }
  298.  
  299. /* dactual is the length of one channel's complete data */
  300.  
  301.    dactual=remaining;     k=count=0;
  302.  
  303. /* we be doing loops here */
  304.  
  305.    do
  306.    {
  307.  
  308. /* be CERTAIN ioa_Length is an even number & set datalength */
  309.  
  310.       if(remaining>BUFSIZE) dlength=BUFSIZE;
  311.        else  { dlength=remaining;  dlength-=(dlength&1L); }
  312.  
  313. /* Move the data into the proper CHIP buffer of BUFSIZE */
  314.  
  315.       movmem(sdata[snum].sbuffer+(dactual-remaining),cbuf[k],(int)dlength);
  316.  
  317. /* Don't load or use the right CHIP buffers if MONO. Saves time. */
  318.  
  319.       if(sdata[snum].stereo) movmem(sdata[snum].sbuffer+(sdata[snum].sactual-remaining),
  320.                         cbuf[k+1],(int)dlength);
  321.  
  322. /* Data has been moved, so adjust 'remaining' */
  323.  
  324.       remaining-=dlength;
  325.  
  326. /* Left and Right Lengths are the same, no matter what! */
  327.  
  328.       sound[k]->ioa_Length = sound[k+1]->ioa_Length = dlength;
  329.  
  330. /* Start one set of Left/Right Channels. */
  331.       BeginIO(sound[k]);      BeginIO(sound[k+1]);
  332.  
  333. /* Is this the last time AND the last cycle? If yes & no, reset. */
  334.  
  335.       if(remaining<2L) if(--cycles!=0L)
  336.          { remaining=dactual;   dlength=BUFSIZE; }
  337.  
  338. /* Is this the last time, or what? */
  339.  
  340.       if(remaining<2L)  WaitIO(sound[k+1]);   /* wait for LAST request */
  341.       else
  342.       {
  343.          if(k) k=0; else k=2;    /* switch buffers & wait for PREVIOUS */
  344.          if(count++)  WaitIO(sound[k+1]);
  345.       }
  346.  
  347. /* Keep going until we run out of data */
  348.  
  349.    } while(remaining>1L);                   /* End of Loop */
  350. }
  351.  
  352. /******** initialize everything ********/
  353.  
  354. void initSounds()
  355. {
  356.  
  357. /* Load 'em up! */
  358.  
  359.     loadSound("sounds/death",    &sdata[DEATH_SOUND]);
  360.     loadSound("sounds/arrow",    &sdata[ARROW_SOUND]);
  361.     loadSound("sounds/boulder",    &sdata[BOULDER_SOUND]);
  362.     loadSound("sounds/clock",    &sdata[CLOCK_SOUND]);
  363.     loadSound("sounds/diamond",    &sdata[DIAMOND_SOUND]);
  364.     loadSound("sounds/deadmonster", &sdata[DEADMONSTER_SOUND]);
  365.     loadSound("sounds/kaboom",    &sdata[KABOOM_SOUND]);
  366.     loadSound("sounds/exit",    &sdata[EXIT_SOUND]);
  367.     loadSound("sounds/teleport",&sdata[TELEPORT_SOUND]);
  368.     loadSound("sounds/munch",    &sdata[MUNCH_SOUND]);
  369.     loadSound("sounds/step",    &sdata[STEP_SOUND]);
  370.     loadSound("sounds/cage",    &sdata[CAGE_SOUND]);
  371.     loadSound("sounds/push",    &sdata[PUSH_SOUND]);
  372.  
  373. /* Setup chip buffers and I/O structures */
  374.  
  375.     initSoundMem();
  376. }
  377.  
  378. #endif
  379.