home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 10 / Fresh_Fish_10_2352.bin / useful / mus / play / dsound / play.c < prev    next >
C/C++ Source or Header  |  1994-07-18  |  19KB  |  713 lines

  1.  
  2. /*************************************************************************/
  3. /*                   Play.c                 */
  4. /*Contains code used to play samples (mono out of one or both speakers,  */
  5. /*and stereo).                                 */
  6. /*************************************************************************/
  7.  
  8. #include <exec/types.h>
  9. #include <exec/exec.h>
  10. #include <devices/audio.h>
  11. #include <dos/dos.h>
  12. #include <intuition/intuition.h>
  13. #include <intuition/intuitionbase.h>
  14. #include <graphics/gfxbase.h>
  15. #include <stdlib.h>
  16.  
  17. #include "dsound.h"
  18.  
  19. #include <proto/intuition.h>
  20. #include <proto/exec.h>
  21. #include <proto/dos.h>
  22.  
  23. UBYTE rightAMap[]={4,2,1,8};
  24. UBYTE leftAMap[]={1,8,2,4};
  25. UBYTE eitherAMap[]={1,2,4,8};
  26. UBYTE bothAMap[]={8,3,5,10};
  27.  
  28. extern UBYTE volume;
  29. extern UWORD speed;
  30. extern ULONG bufSize;
  31.  
  32. extern BOOL readAll;
  33. extern BOOL loop;
  34. extern struct Window *window;
  35.  
  36. /*Play a sample out of one speaker (left, right, or either)*/
  37. void playMonoSample(BPTR file,channel audioChannel,struct Voice8Header *vhdr,
  38.             ULONG len)
  39. {
  40.    struct IOAudio *iob1,*iob2;
  41.    ULONG toRead;
  42.    ULONG sampleSize=len;
  43.    BOOL done=FALSE;
  44.    UBYTE *allocationMap;
  45.  
  46.    /*Load the entire sample into memory, if the user so specified*/
  47.    if(readAll)
  48.    {
  49.       storeLeft(file,len,bufSize);
  50.       file=0L;
  51.    }
  52.  
  53.    /*Decide which audio channel will be allocated*/
  54.    switch(audioChannel)
  55.    {
  56.       case MONO_LEFT:
  57.      allocationMap=leftAMap;
  58.      break;
  59.       case MONO_RIGHT:
  60.      allocationMap=rightAMap;
  61.      break;
  62.       case UNSPECIFIED:
  63.      allocationMap=eitherAMap;
  64.      break;
  65.    }
  66.  
  67.    /*Get the first audio channel*/
  68.    iob1=GetAudioChannel(bufSize,allocationMap);
  69.    if(iob1==NULL)
  70.    {
  71.       WriteMsg("Couldn't create the first buffer\n");
  72.       cleanup(150);
  73.    }
  74.  
  75.    /* If the user didn't specify a volume, get it from the VHDR */
  76.    if(volume==0)
  77.       volume=(vhdr->volume>>10);
  78.  
  79.    /* If the VHDR gave a volume of zero, use maximum volume*/
  80.    if(volume==0)
  81.       volume=64;
  82.  
  83.    /* Get the samples/sec rate (either the rate given by the user, or the*/
  84.    /* rate found in the VHDR) */
  85.    if(speed==0)
  86.       speed=1000000000/(vhdr->samplesPerSec*279);
  87.    else
  88.       speed=1000000000/(speed*279);
  89.  
  90.    InitAudioChannel(iob1,volume,speed);
  91.  
  92.    /*Get the 2nd audio channel*/
  93.    iob2=DuplicateAudioChannel(iob1);
  94.  
  95.    if(iob2==NULL)
  96.    {
  97.       FreeAudioChannel(iob1);
  98.       WriteMsg("Couldn't create the second buffer\n");
  99.       cleanup(175);
  100.    }
  101.  
  102.    /* Load the first buffer*/
  103.    toRead=MIN(len,bufSize);
  104.    LoadAudioBuffer(file,iob1,toRead);
  105.  
  106.    len-=toRead;
  107.    if(len==0 && loop)
  108.    {
  109.       len=sampleSize;
  110.       Seek(file,-sampleSize,OFFSET_CURRENT);
  111.    }
  112.  
  113.    /*Store the number of samples to be played*/
  114.    iob1->ioa_Length=toRead;
  115.  
  116.    /* Make sure there's enough data so that we have something to put in */
  117.    /* the second buffer */
  118.    if(len!=0)
  119.    {
  120.       toRead=MIN(len,bufSize);
  121.       LoadAudioBuffer(file,iob2,toRead);
  122.       len-=toRead;
  123.       if(len==0 && loop)
  124.       {
  125.      len=sampleSize;
  126.      Seek(file,-sampleSize,OFFSET_CURRENT);
  127.       }
  128.       iob2->ioa_Length=toRead;
  129.    }
  130.    else
  131.       /* It appears that the entire sound sample is small enough to */
  132.       /* fit into the first buffer, so don't play the second */
  133.       iob2->ioa_Length=0;
  134.  
  135.    /*And queue up the play requests*/
  136.    BeginIO((struct IORequest *)iob1);
  137.    if(iob2->ioa_Length!=0)
  138.       BeginIO((struct IORequest *)iob2);
  139.  
  140.    /* If the sound sample was small enough to fit into the two buffers, */
  141.    /* play them then finish up */
  142.    if(len==0)
  143.    {
  144.       Wait((1<<iob1->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) +
  145.        (1<<window->UserPort->mp_SigBit));
  146.  
  147.                            /*    vvvv Bug fix */
  148.       if(iob2->ioa_Length!=0 && GetMsg(window->UserPort)==NULL)
  149.      Wait((1<<iob2->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
  150.           (1<<window->UserPort->mp_SigBit));
  151.  
  152.      done=TRUE;
  153.    }
  154.  
  155.    /*Otherwise, play those samples then read more from disk*/
  156.  
  157.    /*Loop while there's stuff to read*/
  158.    while(!done)
  159.    {
  160.       /*Fill the first buffer*/
  161.       Wait((1<<iob1->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
  162.        (1<<window->UserPort->mp_SigBit));
  163.  
  164.       toRead=MIN(len,bufSize);
  165.  
  166.       if(GetMsg(window->UserPort)!=NULL)
  167.       {
  168.      done=TRUE;
  169.      break;
  170.       }
  171.       else
  172.      if(toRead==0)
  173.      {
  174.         /*If there's no stuff left to read, wait 'till the second buffer*/
  175.         /*finishes, then quit*/
  176.         Wait((1<<iob2->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
  177.          (1<<window->UserPort->mp_SigBit));
  178.         done=TRUE;
  179.         break;
  180.      }
  181.  
  182.       LoadAudioBuffer(file,iob1,toRead);
  183.       len-=toRead;
  184.       if(len==0 && loop)
  185.       {
  186.      len=sampleSize;
  187.      Seek(file,-sampleSize,OFFSET_CURRENT);
  188.       }
  189.  
  190.       iob1->ioa_Length=toRead;
  191.  
  192.       /*Play the first buffer*/
  193.       BeginIO((struct IORequest *)iob1);
  194.  
  195.       /*Wait for the second buffer to finish*/
  196.       Wait((1<<iob2->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
  197.        (1<<window->UserPort->mp_SigBit));
  198.  
  199.       toRead=MIN(len,bufSize);
  200.  
  201.       if(GetMsg(window->UserPort)!=NULL)
  202.       {
  203.      done=TRUE;
  204.      break;
  205.       }
  206.       else
  207.      if(toRead==0)
  208.      {
  209.         /*If there's no stuff left to read, wait 'till the first buffer*/
  210.         /*finishes, then quit*/
  211.         Wait((1<<iob1->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
  212.          (1<<window->UserPort->mp_SigBit));
  213.         done=TRUE;
  214.         break;
  215.      }
  216.  
  217.       /*Reload it*/
  218.       LoadAudioBuffer(file,iob2,toRead);
  219.       len-=toRead;
  220.       if(len==0 && loop)
  221.       {
  222.      len=sampleSize;
  223.      Seek(file,-sampleSize,OFFSET_CURRENT);
  224.       }
  225.       iob2->ioa_Length=toRead;
  226.  
  227.       /*Play it*/
  228.       BeginIO((struct IORequest *)iob2);
  229.    }
  230.  
  231.    /*Restore the buffer lengths, so that FreeAudio() channel, etc., knows*/
  232.    /*how much memory to free*/
  233.    iob1->ioa_Length=iob2->ioa_Length=bufSize;
  234.  
  235.    FreeAudioChannel(iob1);
  236.    DeleteDuplication(iob2);
  237.  
  238.    return;
  239. }
  240.  
  241. /*Play a stereo sample out of both speakers*/
  242. /*If the user specifies that just one of the two stereo channels will*/
  243. /*be played, DSound.c calls playMonoSample*/
  244.  
  245. void playStereoSample(BPTR leftFile,channel audioChannel,
  246.               struct Voice8Header *vhdr, ULONG length, char *filename)
  247. {
  248.    struct IOAudio *iob1_right,*iob2_right,*iob1_left,*iob2_left;
  249.    ULONG toRead;
  250.    ULONG sampleSize=length;
  251.    BOOL done=FALSE;
  252.    BPTR rightFile;
  253.  
  254.    /*Open the file again*/
  255.    rightFile=dupFileHandle(leftFile,filename);
  256.  
  257.    /*And position ourselves at the start of the right channel's data*/
  258.    Seek(rightFile,length,OFFSET_CURRENT);
  259.  
  260.    /*Read the entire sample into memory, if specified*/
  261.    if(readAll)
  262.    {
  263.       storeLeft(leftFile,length,bufSize);
  264.       storeRight(rightFile,length,bufSize);
  265.       Close(rightFile);
  266.       leftFile=0L;
  267.       rightFile=4L;
  268.    }
  269.  
  270.    /*Get the first audio channel*/
  271.    iob1_left=GetAudioChannel(bufSize,leftAMap);
  272.    if(iob1_left==NULL)
  273.    {
  274.       WriteMsg("Couldn't create the first stereo buffer\n");
  275.       cleanup(150);
  276.    }
  277.  
  278.    iob1_right=GetAudioChannel(bufSize,rightAMap);
  279.    if(iob1_right==NULL)
  280.    {
  281.       WriteMsg("Couldn't create the second stereo buffer\n");
  282.       cleanup(150);
  283.    }
  284.  
  285.    /* If the user didn't specify a volume, get it from the VHDR */
  286.    if(volume==0)
  287.       volume=(vhdr->volume>>10);
  288.  
  289.    /* If the VHDR gave a volume of zero, use maximum volume*/
  290.    if(volume==0)
  291.       volume=64;
  292.  
  293.    /* Get the samples/sec rate (either the rate given by the user, or the*/
  294.    /* rate found in the VHDR) */
  295.    if(speed==0)
  296.       speed=1000000000/(vhdr->samplesPerSec*279);
  297.    else
  298.       speed=1000000000/(speed*279);
  299.  
  300.    InitAudioChannel(iob1_left,volume,speed);
  301.    InitAudioChannel(iob1_right,volume,speed);
  302.  
  303.    /*Get the 2nd audio channel*/
  304.    iob2_left=DuplicateAudioChannel(iob1_left);
  305.  
  306.    if(iob2_left==NULL)
  307.    {
  308.       FreeAudioChannel(iob1_left);
  309.       FreeAudioChannel(iob1_right);
  310.       WriteMsg("Couldn't create the second buffer");
  311.       cleanup(175);
  312.    }
  313.  
  314.    iob2_right=DuplicateAudioChannel(iob1_right);
  315.    if(iob2_right==NULL)
  316.    {
  317.       FreeAudioChannel(iob1_left);
  318.       DeleteDuplication(iob2_left);
  319.       FreeAudioChannel(iob1_right);
  320.       WriteMsg("Couldn't create the second buffer");
  321.       cleanup(175);
  322.    }
  323.  
  324.  
  325.    /* Load the first buffer*/
  326.    toRead=MIN(length,bufSize);
  327.    LoadAudioBuffer(leftFile,iob1_left,toRead);
  328.    LoadAudioBuffer(rightFile,iob1_right