home *** CD-ROM | disk | FTP | other *** search
/ World of A1200 / World_Of_A1200.iso / datafiles / text / c_manual / sound / easysound / easysound.c < prev    next >
C/C++ Source or Header  |  1995-02-27  |  27KB  |  757 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: EasySound                   Tulevagen 22       */
  8. /* File:    EasySound.c                 181 41  LIDINGO    */
  9. /* Author:  Anders Bjerin               SWEDEN             */
  10. /* Date:    92-05-10                                       */
  11. /* Version: 2.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 "EasySound.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. typedef LONG Fixed;
  38. typedef struct
  39. {
  40.   ULONG  oneShotHiSamples;  /* #samples in the high octave 1-shot part */
  41.   ULONG  repeatHiSamples;   /* #samples in the high octave repeat part */
  42.   ULONG  samplesPerHiCycle; /* #samples/cycle in high octave, else 0   */
  43.   UWORD  samplesPerSec;     /* Data sampling rate */
  44.   UBYTE  ctOctave;          /* Number of octaves of waveforms */
  45.   UBYTE  sCompression;      /* Data compression technique used */
  46.   Fixed  volume;            /* Playback volume from 0 to 0x10000 */
  47. } Voice8Header;
  48.  
  49.  
  50.  
  51. /* Declare the functions we are going to use: */
  52.  
  53. BOOL ESPlaySound(
  54.   struct SoundInfo *info,
  55.   UWORD volume,
  56.   UBYTE channel,
  57.   BYTE priority,
  58.   WORD delta_rate,
  59.   UWORD repeat,
  60.   ULONG start,
  61.   ULONG time,
  62.   BOOL wait 
  63. );
  64.  
  65. void ESStopSound( UBYTE channel );
  66.  
  67. BOOL ESPrepareIOA(
  68.   UWORD period,
  69.   UWORD volume,
  70.   UWORD cycles,
  71.   UBYTE channel,
  72.   BYTE priority,
  73.   struct SoundInfo *info,
  74.   ULONG start,
  75.   ULONG time
  76. );
  77.  
  78. void ESRemoveSound( struct SoundInfo *info );
  79.  
  80. struct SoundInfo *ESPrepareSound( STRPTR file );
  81.  
  82. UWORD ESLoadSound( STRPTR filename, struct SoundInfo *info );
  83.  
  84. ULONG ESGetSize( STRPTR filename );
  85.  
  86. ULONG ESSizeIFF( STRPTR filename );
  87.  
  88. UWORD ESReadIFF( STRPTR filename, struct SoundInfo *info );
  89.  
  90. BOOL ESMoveTo( STRPTR check_string, FILE *file_ptr );
  91.  
  92.  
  93.  
  94. /* ESPlaySound()                                                         */
  95. /* ESPlaySound() plays one already prepared sound effect. You can decide */
  96. /* what volume, which channel, what rate, which priority, how many times */
  97. /* the sound should be played and so on...                               */
  98. /*                                                                       */
  99. /* Synopsis: ok = PlaySound( ptr, vol, cha, pri, drate, times, start,    */
  100. /*                           time, wait );                               */
  101. /*                                                                       */
  102. /* ok:    (BOOL) If the sound was played successfully TRUE is            */
  103. /*        returned, else FALSE.                                          */
  104. /*                                                                       */
  105. /* ptr:   (struct SoundInfo *) Pointer to a SoundInfo structure. This    */
  106. /*        pointer was returned by PrepareSound().                        */
  107. /*                                                                       */
  108. /* vol:   (UWORD) Volume, 0 to 64.                                       */
  109. /*                                                                       */
  110. /* cha:   (UBYTE) Which channel should be used. (LEFT0, RIGHT0,          */
  111. /*        RIGHT1 or LEFT1)                                               */
  112. /*                                                                       */
  113. /* pri:   (BYTE) What priority should be used. See header file for a     */
  114. /*        complete list of recommended priorities.                       */
  115. /*                                                                       */
  116. /* drate: (WORD) Delta rate. When the sound is prepared, the record      */
  117. /*        rate is automatically stored in the SoundInfo structure,       */
  118. /*        so if you do not want to change the rate, write NORMALRATE.    */
  119. /*                                                                       */
  120. /* times: (UWORD) How many times the sound should be played. If you      */
  121. /*        want to play the sound forever, write NONSTOP. (To stop a      */
  122. /*        sound call the function StopSound().)                          */
  123. /*                                                                       */
  124. /* start: (ULONG) Where in the sound data we should start to play. (If   */
  125. /*        you want to start at the beginning of the sound data set start */
  126. /*        to 0.)                                                         */
  127. /*                                                                       */
  128. /* time:  (ULONG) For how long time the sound should be played. If you   */
  129. /*        want to play all of the sound data set time to 0.              */
  130. /*                                                                       */
  131. /* wait:  (BOOL) Set this parameter to WAIT if you want to wait for the  */
  132. /*        sound to be completed. If you set it to DO_NOT_WAIT, your      */
  133. /*        program will continue to run while the sound is played.        */
  134. /*        NOTE! Do not try to play a sound continiously (times set to    */
  135. /*        NONSTOP) and at the same time set this field to TRUE! The      */
  136. /*        request will then never be completed and your program will     */
  137. /*        come to a dead lock!!                                          */ 
  138.  
  139. BOOL ESPlaySound(
  140.   struct SoundInfo *info,
  141.   UWORD volume,
  142.   UBYTE channel,
  143.   BYTE priority,
  144.   WORD delta_rate,
  145.   UWORD times,
  146.   ULONG start,
  147.   ULONG time,
  148.   BOOL wait 
  149. )
  150. {
  151.   /* Before we may play the sound, we must make sure that the sound is */
  152.   /* not already being played. We will therefore call the function     */
  153.   /* ISStopSound(), in order to stop the sound if it is playing:       */
  154.   ESStopSound( channel );
  155.  
  156.   /* Call the PrepareIOA() function that will declare and initialize an */
  157.   /* IOAudio structure:                                 */
  158.   if( ESPrepareIOA( CLOCK_CONSTANT / info->RecordRate + delta_rate, volume,
  159.                   times, channel, priority, info, start, time ) )
  160.   {
  161.     /* We will now start playing the sound: */
  162.     BeginIO( IOA[ channel ] );
  163.  
  164.     /* Should we wait for the sound to be completed? */
  165.     if( wait )
  166.       WaitIO( IOA[ channel ] );
  167.  
  168.     return( TRUE );  /* OK! */
  169.   }
  170.   else
  171.     return( FALSE ); /* ERROR! */
  172. }
  173.  
  174.  
  175.  
  176. /* ESStopSound()                                                       */
  177. /* ESStopSound() will stop the specified audio channel from continuing */
  178. /* to play the sound. It will also close all devices and ports that    */
  179. /* have been opened, and deallocate some memory that have been         */
  180. /* allocated.                                                          */
  181. /*                                                                     */
  182. /* Synopsis: ISStopSound( channel );                                   */
  183. /* channel:  (UBYTE) The audio channel that should be stopped. (LEFT0, */
  184. /*           LEFT1, RIGHT0 or RIGHT1.)                                 */
  185.  
  186. void ESStopSound( UBYTE channel )
  187. {
  188.   /* Check if the IOAudio structure exist: */
  189.   if( IOA[ channel ] )
  190.   {
  191.     /* 1. Stop the sound: */
  192.     AbortIO( IOA[ channel ] );
  193.    
  194.     /* 2. If there exist a Sound Device, close it: */
  195.     if( IOA[ channel ]->ioa_Request.io_Device )
  196.     CloseDevice( IOA[ channel ] );
  197.  
  198.     /* 3. If there exist a Message Port, delete it: */
  199.     if( IOA[ channel ]->ioa_Request.io_Message.mn_ReplyPort )
  200.       DeletePort( IOA[ channel ]->ioa_Request.io_Message.mn_ReplyPort );
  201.  
  202.     /* 4. Remove the request block: */
  203.     DeleteExtIO( IOA[ channel ], sizeof( struct IOAudio ) );
  204.     
  205.     /* 5. Set the pointer to NULL so we know that this */
  206.     /*    request has now been deleted:                */
  207.     IOA[ channel ] = NULL;
  208.   }
  209. }
  210.  
  211.  
  212.  
  213. /* ESPrepareIOA()                                                       */
  214. /* ESPrepareIOA() allocates and initializes an IOAudio structure.       */
  215. /*                                                                      */
  216. /* Synopsis: ok = ISPrepareIOA( per, vol, cyc, cha, ptr, start, time ); */
  217. /*                                                                      */
  218. /* ok:    (BOOL) If the IOAudio structure was allocated and             */
  219. /*        initialized successfully, TRUE is returned, else FALSE.       */
  220. /* per:   (UWORD) Period time.                                          */
  221. /* vol:   (UWORD) Volume, 0 to 64.                                      */
  222. /* cyc:   (UWORD) How many times the sound should be played.            */
  223. /*        (0 : forever)                                                 */
  224. /* cha:   (UBYTE) Which channel should be used. (LEFT0, RIGHT0,         */
  225. /*        RIGHT1 or LEFT1)                                              */
  226. /* ptr:   (struct SoundInfo *) Pointer to a SoundInfo structure.        */
  227. /* start: (ULONG) Where in the sound data we should start to play.      */
  228. /* time:  (ULONG) For how long time the sound should be played.         */
  229.  
  230. BOOL ESPrepareIOA(
  231.   UWORD period,
  232.   UWORD volume,
  233.   UWORD cycles,
  234.   UBYTE channel,
  235.   BYTE priority,
  236.   struct SoundInfo *info,
  237.   ULONG start,
  238.   ULONG time
  239. )
  240. {
  241.   /* Store error numbers here: */
  242.   BYTE error;
  243.  
  244.   /* Declare a pointer to a MsgPort structure: */ 
  245.   struct MsgPort *port;
  246.  
  247.  
  248.  
  249.   /* Get a reply port: (No name, normal priority) */
  250.   port = (struct MsgPort *)
  251.     CreatePort( NULL, 0 );
  252.     
  253.   /* Did we get a reply port? */  
  254.   if( !port )
  255.   {
  256.     /* Bad news! We did not get a reply port. */
  257.     
  258.     /* Return with an error value: */
  259.     return( FALSE );
  260.   }
  261.  
  262.  
  263.  
  264.   /* Create an IOAudio request: */
  265.   IOA[ channel ] = (struct IOAudio *)
  266.     CreateExtIO( port, sizeof( struct IOAudio ) );
  267.  
  268.   /* Could we allocate enough memory? */
  269.   if( !IOA[ channel ] )
  270.   {
  271.     /* Tough luck! We did not get a request block. */
  272.  
  273.     /* Close the reply port: */
  274.     DeletePort( port );
  275.     
  276.     /* Return with an error value: */
  277.     return( FALSE );
  278.   }
  279.  
  280.  
  281.  
  282.   /* Initialize the IOAudion structure: */
  283.       
  284.   /* Set priority: */
  285.   IOA[ channel ]->ioa_Request.io_Message.mn_Node.ln_Pri = priority;
  286.     
  287.   /* Set channel: (This program tries to reserve one specific */
  288.   /* audio channel. It does not support an allocation array   */
  289.   /* with several options.)                                   */
  290.   info->channel_bit = 1<<channel;
  291.  
  292.   /* Give the request block a pointer to our simple allocation array: */
  293.   IOA[ channel ]->ioa_Data = &(info->channel_bit);
  294.     
  295.   /* Set the length of our allocation array: */
  296.   IOA[ channel ]->ioa_Length = sizeof( UBYTE );
  297.     
  298.   /* Open Audio Device: */
  299.   error =  OpenDevice( AUDIONAME, 0, IOA[ channel ], 0);
  300.  
  301.   /* Have wee successfully opened it? */
  302.   if( error )
  303.   {
  304.     /* Hard times! Could not open the device! */
  305.  
  306.     /* Delete the request block: */
  307.     DeleteExtIO( IOA[ channel ], sizeof(struct IOAudio) );
  308.     
  309.     /* Close the reply port: */
  310.     DeletePort( port );
  311.  
  312.     /* Set audio pointer to NULL so we know that */
  313.     /* we do not have any request block here:    */
  314.     IOA[ channel ] = NULL;
  315.  
  316.     /* Return with an error value: */
  317.     return( FALSE ); /* ERROR! */
  318.   }
  319.  
  320.  
  321.  
  322.   /* We now have a reply port, a request block, one  */
  323.   /* audio channel reserved and the audio device has */
  324.   /* been opened. Prepare to play:                   */ 
  325.  
  326.  
  327.  
  328.   /* Initialize the request block with the users requirements: */
  329.   IOA[ channel ]->ioa_Request.io_Flags = ADIOF_PERVOL;
  330.  
  331.   /* We want to play sound (write data to the audio device): */
  332.   IOA[ channel ]->ioa_Request.io_Command = CMD_WRITE;
  333.  
  334.   /* Set period value: */
  335.   IOA[ channel ]->ioa_Period = period;
  336.  
  337.   /* Set volume: */
  338.   IOA[ channel ]->ioa_Volume = volume;
  339.  
  340.   /* Number of times the sound wave should be played: */
  341.   IOA[ channel ]->ioa_Cycles = cycles;
  342.  
  343.   /* If the user has specified a play time we use */
  344.   /* it, else we play the complete sound:         */
  345.   if( time )
  346.     IOA[ channel ]->ioa_Length = time;
  347.   else
  348.     IOA[ channel ]->ioa_Length = info->FileLength;
  349.  
  350.   /* Set start position in the waveform: */
  351.   IOA[ channel ]->ioa_Data = info->SoundBuffer + start;
  352.  
  353.  
  354.  
  355.   /* Everything has been prepared, return with OK: */
  356.   return( TRUE );
  357. }
  358.  
  359.  
  360.  
  361. /* ESRemoveSound()                                                        */
  362. /* ESRemoveSound() will stop playing the sound, and deallocate all memory */
  363. /* that was allocated by the PrepareSound() function. Before your program */
  364. /* terminates, all soundeffects that have been prepared, MUST be removed. */
  365. /*                                                                        */
  366. /* IMPORTANT! Each channel that is currently playing the sound must be    */
  367. /* stopped before you may remove the sound!!!! (Use the ESStopSound()     */
  368. /* function.)                                                             */
  369. /*                                                                        */
  370. /* Synopsis: ESRemoveSound( pointer );                                    */
  371. /*                                                                        */
  372. /* pointer:  (struct SoundInfo *) Pointer to a SoundInfo structure.       */
  373.  
  374. void ESRemoveSound( struct SoundInfo *info )
  375. {
  376.   /* IMPORTANT! The sound must have been */
  377.   /* stopped before you may remove it!!! */
  378.  
  379.   /* Have we allocated a SoundInfo structure? */
  380.   if( info )
  381.   {
  382.     /* Deallocate the sound buffer: */
  383.     FreeMem( info->SoundBuffer, info->FileLength );
  384.  
  385.     /* Deallocate the SoundInfo structure: */
  386.     FreeMem( info, sizeof( struct SoundInfo ) );
  387.     info = NULL;
  388.   }
  389. }
  390.  
  391.  
  392.  
  393. /* ESPrepareSound()                                                      */
  394. /* ESPrepareSound() loads a sampled sound file (IFF or FutureSound) into */
  395. /* a buffer that is automatically allocated. All information about the   */
  396. /* sound (record rate, length, buffersize etc) is put into an SoundInfo  */
  397. /* structure. If ESPrepareSound() has successfully prepared the sound it */
  398. /* returns a pointer to a SoundInfo structure, otherwise it returns      */
  399. /* NULL.                                                                 */
  400. /*                                                                       */
  401. /* Synopsis: pointer = ESPrepareSound( filename );                       */
  402. /*                                                                       */
  403. /* pointer:  (struct SoundInfo *) Pointer to a SoundInfo structure.      */
  404. /*                                                                       */
  405. /* filename: (STRPTR) Pointer to a string containing the name of the     */
  406. /*           sound file. For example "df0:Explosion.snd".                */
  407.  
  408. struct SoundInfo *ESPrepareSound( STRPTR file )
  409. {
  410.   /* Declare a pointer to a SoundInfo structure: */
  411.   struct SoundInfo *info;
  412.  
  413.  
  414.  
  415.   /* Allocate memory for a SoundInfo structure: (The memory */
  416.   /* can be of any type, and should be cleared.)            */
  417.   info = (struct SoundInfo *)
  418.     AllocMem( sizeof( struct SoundInfo ), MEMF_CLEAR );
  419.  
  420.   /* Have we successfully allocated the memory? */
  421.   if( !info )
  422.   {
  423.     /* A black day! Not enough memory. */
  424.  
  425.     /* Return error value (NULL): */
  426.     return( NULL );
  427.   }
  428.  
  429.  
  430.   /* Get the size of the sound file, and store */
  431.   /* it in the SoundInfo structure:            */
  432.   info->FileLength = ESGetSize( file );
  433.   
  434.   /* Does the file contain any data? */
  435.   if( info->FileLength == 0 ) 
  436.   {
  437.     /* Not your day! File is empty or we */
  438.     /* have not been able to open it.    */
  439.  
  440.     /* Deallocate the SoundInfo structure: */
  441.     FreeMem( info, sizeof( struct SoundInfo ) );
  442.  
  443.     /* Return error value (NULL): */
  444.     return( NULL );
  445.   }
  446.  
  447.  
  448.  
  449.   /* Allocate enough memory for the sampled sound, and store a  */
  450.   /* pointer to the buffer in the SoundInfo structure: (Remeber */
  451.   /* that sound data must be in chip memory.)                   */
  452.   info->SoundBuffer = (BYTE *)
  453.     AllocMem( info->FileLength, MEMF_CHIP|MEMF_CLEAR );
  454.  
  455.   /* Have we successfully allocated the memory? */
  456.   if( !info->SoundBuffer )
  457.   {
  458.     /* This really &%*£$"! Not enough memory. */
  459.  
  460.     /* Deallocate the SoundInfo structure: */
  461.     FreeMem( info, sizeof( struct SoundInfo ) );
  462.  
  463.     /* Return error value (NULL): */
  464.     return( NULL );
  465.   }
  466.  
  467.  
  468.  
  469.   /* Load the sound, and store the record rate in the SoundInfo  */
  470.   /* structure. If the sound could not be loaded, 0 is returned: */
  471.   info->RecordRate = ESLoadSound( file, info );
  472.   
  473.   if( info->RecordRate == 0 )
  474.   {
  475.     /* Horrible times! Could not load the sound. */
  476.  
  477.     /* Deallocate the sound data buffer: */
  478.     FreeMem( info->SoundBuffer, info->FileLength );
  479.   
  480.     /* Deallocate the SoundInfo structure: */
  481.     FreeMem( info, sizeof( struct SoundInfo ) );
  482.  
  483.     /* Return error value (NULL): */
  484.     return( NULL );
  485.   }
  486.   
  487.  
  488.  
  489.   /* The sound has now successfully been loaded! */
  490.           
  491.   /* Old FutureSound files were saved in kHz. If the record rate */
  492.   /* is less than one hundered, we know it is an old FutureSound */
  493.   /* file, and simply multiply the rate with one thousand:       */
  494.   if( info->RecordRate < 100 )
  495.     info->RecordRate *= 1000;
  496.  
  497.  
  498.           
  499.   /* Return a pointer to the SoundInfo structure: */
  500.   return( info );
  501. }
  502.  
  503.  
  504.  
  505. /* ESLoadSound()                                                       */
  506. /* ESLoadSound() will load sampled sound that was either saved in IFF  */
  507. /* or FutureSound format.                                              */
  508. /*                                                                     */
  509. /* Synopsis: rate = ESLoadSound( filename, pointer );                  */
  510. /*                                                                     */
  511. /* rate:     (UWORD) The record rate is returned if the sound was      */
  512. /*           successfully loaded, else 0.                              */
  513. /*                                                                     */
  514. /* filename: (STRPTR) Pointer to a string containing the name of the   */
  515. /*           sound file. For example "df0:Explosion.snd".              */
  516. /*                                                                     */
  517. /* pointer:  (struct SoundInfo *) Pointer to a SoundInfo structure.    */
  518.  
  519. UWORD ESLoadSound( STRPTR filename, struct SoundInfo *info )
  520. {
  521.   FILE  *file_ptr;   /* Pointer to a file. */
  522.   ULONG length;      /* Data Length. */
  523.   UWORD record_rate; /* Record rate. */
  524.  
  525.  
  526.   /* Check if it is an IFF File: */
  527.   if( ESSizeIFF( filename ) )
  528.   {
  529.     /* Yes, it is an IFF file. Read it: */
  530.     return( ESReadIFF( filename, info ) );
  531.   }
  532.   else
  533.   {
  534.     /* No, then it is probably a FutureSound file. */
  535.     /* Open the file so we can read it:            */
  536.     if( (file_ptr = fopen( filename, "r" )) == 0 )
  537.       return( 0 ); /* ERROR! Could not open the file! */
  538.  
  539.     /* Read the data length: */
  540.     if( fread( (char *) &length, sizeof( ULONG ), 1, file_ptr ) == 0 )
  541.     {
  542.       /* ERROR! Could not read the data length! */
  543.       /* Close the file, and return zero:       */
  544.       fclose( file_ptr );
  545.       return( 0 );
  546.     }
  547.  
  548.     /* Read the record rate: */
  549.     if( fread( (char *) &record_rate, sizeof( UWORD ), 1, file_ptr ) == 0 )
  550.     {
  551.       /* ERROR! Could not read the record rate! */
  552.       /* Close the file, and return zero:       */
  553.       fclose( file_ptr );
  554.       return( 0 );
  555.     }
  556.  
  557.     /* Read the sampled sound data into the buffer: */
  558.     if( fread( (char *) info->SoundBuffer, length, 1, file_ptr ) == 0 )
  559.     {
  560.       /* ERROR! Could not read the data!  */
  561.       /* Close the file, and return zero: */    
  562.       fclose( file_ptr );
  563.       return( 0 );
  564.     }
  565.  
  566.     /* Close the file: */
  567.     fclose( file_ptr );
  568.  
  569.     /* Return the record rate: */
  570.     return( record_rate );
  571.   }
  572. }
  573.  
  574.  
  575.  
  576. /* ESGetSize()                                                        */
  577. /* ESGetSize() returns the size of the file which was saved in either */
  578. /* IFF or FutureSound format.                                         */
  579. /*                                                                    */
  580. /* Synopsis: length = ESGetSize( filename );                          */
  581. /*                                                                    */
  582. /* length:   (ULONG) Data length.                                     */
  583. /*                                                                    */
  584. /* filename: (STRPTR) Pointer to a string containing the name of the  */
  585. /*           sound file. For example "df0:Explosion.snd".             */
  586.  
  587. ULONG ESGetSize( STRPTR filename )
  588. {
  589.   FILE *file_ptr; /* Pointer to a file. */
  590.   ULONG length;  /* Data length. */
  591.  
  592.  
  593.   /* Check if it is an IFF File: */
  594.   if( ( length = ESSizeIFF( filename ) ) == 0 )
  595.   {
  596.     /* No, then it is probably a FutureSound file. */
  597.     /* Open the file so we can read it:            */
  598.     if( ( file_ptr = fopen( filename, "r" ) ) == 0 )
  599.       return( 0 ); /* ERROR! Could not open the file! */
  600.  
  601.     /* Read the data length: */
  602.     if( fread( (char *) &length, sizeof( ULONG ), 1, file_ptr ) == 0)
  603.     {
  604.       /* ERROR! Could not read the data length! */
  605.       /* Close the file, and return zero:       */
  606.       fclose( file_ptr );
  607.       return( 0 );
  608.     }
  609.     
  610.     /* Close the file: */
  611.     fclose( file_ptr );
  612.   }
  613.   return( length );
  614. }
  615.  
  616.  
  617.  
  618. /* ESSizeIFF()                                                       */
  619. /* ESSizeIFF() returns the size of an IFF file, or zero if something */
  620. /* went wrong (for example, It was not an IFF file).                 */
  621. /*                                                                   */
  622. /* Synopsis: length = ESSizeIFF( filename );                         */
  623. /*                                                                   */
  624. /* length:   (ULONG) Data length.                                    */
  625. /*                                                                   */
  626. /* filename: (STRPTR) Pointer to a string containing the name of the */
  627. /*           IFF file. For example "df0:Explosion.snd".              */
  628.  
  629. ULONG ESSizeIFF( STRPTR filename )
  630. {
  631.   FILE  *file_ptr;              /* Pointer to a file. */
  632.   STRPTR empty_string = "    "; /* Four spaces. */ 
  633.   LONG dummy;                   /* A dummy variable. */
  634.   Voice8Header Header;          /* Voice8Header structure. */
  635.  
  636.  
  637.   /* Try to open the file: */
  638.   if( file_ptr = fopen( filename, "r" ) )
  639.   {
  640.     fread( (char *) empty_string, 4, 1, file_ptr );
  641.     if( strcmp( empty_string, "FORM" ) == 0)
  642.     {
  643.       /* Read twice: */
  644.       fread( (char *) empty_string, 4, 1, file_ptr );
  645.       fread( (char *) empty_string, 4, 1, file_ptr );
  646.  
  647.       /* Check if it is a "8SVX" file, or not: */
  648.       if( strcmp( empty_string, "8SVX" ) == 0 )
  649.       {
  650.         ESMoveTo( "VHDR", file_ptr );
  651.         fread( (char *) &dummy, sizeof( LONG ), 1, file_ptr );
  652.         fread( (char *) &Header, sizeof( Header ), 1, file_ptr );
  653.  
  654.         /* Close the file, and return the length: */
  655.         fclose( file_ptr );
  656.         return( Header.oneShotHiSamples + Header.repeatHiSamples );
  657.       }
  658.     }
  659.     /* Close the file: */
  660.     fclose( file_ptr );
  661.   }
  662.   /* Return zero: (ERROR) */
  663.   return( 0 );
  664. }
  665.  
  666.  
  667.  
  668. /* ESReadIFF()                                                           */
  669. /* ESReadIFF() reads an IFF file into the buffer, and returns the record */
  670. /* rate.                                                                 */
  671. /*                                                                       */
  672. /* Synopsis: rate = ESReadIFF( filename, pointer );                      */
  673. /*                                                                       */
  674. /* rate:     (UWORD) The record rate is returned if the sound was        */
  675. /*           successfully loaded, else 0.                                */
  676. /*                                                                       */
  677. /* filename: (STRPTR) Pointer to a string containing the name of the     */
  678. /*           sound file. For example "df0:Explosion.snd".                */
  679. /*                                                                       */
  680. /* pointer:  (struct SoundInfo *) Pointer to a SoundInfo structure.      */
  681.  
  682. UWORD ESReadIFF( STRPTR filename, struct SoundInfo *info )
  683. {
  684.   FILE  *file_ptr;              /* Pointer to a file. */
  685.   STRPTR empty_string = "    "; /* Four spaces. */ 
  686.   LONG dummy;                   /* A dummy variable. */
  687.   Voice8Header Header;          /* Voice8Header structure. */
  688.  
  689.  
  690.   /* Try to open the file: */
  691.   if( file_ptr = fopen( filename, "r" ) )
  692.   {
  693.     fread( (char *) empty_string, 4, 1, file_ptr );
  694.     if( strcmp( empty_string, "FORM" ) == 0 )
  695.     {
  696.       /* Read twice: */
  697.       fread( (char *) empty_string, 4, 1, file_ptr );
  698.       fread( (char *) empty_string, 4, 1, file_ptr );
  699.  
  700.       /* Check if it is a "8SVX" file, or not: */
  701.       if( strcmp( empty_string, "8SVX" ) == 0 )
  702.       {
  703.         ESMoveTo( "VHDR", file_ptr );
  704.         fread( (char *) &dummy, sizeof( LONG ), 1, file_ptr );
  705.         fread( (char *) &Header, sizeof( Header ), 1, file_ptr );
  706.  
  707.         ESMoveTo( "BODY", file_ptr );
  708.         fread( (char *) &dummy, sizeof( LONG ), 1, file_ptr );
  709.         fread( (char *) info->SoundBuffer, Header.oneShotHiSamples +
  710.                                  Header.repeatHiSamples, 1, file_ptr );
  711.  
  712.         /* Close the file, and return the record rate: */
  713.         fclose( file_ptr );
  714.         return( Header.samplesPerSec );
  715.       }
  716.     }
  717.     /* Close the file: */
  718.     fclose( file_ptr );
  719.   }
  720.   /* Return zero: (ERROR) */
  721.   return( 0 );
  722.  
  723.  
  724.  
  725. /* ESMoveTo()                                                  */
  726. /* ESMoveTo() walks through an IFF file, and looks for chunks. */
  727. /*                                                             */
  728. /* Synopsis: ESMoveTo( chunk, file_ptr );                      */
  729. /*                                                             */
  730. /* chunk:    (STRPTR) The chunk we want to get to.             */
  731. /*                                                             */
  732. /* file_ptr: (FILE *) Pointer to an already opened file.       */
  733.  
  734. BOOL ESMoveTo( STRPTR check_string, FILE *file_ptr )
  735. {
  736.   STRPTR empty_string = "    "; /* Four spaces. */ 
  737.   int skip, loop;               /* How much data should be skiped. */
  738.   LONG dummy;                   /* A dummy variable. */
  739.  
  740.  
  741.   /* As long as we have not reached the EOF, continue: */
  742.   while( !feof( file_ptr ) )
  743.   {
  744.     fread( (char *) empty_string, 4, 1, file_ptr);
  745.  
  746.     /* Have we found the right chunk? */    
  747.     if( strcmp( check_string, empty_string ) ==0 )
  748.       return( 0 ); /* YES! Return nothing. */
  749.  
  750.     /* Move foreward: */
  751.     fread( (char *) &skip, sizeof( LONG ), 1, file_ptr );
  752.     for( loop = 0; loop < skip; loop++ )
  753.       fread( (char *) &dummy, 1, 1, file_ptr);
  754.   }
  755. }
  756.