home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 377b.lha / devices / audio / audio2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1980-02-03  |  13.5 KB  |  466 lines

  1. ;/* audio2.c - Execute me to compile me with Lattice 5.04
  2. LC -b1 -cfistq -v -y -j73 audio2.c
  3. Blink FROM LIB:c.o,audio2.o TO audio2 LIBRARY LIB:LC.lib,LIB:Amiga.lib
  4. quit
  5. */
  6.  
  7. /* Audio2.c - 8SVX example - double buffers >128K samples
  8.  *
  9.  * Copyright (c) 1990 Commodore-Amiga, Inc.
  10.  *
  11.  * This example is provided in electronic form by Commodore-Amiga, Inc. for
  12.  * use with the 1.3 revisions of the Addison-Wesley Amiga reference manuals. 
  13.  * The 1.3 Addison-Wesley Amiga Reference Manual series contains additional
  14.  * information on the correct usage of the techniques and operating system
  15.  * functions presented in this example.  The source and executable code of
  16.  * this example may only be distributed in free electronic form, via bulletin
  17.  * board or as part of a fully non-commercial and freely redistributable
  18.  * diskette.  Both the source and executable code (including comments) must
  19.  * be included, without modification, in any copy.  This example may not be
  20.  * published in printed form or distributed with any commercial product.
  21.  * However, the programming techniques and support routines set forth in
  22.  * this example may be used in the development of original executable
  23.  * software products for Commodore Amiga computers.
  24.  * All other rights reserved.
  25.  * This example is provided "as-is" and is subject to change; no warranties
  26.  * are made.  All use is at your own risk.  No liability or responsibility
  27.  * is assumed.
  28.  */
  29.  
  30. /* Lattice use lc -b1 -cfist -v -y. Link with lc.lib and amiga.lib   */
  31. /*----------------*/
  32. /*   INCLUDES     */
  33. /*----------------*/
  34. #include <exec/types.h>
  35. #include <exec/memory.h>
  36. #include <devices/audio.h>
  37. #include <libraries/dos.h>
  38. #include <libraries/dosextens.h>
  39. #include <graphics/gfxbase.h>
  40. #include <iff/iff.h>
  41. #include <iff/8svx.h>
  42. #include <proto/all.h>
  43. #include <stdlib.h>
  44. #include <stdio.h>
  45.  
  46. #define VHDR MakeID('V','H','D','R')
  47. #define BODY MakeID('B','O','D','Y')
  48. #define MY8S MakeID('8','S','V','X')
  49.  
  50. #ifdef LATTICE
  51. int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
  52. int chkabort(void) { return(0); }  /* really */
  53. #endif
  54.  
  55. void              kill8svx(char *);
  56. void              kill8(void); 
  57.  
  58. /*--------------------*/               /* These globals are needed */
  59. /*   G L O B A L S    */               /* by the clean up routines */ 
  60. /*--------------------*/
  61. struct IOAudio     *AIOptr1,           /* Pointers to Audio IOBs      */
  62.                    *AIOptr2,
  63.                    *Aptr;
  64. struct Message     *msg;               /* Msg, port and device for    */
  65. struct MsgPort     *port,              /* driving audio               */
  66.                    *port1,*port2;
  67.        ULONG        device;
  68.        UBYTE       *sbase,*fbase;      /* For sample memory allocation */
  69.        ULONG        fsize,ssize;       /* and freeing                  */
  70. struct FileHandle  *v8handle;
  71.        UBYTE        chan1[]  = {  1 }; /* Audio channel allocation arrays */
  72.        UBYTE        chan2[]  = {  2 };
  73.        UBYTE        chan3[]  = {  4 };
  74.        UBYTE        chan4[]  = {  8 };
  75.        UBYTE       *chans[] = {chan1,chan2,chan3,chan4};
  76.  
  77.        BYTE          oldpri,c;            /* Stuff for bumping priority */
  78.        struct Task  *mt=0L;
  79.  
  80. /*-----------*/
  81. /*  M A I N  */
  82. /*-----------*/
  83. void main(int argc,char **argv)
  84. {
  85. /*-------------*/
  86. /* L O C A L S */
  87. /*-------------*/
  88.        char         *fname;               /* File name and data pointer*/
  89.        UBYTE        *p8data;              /* for file read.            */
  90.        ULONG         clock;               /* Clock constant            */
  91.        ULONG         length[2];           /* Sample lengths            */
  92.        BYTE          iobuffer[8],         /* Buffer for 8SVX header    */
  93.                     *psample[2];          /* Sample pointers           */
  94.        Chunk        *p8Chunk;             /* Pointers for 8SVX parsing */
  95.        Voice8Header *pVoice8Header;
  96.        ULONG         y,rd8count,speed;    /* Counters, sampling speed   */
  97.        ULONG         wakebit;             /* A wakeup mask              */
  98.  
  99. /*-------------*/
  100. /*   C O D E   */
  101. /*-------------*/
  102.  
  103. /*------------------------------*/
  104. /* Check Arguments, Initialize  */
  105. /*------------------------------*/
  106. fbase=0L;
  107. sbase=0L;
  108. AIOptr1=0L;
  109. AIOptr2=0L;
  110. port=0L;
  111. port1=0L;
  112. port2=0L;
  113. v8handle=0L;
  114. device=1L;
  115.  
  116. if (argc < 2)
  117.     {
  118.     kill8svx("No file name given.\n");
  119.     exit(1L);
  120.     }
  121. fname=argv[1];
  122.  
  123. /*---------------------------*/
  124. /* Initialize Clock Constant */
  125. /*---------------------------*/
  126. GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",0L);
  127. if(GfxBase==0L)
  128.     {
  129.     puts("Can't open graphics library\n");
  130.     exit(1L);
  131.     }
  132.  
  133. if(GfxBase->DisplayFlags & PAL) clock=3546895L;        /* PAL clock */
  134. else                            clock=3579545L;        /* NTSC clock */
  135.  
  136. if(GfxBase) 
  137.     CloseLibrary( (struct Library *) GfxBase);
  138.  
  139. /*---------------*/
  140. /* Open the File */
  141. /*---------------*/
  142. v8handle= (struct FileHandle *) Open(fname,MODE_OLDFILE);
  143. if(v8handle==0)
  144.     {
  145.     kill8svx("Can't open 8SVX file.\n");
  146.     exit(1L);
  147.     }
  148.  
  149. /*-------------------------------------------*/
  150. /* Read the 1st 8 Bytes of the File for Size */
  151. /*-------------------------------------------*/
  152. rd8count=Read((BPTR)v8handle,iobuffer,8L);
  153. if(rd8count==-1)
  154.     {
  155.     kill8svx ("Read error.\n");
  156.     exit(1L);
  157.     }
  158. if(rd8count<8) 
  159.     {
  160.     kill8svx ("Not an IFF 8SVX file, too short\n");
  161.     exit(1L);
  162.     }
  163.  
  164. /*-----------------*/
  165. /* Evaluate Header */
  166. /*-----------------*/
  167. p8Chunk=(Chunk *)iobuffer;
  168. if( p8Chunk->ckID != FORM ) 
  169.     {
  170.     kill8svx("Not an IFF FORM.\n");
  171.     exit(1L);
  172.     }
  173.  
  174. /*--------------------------------------------*/
  175. /* Allocate Memory for File and Read it in.   */
  176. /*--------------------------------------------*/
  177. fbase= (UBYTE *)AllocMem(fsize=p8Chunk->ckSize , MEMF_PUBLIC|MEMF_CLEAR);
  178. if(fbase==0)   
  179.     {
  180.     kill8svx("No memory for read.\n");
  181.     exit(1L);
  182.     }
  183. p8data=fbase;
  184.  
  185. rd8count=Read((BPTR)v8handle,p8data,p8Chunk->ckSize);
  186. if(rd8count==-1)
  187.     {
  188.     kill8svx ("Read error.\n");
  189.     exit(1L);
  190.     }
  191. if(rd8count<p8Chunk->ckSize)
  192.     {
  193.     kill8svx ("Malformed IFF, too short.\n");
  194.     exit(1L);
  195.     }
  196. /*-------------------*/
  197. /* Evaluate IFF Type */
  198. /*-------------------*/
  199. if(MakeID( *p8data, *(p8data+1) , *(p8data+2) , *(p8data+3) ) != MY8S )
  200.     {
  201.     kill8svx("Not an IFF 8SVX file.\n");
  202.     exit(1L);
  203.     }
  204.  
  205. /*----------------------*/
  206. /* Evaluate 8SVX Chunks */
  207. /*----------------------*/
  208.  
  209. p8data=p8data+4;
  210.  
  211. while( p8data < fbase+fsize )
  212.   {
  213.   p8Chunk=(Chunk *)p8data;
  214.  
  215.   switch(p8Chunk->ckID)
  216.     {
  217.     case VHDR:
  218.       /*------------------------------------------------*/
  219.       /* Get a pointer to the 8SVX header for later use */
  220.       /*------------------------------------------------*/
  221.       pVoice8Header=(Voice8Header *)(p8data+8L);
  222.       break;
  223.     case BODY:
  224.  
  225.       /*-------------------------------------------------*/
  226.       /* Create pointers to 1-shot and continuous parts  */
  227.       /* for the top octave and get length. Store them.  */
  228.       /*-------------------------------------------------*/
  229.         psample[0] = (BYTE *)(p8data + 8L);
  230.         psample[1] = psample[0] + pVoice8Header->oneShotHiSamples;
  231.         length[0] = (ULONG)pVoice8Header->oneShotHiSamples;
  232.         length[1] = (ULONG)pVoice8Header->repeatHiSamples;
  233.         break;
  234.  
  235.     default:
  236.       break;
  237.     }
  238.  
  239.     /* end switch */
  240.  
  241.   p8data = p8data + 8L + p8Chunk->ckSize;
  242.  
  243.   if(p8Chunk->ckSize&1L == 1)
  244.       p8data++;
  245.   }
  246.  
  247. /* Play either the one-shot or continuous, not both */
  248. if  (length[0]==0)
  249.     y=1;
  250. else
  251.     y=0;
  252.  
  253. /*---------------------------------------*/
  254. /* Allocate chip memory for samples and  */
  255. /* copy from read buffer to chip memory. */
  256. /*---------------------------------------*/
  257. if(length[y]<=102400)ssize=length[y];
  258. else                 ssize=102400;
  259.  
  260. sbase=(UBYTE *)AllocMem( ssize , MEMF_CHIP | MEMF_CLEAR);
  261. if(sbase==0)  
  262.     {
  263.     kill8svx("No chip memory.\n");
  264.     exit(1L);
  265.     }
  266. CopyMem(psample[y],sbase,ssize);
  267. psample[y]+=ssize;
  268.  
  269. /*----------------------------------*/
  270. /* Calculate playback sampling rate */
  271. /*----------------------------------*/
  272. speed =  clock / pVoice8Header->samplesPerSec;
  273.  
  274. /*-------------------*/
  275. /* Bump our priority */
  276. /*-------------------*/
  277. mt=FindTask(NULL);
  278. oldpri=SetTaskPri(mt,21);
  279.  
  280. /*--------------------------------*/
  281. /* Allocate two audio I/O blocks  */
  282. /*--------------------------------*/
  283. AIOptr1=(struct IOAudio *)
  284.       AllocMem( sizeof(struct IOAudio),MEMF_PUBLIC|MEMF_CLEAR);
  285. if(AIOptr1==0)
  286.     {
  287.     kill8svx("No IO memory\n");
  288.     exit(1L);
  289.     }
  290.  
  291. AIOptr2=(struct IOAudio *)
  292.       AllocMem( sizeof(struct IOAudio),MEMF_PUBLIC|MEMF_CLEAR);
  293. if(AIOptr2==0)
  294.     {
  295.     kill8svx("No IO memory\n");
  296.     exit(1L);
  297.     }
  298.  
  299. /*----------------------*/
  300. /* Make two reply ports */
  301. /*----------------------*/
  302. port1=CreatePort(0,0);
  303. if(port1==0)
  304.     {
  305.     kill8svx("No port\n");
  306.     exit(1L);
  307.     }
  308. port2=CreatePort(0,0);
  309. if(port2==0)
  310.     {
  311.     kill8svx("No port\n");
  312.     exit(1L);
  313.     }
  314.  
  315. c=0;
  316. while(device!=0 && c<4)
  317.   {
  318.   /*---------------------------------------*/
  319.   /* Set up audio I/O block for channel    */
  320.   /* allocation and Open the audio device  */
  321.   /*---------------------------------------*/
  322.   AIOptr1->ioa_Request.io_Message.mn_ReplyPort   = port1;
  323.   AIOptr1->ioa_Request.io_Message.mn_Node.ln_Pri = 128;  /* No stealing! */
  324.   AIOptr1->ioa_AllocKey                          = 0;
  325.   AIOptr1->ioa_Data                              = chans[c];
  326.   AIOptr1->ioa_Length                            = 1;
  327.  
  328.   device=OpenDevice("audio.device",0L,(struct IORequest *)AIOptr1,0L);
  329.   c++;
  330.   }
  331. if(device!=0)
  332.     {
  333.     kill8svx("No channel\n");
  334.     exit(1L);
  335.     }
  336.  
  337. /*-------------------------------------------*/
  338. /* Set Up Audio IO Blocks for Sample Playing */
  339. /*-------------------------------------------*/
  340. AIOptr1->ioa_Request.io_Command                =CMD_WRITE;
  341. AIOptr1->ioa_Request.io_Flags                  =ADIOF_PERVOL;
  342. /*--------*/
  343. /* Volume */
  344. /*--------*/
  345. AIOptr1->ioa_Volume=60;
  346. /*---------------*/
  347. /* Period/Cycles */
  348. /*---------------*/
  349. AIOptr1->ioa_Period =(UWORD)speed;
  350. AIOptr1->ioa_Cycles =1;
  351.  
  352. *AIOptr2 = *AIOptr1;   /* Make sure we have the same allocation keys, */
  353.                        /* same channels selected and same flags       */
  354.                        /* (but different ports...)                    */
  355. AIOptr1->ioa_Request.io_Message.mn_ReplyPort   = port1;
  356. AIOptr2->ioa_Request.io_Message.mn_ReplyPort   = port2;
  357.  
  358. /*--------*/
  359. /*  Data  */
  360. /*--------*/
  361. AIOptr1->ioa_Data            =(UBYTE *)sbase;
  362. AIOptr2->ioa_Data            =(UBYTE *)sbase + 51200;
  363.  
  364. /*-----------------*/
  365. /*  Run the sample */
  366. /*-----------------*/
  367. if(length[y]<=102400)
  368.   {
  369.   AIOptr1->ioa_Length=length[y];         /* No double buffering needed */
  370.   BeginIO((struct IORequest *)AIOptr1);  /* Begin the sample, wait for */
  371.   wakebit=0L;                            /* it to finish, then quit.   */
  372.   wakebit=Wait(1 << port1->mp_SigBit);
  373.   msg=GetMsg(port1);
  374.   }
  375. else
  376.   {
  377.   length[y]-=102400;                    /* It's a real long sample so  */
  378.   AIOptr1->ioa_Length=51200L;           /* double buffering is needed  */
  379.   AIOptr2->ioa_Length=51200L;
  380.   BeginIO((struct IORequest *)AIOptr1); /* Start up the first 2 blocks... */
  381.   BeginIO((struct IORequest *)AIOptr2); 
  382.   Aptr=AIOptr1;
  383.   port=port1;                           /* Set the switch... */
  384.  
  385.   while(length[y]>0)                    
  386.     {                                   /* We Wait() for one IO to finish, */
  387.     wakebit=Wait(1 << port->mp_SigBit); /* then reuse the IO block & queue */
  388.     msg=GetMsg(port);                   /* it up again while the 2nd IO    */
  389.                                         /* block plays. Switch and repeat. */
  390.     /* Set length of next IO block */
  391.     if(length[y]<=51200)  Aptr->ioa_Length=length[y];
  392.     else                  Aptr->ioa_Length=51200L;
  393.  
  394.     /* Copy sample fragment from read buffer to chip memory */
  395.     CopyMem(psample[y],Aptr->ioa_Data,Aptr->ioa_Length);
  396.  
  397.     /* Adjust size and pointer of read buffer*/
  398.     length[y]-=Aptr->ioa_Length;
  399.     psample[y]+=51200;
  400.  
  401.     BeginIO((struct IORequest *)Aptr);
  402.  
  403.     if(Aptr==AIOptr1) 
  404.          {Aptr=AIOptr2;                  /* This logic handles switching  */
  405.           port=port2;                    /* between the 2 IO blocks and   */
  406.          }                               /* the 2 ports we are using.     */
  407.     else {Aptr=AIOptr1;   
  408.           port=port1;     
  409.          }                                     
  410.     }
  411.  
  412.   /*-------------------------------------------------*/
  413.   /* OK we are at the end of the sample so just wait */
  414.   /* for the last two parts of the sample to finish  */
  415.   /*-------------------------------------------------*/
  416.   wakebit=Wait(1 << port->mp_SigBit);
  417.   msg=GetMsg(port);
  418.  
  419.   if(Aptr==AIOptr1) 
  420.        {Aptr=AIOptr2;                  /* This logic handles switching  */
  421.         port=port2;                    /* between the 2 IO blocks and   */
  422.        }                               /* the 2 ports we are using.     */
  423.   else {Aptr=AIOptr1;   
  424.         port=port1;     
  425.        }                                     
  426.  
  427.   wakebit=Wait(1 << port->mp_SigBit);
  428.   msg=GetMsg(port);
  429.  
  430.   }
  431.  
  432. kill8();
  433. exit(0L);
  434. }
  435.  
  436. /*----------------*/
  437. /* Abort the Read */
  438. /*----------------*/
  439. void
  440. kill8svx(kill8svxstring)
  441. char *kill8svxstring;
  442. {
  443. puts(kill8svxstring);
  444. kill8();
  445. }
  446.  
  447. /*-------------------------*/
  448. /* Return system resources */
  449. /*-------------------------*/
  450. void
  451. kill8()
  452. {
  453. if(mt!=0)       SetTaskPri(mt,oldpri);
  454.  
  455. if(v8handle!=0) Close((BPTR)v8handle);
  456. if(fbase !=0)   FreeMem(fbase,fsize);
  457. if(sbase !=0)   FreeMem (sbase, ssize);
  458.  
  459. if(device ==0)  CloseDevice((struct IORequest *)AIOptr1);
  460. if(port1  !=0)  DeletePort(port1);
  461. if(port2  !=0)  DeletePort(port2);
  462. if(AIOptr1!=0)  FreeMem( AIOptr1,sizeof(struct IOAudio) );
  463. if(AIOptr2!=0)  FreeMem( AIOptr2,sizeof(struct IOAudio) );
  464. }
  465.  
  466.