home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / sound / sampplay / intsnd.lha / easysound.c < prev    next >
C/C++ Source or Header  |  1993-01-20  |  22KB  |  617 lines

  1. /*   EasySound.c
  2.  
  3.      EEEEE  AAA   SSS Y   Y       SSS   OOO  U   U N   N DDD
  4.      E     A   A S     Y Y       S     O   O U   U NN  N D  D
  5.      EEEE  AAAAA  SSS   Y   ===   SSS  O   O U   U N N N D   D
  6.      E     A   A     S  Y            S O   O U   U N  NN D  D
  7.      EEEEE A   A SSSS   Y        SSSS   OOO   UUU  N   N DDD
  8.  
  9.  
  10.      EASY-SOUND   V2.00   1990-09-23   ANDERS BJERIN
  11.  
  12.      AMIGA C CLUB (ACC)
  13.      Anders Bjerin
  14.          Tulevagen 22
  15.          181 41  LIDINGO
  16.          SWEDEN
  17. */
  18.  
  19.  
  20.  
  21. /* Include some important header files: */
  22. #include <exec/types.h>
  23. #include <exec/memory.h>
  24. #include <devices/audio.h> 
  25. #include <stdio.h>
  26.  
  27.  
  28. #define CLOCK_CONSTANT 3579545
  29. #define MUSIC_PRIORITY 0
  30.  
  31.  
  32. /* Structure containing all necessary information about the sound: */
  33. struct SoundInfo
  34. {
  35.   BYTE *SoundBuffer;   /* WaveForm Buffers */
  36.   UWORD RecordRate;    /* Record Rate */
  37.   ULONG FileLength;    /* WaveForm Lengths */
  38. };
  39.  
  40.  
  41. /* An IOAudio pointer to each sound channel: */
  42. struct IOAudio *IOA[ 4 ] = { NULL, NULL, NULL, NULL };
  43.  
  44.  
  45. typedef LONG Fixed;
  46. typedef struct
  47. {
  48.   ULONG  oneShotHiSamples;  /* #samples in the high octave 1-shot part */
  49.   ULONG  repeatHiSamples;   /* #samples in the high octave repeat part */
  50.   ULONG  samplesPerHiCycle; /* #samples/cycle in high octave, else 0   */
  51.   UWORD  samplesPerSec;     /* Data sampling rate */
  52.   UBYTE  ctOctave;          /* Number of octaves of waveforms */
  53.   UBYTE  sCompression;      /* Data compression technique used */
  54.   Fixed  volume;            /* Playback volume from 0 to 0x10000 */
  55. } Voice8Header;
  56.  
  57.  
  58. /* Declare the functions we are going to use: */
  59. CPTR PrepareSound();
  60. BOOL PlaySound();
  61. void StopSound();
  62. void RemoveSound();
  63.  
  64. BOOL PrepareIOA();
  65. UWORD LoadSound();
  66. ULONG GetSize();
  67. ULONG SizeIFF();
  68. UWORD ReadIFF();
  69. BOOL MoveTo();
  70.  
  71.  
  72.  
  73. /* PrepareSound()                                                       */
  74. /* PrepareSound() loads a sampled sound file (IFF or FutureSound) into  */
  75. /* a buffer that is automatically allocated. All information about the  */
  76. /* sound (record rate, length, buffersize etc) is put into an SoundInfo */
  77. /* structure. If PrepareSound() has successfully prepared the sound it  */
  78. /* returns a pointer to a SoundInfo structure, otherwise it returns     */
  79. /* NULL.                                                                */
  80. /*                                                                      */
  81. /* Synopsis: pointer = PrepareSound( filename );                        */
  82. /* pointer:  (CPTR) Actually a pointer to a SoundInfo structure, but    */
  83. /*           since we do not want to confuse the user, we simply use a  */
  84. /*           normal memory pointer.                                     */
  85. /* filename: (STRPTR) Pointer to a string containing the name of the    */
  86. /*           sound file. For example "df0:Explosion.snd".               */
  87.  
  88. CPTR PrepareSound( file )
  89. STRPTR file;
  90. {
  91.   /* Declare a pointer to a SoundInfo structure: */
  92.   struct SoundInfo *info;
  93.  
  94.   /* Allocate memory for a SoundInfo structure: (The memory can be of */
  95.   /* any type, and should be cleared.                                 */
  96.   info = (struct SoundInfo *) AllocMem( sizeof( struct SoundInfo ),
  97.                                         MEMF_PUBLIC|MEMF_CLEAR );
  98.  
  99.  
  100.   if( info )
  101.   {
  102.     /* The memory have been successfully allocated. */ 
  103.     
  104.     /* Get the size of the file, and store it in the SoundInfo struct.: */
  105.     if( info->FileLength = GetSize( file ) )
  106.     {
  107.       /* Allocate enough memory for the sampled sound, and store a */
  108.       /* pointer to the buffer in the SoundInfo structure:         */
  109.       info->SoundBuffer = (BYTE *) AllocMem( info->FileLength,
  110.                                           MEMF_CHIP|MEMF_CLEAR );
  111.  
  112.       if( info->SoundBuffer )
  113.       {
  114.         /* The memory have been successfully allocated. */ 
  115.  
  116.             /* Load the sound, and store the record rate in the SoundInfo  */
  117.                 /* structure. If the sound could not be loaded, 0 is returned: */
  118.         if( info->RecordRate = LoadSound( file, info ) )
  119.         {
  120.                     /* OK! The sound has successfully been loaded. */
  121.           
  122.                     /* Old FutureSound files were saved in kHz. If the record rate */
  123.                     /* is less than one hundered, we know it is an old FutureSound */
  124.                     /* file, and simply multiply the rate with one thousand:       */
  125.           if( info->RecordRate < 100 )
  126.             info->RecordRate *= 1000;
  127.           
  128.                     /* Return a pointer to the SoundInfo structure. (We return a */
  129.                     /* normal memory pointer.)                                   */
  130.                     return( (CPTR) info ); /* OK! */
  131.         }
  132.                 else
  133.         {
  134.                     /* ERROR! We could not load the sound! */
  135.                     
  136.           /* Deallocate the memory for the sound buffer: */
  137.           FreeMem( info->SoundBuffer, info->FileLength );
  138.         }
  139.       }
  140.     }
  141.     /* Deallocate the memory the SoundInfo structure: */
  142.     FreeMem( info, sizeof( struct SoundInfo ) );
  143.   }
  144.     
  145.     /* We have not been able to prepare the sound. All allocated memory */
  146.     /* have been deallocated, and we return NULL.                       */
  147.   return( NULL ); /* ERROR! */
  148. }
  149.  
  150.  
  151.  
  152. /* PlaySound()                                                          */
  153. /* PlaySound() plays one already prepared sound effect. You can decide  */
  154. /* what volume, which channel should, what rate, and how many times the */
  155. /* sound should be played.                                              */ 
  156. /*                                                                      */
  157. /* Synopsis: ok = PlaySound( pointer, volume, channel, drate, times );  */
  158. /* ok:       (BOOL) If the sound was played successfully TRUE is        */
  159. /*           returned, else FALSE.                                      */
  160. /* pointer:  (CPTR) Actually a pointer to a SoundInfo structure. This   */
  161. /*           pointer was returned by PrepareSound().                    */
  162. /* volume:   (UWORD) Volume, 0 to 64.                                   */
  163. /* channel:  (UBYTE) Which channel should be used. (LEFT0, RIGHT0,      */
  164. /*           RIGHT1 or LEFT1)                                           */
  165. /* drate:    (WORD) Delta rate. When the sound is prepared, the record  */
  166. /*           rate is automatically stored in the SoundInfo structure,   */
  167. /*           so if you do not want to change the rate, write 0.         */
  168. /* times:    (UWORD) How many times the sound should be played. If you  */
  169. /*           want to play the sound forever, write 0. (To stop a sound  */
  170. /*           call the function StopSound().)                            */ 
  171.  
  172. BOOL PlaySound( info, volume, channel, delta_rate, repeat )
  173. struct SoundInfo *info;
  174. UWORD volume;
  175. UBYTE channel;
  176. WORD delta_rate;
  177. UWORD repeat;
  178. {
  179.   /* Before we may play the sound, we must make sure that the sound is */
  180.     /* not already being played. We will therefore call the function     */
  181.     /* StopSound(), in order to stop the sound if it is playing:         */
  182.   StopSound( channel );
  183.  
  184.   /* Call the PrepareIOA() function that will declare and initialize an */
  185.     /* IOAudio structure:                                                 */
  186.   if( PrepareIOA( CLOCK_CONSTANT / info->RecordRate + delta_rate, volume,
  187.               repeat, channel, info ) )
  188.   {
  189.     /* We will now start playing the sound: */
  190.     BeginIO( IOA[ channel ] );
  191.     return( TRUE );  /* OK! */
  192.     }
  193.   else
  194.     return( FALSE ); /* ERROR! */
  195. }
  196.  
  197.  
  198.  
  199. /* StopSound()                                                         */
  200. /* StopSound() will stop the specified audio channel from continuing   */
  201. /* to play the sound. It will also close all devices and ports that    */
  202. /* have been opened, and deallocate some memory that have been         */
  203. /* allocated.                                                          */
  204. /*                                                                     */
  205. /* Synopsis: StopSound( channel );                                     */
  206. /* channel:  (UBYTE) The audio channel that should be stopped. (LEFT0, */
  207. /*           LEFT1, RIGHT0 or RIGHT1.)                                 */
  208.  
  209. void StopSound( channel )
  210. UBYTE channel;
  211. {
  212.     /* Check if the IOAudio structure exist: */
  213.   if( IOA[ channel ] )
  214.   {
  215.         /* 1. Stop the sound: */
  216.     AbortIO( IOA[ channel ] );
  217.     
  218.     /* 2. If there exist a Sound Device, close it: */
  219.     if( IOA[ channel ]->ioa_Request.io_Device )
  220.       CloseDevice( IOA[ channel ] );
  221.  
  222.     /* 3. If there exist a Message Port, delete it: */
  223.     if( IOA[ channel ]->ioa_Request.io_Message.mn_ReplyPort )
  224.       DeletePort( IOA[ channel ]->ioa_Request.io_Message.mn_ReplyPort );
  225.  
  226.     FreeMem( IOA[ channel ], sizeof( struct IOAudio ) );
  227.     IOA[ channel ] = NULL;
  228.   }
  229. }
  230.  
  231.  
  232.  
  233. /* RemoveSound()                                                        */
  234. /* RemoveSound() will stop playing the sound, and deallocate all memory */
  235. /* that was allocated by the PrepareSound() function. Before your       */
  236. /* program terminates, all sound that has been prepared, MUST be        */
  237. /* removed.                                                             */
  238. /*                                                                      */
  239. /* IMPORTANT! The each channel that is currently playing the sound must */
  240. /* be stopped! (Use the StopSound() function.)                          */
  241.  
  242. /* Synopsis: RemoveSound( pointer );                                    */
  243. /* pointer:  (CPTR) Actually a pointer to a SoundInfo structure.        */
  244.  
  245. void RemoveSound( info )
  246. struct SoundInfo *info;
  247. {
  248.   /* IMPORTANT! The sound must have been */
  249.     /* stopped before you may remove it!!! */
  250.  
  251.   /* Have we allocated a SoundInfo structure? */
  252.   if( info )
  253.   {
  254.     /* Deallocate the sound buffer: */
  255.     FreeMem( info->SoundBuffer, info->FileLength );
  256.  
  257.     /* Deallocate the SoundInfo structure: */
  258.     FreeMem( info, sizeof( struct SoundInfo ) );
  259.     info = NULL;
  260.   }
  261. }
  262.  
  263.  
  264.  
  265. /* PrepareIOA()                                                           */
  266. /* PrepareIOA() allocates and initializes an IOAudio structure.           */
  267. /*                                                                        */
  268. /* Synopsis: ok = PrepareIOA( period, volume, cycles, channel, pointer ); */
  269. /*                                                                        */
  270. /* ok:       (BOOL) If the IOAudio structure was allocated and            */
  271. /*           initialized successfully, TRUE is returned, else FALSE.      */
  272. /* period:   (UWORD) Period time.                                         */
  273. /* volume:   (UWORD) Volume, 0 to 64.                                     */
  274. /* cycles:   (UWORD) How many times the sound should be played.           */
  275. /*           (0 : forever)                                                */
  276. /* channel:  (UBYTE) Which channel should be used. (LEFT0, RIGHT0,        */
  277. /*           RIGHT1 or LEFT1)                                             */
  278. /* pointer:  (CPTR) Actually a pointer to a SoundInfo structure.          */
  279.  
  280. BOOL PrepareIOA( period, volume, cycles, channel, info)
  281. UWORD period, volume, cycles;
  282. UBYTE channel;
  283. struct SoundInfo *info;
  284. {
  285.     UBYTE ch;
  286.  
  287.     /* Declare a pointer to a MsgPort structure: */ 
  288.   struct MsgPort *port;
  289.  
  290.   /* Allocate space for an IOAudio structure: */
  291.   IOA[ channel ] = (struct IOAudio *) AllocMem( sizeof( struct IOAudio ),
  292.                       MEMF_PUBLIC|MEMF_CLEAR );
  293.  
  294.   /* Could we allocate enough memory? */
  295.   if( IOA[ channel ] )
  296.   {
  297.     /* Create Message port: */
  298.     if((port = (struct MsgPort *) CreatePort( "Sound Port", 0 )) == NULL)
  299.     {
  300.       /* ERROR! Could not create message port! */
  301.             /* Deallocate the IOAudio structure: */
  302.       FreeMem( IOA[ channel ], sizeof(struct IOAudio) );
  303.       IOA[ channel ] = NULL;
  304.       
  305.             return( FALSE ); /* ERROR! */
  306.     }
  307.     else
  308.     {
  309.       /* Port created successfully! */
  310.       /* Initialize the IOAudion structure: */
  311.             
  312.             /* Priority: */
  313.       IOA[ channel ]->ioa_Request.io_Message.mn_Node.ln_Pri = MUSIC_PRIORITY;
  314.       
  315.             /* Port: */
  316.             IOA[ channel ]->ioa_Request.io_Message.mn_ReplyPort = port;
  317.       
  318.             /* Channel: */
  319.       ch = 1<<channel;
  320.             IOA[ channel ]->ioa_Data = &ch;
  321.       
  322.             /* Length: */
  323.             IOA[ channel ]->ioa_Length = sizeof( UBYTE );
  324.       
  325.       /* Open Audio Device: */
  326.       if( OpenDevice( AUDIONAME, 0, IOA[ channel ], 0) )
  327.       {
  328.         /* ERROR! Could not open the device! */
  329.         /* Delete Sound Port: */
  330.                 DeletePort( port );
  331.  
  332.                 /* Deallocate the IOAudio structure: */
  333.         FreeMem( IOA[ channel ], sizeof(struct IOAudio) );
  334.         IOA[ channel ] = NULL;
  335.  
  336.                 return( FALSE ); /* ERROR! */
  337.       }
  338.       else
  339.       {
  340.         /* Device opened successfully! */
  341.         /* Initialize the rest of the IOAudio structure: */
  342.         IOA[ channel ]->ioa_Request.io_Flags = ADIOF_PERVOL;
  343.         IOA[ channel ]->ioa_Request.io_Command = CMD_WRITE;
  344.         IOA[ channel ]->ioa_Period = period;
  345.         IOA[ channel ]->ioa_Volume = volume;
  346.         IOA[ channel ]->ioa_Cycles = cycles;
  347.  
  348.         /* The Audion Chip can of some strange reason not play sampled  */
  349.                 /* sound that is longer than 131KB. So if the sound is to long, */
  350.                 /* we simply cut it off:                                        */
  351.         if( info->FileLength > 131000 )
  352.           IOA[ channel ]->ioa_Length = 131000;
  353.         else
  354.           IOA[ channel ]->ioa_Length = info->FileLength;
  355.  
  356.         IOA[ channel ]->ioa_Data = info->SoundBuffer;
  357.  
  358.         return( TRUE ); /* OK! */
  359.       }
  360.     }
  361.   }
  362.   return( FALSE ); /* ERROR! */
  363. }
  364.  
  365.  
  366.  
  367. /* LoadSound()                                                         */
  368. /* LoadSound() will load sampled sound that was either saved in IFF or */
  369. /* FutureSound format.                                                 */
  370. /*                                                                     */
  371. /* Synopsis: rate = LoadSound( filename, pointer );                    */
  372. /* rate:     (UWORD) The record rate is returned if the sound was      */
  373. /*           successfully loaded, else 0.                              */
  374. /* filename: (STRPTR) Pointer to a string containing the name of the   */
  375. /*           sound file. For example "df0:Explosion.snd".              */
  376. /* pointer:  (CPTR) Actually a pointer to a SoundInfo structure.       */
  377.  
  378.  
  379. UWORD LoadSound( filename, info )
  380. STRPTR filename;
  381. struct SoundInfo *info;
  382. {
  383.   FILE  *file_ptr;   /* Pointer to a file. */
  384.   ULONG length;      /* Data Length. */
  385.   UWORD record_rate; /* Record rate. */
  386.  
  387.  
  388.   /* Check if it is an IFF File: */
  389.   if( SizeIFF( filename ) )
  390.   {
  391.     /* Yes, it is an IFF file. Read it: */
  392.     return( ReadIFF( filename, info ) );
  393.   }
  394.   else
  395.   {
  396.     /* No, then it is probably a FutureSound file. */
  397.     /* Open the file so we can read it:            */
  398.     if( (file_ptr = fopen( filename, "r" )) == 0 )
  399.       return( 0 ); /* ERROR! Could not open the file! */
  400.  
  401.     /* Read the data length: */
  402.     if( fread( (char *) &length, sizeof( ULONG ), 1, file_ptr ) == 0 )
  403.     {
  404.             /* ERROR! Could not read the data length! */
  405.             /* Close the file, and return zero:       */
  406.       fclose( file_ptr );
  407.       return( 0 );
  408.     }
  409.  
  410.     /* Read the record rate: */
  411.     if( fread( (char *) &record_rate, sizeof( UWORD ), 1, file_ptr ) == 0 )
  412.     {
  413.             /* ERROR! Could not read the record rate! */
  414.             /* Close the file, and return zero:       */
  415.       fclose( file_ptr );
  416.       return( 0 );
  417.     }
  418.  
  419.     /* Read the sampled sound data into the buffer: */
  420.     if( fread( (char *) info->SoundBuffer, length, 1, file_ptr ) == 0 )
  421.     {
  422.             /* ERROR! Could not read the data!  */
  423.             /* Close the file, and return zero: */        
  424.       fclose( file_ptr );
  425.       return( 0 );
  426.     }
  427.  
  428.     /* Close the file: */
  429.     fclose( file_ptr );
  430.  
  431.     /* Return the record rate: */
  432.     return( record_rate );
  433.   }
  434. }
  435.  
  436.  
  437.  
  438.  
  439. /* GetSize()                                                         */
  440. /* GetSize() returns the size of the file which was saved in either  */
  441. /* IFF or FutureSound format.                                        */
  442. /*                                                                   */
  443. /* Synopsis: length = GetSize( filename );                           */
  444. /* length:   (ULONG) Data length.                                    */
  445. /* filename: (STRPTR) Pointer to a string containing the name of the */
  446. /*           sound file. For example "df0:Explosion.snd".            */
  447.  
  448. ULONG GetSize( filename )
  449. STRPTR filename;
  450. {
  451.   FILE *file_ptr; /* Pointer to a file. */
  452.   ULONG length;  /* Data length. */
  453.  
  454.  
  455.   /* Check if it is an IFF File: */
  456.   if( ( length = SizeIFF( filename ) ) == 0 )
  457.   {
  458.     /* No, then it is probably a FutureSound file. */
  459.     /* Open the file so we can read it:            */
  460.     if( ( file_ptr = fopen( filename, "r" ) ) == 0 )
  461.       return( 0 ); /* ERROR! Could not open the file! */
  462.  
  463.     /* Read the data length: */
  464.     if( fread( (char *) &length, sizeof( ULONG ), 1, file_ptr ) == 0)
  465.     {
  466.             /* ERROR! Could not read the data length! */
  467.             /* Close the file, and return zero:       */
  468.       fclose( file_ptr );
  469.       return( 0 );
  470.     }
  471.         
  472.     /* Close the file: */
  473.     fclose( file_ptr );
  474.   }
  475.   return( length );
  476. }
  477.  
  478.  
  479.  
  480. /* SizeIFF()                                                         */
  481. /* SizeIFF() returns the size of an IFF file, or zero if something   */
  482. /* went wrong (for example, It was not an IFF file).                 */
  483. /*                                                                   */
  484. /* Synopsis: length = SizeIFF( filename );                           */
  485. /* length:   (ULONG) Data length.                                    */
  486. /* filename: (STRPTR) Pointer to a string containing the name of the */
  487. /*           IFF file. For example "df0:Explosion.snd".              */
  488.  
  489. ULONG SizeIFF( filename )
  490. STRPTR filename;
  491. {
  492.   FILE  *file_ptr;              /* Pointer to a file. */
  493.   STRPTR empty_string = "    "; /* Four spaces. */ 
  494.   LONG dummy;                   /* A dummy variable. */
  495.   Voice8Header Header;          /* Voice8Header structure. */
  496.  
  497.  
  498.   /* Try to open the file: */
  499.   if( file_ptr = fopen( filename, "r" ) )
  500.   {
  501.     fread( (char *) empty_string, 4, 1, file_ptr );
  502.     if( strcmp( empty_string, "FORM" ) == 0)
  503.     {
  504.             /* Read twice: */
  505.       fread( (char *) empty_string, 4, 1, file_ptr );
  506.       fread( (char *) empty_string, 4, 1, file_ptr );
  507.  
  508.       /* Check if it is a "8SVX" file, or not: */
  509.             if( strcmp( empty_string, "8SVX" ) == 0 )
  510.       {
  511.         MoveTo( "VHDR", file_ptr );
  512.         fread( (char *) &dummy, sizeof( LONG ), 1, file_ptr );
  513.         fread( (char *) &Header, sizeof( Header ), 1, file_ptr );
  514.  
  515.             /* Close the file, and return the length: */
  516.         fclose( file_ptr );
  517.         return( Header.oneShotHiSamples + Header.repeatHiSamples );
  518.       }
  519.     }
  520.         /* Close the file: */
  521.     fclose( file_ptr );
  522.   }
  523.     /* Return zero: (ERROR) */
  524.   return( 0 );
  525. }
  526.  
  527.  
  528.  
  529. /* ReadIFF()                                                           */
  530. /* ReadIFF() reads an IFF file into the buffer, and returns the record */
  531. /* rate.                                                               */
  532. /*                                                                     */
  533. /* Synopsis: rate = ReadIFF( filename, pointer );                      */
  534. /* rate:     (UWORD) The record rate is returned if the sound was      */
  535. /*           successfully loaded, else 0.                              */
  536. /* filename: (STRPTR) Pointer to a string containing the name of the   */
  537. /*           sound file. For example "df0:Explosion.snd".              */
  538. /* pointer:  (CPTR) Actually a pointer to a SoundInfo structure.       */
  539.  
  540. UWORD ReadIFF( filename, info )
  541. STRPTR filename;
  542. struct SoundInfo *info;
  543. {
  544.   FILE  *file_ptr;              /* Pointer to a file. */
  545.   STRPTR empty_string = "    "; /* Four spaces. */ 
  546.   LONG dummy;                   /* A dummy variable. */
  547.   Voice8Header Header;          /* Voice8Header structure. */
  548.  
  549.  
  550.   /* Try to open the file: */
  551.   if( file_ptr = fopen( filename, "r" ) )
  552.   {
  553.     fread( (char *) empty_string, 4, 1, file_ptr );
  554.     if( strcmp( empty_string, "FORM" ) == 0 )
  555.     {
  556.             /* Read twice: */
  557.       fread( (char *) empty_string, 4, 1, file_ptr );
  558.       fread( (char *) empty_string, 4, 1, file_ptr );
  559.  
  560.       /* Check if it is a "8SVX" file, or not: */
  561.       if( strcmp( empty_string, "8SVX" ) == 0 )
  562.       {
  563.         MoveTo( "VHDR", file_ptr );
  564.         fread( (char *) &dummy, sizeof( LONG ), 1, file_ptr );
  565.         fread( (char *) &Header, sizeof( Header ), 1, file_ptr );
  566.  
  567.         MoveTo( "BODY", file_ptr );
  568.         fread( (char *) &dummy, sizeof( LONG ), 1, file_ptr );
  569.         fread( (char *) info->SoundBuffer, Header.oneShotHiSamples +
  570.                                  Header.repeatHiSamples, 1, file_ptr );
  571.  
  572.             /* Close the file, and return the record rate: */
  573.         fclose( file_ptr );
  574.         return( Header.samplesPerSec );
  575.       }
  576.     }
  577.         /* Close the file: */
  578.     fclose( file_ptr );
  579.   }
  580.     /* Return zero: (ERROR) */
  581.   return( 0 );
  582.  
  583.  
  584.  
  585. /* MoveTo()                                                  */
  586. /* MoveTo() walks through an IFF file, and looks for chunks. */
  587. /*                                                           */
  588. /* Synopsis: MoveTo( chunk, file_ptr );                      */
  589. /* chunk:    (STRPTR) The chunk we want to get to.           */
  590. /* file_ptr: (FILE *) Pointer to an already opened file.     */
  591.  
  592. BOOL MoveTo( check_string, file_ptr )
  593. STRPTR check_string;
  594. FILE *file_ptr;
  595. {
  596.   STRPTR empty_string = "    "; /* Four spaces. */ 
  597.   int skip, loop;               /* How much data should be skiped. */
  598.   LONG dummy;                   /* A dummy variable. */
  599.  
  600.  
  601.   /* As long as we have not reached the EOF, continue: */
  602.   while( !feof( file_ptr ) )
  603.   {
  604.     fread( (char *) empty_string, 4, 1, file_ptr);
  605.  
  606.     /* Have we found the right chunk? */    
  607.         if( strcmp( check_string, empty_string ) ==0 )
  608.       return( 0 ); /* YES! Return nothing. */
  609.  
  610.     /* Move foreward: */
  611.     fread( (char *) &skip, sizeof( LONG ), 1, file_ptr );
  612.     for( loop = 0; loop < skip; loop++ )
  613.       fread( (char *) &dummy, 1, 1, file_ptr);
  614.   }
  615. }
  616.