#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;
}