home *** CD-ROM | disk | FTP | other *** search
/ World of A1200 / World_Of_A1200.iso / datafiles / text / c_manual / sound / includesound / printsound.c < prev    next >
C/C++ Source or Header  |  1995-02-27  |  19KB  |  492 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:    PrintSound.c                181 41  LIDINGO    */
  9. /* Author:  Anders Bjerin               SWEDEN             */
  10. /* Date:    92-05-01                                       */
  11. /* Version: 1.10                                           */
  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. /* PrintSound() loads a sampled sound file (IFF or FutureSound) and      */
  21. /* prints the sound data as a large array. This array can then simply    */
  22. /* be included in your own programs together with the IncludeSound       */
  23. /* file. The advantage to this compared to EasySound is that you do      */
  24. /* not need to have to load the sound data when you run your program.    */
  25. /* This is both much faster and more convinient.                         */
  26. /*                                                                       */
  27. /* NOTE! Do not try to print too large samples. Even a short sample      */
  28. /* can result in several pages of data! (However, once the file has      */
  29. /* been compiled it will not use more memory than normal. The program    */
  30. /* itself will also be some kilo bytes shorter since you do not need     */
  31. /* to include any routines to load the sound.)                           */
  32. /*                                                                       */
  33. /* Sounds that have been prepared with PrintSound can also be used with  */
  34. /* EasySound. Note that the sound should then NOT be prepared NOR should */
  35. /* it be removed. Everything else is as normal.                          */
  36. /*                                                                       */
  37. /*                                                                       */
  38. /*                                                                       */
  39. /* I N S T R U C T I O N S                                               */
  40. /* -----------------------                                               */
  41. /*                                                                       */
  42. /* PrintSound > "output file" "sound file" "name of array"               */
  43. /*                                                                       */
  44. /* Example: "PrintSound > RAM:Data Explosion.snd Bang"                   */
  45. /*                                                                       */
  46. /*   PrintSound will load file "Explosion.snd", and print the sound      */
  47. /*   data in file "RAM:Data". The SoundInfo structure will be called     */
  48. /*   "Bang".                                                             */
  49.  
  50.  
  51.  
  52. /* Include some important header files: */
  53. #include <exec/types.h>
  54. #include <exec/memory.h>
  55. #include <devices/audio.h>
  56. #include <stdio.h>
  57.  
  58.  
  59. #define CLOCK_CONSTANT 3579545
  60. #define MUSIC_PRIORITY 0
  61.  
  62.  
  63.  
  64. /* Structure containing all necessary information about the sound: */
  65. struct SoundInfo
  66. {
  67.   BYTE *SoundBuffer;  /* WaveForm Buffers */
  68.   UWORD RecordRate;   /* Record Rate */
  69.   ULONG FileLength;   /* WaveForm Lengths */
  70. };
  71.  
  72.  
  73. /* An IOAudio pointer to each sound channel: */
  74. struct IOAudio *IOA[ 4 ] = { NULL, NULL, NULL, NULL };
  75.  
  76.  
  77. typedef LONG Fixed;
  78. typedef struct
  79. {
  80.   ULONG  oneShotHiSamples;  /* #samples in the high octave 1-shot part */
  81.   ULONG  repeatHiSamples;   /* #samples in the high octave repeat part */
  82.   ULONG  samplesPerHiCycle; /* #samples/cycle in high octave, else 0  */
  83.   UWORD  samplesPerSec;     /* Data sampling rate */
  84.   UBYTE  ctOctave;          /* Number of octaves of waveforms */
  85.   UBYTE  sCompression;      /* Data compression technique used */
  86.   Fixed  volume;            /* Playback volume from 0 to 0x10000 */
  87. } Voice8Header;
  88.  
  89.  
  90. /* Declare the functions we are going to use: */
  91. void main();
  92. BOOL PrintSound();
  93. UWORD LoadSound();
  94. ULONG GetSize();
  95. ULONG SizeIFF();
  96. UWORD ReadIFF();
  97. BOOL MoveTo();
  98.  
  99.  
  100. /* PrintSound <sound file> <name of array> */
  101. void main( argc, argv )
  102. int argc;
  103. char *argv[];
  104. {
  105.   /* Two arguments + program name: */
  106.   if( argc == 3 )
  107.   {
  108.     if( !PrintSound( argv[ 1 ], argv[ 2 ] ) )
  109.     {
  110.       printf( "ERROR!" );
  111.     }
  112.   }
  113.   else
  114.   {
  115.     /* Not enough or to many arguments. */
  116.  
  117.     /* Print instructions: */
  118.     printf( "PrintSound > \"output file\" \"sound file\" \"name of array\"\n" );
  119.     printf( "Example: \"PrintSound > RAM:Data Explosion.snd Bang\"\n" );
  120.     printf( "         PrintSound will load file \"Explosion.snd\",\n" );
  121.     printf( "         and print the sound data in file \"RAM:Data\".\n" );
  122.     printf( "         The SoundInfo structure will be called \"Bang\".\n" );
  123.   }
  124. }
  125.  
  126.  
  127. /* PrintSound()                                                       */
  128. /* PrintSound() loads a sampled sound file (IFF or FutureSound) and   */
  129. /* prints the sound data as a large array. This array can then simply */
  130. /* be included in your own programs together with the IncludeSound    */
  131. /* file. The advantage to this compared to EasySound is that you do   */
  132. /* not need to have to load the sound data when you run your program. */
  133. /* This is both much faster and more convinient.                      */
  134. /* NOTE! Do not try to print too large samples. Even a short sample   */
  135. /* can result in several pages of data! (However, once the file has   */
  136. /* been compiled it will not use more memory than normal. The proram  */
  137. /* itself will also be some kilo bytes shorter since you do not need  */
  138. /* to include any routines to load the sound.)                        */
  139. /*                                                                    */
  140. /* Synopsis: result = PrintSound( filename, name );                   */
  141. /* result:   (BOOL) If PrintSound has successfully loaded and printed */
  142. /*           the sound data it will return TRUE, else FALSE.          */
  143. /* filename: (STRPTR) Name of the sound file.                         */
  144. /* name:     (STRPTR) Name of the sound data array.                   */
  145.  
  146. BOOL PrintSound( file, name )
  147. STRPTR file, name;
  148. {
  149.   BYTE *pointer;
  150.   ULONG position;
  151.   BOOL result = FALSE;
  152.  
  153.  
  154.   /* Declare a pointer to a SoundInfo structure: */
  155.   struct SoundInfo *info;
  156.  
  157.   /* Allocate memory for a SoundInfo structure: (The memory can be of */
  158.   /* any type, and should be cleared.                                 */
  159.   info = (struct SoundInfo *) AllocMem( sizeof( struct SoundInfo ),
  160.                                         MEMF_PUBLIC|MEMF_CLEAR );
  161.  
  162.  
  163.   if( info )
  164.   {
  165.     /* The memory have been successfully allocated. */ 
  166.    
  167.     /* Get the size of the file, and store it in the SoundInfo struct.: */
  168.     if( info->FileLength = GetSize( file ) )
  169.     {
  170.       /* Allocate enough memory for the sampled sound, and store a */
  171.       /* pointer to the buffer in the SoundInfo structure:         */
  172.       info->SoundBuffer = (BYTE *) AllocMem( info->FileLength,
  173.                                              MEMF_CHIP|MEMF_CLEAR );
  174.  
  175.       if( info->SoundBuffer )
  176.       {
  177.         /* The memory have been successfully allocated. */ 
  178.  
  179.         /* Load the sound, and store the record rate in the SoundInfo  */
  180.         /* structure. If the sound could not be loaded, 0 is returned: */
  181.         if( info->RecordRate = LoadSound( file, info ) )
  182.         {
  183.           /* OK! The sound has successfully been loaded. */
  184.        
  185.           /* Old FutureSound files were saved in kHz. If the record rate */
  186.           /* is less than one hundered, we know it is an old FutureSound */
  187.           /* file, and simply multiply the rate with one thousand:       */
  188.           if( info->RecordRate < 100 )
  189.           info->RecordRate *= 1000;
  190.  
  191.           pointer = info->SoundBuffer;
  192.  
  193.           printf( "#include \"IncludeSound.h\"\n\n" );
  194.           printf( "\n/************************************/\n" );
  195.           printf( "/* SoundData prepared by PrintSound */\n" );
  196.           printf( "/* Anders Bjerin       Amiga C Club */\n" );
  197.           printf( "/*                                  */\n" );
  198.           printf( "/* File name:   %19s */\n", file );
  199.           printf( "/* Record Rate: %19d */\n", info->RecordRate );
  200.           printf( "/* File Length: %19d */\n", info->FileLength );
  201.           printf( "/************************************/\n\n" );
  202.  
  203.           /* NOTE! This data must be in "Chip Memory"! */
  204.           printf( "BYTE chip %s_data[]=\n{", name );
  205.           for( position = 0; position < info->FileLength; position++ )
  206.           {
  207.             /* New line after each ten values: */
  208.             if( position % 10 == 0 )
  209.               printf( "\n  " );
  210.  
  211.             /* Print a sample (one byte): */
  212.             printf( "%d%s",
  213.               pointer[ position ],
  214.               position < info->FileLength - 1 ? "," : " " );
  215.           }
  216.           printf( "\n};\n\n" );
  217.  
  218.           printf( "struct SoundInfo %s=\n{\n", name );
  219.           printf( "  %s_data, /* WaveForm Buffers */\n", name );
  220.           printf( "  %8d, /* Record Rate */\n", info->RecordRate );
  221.           printf( "  %8d  /* WaveForm Length */\n};\n\n", info->FileLength );
  222.  
  223.           printf( "/************************************/\n" );
  224.           printf( "/* End of sound: %18s */\n", file );
  225.           printf( "/************************************/\n\n" );
  226.  
  227.           result = TRUE;
  228.         }
  229.  
  230.         /* Deallocate the memory for the sound buffer: */
  231.         FreeMem( info->SoundBuffer, info->FileLength );
  232.       }
  233.     }
  234.     /* Deallocate the memory the SoundInfo structure: */
  235.     FreeMem( info, sizeof( struct SoundInfo ) );
  236.   }
  237.   
  238.   return( result );
  239. }
  240.  
  241.  
  242.  
  243. /* LoadSound()                                                         */
  244. /* LoadSound() will load sampled sound that was either saved in IFF or */
  245. /* FutureSound format.                                                 */
  246. /*                                                                     */
  247. /* Synopsis: rate = LoadSound( filename, pointer );                    */
  248. /* rate:     (UWORD) The record rate is returned if the sound was      */
  249. /*           successfully loaded, else 0.                              */
  250. /* filename: (STRPTR) Pointer to a string containing the name of the   */
  251. /*           sound file. For example "df0:Explosion.snd".              */
  252. /* pointer:  (struct SoundInfo *info) Pointer to a SoundInfo structure.*/
  253.  
  254. UWORD LoadSound( filename, info )
  255. STRPTR filename;
  256. struct SoundInfo *info;
  257. {
  258.   FILE  *file_ptr;   /* Pointer to a file. */
  259.   ULONG length;      /* Data Length.       */
  260.   UWORD record_rate; /* Record rate.       */
  261.  
  262.  
  263.   /* Check if it is an IFF File: */
  264.   if( SizeIFF( filename ) )
  265.   {
  266.     /* Yes, it is an IFF file. Read it: */
  267.     return( ReadIFF( filename, info ) );
  268.   }
  269.   else
  270.   {
  271.     /* No, then it is probably a FutureSound file. */
  272.     /* Open the file so we can read it:            */
  273.     if( (file_ptr = fopen( filename, "r" )) == 0 )
  274.     return( 0 ); /* ERROR! Could not open the file! */
  275.  
  276.     /* Read the data length: */
  277.     if( fread( (char *) &length, sizeof( ULONG ), 1, file_ptr ) == 0 )
  278.     {
  279.       /* ERROR! Could not read the data length! */
  280.       /* Close the file, and return zero:       */
  281.       fclose( file_ptr );
  282.       return( 0 );
  283.     }
  284.  
  285.     /* Read the record rate: */
  286.     if( fread( (char *) &record_rate, sizeof( UWORD ), 1, file_ptr ) == 0 )
  287.     {
  288.       /* ERROR! Could not read the record rate! */
  289.       /* Close the file, and return zero:       */
  290.       fclose( file_ptr );
  291.       return( 0 );
  292.     }
  293.  
  294.     /* Read the sampled sound data into the buffer: */
  295.     if( fread( (char *) info->SoundBuffer, length, 1, file_ptr ) == 0 )
  296.     {
  297.       /* ERROR! Could not read the data!  */
  298.       /* Close the file, and return zero: */    
  299.       fclose( file_ptr );
  300.       return( 0 );
  301.     }
  302.  
  303.     /* Close the file: */
  304.     fclose( file_ptr );
  305.  
  306.     /* Return the record rate: */
  307.     return( record_rate );
  308.   }
  309. }
  310.  
  311.  
  312.  
  313.  
  314. /* GetSize()                                                         */
  315. /* GetSize() returns the size of the file which was saved in either  */
  316. /* IFF or FutureSound format.                                        */
  317. /*                                                                   */
  318. /* Synopsis: length = GetSize( filename );                           */
  319. /* length:   (ULONG) Data length.                                    */
  320. /* filename: (STRPTR) Pointer to a string containing the name of the */
  321. /*           sound file. For example "df0:Explosion.snd".            */
  322.  
  323. ULONG GetSize( filename )
  324. STRPTR filename;
  325. {
  326.   FILE *file_ptr; /* Pointer to a file. */
  327.   ULONG length;   /* Data length.       */
  328.  
  329.  
  330.   /* Check if it is an IFF File: */
  331.   if( ( length = SizeIFF( filename ) ) == 0 )
  332.   {
  333.     /* No, then it is probably a FutureSound file. */
  334.     /* Open the file so we can read it:            */
  335.     if( ( file_ptr = fopen( filename, "r" ) ) == 0 )
  336.       return( 0 ); /* ERROR! Could not open the file! */
  337.  
  338.     /* Read the data length: */
  339.     if( fread( (char *) &length, sizeof( ULONG ), 1, file_ptr ) == 0)
  340.     {
  341.       /* ERROR! Could not read the data length! */
  342.       /* Close the file, and return zero:       */
  343.       fclose( file_ptr );
  344.       return( 0 );
  345.     }
  346.     
  347.     /* Close the file: */
  348.     fclose( file_ptr );
  349.   }
  350.   return( length );
  351. }
  352.  
  353.  
  354.  
  355. /* SizeIFF()                                                         */
  356. /* SizeIFF() returns the size of an IFF file, or zero if something   */
  357. /* went wrong (for example, It was not an IFF file).                 */
  358. /*                                                                   */
  359. /* Synopsis: length = SizeIFF( filename );                           */
  360. /* length:  (ULONG) Data length.                                     */
  361. /* filename: (STRPTR) Pointer to a string containing the name of the */
  362. /*        IFF file. For example "df0:Explosion.snd".                 */
  363.  
  364. ULONG SizeIFF( filename )
  365. STRPTR filename;
  366. {
  367.   FILE  *file_ptr;              /* Pointer to a file.      */
  368.   STRPTR empty_string = "    "; /* Four spaces.            */ 
  369.   LONG dummy;                   /* A dummy variable.       */
  370.   Voice8Header Header;          /* Voice8Header structure. */
  371.  
  372.  
  373.   /* Try to open the file: */
  374.   if( file_ptr = fopen( filename, "r" ) )
  375.   {
  376.     fread( (char *) empty_string, 4, 1, file_ptr );
  377.     if( strcmp( empty_string, "FORM" ) == 0)
  378.     {
  379.       /* Read twice: */
  380.       fread( (char *) empty_string, 4, 1, file_ptr );
  381.       fread( (char *) empty_string, 4, 1, file_ptr );
  382.  
  383.       /* Check if it is a "8SVX" file, or not: */
  384.       if( strcmp( empty_string, "8SVX" ) == 0 )
  385.       {
  386.         MoveTo( "VHDR", file_ptr );
  387.         fread( (char *) &dummy, sizeof( LONG ), 1, file_ptr );
  388.         fread( (char *) &Header, sizeof( Header ), 1, file_ptr );
  389.  
  390.         /* Close the file, and return the length: */
  391.         fclose( file_ptr );
  392.         return( Header.oneShotHiSamples + Header.repeatHiSamples );
  393.       }
  394.     }
  395.     /* Close the file: */
  396.     fclose( file_ptr );
  397.   }
  398.   /* Return zero: (ERROR) */
  399.   return( 0 );
  400. }
  401.  
  402.  
  403.  
  404. /* ReadIFF()                                                           */
  405. /* ReadIFF() reads an IFF file into the buffer, and returns the record */
  406. /* rate.                                                               */
  407. /*                                                                     */
  408. /* Synopsis: rate = ReadIFF( filename, pointer );                      */
  409. /* rate:     (UWORD) The record rate is returned if the sound was      */
  410. /*           successfully loaded, else 0.                              */
  411. /* filename: (STRPTR) Pointer to a string containing the name of the   */
  412. /*           sound file. For example "df0:Explosion.snd".              */
  413. /* pointer:  (struct SoundInfo *info) Pointer to a SoundInfo structure.*/
  414.  
  415. UWORD ReadIFF( filename, info )
  416. STRPTR filename;
  417. struct SoundInfo *info;
  418. {
  419.   FILE  *file_ptr;              /* Pointer to a file.      */
  420.   STRPTR empty_string = "    "; /* Four spaces.            */
  421.   LONG dummy;                   /* A dummy variable.       */
  422.   Voice8Header Header;          /* Voice8Header structure. */
  423.  
  424.  
  425.   /* Try to open the file: */
  426.   if( file_ptr = fopen( filename, "r" ) )
  427.   {
  428.     fread( (char *) empty_string, 4, 1, file_ptr );
  429.     if( strcmp( empty_string, "FORM" ) == 0 )
  430.     {
  431.       /* Read twice: */
  432.       fread( (char *) empty_string, 4, 1, file_ptr );
  433.       fread( (char *) empty_string, 4, 1, file_ptr );
  434.  
  435.       /* Check if it is a "8SVX" file, or not: */
  436.       if( strcmp( empty_string, "8SVX" ) == 0 )
  437.       {
  438.         MoveTo( "VHDR", file_ptr );
  439.         fread( (char *) &dummy, sizeof( LONG ), 1, file_ptr );
  440.         fread( (char *) &Header, sizeof( Header ), 1, file_ptr );
  441.  
  442.         MoveTo( "BODY", file_ptr );
  443.         fread( (char *) &dummy, sizeof( LONG ), 1, file_ptr );
  444.         fread( (char *) info->SoundBuffer, Header.oneShotHiSamples +
  445.                         Header.repeatHiSamples, 1, file_ptr );
  446.  
  447.         /* Close the file, and return the record rate: */
  448.         fclose( file_ptr );
  449.         return( Header.samplesPerSec );
  450.       }
  451.     }
  452.     /* Close the file: */
  453.     fclose( file_ptr );
  454.   }
  455.   /* Return zero: (ERROR) */
  456.   return( 0 );
  457.  
  458.  
  459.  
  460. /* MoveTo()                                                  */
  461. /* MoveTo() walks through an IFF file, and looks for chunks. */
  462. /*                                                           */
  463. /* Synopsis: MoveTo( chunk, file_ptr );                      */
  464. /* chunk:    (STRPTR) The chunk we want to get to.           */
  465. /* file_ptr: (FILE *) Pointer to an already opened file.     */
  466.  
  467. BOOL MoveTo( check_string, file_ptr )
  468. STRPTR check_string;
  469. FILE *file_ptr;
  470. {
  471.   STRPTR empty_string = "    "; /* Four spaces.                    */
  472.   int skip, loop;               /* How much data should be skiped. */
  473.   LONG dummy;                   /* A dummy variable.               */
  474.  
  475.  
  476.   /* As long as we have not reached the EOF, continue: */
  477.   while( !feof( file_ptr ) )
  478.   {
  479.     fread( (char *) empty_string, 4, 1, file_ptr);
  480.  
  481.     /* Have we found the right chunk? */   
  482.     if( strcmp( check_string, empty_string ) ==0 )
  483.     return( 0 ); /* YES! Return nothing. */
  484.  
  485.     /* Move foreward: */
  486.     fread( (char *) &skip, sizeof( LONG ), 1, file_ptr );
  487.     for( loop = 0; loop < skip; loop++ )
  488.     fread( (char *) &dummy, 1, 1, file_ptr);
  489.   }
  490. }
  491.