home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 5 / FreshFish_July-August1994.bin / bbs / dev / cmanual-3.0.lha / CManual-3.0 / Sound / IncludeSound / IncludeSound.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-10-12  |  12.2 KB  |  352 lines

  1. /***********************************************************/
  2. /*                                                         */
  3. /* Amiga C Encyclopedia (ACE) V3.0      Amiga C Club (ACC) */
  4. /* -------------------------------      ------------------ */
  5. /*                                                         */
  6. /* Book:    ACM Sound                   Amiga C Club       */
  7. /* Chapter: IncludeSound                Tulevagen 22       */
  8. /* File:    IncludeSound.c              181 41  LIDINGO    */
  9. /* Author:  Anders Bjerin               SWEDEN             */
  10. /* Date:    92-05-10                                       */
  11. /* Version: 1.15                                           */
  12. /*                                                         */
  13. /*   Copyright 1992, Anders Bjerin - Amiga C Club (ACC)    */
  14. /*                                                         */
  15. /* Registered members may use this program freely in their */
  16. /*     own commercial/noncommercial programs/articles.     */
  17. /*                                                         */
  18. /***********************************************************/
  19.  
  20.  
  21.  
  22. /* Include some important header files: */
  23. #include <exec/types.h>
  24. #include <exec/memory.h>
  25. #include <devices/audio.h> 
  26. #include <stdio.h>
  27. #include "IncludeSound.h"
  28.  
  29.  
  30.  
  31. #define CLOCK_CONSTANT 3579545
  32.  
  33.  
  34. /* An IOAudio pointer to each sound channel: */
  35. struct IOAudio *IOA[ 4 ] = { NULL, NULL, NULL, NULL };
  36.  
  37.  
  38.  
  39. typedef LONG Fixed;
  40. typedef struct
  41. {
  42.   ULONG  oneShotHiSamples;  /* #samples in the high octave 1-shot part */
  43.   ULONG  repeatHiSamples;   /* #samples in the high octave repeat part */
  44.   ULONG  samplesPerHiCycle; /* #samples/cycle in high octave, else 0  */
  45.   UWORD  samplesPerSec;     /* Data sampling rate */
  46.   UBYTE  ctOctave;          /* Number of octaves of waveforms */
  47.   UBYTE  sCompression;      /* Data compression technique used */
  48.   Fixed  volume;            /* Playback volume from 0 to 0x10000 */
  49. } Voice8Header;
  50.  
  51.  
  52.  
  53. /* Declare the functions we are going to use: */
  54.  
  55. BOOL PlaySound(
  56.   struct SoundInfo *info,
  57.   UWORD volume,
  58.   UBYTE channel,
  59.   BYTE priority,
  60.   WORD delta_rate,
  61.   UWORD repeat,
  62.   ULONG start,
  63.   ULONG time,
  64.   BOOL wait 
  65. );
  66.  
  67. void StopSound( UBYTE channel );
  68.  
  69. BOOL PrepareIOA(
  70.   UWORD period,
  71.   UWORD volume,
  72.   UWORD cycles,
  73.   UBYTE channel,
  74.   BYTE priority,
  75.   struct SoundInfo *info,
  76.   ULONG start,
  77.   ULONG time
  78. );
  79.  
  80.  
  81.  
  82. /* PlaySound()                                                           */
  83. /* PlaySound() plays one already prepared sound effect. You can decide   */
  84. /* what volume, which channel, what rate, which priority, how many times */
  85. /* the sound should be played and so on...                               */
  86. /*                                                                       */
  87. /* Synopsis: ok = PlaySound( ptr, vol, cha, pri, drate, times, start,    */
  88. /*                           time, wait );                               */
  89. /*                                                                       */
  90. /* ok:    (BOOL) If the sound was played successfully TRUE is            */
  91. /*        returned, else FALSE.                                          */
  92. /*                                                                       */
  93. /* ptr:   (struct SoundInfo *) Pointer to a SoundInfo structure. This    */
  94. /*        pointer was returned by PrepareSound().                        */
  95. /*                                                                       */
  96. /* vol:   (UWORD) Volume, 0 to 64.                                       */
  97. /*                                                                       */
  98. /* cha:   (UBYTE) Which channel should be used. (LEFT0, RIGHT0,          */
  99. /*        RIGHT1 or LEFT1)                                               */
  100. /*                                                                       */
  101. /* pri:   (BYTE) What priority should be used. See header file for a     */
  102. /*        complete list of recommended priorities.                       */
  103. /*                                                                       */
  104. /* drate: (WORD) Delta rate. When the sound is prepared, the record      */
  105. /*        rate is automatically stored in the SoundInfo structure,       */
  106. /*        so if you do not want to change the rate, write NORMALRATE.    */
  107. /*                                                                       */
  108. /* times: (UWORD) How many times the sound should be played. If you      */
  109. /*        want to play the sound forever, write NONSTOP. (To stop a      */
  110. /*        sound call the function StopSound().)                          */
  111. /*                                                                       */
  112. /* start: (ULONG) Where in the sound data we should start to play. (If   */
  113. /*        you want to start at the beginning of the sound data set start */
  114. /*        to 0.)                                                         */
  115. /*                                                                       */
  116. /* time:  (ULONG) For how long time the sound should be played. If you   */
  117. /*        want to play all of the sound data set time to 0.              */
  118. /*                                                                       */
  119. /* wait:  (BOOL) Set this parameter to WAIT if you want to wait for the  */
  120. /*        sound to be completed. If you set it to DO_NOT_WAIT, your      */
  121. /*        program will continue to run while the sound is played.        */
  122. /*        NOTE! Do not try to play a sound continiously (times set to    */
  123. /*        NONSTOP) and at the same time set this field to TRUE! The      */
  124. /*        request will then never be completed and your program will     */
  125. /*        come to a dead lock!!                                          */ 
  126.  
  127. BOOL PlaySound
  128. (
  129.   struct SoundInfo *info,
  130.   UWORD volume,
  131.   UBYTE channel,
  132.   BYTE priority,
  133.   WORD delta_rate,
  134.   UWORD times,
  135.   ULONG start,
  136.   ULONG time,
  137.   BOOL wait 
  138. )
  139. {
  140.   /* Before we may play the sound, we must make sure that the sound is */
  141.   /* not already being played. We will therefore call the function     */
  142.   /* StopSound(), in order to stop the sound if it is playing:         */
  143.   StopSound( channel );
  144.  
  145.   /* Call the PrepareIOA() function that will declare and initialize an */
  146.   /* IOAudio structure:                                 */
  147.   if( PrepareIOA( CLOCK_CONSTANT / info->RecordRate + delta_rate, volume,
  148.                   times, channel, priority, info, start, time ) )
  149.   {
  150.     /* We will now start playing the sound: */
  151.     BeginIO( IOA[ channel ] );
  152.  
  153.     /* Should we wait for the sound to be completed? */
  154.     if( wait )
  155.       WaitIO( IOA[ channel ] );
  156.  
  157.     return( TRUE );  /* OK! */
  158.   }
  159.   else
  160.     return( FALSE ); /* ERROR! */
  161. }
  162.  
  163.  
  164.  
  165. /* StopSound()                                                         */
  166. /* StopSound() will stop the specified audio channel from continuing   */
  167. /* to play the sound. It will also close all devices and ports that    */
  168. /* have been opened, and deallocate some memory that have been         */
  169. /* allocated.                                                          */
  170. /*                                                                     */
  171. /* Synopsis: StopSound( channel );                                     */
  172. /*                                                                     */
  173. /* channel:  (UBYTE) The audio channel that should be stopped.         */
  174. /*           (LEFT0, LEFT1, RIGHT0 or RIGHT1.)                         */
  175.  
  176. void StopSound( UBYTE channel )
  177. {
  178.   /* Check if the IOAudio structure exist: */
  179.   if( IOA[ channel ] )
  180.   {
  181.     /* 1. Stop the sound: */
  182.     AbortIO( IOA[ channel ] );
  183.    
  184.     /* 2. If there exist a Sound Device, close it: */
  185.     if( IOA[ channel ]->ioa_Request.io_Device )
  186.     CloseDevice( IOA[ channel ] );
  187.  
  188.     /* 3. If there exist a Message Port, delete it: */
  189.     if( IOA[ channel ]->ioa_Request.io_Message.mn_ReplyPort )
  190.       DeletePort( IOA[ channel ]->ioa_Request.io_Message.mn_ReplyPort );
  191.  
  192.     /* 4. Remove the request block: */
  193.     DeleteExtIO( IOA[ channel ], sizeof( struct IOAudio ) );
  194.     
  195.     /* 5. Set the pointer to NULL so we know that this */
  196.     /*    request has now been deleted:                */
  197.     IOA[ channel ] = NULL;
  198.   }
  199. }
  200.  
  201.  
  202.  
  203. /* PrepareIOA()                                                         */
  204. /* PrepareIOA() allocates and initializes an IOAudio structure.         */
  205. /*                                                                      */
  206. /* Synopsis: ok = PrepareIOA( per, vol, cyc, cha, ptr, start, time );   */
  207. /*                                                                      */
  208. /* ok:    (BOOL) If the IOAudio structure was allocated and             */
  209. /*        initialized successfully, TRUE is returned, else FALSE.       */
  210. /* per:   (UWORD) Period time.                                          */
  211. /* vol:   (UWORD) Volume, 0 to 64.                                      */
  212. /* cyc:   (UWORD) How many times the sound should be played.            */
  213. /*        (0 : forever)                                                 */
  214. /* cha:   (UBYTE) Which channel should be used. (LEFT0, RIGHT0,         */
  215. /*        RIGHT1 or LEFT1)                                              */
  216. /* ptr:   (struct SoundInfo *) Pointer to a SoundInfo structure.        */
  217. /* start: (ULONG) Where in the sound data we should start to play.      */
  218. /* time:  (ULONG) For how long time the sound should be played.         */
  219.  
  220. BOOL PrepareIOA
  221. (
  222.   UWORD period,
  223.   UWORD volume,
  224.   UWORD cycles,
  225.   UBYTE channel,
  226.   BYTE priority,
  227.   struct SoundInfo *info,
  228.   ULONG start,
  229.   ULONG time
  230. )
  231. {
  232.   /* Store error numbers here: */
  233.   BYTE error;
  234.  
  235.   /* Declare a pointer to a MsgPort structure: */ 
  236.   struct MsgPort *port;
  237.  
  238.  
  239.  
  240.   /* Get a reply port: (No name, normal priority) */
  241.   port = (struct MsgPort *)
  242.     CreatePort( NULL, 0 );
  243.     
  244.   /* Did we get a reply port? */  
  245.   if( !port )
  246.   {
  247.     /* Bad news! We did not get a reply port. */
  248.     
  249.     /* Return with an error value: */
  250.     return( FALSE );
  251.   }
  252.  
  253.  
  254.  
  255.   /* Create an IOAudio request: */
  256.   IOA[ channel ] = (struct IOAudio *)
  257.     CreateExtIO( port, sizeof( struct IOAudio ) );
  258.  
  259.   /* Could we allocate enough memory? */
  260.   if( !IOA[ channel ] )
  261.   {
  262.     /* Tough luck! We did not get a request block. */
  263.  
  264.     /* Close the reply port: */
  265.     DeletePort( port );
  266.     
  267.     /* Return with an error value: */
  268.     return( FALSE );
  269.   }
  270.  
  271.  
  272.  
  273.   /* Initialize the IOAudion structure: */
  274.       
  275.   /* Set priority: */
  276.   IOA[ channel ]->ioa_Request.io_Message.mn_Node.ln_Pri = priority;
  277.     
  278.   /* Set channel: (This program tries to reserve one specific */
  279.   /* audio channel. It does not support an allocation array   */
  280.   /* with several options.)                                   */
  281.   info->channel_bit = 1<<channel;
  282.  
  283.   /* Give the request block a pointer to our simple allocation array: */
  284.   IOA[ channel ]->ioa_Data = &(info->channel_bit);
  285.     
  286.   /* Set the length of our allocation array: */
  287.   IOA[ channel ]->ioa_Length = sizeof( UBYTE );
  288.     
  289.   /* Open Audio Device: */
  290.   error =  OpenDevice( AUDIONAME, 0, IOA[ channel ], 0);
  291.  
  292.   /* Have wee successfully opened it? */
  293.   if( error )
  294.   {
  295.     /* Hard times! Could not open the device! */
  296.  
  297.     /* Delete the request block: */
  298.     DeleteExtIO( IOA[ channel ], sizeof(struct IOAudio) );
  299.     
  300.     /* Close the reply port: */
  301.     DeletePort( port );
  302.  
  303.     /* Set audio pointer to NULL so we know that */
  304.     /* we do not have any request block here:    */
  305.     IOA[ channel ] = NULL;
  306.  
  307.     /* Return with an error value: */
  308.     return( FALSE ); /* ERROR! */
  309.   }
  310.  
  311.  
  312.  
  313.   /* We now have a reply port, a request block, one  */
  314.   /* audio channel reserved and the audio device has */
  315.   /* been opened. Prepare to play:                   */ 
  316.  
  317.  
  318.  
  319.   /* Initialize the request block with the users requirements: */
  320.   IOA[ channel ]->ioa_Request.io_Flags = ADIOF_PERVOL;
  321.  
  322.   /* We want to play sound (write data to the audio device): */
  323.   IOA[ channel ]->ioa_Request.io_Command = CMD_WRITE;
  324.  
  325.   /* Set period value: */
  326.   IOA[ channel ]->ioa_Period = period;
  327.  
  328.   /* Set volume: */
  329.   IOA[ channel ]->ioa_Volume = volume;
  330.  
  331.   /* Number of times the sound wave should be played: */
  332.   IOA[ channel ]->ioa_Cycles = cycles;
  333.  
  334.   /* If the user has specified a play time we use */
  335.   /* it, else we play the complete sound:         */
  336.   if( time )
  337.     IOA[ channel ]->ioa_Length = time;
  338.   else
  339.     IOA[ channel ]->ioa_Length = info->FileLength;
  340.  
  341.   /* Set start position in the waveform: */
  342.   IOA[ channel ]->ioa_Data = info->SoundBuffer + start;
  343.  
  344.  
  345.  
  346.   /* Everything has been prepared, return with OK: */
  347.   return( TRUE );
  348. }
  349.  
  350.  
  351.  
  352.