
/*************************************************************************/
/*			       PlayMono.c				 */
/*	       Contains code used to play mono samples. 		 */
/*************************************************************************/

#include <exec/types.h>
#include <exec/exec.h>
#include <devices/audio.h>
#include <dos/dos.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <graphics/gfxbase.h>
#include <stdlib.h>

#include "dsound.h"

#include <proto/intuition.h>
#include <proto/exec.h>
#include <proto/dos.h>

UBYTE rightAMap[]={4,2,1,8};
UBYTE leftAMap[]={1,8,2,4};
UBYTE eitherAMap[]={1,2,4,8};
UBYTE bothAMap[]={8,3,5,10};

extern UBYTE volume;
extern UWORD speed;
extern ULONG bufSize;

extern BOOL readAll;
extern BOOL loop;
extern struct Window *window;

extern ULONG signalMask;

/*Play a sample out of one speaker (left, right, or either)*/
void playMonoSample(BPTR file,channel audioChannel,struct Voice8Header *vhdr,
		    ULONG len)
{
   struct IOAudio *iob1,*iob2,*curIob,*altIob;
   ULONG toRead;
   ULONG sampleSize=len;
   BOOL done=FALSE;
   UBYTE *allocationMap;

   /*Load the entire sample into memory, if the user so specified*/
   if(readAll)
   {
      storeLeft(file,len,bufSize);
      file=0L;
   }

   /*Decide which audio channel will be allocated*/
   switch(audioChannel)
   {
      case MONO_LEFT:
	 allocationMap=leftAMap;
	 break;
      case MONO_RIGHT:
	 allocationMap=rightAMap;
	 break;
      case UNSPECIFIED:
	 allocationMap=eitherAMap;
	 break;
   }

   /*Get the first audio channel*/
   iob1=GetAudioChannel(bufSize,allocationMap);
   if(iob1==NULL)
   {
      WriteMsg("Couldn't create the first buffer\n");
      cleanup(150);
   }

   /* If the user didn't specify a volume, get it from the VHDR */
   if(volume==0)
      volume=(vhdr->volume>>10);

   /* If the VHDR gave a volume of zero, use maximum volume*/
   if(volume==0)
      volume=64;

   /* Get the samples/sec rate (either the rate given by the user, or the*/
   /* rate found in the VHDR) */
   if(speed==0)
      speed=1000000000/(vhdr->samplesPerSec*279);
   else
      speed=1000000000/(speed*279);

   InitAudioChannel(iob1,volume,speed);

   /*Get the 2nd audio channel*/
   iob2=DuplicateAudioChannel(iob1);

   if(iob2==NULL)
   {
      FreeAudioChannel(iob1);
      WriteMsg("Couldn't create the second buffer\n");
      cleanup(175);
   }

   /* Load the first buffer*/
   toRead=MIN(len,bufSize);
   LoadAudioBuffer(file,iob1,toRead);

   len-=toRead;
   if(len==0 && loop)
   {
      len=sampleSize;
      Seek(file,-sampleSize,OFFSET_CURRENT);
   }

   /*Store the number of samples to be played*/
   iob1->ioa_Length=toRead;

   /*Queue up the play request*/
   BeginIO((struct IORequest *)iob1);

   curIob=iob2;
   altIob=iob1;

   /*Loop while there's stuff to read*/
   while(!done)
   {
      toRead=MIN(len,bufSize);
      if(toRead!=0)
      {
	 LoadAudioBuffer(file,curIob,toRead);
	 curIob->ioa_Length=toRead;
	 BeginIO((struct IORequest *)curIob);
	 len-=toRead;
	 if(len==0 && loop)
	 {
	    len=sampleSize;
	    Seek(file,-sampleSize,OFFSET_CURRENT);
	 }
	 done=FALSE;
      }
      else
	 done=TRUE;

      /*Wait for the buffer to finish*/
      if((Wait((1<<altIob->ioa_Request.io_Message.mn_ReplyPort->mp_SigBit) |
	   signalMask) & SIGBREAKF_CTRL_C) == SIGBREAKF_CTRL_C)
	 done=TRUE;

      if(window!=NULL && GetMsg(window->UserPort)!=NULL)
      {
	 done=TRUE;
      }

      swapPointers(&curIob,&altIob);
   }

   /*Restore the buffer lengths, so that FreeAudio() channel, etc., knows*/
   /*how much memory to free*/
   iob1->ioa_Length=iob2->ioa_Length=bufSize;

   FreeAudioChannel(iob1);
   DeleteDuplication(iob2);

   return;
}

void swapPointers(struct IOAudio **first,struct IOAudio **second)
{
   void *temp;

   temp=*first;
   *first=*second;
   *second=temp;

   return;
}
/*End of PlayMono.c*/
