mirror of
https://github.com/nishiowo/nishbox
synced 2025-04-22 04:34:38 +00:00
Compare commits
4 Commits
ca17a29d57
...
03290d0553
Author | SHA1 | Date | |
---|---|---|---|
![]() |
03290d0553 | ||
![]() |
e9cfa67901 | ||
![]() |
1ad1e250e2 | ||
![]() |
f5036b8a0b |
18
engine/external/jar/jar_mod.h
vendored
18
engine/external/jar/jar_mod.h
vendored
@ -254,6 +254,7 @@ gf_bool_t jar_mod_setcfg(jar_mod_context_t* modctx, int samplerate, int bits, in
|
|||||||
void jar_mod_fillbuffer(jar_mod_context_t* modctx, gf_int16_t* outbuffer, unsigned long nbsample, jar_mod_tracker_buffer_state* trkbuf);
|
void jar_mod_fillbuffer(jar_mod_context_t* modctx, gf_int16_t* outbuffer, unsigned long nbsample, jar_mod_tracker_buffer_state* trkbuf);
|
||||||
void jar_mod_unload(jar_mod_context_t* modctx);
|
void jar_mod_unload(jar_mod_context_t* modctx);
|
||||||
mulong jar_mod_load_file(jar_mod_context_t* modctx, const char* filename);
|
mulong jar_mod_load_file(jar_mod_context_t* modctx, const char* filename);
|
||||||
|
gf_bool_t jar_mod_load(jar_mod_context_t* modctx, void* mod_data, int mod_data_size);
|
||||||
mulong jar_mod_current_samples(jar_mod_context_t* modctx);
|
mulong jar_mod_current_samples(jar_mod_context_t* modctx);
|
||||||
mulong jar_mod_max_samples(jar_mod_context_t* modctx);
|
mulong jar_mod_max_samples(jar_mod_context_t* modctx);
|
||||||
void jar_mod_seek_start(jar_mod_context_t* ctx);
|
void jar_mod_seek_start(jar_mod_context_t* ctx);
|
||||||
@ -969,7 +970,7 @@ gf_bool_t jar_mod_setcfg(jar_mod_context_t* modctx, int samplerate, int bits, in
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* make certain that mod_data stays in memory while playing */
|
/* make certain that mod_data stays in memory while playing */
|
||||||
static gf_bool_t jar_mod_load(jar_mod_context_t* modctx, void* mod_data, int mod_data_size) {
|
gf_bool_t jar_mod_load(jar_mod_context_t* modctx, void* mod_data, int mod_data_size) {
|
||||||
muint i, max;
|
muint i, max;
|
||||||
unsigned short t;
|
unsigned short t;
|
||||||
sample* sptr;
|
sample* sptr;
|
||||||
@ -1090,7 +1091,7 @@ void jar_mod_fillbuffer(jar_mod_context_t* modctx, gf_int16_t* outbuffer, unsign
|
|||||||
note* nptr;
|
note* nptr;
|
||||||
channel* cptr;
|
channel* cptr;
|
||||||
|
|
||||||
if(modctx && outbuffer) {
|
if(modctx) {
|
||||||
if(modctx->mod_loaded) {
|
if(modctx->mod_loaded) {
|
||||||
state_remaining_steps = 0;
|
state_remaining_steps = 0;
|
||||||
|
|
||||||
@ -1247,8 +1248,10 @@ void jar_mod_fillbuffer(jar_mod_context_t* modctx, gf_int16_t* outbuffer, unsign
|
|||||||
if(r < -32768) r = -32768;
|
if(r < -32768) r = -32768;
|
||||||
|
|
||||||
/* Store the final sample. */
|
/* Store the final sample. */
|
||||||
outbuffer[(i * 2)] = l;
|
if(outbuffer != NULL) {
|
||||||
outbuffer[(i * 2) + 1] = r;
|
outbuffer[(i * 2)] = l;
|
||||||
|
outbuffer[(i * 2) + 1] = r;
|
||||||
|
}
|
||||||
|
|
||||||
ll = tl;
|
ll = tl;
|
||||||
lr = tr;
|
lr = tr;
|
||||||
@ -1257,6 +1260,7 @@ void jar_mod_fillbuffer(jar_mod_context_t* modctx, gf_int16_t* outbuffer, unsign
|
|||||||
modctx->last_l_sample = ll;
|
modctx->last_l_sample = ll;
|
||||||
modctx->last_r_sample = lr;
|
modctx->last_r_sample = lr;
|
||||||
|
|
||||||
|
skip:;
|
||||||
modctx->samplenb = modctx->samplenb + nbsample;
|
modctx->samplenb = modctx->samplenb + nbsample;
|
||||||
} else {
|
} else {
|
||||||
for(i = 0; i < nbsample; i++) {
|
for(i = 0; i < nbsample; i++) {
|
||||||
@ -1351,14 +1355,16 @@ mulong jar_mod_current_samples(jar_mod_context_t* modctx) {
|
|||||||
|
|
||||||
/* Works, however it is very slow, this data should be cached to ensure it is run only once per file */
|
/* Works, however it is very slow, this data should be cached to ensure it is run only once per file */
|
||||||
mulong jar_mod_max_samples(jar_mod_context_t* ctx) {
|
mulong jar_mod_max_samples(jar_mod_context_t* ctx) {
|
||||||
mint buff[2];
|
|
||||||
mulong len;
|
mulong len;
|
||||||
mulong lastcount = ctx->loopcount;
|
mulong lastcount = ctx->loopcount;
|
||||||
|
|
||||||
while(ctx->loopcount <= lastcount) jar_mod_fillbuffer(ctx, buff, 1, 0);
|
while(ctx->loopcount <= lastcount) jar_mod_fillbuffer(ctx, NULL, 1, 0);
|
||||||
|
|
||||||
len = ctx->samplenb;
|
len = ctx->samplenb;
|
||||||
jar_mod_seek_start(ctx);
|
jar_mod_seek_start(ctx);
|
||||||
|
ctx->samplenb = 0;
|
||||||
|
ctx->tablepos = 0;
|
||||||
|
ctx->patternpos = 0;
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
@ -18,19 +18,23 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
const 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"};
|
||||||
|
|
||||||
void gf_audio_callback(ma_device* dev, void* output, const void* input, ma_uint32 frame) {
|
void gf_audio_callback(ma_device* dev, void* output, const void* input, ma_uint32 frame) {
|
||||||
int i;
|
gf_audio_id_t i;
|
||||||
gf_audio_t* audio = dev->pUserData;
|
gf_audio_t* audio = dev->pUserData;
|
||||||
ma_int16* out = (ma_int16*)output;
|
ma_int16* out = (ma_int16*)output;
|
||||||
float* tmp = malloc(sizeof(*tmp) * frame * 2);
|
float* tmp = malloc(sizeof(*tmp) * frame * 2);
|
||||||
|
int unlocked = 0;
|
||||||
|
|
||||||
for(i = 0; i < frame; i++) {
|
for(i = 0; i < frame; i++) {
|
||||||
tmp[2 * i + 0] = 0;
|
tmp[2 * i + 0] = 0;
|
||||||
tmp[2 * i + 1] = 0;
|
tmp[2 * i + 1] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ma_mutex_lock(audio->mutex);
|
||||||
for(i = 0; i < GF_AUDIO_MAX_DECODERS; i++) {
|
for(i = 0; i < GF_AUDIO_MAX_DECODERS; i++) {
|
||||||
if(audio->decoder[i].used == 1) {
|
if(audio->decoder[i].used == 1 && audio->decoder[i].decoder != NULL) {
|
||||||
ma_uint64 readframe;
|
ma_uint64 readframe;
|
||||||
int j;
|
int j;
|
||||||
ma_int16* r = malloc(sizeof(*r) * frame * 2);
|
ma_int16* r = malloc(sizeof(*r) * frame * 2);
|
||||||
@ -41,13 +45,47 @@ void gf_audio_callback(ma_device* dev, void* output, const void* input, ma_uint3
|
|||||||
}
|
}
|
||||||
free(r);
|
free(r);
|
||||||
if(frame > readframe) {
|
if(frame > readframe) {
|
||||||
ma_decoder_uninit(audio->decoder[i].decoder);
|
ma_mutex_unlock(audio->mutex);
|
||||||
free(audio->decoder[i].decoder);
|
unlocked = 1;
|
||||||
audio->decoder[i].decoder = NULL;
|
gf_audio_decoder_destroy(&audio->decoder[i]);
|
||||||
audio->decoder[i].used = 0;
|
}
|
||||||
|
} else if(audio->decoder[i].used == 1 && audio->decoder[i].xm != NULL) {
|
||||||
|
int j;
|
||||||
|
int gotframe;
|
||||||
|
float* r = malloc(sizeof(*r) * frame * 2);
|
||||||
|
jar_xm_generate_samples(audio->decoder[i].xm, r, frame);
|
||||||
|
gotframe = audio->decoder[i].samples > frame ? frame : audio->decoder[i].samples;
|
||||||
|
for(j = 0; j < gotframe; j++) {
|
||||||
|
tmp[2 * j + 0] += (double)r[2 * j + 0];
|
||||||
|
tmp[2 * j + 1] += (double)r[2 * j + 1];
|
||||||
|
}
|
||||||
|
free(r);
|
||||||
|
audio->decoder[i].samples -= frame;
|
||||||
|
if(audio->decoder[i].samples <= 0) {
|
||||||
|
ma_mutex_unlock(audio->mutex);
|
||||||
|
unlocked = 1;
|
||||||
|
gf_audio_decoder_destroy(&audio->decoder[i]);
|
||||||
|
}
|
||||||
|
} else if(audio->decoder[i].used == 1 && audio->decoder[i].mod != NULL) {
|
||||||
|
int j;
|
||||||
|
int gotframe;
|
||||||
|
ma_int16* r = malloc(sizeof(*r) * frame * 2);
|
||||||
|
jar_mod_fillbuffer(audio->decoder[i].mod, r, frame, NULL);
|
||||||
|
gotframe = audio->decoder[i].samples > frame ? frame : audio->decoder[i].samples;
|
||||||
|
for(j = 0; j < gotframe; j++) {
|
||||||
|
tmp[2 * j + 0] += (double)r[2 * j + 0] / 32768.0;
|
||||||
|
tmp[2 * j + 1] += (double)r[2 * j + 1] / 32768.0;
|
||||||
|
}
|
||||||
|
free(r);
|
||||||
|
audio->decoder[i].samples -= frame;
|
||||||
|
if(audio->decoder[i].samples <= 0) {
|
||||||
|
ma_mutex_unlock(audio->mutex);
|
||||||
|
unlocked = 1;
|
||||||
|
gf_audio_decoder_destroy(&audio->decoder[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(!unlocked) ma_mutex_unlock(audio->mutex);
|
||||||
|
|
||||||
for(i = 0; i < frame; i++) {
|
for(i = 0; i < frame; i++) {
|
||||||
out[2 * i + 0] = tmp[2 * i + 0] * 32768;
|
out[2 * i + 0] = tmp[2 * i + 0] * 32768;
|
||||||
@ -56,28 +94,65 @@ void gf_audio_callback(ma_device* dev, void* output, const void* input, ma_uint3
|
|||||||
free(tmp);
|
free(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
int gf_audio_load(gf_audio_t* audio, const void* data, size_t size) {
|
gf_audio_id_t gf_audio_load(gf_audio_t* audio, const void* data, size_t size) {
|
||||||
int i;
|
gf_audio_id_t i;
|
||||||
|
ma_mutex_lock(audio->mutex);
|
||||||
for(i = 0; i < GF_AUDIO_MAX_DECODERS; i++) {
|
for(i = 0; i < GF_AUDIO_MAX_DECODERS; i++) {
|
||||||
if(audio->decoder[i].used == 0) {
|
if(audio->decoder[i].used == 0) {
|
||||||
|
int xm_cond = size > 37 && memcmp(data, "Extended Module: ", 17) == 0 && ((char*)data)[37] == 0x1a;
|
||||||
|
int mod_cond = size > 1080;
|
||||||
|
|
||||||
|
if(mod_cond) {
|
||||||
|
int j;
|
||||||
|
int mod_sig_cond = 0;
|
||||||
|
for(j = 0; j < sizeof(gf_audio_mod_sig) / sizeof(gf_audio_mod_sig[0]); j++) {
|
||||||
|
mod_sig_cond = mod_sig_cond || (memcmp(data + 1080, gf_audio_mod_sig[j], 4) == 0);
|
||||||
|
}
|
||||||
|
mod_cond = mod_cond && mod_sig_cond;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(xm_cond) {
|
||||||
|
if(jar_xm_create_context_safe(&audio->decoder[i].xm, data, size, audio->device_config.sampleRate) == 0) {
|
||||||
|
audio->decoder[i].samples = jar_xm_get_remaining_samples(audio->decoder[i].xm);
|
||||||
|
audio->decoder[i].used = -1;
|
||||||
|
ma_mutex_unlock(audio->mutex);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
audio->decoder[i].xm = NULL;
|
||||||
|
} else if(mod_cond) {
|
||||||
|
audio->decoder[i].mod = malloc(sizeof(*audio->decoder[i].mod));
|
||||||
|
jar_mod_init(audio->decoder[i].mod);
|
||||||
|
jar_mod_setcfg(audio->decoder[i].mod, audio->device_config.sampleRate, 16, 1, 0, 0);
|
||||||
|
if(jar_mod_load(audio->decoder[i].mod, (void*)data, size)) {
|
||||||
|
audio->decoder[i].samples = jar_mod_max_samples(audio->decoder[i].mod);
|
||||||
|
audio->decoder[i].used = -1;
|
||||||
|
ma_mutex_unlock(audio->mutex);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
free(audio->decoder[i].mod);
|
||||||
|
audio->decoder[i].mod = NULL;
|
||||||
|
}
|
||||||
audio->decoder[i].decoder = malloc(sizeof(*audio->decoder[i].decoder));
|
audio->decoder[i].decoder = malloc(sizeof(*audio->decoder[i].decoder));
|
||||||
if(ma_decoder_init_memory(data, size, &audio->decoder[i].decoder_config, audio->decoder[i].decoder) == MA_SUCCESS) {
|
if(ma_decoder_init_memory(data, size, &audio->decoder[i].decoder_config, audio->decoder[i].decoder) == MA_SUCCESS) {
|
||||||
audio->decoder[i].used = 1;
|
audio->decoder[i].used = -1;
|
||||||
return 0;
|
ma_mutex_unlock(audio->mutex);
|
||||||
|
return i;
|
||||||
}
|
}
|
||||||
free(audio->decoder[i].decoder);
|
free(audio->decoder[i].decoder);
|
||||||
audio->decoder[i].decoder = NULL;
|
audio->decoder[i].decoder = NULL;
|
||||||
|
ma_mutex_unlock(audio->mutex);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ma_mutex_unlock(audio->mutex);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int gf_audio_load_file(gf_audio_t* audio, const char* path) {
|
gf_audio_id_t gf_audio_load_file(gf_audio_t* audio, const char* path) {
|
||||||
FILE* f = fopen(path, "rb");
|
FILE* f = fopen(path, "rb");
|
||||||
size_t sz;
|
size_t sz;
|
||||||
unsigned char* data;
|
unsigned char* data;
|
||||||
int st;
|
gf_audio_id_t st;
|
||||||
if(f == NULL) return -1;
|
if(f == NULL) return -1;
|
||||||
fseek(f, 0, SEEK_END);
|
fseek(f, 0, SEEK_END);
|
||||||
sz = ftell(f);
|
sz = ftell(f);
|
||||||
@ -108,7 +183,10 @@ gf_audio_t* gf_audio_create(gf_engine_t* engine) {
|
|||||||
|
|
||||||
for(i = 0; i < GF_AUDIO_MAX_DECODERS; i++) {
|
for(i = 0; i < GF_AUDIO_MAX_DECODERS; i++) {
|
||||||
audio->decoder[i].used = 0;
|
audio->decoder[i].used = 0;
|
||||||
|
audio->decoder[i].audio = NULL;
|
||||||
audio->decoder[i].decoder = NULL;
|
audio->decoder[i].decoder = NULL;
|
||||||
|
audio->decoder[i].xm = NULL;
|
||||||
|
audio->decoder[i].mod = NULL;
|
||||||
audio->decoder[i].decoder_config = ma_decoder_config_init(audio->device_config.playback.format, audio->device_config.playback.channels, audio->device_config.sampleRate);
|
audio->decoder[i].decoder_config = ma_decoder_config_init(audio->device_config.playback.format, audio->device_config.playback.channels, audio->device_config.sampleRate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,29 +199,77 @@ gf_audio_t* gf_audio_create(gf_engine_t* engine) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
audio->mutex = malloc(sizeof(*audio->mutex));
|
||||||
|
if(ma_mutex_init(audio->mutex) != MA_SUCCESS) {
|
||||||
|
gf_log_function(engine, "Failed to create mutex", "");
|
||||||
|
free(audio->mutex);
|
||||||
|
audio->mutex = NULL;
|
||||||
|
gf_audio_destroy(audio);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if(ma_device_start(audio->device) != MA_SUCCESS) {
|
if(ma_device_start(audio->device) != MA_SUCCESS) {
|
||||||
gf_log_function(engine, "Failed to start playback device", "");
|
gf_log_function(engine, "Failed to start playback device", "");
|
||||||
gf_audio_destroy(audio);
|
gf_audio_destroy(audio);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
gf_log_function(engine, "Audio interface started", "");
|
for(i = 0; i < GF_AUDIO_MAX_DECODERS; i++) {
|
||||||
|
audio->decoder[i].audio = audio;
|
||||||
|
}
|
||||||
|
|
||||||
|
gf_log_function(engine, "Audio interface started, max %d decoders", GF_AUDIO_MAX_DECODERS);
|
||||||
|
|
||||||
return audio;
|
return audio;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gf_audio_decoder_destroy(gf_audio_decoder_t* decoder) {
|
||||||
|
ma_mutex_lock(decoder->audio->mutex);
|
||||||
|
if(decoder->decoder != NULL) {
|
||||||
|
ma_decoder_uninit(decoder->decoder);
|
||||||
|
free(decoder->decoder);
|
||||||
|
decoder->decoder = NULL;
|
||||||
|
}
|
||||||
|
if(decoder->xm != NULL) {
|
||||||
|
jar_xm_free_context(decoder->xm);
|
||||||
|
decoder->xm = NULL;
|
||||||
|
}
|
||||||
|
if(decoder->mod != NULL) {
|
||||||
|
jar_mod_unload(decoder->mod);
|
||||||
|
free(decoder->mod);
|
||||||
|
decoder->mod = NULL;
|
||||||
|
}
|
||||||
|
decoder->used = 0;
|
||||||
|
ma_mutex_unlock(decoder->audio->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
void gf_audio_destroy(gf_audio_t* audio) {
|
void gf_audio_destroy(gf_audio_t* audio) {
|
||||||
int i;
|
int i;
|
||||||
if(audio->device != NULL) {
|
if(audio->device != NULL) {
|
||||||
ma_device_uninit(audio->device);
|
ma_device_uninit(audio->device);
|
||||||
free(audio->device);
|
free(audio->device);
|
||||||
}
|
}
|
||||||
|
if(audio->mutex != NULL) {
|
||||||
|
ma_mutex_uninit(audio->mutex);
|
||||||
|
free(audio->mutex);
|
||||||
|
}
|
||||||
for(i = 0; i < GF_AUDIO_MAX_DECODERS; i++) {
|
for(i = 0; i < GF_AUDIO_MAX_DECODERS; i++) {
|
||||||
if(audio->decoder[i].decoder != NULL) {
|
gf_audio_decoder_destroy(&audio->decoder[i]);
|
||||||
ma_decoder_uninit(audio->decoder[i].decoder);
|
|
||||||
free(audio->decoder[i].decoder);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
gf_log_function(audio->engine, "Destroyed audio interface", "");
|
gf_log_function(audio->engine, "Destroyed audio interface", "");
|
||||||
free(audio);
|
free(audio);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gf_audio_resume(gf_audio_t* audio, gf_audio_id_t id) {
|
||||||
|
ma_mutex_lock(audio->mutex);
|
||||||
|
if(audio->decoder[id].used != 0) audio->decoder[id].used = 1;
|
||||||
|
ma_mutex_unlock(audio->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gf_audio_pause(gf_audio_t* audio, gf_audio_id_t id) {
|
||||||
|
ma_mutex_lock(audio->mutex);
|
||||||
|
if(audio->decoder[id].used != 0) audio->decoder[id].used = -1;
|
||||||
|
ma_mutex_unlock(audio->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gf_audio_stop(gf_audio_t* audio, gf_audio_id_t id) { gf_audio_decoder_destroy(&audio->decoder[id]); }
|
||||||
|
@ -34,14 +34,21 @@ GF_EXPORT gf_audio_t* gf_audio_create(gf_engine_t* engine);
|
|||||||
*/
|
*/
|
||||||
GF_EXPORT void gf_audio_destroy(gf_audio_t* audio);
|
GF_EXPORT void gf_audio_destroy(gf_audio_t* audio);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @~english
|
||||||
|
* @brief Destroy audio decoder
|
||||||
|
* @param decoder Audio decoder
|
||||||
|
*/
|
||||||
|
GF_EXPORT void gf_audio_decoder_destroy(gf_audio_decoder_t* decoder);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @~english
|
* @~english
|
||||||
* @brief Load and play file
|
* @brief Load and play file
|
||||||
* @param audio Audio interface
|
* @param audio Audio interface
|
||||||
* @param path Path
|
* @param path Path
|
||||||
* @return `0` if successful, otherwise `-1`
|
* @return ID if successful, otherwise `-1`
|
||||||
*/
|
*/
|
||||||
int gf_audio_load_file(gf_audio_t* audio, const char* path);
|
GF_EXPORT gf_audio_id_t gf_audio_load_file(gf_audio_t* audio, const char* path);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @~english
|
* @~english
|
||||||
@ -49,8 +56,32 @@ int gf_audio_load_file(gf_audio_t* audio, const char* path);
|
|||||||
* @param audio Audio interface
|
* @param audio Audio interface
|
||||||
* @param data Data
|
* @param data Data
|
||||||
* @param size Data size
|
* @param size Data size
|
||||||
* @return `0` if successful, otherwise `-1`
|
* @return ID if successful, otherwise `-1`
|
||||||
*/
|
*/
|
||||||
int gf_audio_load(gf_audio_t* audio, const void* data, size_t size);
|
GF_EXPORT gf_audio_id_t gf_audio_load(gf_audio_t* audio, const void* data, size_t size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @~english
|
||||||
|
* @brief Pause audio
|
||||||
|
* @param audio Audio interface
|
||||||
|
* @param id Audio ID
|
||||||
|
*/
|
||||||
|
GF_EXPORT void gf_audio_pause(gf_audio_t* audio, gf_audio_id_t id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @~english
|
||||||
|
* @brief Resume audio
|
||||||
|
* @param audio Audio interface
|
||||||
|
* @param id Audio ID
|
||||||
|
*/
|
||||||
|
GF_EXPORT void gf_audio_resume(gf_audio_t* audio, gf_audio_id_t id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @~english
|
||||||
|
* @brief Stop audio
|
||||||
|
* @param audio Audio interface
|
||||||
|
* @param id Audio ID
|
||||||
|
*/
|
||||||
|
GF_EXPORT void gf_audio_stop(gf_audio_t* audio, gf_audio_id_t id);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -10,12 +10,16 @@
|
|||||||
#include <gf_pre.h>
|
#include <gf_pre.h>
|
||||||
#include <gf_macro.h>
|
#include <gf_macro.h>
|
||||||
|
|
||||||
|
typedef int gf_audio_id_t;
|
||||||
|
|
||||||
#ifdef GF_EXPOSE_AUDIO
|
#ifdef GF_EXPOSE_AUDIO
|
||||||
typedef struct gf_audio_t gf_audio_t;
|
typedef struct gf_audio_t gf_audio_t;
|
||||||
typedef struct gf_audio_decoder_t gf_audio_decoder_t;
|
typedef struct gf_audio_decoder_t gf_audio_decoder_t;
|
||||||
|
|
||||||
/* External library */
|
/* External library */
|
||||||
#include <miniaudio.h>
|
#include <miniaudio.h>
|
||||||
|
#include <jar_xm.h>
|
||||||
|
#include <jar_mod.h>
|
||||||
|
|
||||||
/* Engine */
|
/* Engine */
|
||||||
#include <gf_type/core.h>
|
#include <gf_type/core.h>
|
||||||
@ -33,19 +37,35 @@ typedef struct gf_audio_decoder_t gf_audio_decoder_t;
|
|||||||
* @~english
|
* @~english
|
||||||
* @brief Audio decoder
|
* @brief Audio decoder
|
||||||
*
|
*
|
||||||
|
* @var gf_audio_decoder_t::audio
|
||||||
|
* @brief Audio interface
|
||||||
|
*
|
||||||
* @var gf_audio_decoder_t::decoder_config
|
* @var gf_audio_decoder_t::decoder_config
|
||||||
* @brief miniaudio decoder config
|
* @brief miniaudio decoder config
|
||||||
*
|
*
|
||||||
* @var gf_audio_decoder_t::decoder
|
* @var gf_audio_decoder_t::decoder
|
||||||
* @brief miniaudio decoder
|
* @brief miniaudio decoder
|
||||||
*
|
*
|
||||||
|
* @var gf_audio_decoder_t::xm
|
||||||
|
* @brief XM context
|
||||||
|
*
|
||||||
|
* @var gf_audio_decoder_t::mod
|
||||||
|
* @brief MOD context
|
||||||
|
*
|
||||||
|
* @var gf_audio_decoder_t::samples
|
||||||
|
* @brief Remaining samples
|
||||||
|
*
|
||||||
* @var gf_audio_decoder_t::used
|
* @var gf_audio_decoder_t::used
|
||||||
* @brief `1` if used, otherwise `0`
|
* @brief `1` if used, `-1` if used but paused, otherwise `0`
|
||||||
*/
|
*/
|
||||||
GF_DECLARE_TYPE(audio_decoder, {
|
GF_DECLARE_TYPE(audio_decoder, {
|
||||||
ma_decoder_config decoder_config;
|
gf_audio_t* audio;
|
||||||
ma_decoder* decoder;
|
ma_decoder_config decoder_config;
|
||||||
int used;
|
ma_decoder* decoder;
|
||||||
|
jar_xm_context_t* xm;
|
||||||
|
jar_mod_context_t* mod;
|
||||||
|
int samples;
|
||||||
|
int used;
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -64,12 +84,16 @@ GF_DECLARE_TYPE(audio_decoder, {
|
|||||||
*
|
*
|
||||||
* @var gf_audio_t::decoder
|
* @var gf_audio_t::decoder
|
||||||
* @brief Decoder
|
* @brief Decoder
|
||||||
|
*
|
||||||
|
* @var gf_audio_t::mutex
|
||||||
|
* @brief Mutex
|
||||||
*/
|
*/
|
||||||
GF_DECLARE_TYPE(audio, {
|
GF_DECLARE_TYPE(audio, {
|
||||||
gf_engine_t* engine;
|
gf_engine_t* engine;
|
||||||
ma_device_config device_config;
|
ma_device_config device_config;
|
||||||
ma_device* device;
|
ma_device* device;
|
||||||
gf_audio_decoder_t decoder[GF_AUDIO_MAX_DECODERS];
|
gf_audio_decoder_t decoder[GF_AUDIO_MAX_DECODERS];
|
||||||
|
ma_mutex* mutex;
|
||||||
});
|
});
|
||||||
#else
|
#else
|
||||||
typedef void gf_audio_decoder_t;
|
typedef void gf_audio_decoder_t;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user