Sona 0.50 Source

Sona 0.50/tools/ewf2swav/ewf2swav.c

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#define ERRORMSG_USAGE     "Usage: %s input.ewf output.swav\n"
#define ERRORMSG_INOPEN    "Error: can't open Echo PCM instrument\"%s\"\n"
#define ERRORMSG_INREAD    "Error: can't read Echo PCM instrument \"%s\"\n"
#define ERRORMSG_INVALID   "Error: Echo PCM instrument \"%s\" is not valid\n"
#define ERRORMSG_OUTOPEN   "Error: can't create Sona PCM instrument\"%s\"\n"
#define ERRORMSG_OUTWRITE  "Error: can't write Sona PCM instrument \"%s\"\n"

int main(int argc, char **argv)
{
   // Check arguments
   if (argc != 3) {
      fprintf(stderr, ERRORMSG_USAGE, argv[0]);
      return EXIT_FAILURE;
   }
   const char *in_filename = argv[1];
   const char *out_filename = argv[2];
   
   // Open files
   FILE *in_file = fopen(in_filename, "rb");
   if (in_file == NULL) {
      fprintf(stderr, ERRORMSG_INOPEN, in_filename);
      return EXIT_FAILURE;
   }
   FILE *out_file = fopen(out_filename, "wb");
   if (out_file == NULL) {
      fprintf(stderr, ERRORMSG_OUTOPEN, out_filename);
      fclose(in_file);
      return EXIT_FAILURE;
   }
   
   // Read all samples
   unsigned align = 0;
   
   for (;;) {
      // Read next byte
      int byte = fgetc(in_file);
      
      // Ran out of bytes?
      // Note: Echo PCM instruments *always* end with a 0xFF file, so this
      // is an error either way (no 0xFF terminator means file is not valid,
      // while a read error is… an error)
      if (byte == EOF) {
         fprintf(stderr,
            feof(in_file) ? ERRORMSG_INVALID : ERRORMSG_INREAD,
            in_filename);
         
         fclose(in_file);
         fclose(out_file);
         return EXIT_FAILURE;
      }
      
      // End of data?
      if (byte == 0xFF) break;
      
      // Write sample to Sona file
      if (fputc(byte, out_file) == EOF) {
         fprintf(stderr, ERRORMSG_OUTWRITE, out_filename);
         fclose(in_file);
         fclose(out_file);
         return EXIT_FAILURE;
      }
      
      // Advance alignment offset
      // Sona PCM instruments are aligned to 32 byte blocks
      align++;
      align &= 0x1F;
   }
   
   // Pad to the end of the block (if needed) with silence
   while (align) {
      align++;
      align &= 0x1F;
      
      if (fputc(0x7F, out_file) == EOF) {
         fprintf(stderr, ERRORMSG_OUTWRITE, out_filename);
         fclose(in_file);
         fclose(out_file);
         return EXIT_FAILURE;
      }
   }
   
   // Now write the final block
   for (int i = 0; i < 0x20; i++) {
      if (fputc(0xFF, out_file) == EOF) {
         fprintf(stderr, ERRORMSG_OUTWRITE, out_filename);
         fclose(in_file);
         fclose(out_file);
         return EXIT_FAILURE;
      }
   }
   
   // We're done
   fclose(in_file);
   fclose(out_file);
   return EXIT_SUCCESS;
}