  /* Copyright © 1988 Lake Forest Logic, Inc. (312)816-6666 */
 /* FREELY REDISTRIBUTABLE SOURCE CODE                     */
/* 7.16 megahertz CPU clock speed timer base              */

#include <exec/types.h>
#include <exec/memory.h>
#include <devices/audio.h>
#include <libraries/dos.h>
#include <stdio.h>
#include <proto/all.h>
/* #include <functions.h >  use this line instead for Manx 5.0 */


#define CPU 3579545
#define SHOT (128*1024)

/* Prototypes for functions defined in listen.c */

void OpenSound(void);
void CloseSound(void);
void AtomSound(UBYTE *sound,int length,int volume,int period,int number);
void MakeSound(UBYTE *sound,int length,int volume,int period,int number);
void main(int argc,char **argv);
void Xexit(int why);
void Reverse(UBYTE *wave,int cnt);
UBYTE *Reflect(UBYTE *wave,int cnt);

UBYTE allocationMap[]={1,8,2,4};  /* this controls channel selection */

struct MsgPort *replyPort;
struct IOAudio *AM;

/*
   you may use the functions OpenSound(), CloseSound() and MakeSound()
   in your own programs.
*/


void OpenSound() /* opens an audio channel for you to use */
 {
  replyPort=CreatePort(0,0); 
  AM=(struct IOAudio *)CreateExtIO(replyPort,sizeof(struct IOAudio));
  AM->ioa_Request.io_Message.mn_Node.ln_Pri=0;
  AM->ioa_Data=allocationMap;
  AM->ioa_Length=sizeof(allocationMap);
  OpenDevice(AUDIONAME,0,(struct IORequest *)AM,0);
 }

void CloseSound() /* closes the audio channel */
 {
  CloseDevice((struct IORequest *)AM);
  DeleteExtIO((struct IORequest *)AM);
  DeletePort(replyPort);
 }

void AtomSound(UBYTE *sound,int length,int volume,int period,int number) /* plays a 128K sample */
  {
   AM->ioa_Request.io_Command=CMD_WRITE;
   AM->ioa_Request.io_Flags=ADIOF_PERVOL;
   AM->ioa_Data=sound;                         /* pointer to audio data */
   AM->ioa_Length=length;                     /* length of audio data  */
   AM->ioa_Period=CPU/period;                /* sampling rate         */
   AM->ioa_Volume=volume;                   /* volume (0-64)         */
   AM->ioa_Cycles=number;                  /* repititions           */
   BeginIO((struct IORequest *)AM);

   WaitIO((struct IORequest *)AM); /*OPTIONAL:  routine will wait for sound to finish */
  } 

void MakeSound(UBYTE *sound,int length,int volume,int period,int number) /* plays a sound sample */
   {
   int loop,ream;

   if(length>SHOT)	/* sample longer than 128K */
    {
     printf(" Long sound sample.\n");
     for(loop=0;loop<(length/SHOT);loop++)
      {
       AtomSound(&sound[SHOT*loop],SHOT,volume,period,number);
       putchar('.'); fflush(stdout);
      }
     if(ream=length%SHOT)
      AtomSound(&sound[SHOT*loop],ream,volume,period,number);
    }
   else
    {
     AtomSound(sound,length,volume,period,number);
    }
  } 

void main(int argc,char **argv)
  {
   int loop,count,rate,vol,rep,start,value,master;
   char twine[128];
   ULONG handle,lock;
   struct FileInfoBlock info;
   UBYTE *WaveForm;
   
   printf("\2331mListen V1.2 © 1990 Lake Forest Logic Inc.\2330m\n");
   if(argc<2) Xexit(1);

   lock=Lock(argv[1],ACCESS_READ);
   if(!lock) Xexit(2);

    Examine(lock,&info);
    UnLock(lock);
    count=info.fib_Size;
     WaveForm=AllocMem(count,MEMF_CHIP|MEMF_CLEAR);
     if(!WaveForm) Xexit(3);

     handle=Open(argv[1],MODE_OLDFILE);
     if(!handle)
      {
       FreeMem(WaveForm,count);
       Xexit(4);
      }
     Read(handle,WaveForm,count);
     Close(handle);
   master=count;
   rate=14914; /* this is the default sampling rate for playback */
   rep=1;
   vol=64;
   start=0;
   if(argc>2) for(loop=0;loop<argc-2;loop++)
    {
     sprintf(twine,"%s",argv[loop+2]);
     sscanf(&twine[1],"%d",&value);     
     if(twine[0]=='R') rate=value;
     else if(twine[0]=='B')
      {
       Reverse(WaveForm,count);
       printf("Backward sample.\n");
      }
     else if(twine[0]=='M') 
      {
       WaveForm=Reflect(WaveForm,count);
       if(((ULONG)WaveForm)&0xf0000000)
        {
         master*=2;
         count=master;
         WaveForm=(UBYTE *) ( ( (ULONG)WaveForm )&(0x0fffffff));
       }
      }
     else if(twine[0]=='N') rep=value;
     else if(twine[0]=='V') vol=value;
     else if(twine[0]=='S') { start=value; count-=start; }
     else if(twine[0]=='L') if(value<=count) count=value;
     else printf("Invalid option: %s\n",twine);
    }
  
   printf("Rate:  %6d\n",rate);
   printf("Volume:%6d\n",vol);
   printf("Number:%6d\n",rep);
   printf("Start: %6d\n",start);
   printf("Length:%6d\n",count);
   OpenSound();
   MakeSound(WaveForm+start,count,vol,rate,rep);
   CloseSound();

   FreeMem(WaveForm,master);
  }

void Xexit(int why)
  {

   if(why==2) printf("Error: unable to lock file.\n");
   if(why==3) printf("Error: not enough sample memory.\n");
   if(why==4) printf("Error: unable to open file.\n");
   if(why==1)
    {
     printf("Syntax:  Listen <filename> [R] [N] [V] [S] [L] [B] [M]\n");
     printf("Options: (R)ate (N)umber (V)olume (S)tart byte\n");
     printf("         (L)ength [B]ackwards [M]irror\n");
    }
   exit(0);
  }

void Reverse(UBYTE *wave,int cnt)
  {
   UBYTE hold;
   int loop;

   for(loop=0;loop<cnt/2;loop++)
    {
     hold=wave[loop];
     wave[loop]=wave[cnt-loop];
     wave[cnt-loop]=hold;
    }
  }
 
UBYTE *Reflect(UBYTE *wave,int cnt)
  {
   UBYTE *newwave;

   printf("Mirrored sample.\n"); 
   newwave=AllocMem(cnt*2,MEMF_CHIP);
   if(!newwave)
    {
     printf("Not enough RAM for mirror sound.\n");
     return(wave);
    }
   CopyMem(wave,newwave,cnt);
   CopyMem(wave,newwave+cnt,cnt);

   Reverse(newwave+cnt,cnt);   
   FreeMem(wave,cnt);

   return((UBYTE *)(((ULONG)newwave)|0xf0000000));
  }
