]> git.draconx.ca Git - upkg.git/blob - src/engine/music-modplug.c
e0a069533e7bcb4db9610432bb7efb7fe815ef36
[upkg.git] / src / engine / music-modplug.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <modplug.h>
4 #include "modplug-types.h"
5
6 #include "music-module.h"
7 #include "upkg.h"
8
9 struct music_mod {
10         ModPlugFile *f;
11         size_t len, alloc;
12         unsigned char buf[];
13 };
14
15 #define BUF_INIT_SIZE 65536
16
17 int music_mod_init(void)
18 {
19         ModPlug_Settings settings = {
20                 .mFlags          = MODPLUG_ENABLE_OVERSAMPLING,
21                 .mChannels       = 2,
22                 .mFrequency      = 44100,
23                 .mResamplingMode = MODPLUG_RESAMPLE_SPLINE,
24                 .mLoopCount      = -1,
25         };
26
27         ModPlug_SetSettings(&settings);
28         return 0;
29 }
30
31 void music_mod_exit(void)
32 {
33 }
34
35 static struct music_mod *readfile(struct upkg_file *f)
36 {
37         struct music_mod *m = malloc(sizeof *m + BUF_INIT_SIZE);
38         if (!m) return NULL;
39         *m = (struct music_mod) {
40                 .alloc = BUF_INIT_SIZE
41         };
42
43         while (1) {
44                 struct music_mod *tmp;
45                 size_t sz = m->alloc - m->len;
46                 
47                 m->len += upkg_export_read(f, m->buf + m->len, sz);
48                 if (m->alloc != m->len) {
49                         if (f->eof) {
50                                 tmp = realloc(m, sizeof *m + m->len);
51                                 return tmp ? tmp : m;
52                         }
53
54                         break;
55                 }
56
57                 tmp = realloc(m, sizeof *m + 2*m->alloc);
58                 if (!tmp)
59                         break;
60                 m = tmp;
61                 m->alloc *= 2;
62         }
63
64         free(m);
65         return NULL;
66 }
67
68 struct music_mod *music_mod_open(struct upkg_file *f)
69 {
70         struct music_mod *m = readfile(f);
71         if (!m) return NULL;
72
73         m->f = ModPlug_Load(m->buf, m->len);
74         if (!m->f) {
75                 free(m);
76                 return NULL;
77         }
78
79         return m;
80 }
81
82 int music_mod_dump(struct music_mod *m, FILE *of)
83 {
84         if (fwrite(m->buf, m->len, 1, of) != 1)
85                 return -1;
86         return 0;
87 }
88
89 void music_mod_close(struct music_mod *m)
90 {
91         ModPlug_Unload(m->f);
92         free(m);
93 }
94
95 const char *music_mod_type(struct music_mod *m)
96 {
97         int type = ModPlug_GetModuleType(m->f);
98
99         if (type & MOD_TYPE_MOD)
100                 return "mod";
101         if (type & MOD_TYPE_S3M)
102                 return "s3m";
103         if (type & MOD_TYPE_XM)
104                 return "xm";
105         if (type & MOD_TYPE_IT)
106                 return "it";
107         return "unknown";
108 }