NO_AUDIO option
[shapestoy] / src / music.c
1 #ifndef NO_AUDIO
2
3 #include <stdio.h>
4 #include <sys/stat.h>
5 #include "music.h"
6 #include "assfile.h"
7 #include "miniaudio/miniaudio.h"
8
9 static const char *fmtname(ma_format fmt);
10 static ma_result vopen(ma_vfs *vfs, const char *path, ma_uint32 mode, ma_vfs_file *fret);
11 static ma_result vclose(ma_vfs *vfs, ma_vfs_file fp);
12 static ma_result vread(ma_vfs *vfs, ma_vfs_file fp, void *dest, size_t sz, size_t *numread);
13 static ma_result vseek(ma_vfs *vfs, ma_vfs_file fp, ma_int64 offs, ma_seek_origin from);
14 static ma_result vtell(ma_vfs *vfs, ma_vfs_file fp, ma_int64 *pos);
15 static ma_result vinfo(ma_vfs *vfs, ma_vfs_file fp, ma_file_info *inf);
16
17 static int init_done;
18 static ma_engine engine;
19 static ma_sound sound;
20 static ma_resource_manager resman;
21 static ma_uint32 sample_rate;
22 static float volume;
23
24 static ma_vfs_callbacks vfs = {
25         vopen, 0,
26         vclose,
27         vread, 0,
28         vseek,
29         vtell,
30         vinfo
31 };
32
33 int init_music(void)
34 {
35         ma_engine_config engcfg;
36         ma_resource_manager_config rescfg;
37         unsigned int flags;
38         ma_format fmt;
39         ma_uint32 nchan;
40
41         rescfg = ma_resource_manager_config_init();
42         rescfg.pVFS = &vfs;
43         if(ma_resource_manager_init(&rescfg, &resman) != 0) {
44                 fprintf(stderr, "failed to initialize miniaudio resource manager\n");
45                 return -1;
46         }
47
48         engcfg = ma_engine_config_init();
49         engcfg.pResourceManager = &resman;
50
51         if(ma_engine_init(&engcfg, &engine) != 0) {
52                 fprintf(stderr, "failed to initialize miniaudio engine\n");
53                 return -1;
54         }
55
56         flags = MA_SOUND_FLAG_STREAM;
57         if(ma_sound_init_from_file(&engine, "data/woodclick.wav", flags, 0, 0, &sound) != 0) {
58                 fprintf(stderr, "failed to load music\n");
59                 return -1;
60         }
61         ma_sound_get_data_format(&sound, &fmt, &nchan, &sample_rate, 0, 0);
62         printf("loaded sound: %s %u.%03u khz, %u channels\n", fmtname(fmt),
63                         (unsigned int)sample_rate / 1000, (unsigned int)sample_rate % 1000,
64                         (unsigned int)nchan);
65
66         init_done = 1;
67         volume = 1.0f;
68         return 0;
69 }
70
71 void destroy_music(void)
72 {
73         if(init_done) {
74                 ma_sound_stop(&sound);
75                 ma_sound_uninit(&sound);
76                 ma_engine_uninit(&engine);
77         }
78         init_done = 0;
79 }
80
81 void play_music(void)
82 {
83         if(init_done) {
84                 ma_sound_start(&sound);
85         }
86 }
87
88 void stop_music(void)
89 {
90         if(init_done) {
91                 ma_sound_stop(&sound);
92         }
93 }
94
95 void seek_music(long tm)
96 {
97         ma_uint64 frm;
98
99         if(init_done) {
100                 if(tm < 0) tm = 0;
101                 frm = (ma_uint64)tm * (ma_uint64)sample_rate / 1000llu;
102                 ma_sound_seek_to_pcm_frame(&sound, frm);
103         }
104 }
105
106 void set_music_volume(float vol)
107 {
108         if(init_done) {
109                 volume = vol;
110                 ma_engine_set_volume(&engine, vol);
111         }
112 }
113
114
115 static const char *fmtname(ma_format fmt)
116 {
117         switch(fmt) {
118         case ma_format_u8: return "8 bit";
119         case ma_format_s16: return "16 bit";
120         case ma_format_s24: return "24 bit";
121         case ma_format_s32: return "32 bit";
122         case ma_format_f32: return "float";
123         default:
124                 return "unknown";
125         }
126 }
127
128 static ma_result vopen(ma_vfs *vfs, const char *path, ma_uint32 mode, ma_vfs_file *fret)
129 {
130         ass_file *fp;
131
132         if(mode != MA_OPEN_MODE_READ) return -1;
133
134         if(!(fp = ass_fopen(path, "rb"))) {
135                 return -1;
136         }
137         *fret = fp;
138         return 0;
139 }
140
141 static ma_result vclose(ma_vfs *vfs, ma_vfs_file fp)
142 {
143         ass_fclose(fp);
144         return 0;
145 }
146
147 static ma_result vread(ma_vfs *vfs, ma_vfs_file fp, void *dest, size_t sz, size_t *numread)
148 {
149         size_t res;
150
151         res = ass_fread(dest, 1, sz, fp);
152         if(numread) *numread = res;
153
154         if(res != sz) {
155                 if(res == 0) return MA_AT_END;
156         }
157         return MA_SUCCESS;
158 }
159
160 static ma_result vseek(ma_vfs *vfs, ma_vfs_file fp, ma_int64 offs, ma_seek_origin org)
161 {
162         int from;
163         switch(org) {
164         case ma_seek_origin_start:
165                 from = SEEK_SET;
166                 break;
167         case ma_seek_origin_current:
168                 from = SEEK_CUR;
169                 break;
170         case ma_seek_origin_end:
171                 from = SEEK_END;
172                 break;
173         }
174         return ass_fseek(fp, offs, from) == -1 ? -1 : 0;
175 }
176
177 static ma_result vtell(ma_vfs *vfs, ma_vfs_file fp, ma_int64 *pos)
178 {
179         *pos = ass_ftell(fp);
180         return 0;
181 }
182
183 static ma_result vinfo(ma_vfs *vfs, ma_vfs_file fp, ma_file_info *inf)
184 {
185         int fd;
186         struct stat st;
187
188 #ifdef _MSC_VER
189         fd = _fileno(fp);
190 #else
191         fd = fileno(fp);
192 #endif
193
194         if(fstat(fd, &st) != 0) {
195                 return MA_ERROR;
196         }
197         inf->sizeInBytes = st.st_size;
198         return MA_SUCCESS;
199 }
200
201 #else   /* NO_AUDIO */
202
203 int init_music(void)
204 {
205         return 0;
206 }
207
208 void destroy_music(void)
209 {
210 }
211
212 void play_music(void)
213 {
214 }
215
216 void stop_music(void)
217 {
218 }
219
220 void seek_music(long tm)
221 {
222 }
223
224
225 void set_music_volume(float vol)
226 {
227 }
228
229 #endif