mirror of
https://github.com/nishiowo/nishbox
synced 2025-04-21 12:14:39 +00:00
do lock
This commit is contained in:
parent
1ad1e250e2
commit
e9cfa67901
@ -21,18 +21,20 @@
|
||||
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) {
|
||||
int i;
|
||||
gf_audio_t* audio = dev->pUserData;
|
||||
ma_int16* out = (ma_int16*)output;
|
||||
float* tmp = malloc(sizeof(*tmp) * frame * 2);
|
||||
gf_audio_id_t i;
|
||||
gf_audio_t* audio = dev->pUserData;
|
||||
ma_int16* out = (ma_int16*)output;
|
||||
float* tmp = malloc(sizeof(*tmp) * frame * 2);
|
||||
int unlocked = 0;
|
||||
|
||||
for(i = 0; i < frame; i++) {
|
||||
tmp[2 * i + 0] = 0;
|
||||
tmp[2 * i + 1] = 0;
|
||||
}
|
||||
|
||||
ma_mutex_lock(audio->mutex);
|
||||
for(i = 0; i < GF_AUDIO_MAX_DECODERS; i++) {
|
||||
if(audio->decoder[i].used && audio->decoder[i].decoder != NULL) {
|
||||
if(audio->decoder[i].used == 1 && audio->decoder[i].decoder != NULL) {
|
||||
ma_uint64 readframe;
|
||||
int j;
|
||||
ma_int16* r = malloc(sizeof(*r) * frame * 2);
|
||||
@ -43,9 +45,11 @@ void gf_audio_callback(ma_device* dev, void* output, const void* input, ma_uint3
|
||||
}
|
||||
free(r);
|
||||
if(frame > readframe) {
|
||||
ma_mutex_unlock(audio->mutex);
|
||||
unlocked = 1;
|
||||
gf_audio_decoder_destroy(&audio->decoder[i]);
|
||||
}
|
||||
} else if(audio->decoder[i].used && audio->decoder[i].xm != NULL) {
|
||||
} else if(audio->decoder[i].used == 1 && audio->decoder[i].xm != NULL) {
|
||||
int j;
|
||||
int gotframe;
|
||||
float* r = malloc(sizeof(*r) * frame * 2);
|
||||
@ -58,9 +62,11 @@ void gf_audio_callback(ma_device* dev, void* output, const void* input, ma_uint3
|
||||
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 && audio->decoder[i].mod != NULL) {
|
||||
} else if(audio->decoder[i].used == 1 && audio->decoder[i].mod != NULL) {
|
||||
int j;
|
||||
int gotframe;
|
||||
ma_int16* r = malloc(sizeof(*r) * frame * 2);
|
||||
@ -73,10 +79,13 @@ void gf_audio_callback(ma_device* dev, void* output, const void* input, ma_uint3
|
||||
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++) {
|
||||
out[2 * i + 0] = tmp[2 * i + 0] * 32768;
|
||||
@ -85,8 +94,9 @@ void gf_audio_callback(ma_device* dev, void* output, const void* input, ma_uint3
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
int gf_audio_load(gf_audio_t* audio, const void* data, size_t size) {
|
||||
int i;
|
||||
gf_audio_id_t gf_audio_load(gf_audio_t* audio, const void* data, size_t size) {
|
||||
gf_audio_id_t i;
|
||||
ma_mutex_lock(audio->mutex);
|
||||
for(i = 0; i < GF_AUDIO_MAX_DECODERS; i++) {
|
||||
if(audio->decoder[i].used == 0) {
|
||||
int xm_cond = size > 37 && memcmp(data, "Extended Module: ", 17) == 0 && ((char*)data)[37] == 0x1a;
|
||||
@ -104,8 +114,9 @@ int gf_audio_load(gf_audio_t* audio, const void* data, size_t size) {
|
||||
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;
|
||||
return 0;
|
||||
audio->decoder[i].used = -1;
|
||||
ma_mutex_unlock(audio->mutex);
|
||||
return i;
|
||||
}
|
||||
audio->decoder[i].xm = NULL;
|
||||
} else if(mod_cond) {
|
||||
@ -114,30 +125,34 @@ int gf_audio_load(gf_audio_t* audio, const void* data, size_t size) {
|
||||
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;
|
||||
return 0;
|
||||
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));
|
||||
if(ma_decoder_init_memory(data, size, &audio->decoder[i].decoder_config, audio->decoder[i].decoder) == MA_SUCCESS) {
|
||||
audio->decoder[i].used = 1;
|
||||
return 0;
|
||||
audio->decoder[i].used = -1;
|
||||
ma_mutex_unlock(audio->mutex);
|
||||
return i;
|
||||
}
|
||||
free(audio->decoder[i].decoder);
|
||||
audio->decoder[i].decoder = NULL;
|
||||
ma_mutex_unlock(audio->mutex);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
ma_mutex_unlock(audio->mutex);
|
||||
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");
|
||||
size_t sz;
|
||||
unsigned char* data;
|
||||
int st;
|
||||
gf_audio_id_t st;
|
||||
if(f == NULL) return -1;
|
||||
fseek(f, 0, SEEK_END);
|
||||
sz = ftell(f);
|
||||
@ -153,8 +168,9 @@ int gf_audio_load_file(gf_audio_t* audio, const char* path) {
|
||||
}
|
||||
|
||||
gf_audio_t* gf_audio_create(gf_engine_t* engine) {
|
||||
gf_audio_t* audio = malloc(sizeof(*audio));
|
||||
int i;
|
||||
gf_audio_t* audio = malloc(sizeof(*audio));
|
||||
int i;
|
||||
gf_audio_id_t id;
|
||||
|
||||
memset(audio, 0, sizeof(*audio));
|
||||
audio->engine = engine;
|
||||
@ -162,20 +178,19 @@ gf_audio_t* gf_audio_create(gf_engine_t* engine) {
|
||||
audio->device_config = ma_device_config_init(ma_device_type_playback);
|
||||
audio->device_config.playback.format = ma_format_s16;
|
||||
audio->device_config.playback.channels = 2;
|
||||
audio->device_config.sampleRate = 48000;
|
||||
audio->device_config.sampleRate = 44100;
|
||||
audio->device_config.dataCallback = gf_audio_callback;
|
||||
audio->device_config.pUserData = audio;
|
||||
|
||||
for(i = 0; i < GF_AUDIO_MAX_DECODERS; i++) {
|
||||
audio->decoder[i].used = 0;
|
||||
audio->decoder[i].audio = 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);
|
||||
}
|
||||
|
||||
gf_audio_load_file(audio, "test.xm");
|
||||
|
||||
audio->device = malloc(sizeof(*audio->device));
|
||||
if(ma_device_init(NULL, &audio->device_config, audio->device) != MA_SUCCESS) {
|
||||
gf_log_function(engine, "Failed to open playback device", "");
|
||||
@ -185,18 +200,34 @@ gf_audio_t* gf_audio_create(gf_engine_t* engine) {
|
||||
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) {
|
||||
gf_log_function(engine, "Failed to start playback device", "");
|
||||
gf_audio_destroy(audio);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for(i = 0; i < GF_AUDIO_MAX_DECODERS; i++) {
|
||||
audio->decoder[i].audio = audio;
|
||||
}
|
||||
|
||||
gf_log_function(engine, "Audio interface started", "");
|
||||
|
||||
gf_audio_resume(audio, (id = gf_audio_load_file(audio, "test.xm")));
|
||||
|
||||
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);
|
||||
@ -212,6 +243,7 @@ void gf_audio_decoder_destroy(gf_audio_decoder_t* decoder) {
|
||||
decoder->mod = NULL;
|
||||
}
|
||||
decoder->used = 0;
|
||||
ma_mutex_unlock(decoder->audio->mutex);
|
||||
}
|
||||
|
||||
void gf_audio_destroy(gf_audio_t* audio) {
|
||||
@ -220,9 +252,25 @@ void gf_audio_destroy(gf_audio_t* audio) {
|
||||
ma_device_uninit(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++) {
|
||||
gf_audio_decoder_destroy(&audio->decoder[i]);
|
||||
}
|
||||
gf_log_function(audio->engine, "Destroyed audio interface", "");
|
||||
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);
|
||||
}
|
||||
|
@ -46,9 +46,9 @@ GF_EXPORT void gf_audio_decoder_destroy(gf_audio_decoder_t* decoder);
|
||||
* @brief Load and play file
|
||||
* @param audio Audio interface
|
||||
* @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
|
||||
@ -56,8 +56,24 @@ int gf_audio_load_file(gf_audio_t* audio, const char* path);
|
||||
* @param audio Audio interface
|
||||
* @param data Data
|
||||
* @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);
|
||||
|
||||
#endif
|
||||
|
@ -10,6 +10,8 @@
|
||||
#include <gf_pre.h>
|
||||
#include <gf_macro.h>
|
||||
|
||||
typedef int gf_audio_id_t;
|
||||
|
||||
#ifdef GF_EXPOSE_AUDIO
|
||||
typedef struct gf_audio_t gf_audio_t;
|
||||
typedef struct gf_audio_decoder_t gf_audio_decoder_t;
|
||||
@ -35,6 +37,9 @@ typedef struct gf_audio_decoder_t gf_audio_decoder_t;
|
||||
* @~english
|
||||
* @brief Audio decoder
|
||||
*
|
||||
* @var gf_audio_decoder_t::audio
|
||||
* @brief Audio interface
|
||||
*
|
||||
* @var gf_audio_decoder_t::decoder_config
|
||||
* @brief miniaudio decoder config
|
||||
*
|
||||
@ -51,9 +56,10 @@ typedef struct gf_audio_decoder_t gf_audio_decoder_t;
|
||||
* @brief Remaining samples
|
||||
*
|
||||
* @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_audio_t* audio;
|
||||
ma_decoder_config decoder_config;
|
||||
ma_decoder* decoder;
|
||||
jar_xm_context_t* xm;
|
||||
@ -78,12 +84,16 @@ GF_DECLARE_TYPE(audio_decoder, {
|
||||
*
|
||||
* @var gf_audio_t::decoder
|
||||
* @brief Decoder
|
||||
*
|
||||
* @var gf_audio_t::mutex
|
||||
* @brief Mutex
|
||||
*/
|
||||
GF_DECLARE_TYPE(audio, {
|
||||
gf_engine_t* engine;
|
||||
ma_device_config device_config;
|
||||
ma_device* device;
|
||||
gf_audio_decoder_t decoder[GF_AUDIO_MAX_DECODERS];
|
||||
ma_mutex* mutex;
|
||||
});
|
||||
#else
|
||||
typedef void gf_audio_decoder_t;
|
||||
|
Loading…
x
Reference in New Issue
Block a user