21const char* gf_audio_mod_sig[] = {
"M!K!",
"M.K.",
"FLT4",
"FLT8",
"4CHN",
"6CHN",
"8CHN",
"10CH",
"12CH",
"14CH",
"16CH",
"18CH",
"20CH",
"22CH",
"24CH",
"26CH",
"28CH",
"30CH",
"32CH"};
23void gf_audio_callback(ma_device* dev,
void* output,
const void* input, ma_uint32 frame) {
26 ma_int16* out = (ma_int16*)output;
27 float* tmp = malloc(
sizeof(*tmp) * frame * 2);
30 for(i = 0; i < frame; i++) {
35 ma_mutex_lock(audio->
mutex);
40 ma_int16* r = malloc(
sizeof(*r) * frame * 2);
41 ma_decoder_read_pcm_frames(audio->
decoder[i].
decoder, r, frame, &readframe);
42 for(j = 0; j < readframe; j++) {
43 tmp[2 * j + 0] += (double)r[2 * j + 0] / 32768.0;
44 tmp[2 * j + 1] += (double)r[2 * j + 1] / 32768.0;
47 if(frame > readframe) {
48 ma_mutex_unlock(audio->
mutex);
55 float* r = malloc(
sizeof(*r) * frame * 2);
56 jar_xm_generate_samples(audio->
decoder[i].
xm, r, frame);
58 for(j = 0; j < gotframe; j++) {
59 tmp[2 * j + 0] += (double)r[2 * j + 0];
60 tmp[2 * j + 1] += (double)r[2 * j + 1];
65 ma_mutex_unlock(audio->
mutex);
72 ma_int16* r = malloc(
sizeof(*r) * frame * 2);
73 jar_mod_fillbuffer(audio->
decoder[i].
mod, r, frame, NULL);
75 for(j = 0; j < gotframe; j++) {
76 tmp[2 * j + 0] += (double)r[2 * j + 0] / 32768.0;
77 tmp[2 * j + 1] += (double)r[2 * j + 1] / 32768.0;
82 ma_mutex_unlock(audio->
mutex);
88 if(!unlocked) ma_mutex_unlock(audio->
mutex);
90 for(i = 0; i < frame; i++) {
91 out[2 * i + 0] = tmp[2 * i + 0] * 32768;
92 out[2 * i + 1] = tmp[2 * i + 1] * 32768;
99 ma_mutex_lock(audio->
mutex);
102 int xm_cond = size > 37 && memcmp(data,
"Extended Module: ", 17) == 0 && ((
char*)data)[37] == 0x1a;
103 int mod_cond = size > 1080;
107 int mod_sig_cond = 0;
108 for(j = 0; j <
sizeof(gf_audio_mod_sig) /
sizeof(gf_audio_mod_sig[0]); j++) {
109 mod_sig_cond = mod_sig_cond || (memcmp(data + 1080, gf_audio_mod_sig[j], 4) == 0);
111 mod_cond = mod_cond && mod_sig_cond;
118 ma_mutex_unlock(audio->
mutex);
122 }
else if(mod_cond) {
126 if(jar_mod_load(audio->
decoder[i].
mod, (
void*)data, size)) {
129 ma_mutex_unlock(audio->
mutex);
138 ma_mutex_unlock(audio->
mutex);
143 ma_mutex_unlock(audio->
mutex);
147 ma_mutex_unlock(audio->
mutex);
152 FILE* f = fopen(path,
"rb");
156 if(f == NULL)
return -1;
157 fseek(f, 0, SEEK_END);
159 fseek(f, 0, SEEK_SET);
162 fread(data, sz, 1, f);
174 memset(audio, 0,
sizeof(*audio));
177 audio->
device_config = ma_device_config_init(ma_device_type_playback);
203 if(ma_mutex_init(audio->
mutex) != MA_SUCCESS) {
211 if(ma_device_start(audio->
device) != MA_SUCCESS) {
229 ma_decoder_uninit(decoder->
decoder);
233 if(decoder->
xm != NULL) {
234 jar_xm_free_context(decoder->
xm);
237 if(decoder->
mod != NULL) {
238 jar_mod_unload(decoder->
mod);
248 if(audio->
device != NULL) {
249 ma_device_uninit(audio->
device);
252 if(audio->
mutex != NULL) {
253 ma_mutex_uninit(audio->
mutex);
264 ma_mutex_lock(audio->
mutex);
266 ma_mutex_unlock(audio->
mutex);
270 ma_mutex_lock(audio->
mutex);
272 ma_mutex_unlock(audio->
mutex);
#define GF_AUDIO_MAX_DECODERS
Max decoders audio interface can handle.
void gf_audio_stop(gf_audio_t *audio, gf_audio_id_t id)
Stop audio.
void gf_audio_resume(gf_audio_t *audio, gf_audio_id_t id)
Resume audio.
gf_audio_id_t gf_audio_load(gf_audio_t *audio, const void *data, size_t size)
Load and play data.
gf_audio_t * gf_audio_create(gf_engine_t *engine)
Create audio interface.
void gf_audio_destroy(gf_audio_t *audio)
Destroy audio interface.
void gf_audio_decoder_destroy(gf_audio_decoder_t *decoder)
Destroy audio decoder.
void gf_audio_pause(gf_audio_t *audio, gf_audio_id_t id)
Pause audio.
gf_audio_id_t gf_audio_load_file(gf_audio_t *audio, const char *path)
Load and play file.
#define gf_log_function(engine, fmt,...)
Output log with line number and function name.
Required headers before anything.
Type definitions related to math.
jar_xm_context_t * xm
XM context.
ma_decoder_config decoder_config
miniaudio decoder config
int used
1 if used, -1 if used but paused, otherwise 0
int samples
Remaining samples.
jar_mod_context_t * mod
MOD context.
gf_audio_t * audio
Audio interface.
ma_decoder * decoder
miniaudio decoder
ma_device_config device_config
miniaudio device config
ma_device * device
miniaudio device
gf_audio_decoder_t decoder[64]
Decoder.
gf_engine_t * engine
Engine instance.