X-Git-Url: https://git.draconx.ca/gitweb/upkg.git/blobdiff_plain/ca8ee16cfde42ea27d40f8e45fa6d96dc24cd5d9..d82c61e8b0ff6b7660ec0288c50e6f3e6547ed4a:/src/engine/music-modplug.c?ds=sidebyside diff --git a/src/engine/music-modplug.c b/src/engine/music-modplug.c new file mode 100644 index 0000000..e0a0695 --- /dev/null +++ b/src/engine/music-modplug.c @@ -0,0 +1,108 @@ +#include +#include +#include +#include "modplug-types.h" + +#include "music-module.h" +#include "upkg.h" + +struct music_mod { + ModPlugFile *f; + size_t len, alloc; + unsigned char buf[]; +}; + +#define BUF_INIT_SIZE 65536 + +int music_mod_init(void) +{ + ModPlug_Settings settings = { + .mFlags = MODPLUG_ENABLE_OVERSAMPLING, + .mChannels = 2, + .mFrequency = 44100, + .mResamplingMode = MODPLUG_RESAMPLE_SPLINE, + .mLoopCount = -1, + }; + + ModPlug_SetSettings(&settings); + return 0; +} + +void music_mod_exit(void) +{ +} + +static struct music_mod *readfile(struct upkg_file *f) +{ + struct music_mod *m = malloc(sizeof *m + BUF_INIT_SIZE); + if (!m) return NULL; + *m = (struct music_mod) { + .alloc = BUF_INIT_SIZE + }; + + while (1) { + struct music_mod *tmp; + size_t sz = m->alloc - m->len; + + m->len += upkg_export_read(f, m->buf + m->len, sz); + if (m->alloc != m->len) { + if (f->eof) { + tmp = realloc(m, sizeof *m + m->len); + return tmp ? tmp : m; + } + + break; + } + + tmp = realloc(m, sizeof *m + 2*m->alloc); + if (!tmp) + break; + m = tmp; + m->alloc *= 2; + } + + free(m); + return NULL; +} + +struct music_mod *music_mod_open(struct upkg_file *f) +{ + struct music_mod *m = readfile(f); + if (!m) return NULL; + + m->f = ModPlug_Load(m->buf, m->len); + if (!m->f) { + free(m); + return NULL; + } + + return m; +} + +int music_mod_dump(struct music_mod *m, FILE *of) +{ + if (fwrite(m->buf, m->len, 1, of) != 1) + return -1; + return 0; +} + +void music_mod_close(struct music_mod *m) +{ + ModPlug_Unload(m->f); + free(m); +} + +const char *music_mod_type(struct music_mod *m) +{ + int type = ModPlug_GetModuleType(m->f); + + if (type & MOD_TYPE_MOD) + return "mod"; + if (type & MOD_TYPE_S3M) + return "s3m"; + if (type & MOD_TYPE_XM) + return "xm"; + if (type & MOD_TYPE_IT) + return "it"; + return "unknown"; +}