home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / prog / c / rkrm1.lha / RKRM_Devices / RKRM_Devices.lha / Audio / audio_8svx.c < prev    next >
C/C++ Source or Header  |  1992-09-03  |  14KB  |  476 lines

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