nuclide-lite/Tools/Source/wav2loop.c

129 lines
2.5 KiB
C
Raw Permalink Normal View History

2025-01-24 09:55:37 +00:00
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <unistd.h>
/* so it's easier to fwrite */
typedef struct
{
char cuehead[4];
int chunk_size;
int numcues;
int cueid;
int cuepos;
char datahead[4];
int chunk_start;
int block_start;
int sample_offset;
} loop_t;
/* -o enables users to specify at which point in the sample to start */
static int sample_offset;
void process_wav2loop(char *filename)
{
FILE *fWAV;
FILE *fLOOP;
size_t szWAV;
char *buffer;
loop_t loopy;
fWAV = fopen(filename, "rb");
if (!fWAV) {
fprintf(stderr, "couldn't find %s\n", filename);
return;
}
/* get wav file size */
fseek(fWAV, 0L, SEEK_END);
szWAV = (size_t)ftell(fWAV);
fseek(fWAV, 0L, SEEK_SET);
/* load wav into memory */
buffer = (char *)malloc(szWAV);
if (buffer == NULL) {
fprintf(stderr, "error: Memory allocation failed. Exiting.\n");
exit(0);
}
fread(buffer, 1, szWAV, fWAV);
fclose(fWAV);
/* this is LAZY, however we're not going to bother writing a full WAV loader LMAO */
for (int i = 0; i < (szWAV - 4); i++ ) {
if (buffer[i] == 'c')
if (buffer[i+1] == 'u')
if (buffer[i+2] == 'e')
if (buffer[i+3] == ' ') {
fprintf(stderr, "wav file %s has cue info already\n", filename);
goto end;
}
}
/* this is quite stupid, we're just appending it at the end,
we don't even care if there already are other cue marks */
fLOOP = fopen(filename, "w+b");
fwrite(buffer, 1, szWAV, fLOOP);
loopy.cuehead[0] = 'c';
loopy.cuehead[1] = 'u';
loopy.cuehead[2] = 'e';
loopy.cuehead[3] = ' ';
loopy.chunk_size = 28;
loopy.numcues = 1;
loopy.cueid = 0;
loopy.cuepos = 0;
loopy.datahead[0] = 'd';
loopy.datahead[1] = 'a';
loopy.datahead[2] = 't';
loopy.datahead[3] = 'a';
loopy.chunk_start = 0;
loopy.block_start = 0;
loopy.sample_offset = sample_offset;
/* append our data to the end of the file */
fwrite(&loopy, 1, sizeof(loop_t), fLOOP);
fclose(fLOOP);
/* inb4 goto considered harmful */
end:
free(buffer);
}
int main(int argc, char *argv[])
{
int c, ch;
if (argc <= 1) {
fprintf(stderr, "usage: wav2loop [-o offset] file.wav ...\n");
return 1;
}
/* by default, we loop at the very start */
sample_offset = 0;
/* process arguments: TODO: add more? probably not */
while ((ch = getopt(argc, argv, "o")) != -1) {
switch (ch) {
case 'o':
sample_offset = atoi(argv[optind]);
optind++;
printf("sample offset: %i\n", sample_offset);
break;
default:
return 1;
}
}
argc -= optind;
argv += optind;
for (c = 0; c < argc; c++)
process_wav2loop(argv[c]);
return 0;
}