mirror of
https://github.com/nishiowo/nishbox
synced 2025-04-21 12:14:39 +00:00
working on audio
This commit is contained in:
parent
558c78863b
commit
ca17a29d57
11
engine/audio/gf_audio_mod.c
Normal file
11
engine/audio/gf_audio_mod.c
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#include <gf_pre.h>
|
||||||
|
|
||||||
|
/* External library */
|
||||||
|
#define JAR_MOD_IMPLEMENTATION
|
||||||
|
#include <jar_mod.h>
|
||||||
|
|
||||||
|
/* Interface */
|
||||||
|
|
||||||
|
/* Engine */
|
||||||
|
|
||||||
|
/* Standard */
|
11
engine/audio/gf_audio_xm.c
Normal file
11
engine/audio/gf_audio_xm.c
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#include <gf_pre.h>
|
||||||
|
|
||||||
|
/* External library */
|
||||||
|
#define JAR_XM_IMPLEMENTATION
|
||||||
|
#include <jar_xm.h>
|
||||||
|
|
||||||
|
/* Interface */
|
||||||
|
|
||||||
|
/* Engine */
|
||||||
|
|
||||||
|
/* Standard */
|
149
engine/gf_audio.c
Normal file
149
engine/gf_audio.c
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
#define GF_EXPOSE_AUDIO
|
||||||
|
|
||||||
|
#include <gf_pre.h>
|
||||||
|
|
||||||
|
/* External library */
|
||||||
|
#include <miniaudio.h>
|
||||||
|
#include <jar_xm.h>
|
||||||
|
#include <jar_mod.h>
|
||||||
|
|
||||||
|
/* Interface */
|
||||||
|
#include <gf_audio.h>
|
||||||
|
|
||||||
|
/* Engine */
|
||||||
|
#include <gf_log.h>
|
||||||
|
|
||||||
|
/* Standard */
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
for(i = 0; i < frame; i++) {
|
||||||
|
tmp[2 * i + 0] = 0;
|
||||||
|
tmp[2 * i + 1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0; i < GF_AUDIO_MAX_DECODERS; i++) {
|
||||||
|
if(audio->decoder[i].used == 1) {
|
||||||
|
ma_uint64 readframe;
|
||||||
|
int j;
|
||||||
|
ma_int16* r = malloc(sizeof(*r) * frame * 2);
|
||||||
|
ma_decoder_read_pcm_frames(audio->decoder[i].decoder, r, frame, &readframe);
|
||||||
|
for(j = 0; j < readframe; 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);
|
||||||
|
if(frame > readframe) {
|
||||||
|
ma_decoder_uninit(audio->decoder[i].decoder);
|
||||||
|
free(audio->decoder[i].decoder);
|
||||||
|
audio->decoder[i].decoder = NULL;
|
||||||
|
audio->decoder[i].used = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i = 0; i < frame; i++) {
|
||||||
|
out[2 * i + 0] = tmp[2 * i + 0] * 32768;
|
||||||
|
out[2 * i + 1] = tmp[2 * i + 1] * 32768;
|
||||||
|
}
|
||||||
|
free(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
int gf_audio_load(gf_audio_t* audio, const void* data, size_t size) {
|
||||||
|
int i;
|
||||||
|
for(i = 0; i < GF_AUDIO_MAX_DECODERS; i++) {
|
||||||
|
if(audio->decoder[i].used == 0) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
free(audio->decoder[i].decoder);
|
||||||
|
audio->decoder[i].decoder = NULL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int gf_audio_load_file(gf_audio_t* audio, const char* path) {
|
||||||
|
FILE* f = fopen(path, "rb");
|
||||||
|
size_t sz;
|
||||||
|
unsigned char* data;
|
||||||
|
int st;
|
||||||
|
if(f == NULL) return -1;
|
||||||
|
fseek(f, 0, SEEK_END);
|
||||||
|
sz = ftell(f);
|
||||||
|
fseek(f, 0, SEEK_SET);
|
||||||
|
|
||||||
|
data = malloc(sz);
|
||||||
|
fread(data, sz, 1, f);
|
||||||
|
st = gf_audio_load(audio, data, sz);
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
return st;
|
||||||
|
}
|
||||||
|
|
||||||
|
gf_audio_t* gf_audio_create(gf_engine_t* engine) {
|
||||||
|
gf_audio_t* audio = malloc(sizeof(*audio));
|
||||||
|
int i;
|
||||||
|
|
||||||
|
memset(audio, 0, sizeof(*audio));
|
||||||
|
audio->engine = 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 = 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].decoder = 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->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", "");
|
||||||
|
free(audio->device);
|
||||||
|
audio->device = 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
gf_log_function(engine, "Audio interface started", "");
|
||||||
|
|
||||||
|
return audio;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gf_audio_destroy(gf_audio_t* audio) {
|
||||||
|
int i;
|
||||||
|
if(audio->device != NULL) {
|
||||||
|
ma_device_uninit(audio->device);
|
||||||
|
free(audio->device);
|
||||||
|
}
|
||||||
|
for(i = 0; i < GF_AUDIO_MAX_DECODERS; i++) {
|
||||||
|
if(audio->decoder[i].decoder != NULL) {
|
||||||
|
ma_decoder_uninit(audio->decoder[i].decoder);
|
||||||
|
free(audio->decoder[i].decoder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gf_log_function(audio->engine, "Destroyed audio interface", "");
|
||||||
|
free(audio);
|
||||||
|
}
|
@ -12,6 +12,7 @@
|
|||||||
#include <gf_draw.h>
|
#include <gf_draw.h>
|
||||||
#include <gf_log.h>
|
#include <gf_log.h>
|
||||||
#include <gf_input.h>
|
#include <gf_input.h>
|
||||||
|
#include <gf_audio.h>
|
||||||
|
|
||||||
/* Standard */
|
/* Standard */
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -31,6 +32,12 @@ gf_client_t* gf_client_create(gf_engine_t* engine, const char* title) {
|
|||||||
gf_client_destroy(client);
|
gf_client_destroy(client);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
client->audio = gf_audio_create(engine);
|
||||||
|
if(client->audio == NULL) {
|
||||||
|
gf_log_function(engine, "Failed to create audio interface", "");
|
||||||
|
gf_client_destroy(client);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
client->input = gf_input_create(engine);
|
client->input = gf_input_create(engine);
|
||||||
gf_draw_set_input(client->draw, client->input);
|
gf_draw_set_input(client->draw, client->input);
|
||||||
return client;
|
return client;
|
||||||
@ -38,6 +45,7 @@ gf_client_t* gf_client_create(gf_engine_t* engine, const char* title) {
|
|||||||
|
|
||||||
void gf_client_destroy(gf_client_t* client) {
|
void gf_client_destroy(gf_client_t* client) {
|
||||||
if(client->draw != NULL) gf_draw_destroy(client->draw);
|
if(client->draw != NULL) gf_draw_destroy(client->draw);
|
||||||
|
if(client->audio != NULL) gf_audio_destroy(client->audio);
|
||||||
if(client->input != NULL) gf_input_destroy(client->input);
|
if(client->input != NULL) gf_input_destroy(client->input);
|
||||||
gf_log_function(client->engine, "Destroyed client interface", "");
|
gf_log_function(client->engine, "Destroyed client interface", "");
|
||||||
free(client);
|
free(client);
|
||||||
|
@ -1,2 +0,0 @@
|
|||||||
#define JAR_MOD_IMPLEMENTATION
|
|
||||||
#include <jar_mod.h>
|
|
@ -1,2 +0,0 @@
|
|||||||
#define JAR_XM_IMPLEMENTATION
|
|
||||||
#include <jar_xm.h>
|
|
56
engine/include/gf_audio.h
Normal file
56
engine/include/gf_audio.h
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
/**
|
||||||
|
* @file gf_audio.h
|
||||||
|
* @~english
|
||||||
|
* @brief Audio interface
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GF_AUDIO_H__
|
||||||
|
#define __GF_AUDIO_H__
|
||||||
|
|
||||||
|
#include <gf_pre.h>
|
||||||
|
#include <gf_macro.h>
|
||||||
|
|
||||||
|
/* Type */
|
||||||
|
#include <gf_type/audio.h>
|
||||||
|
|
||||||
|
/* Engine */
|
||||||
|
#include <gf_type/core.h>
|
||||||
|
|
||||||
|
/* Standard */
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @~english
|
||||||
|
* @brief Create audio interface
|
||||||
|
* @param engine Engine instance
|
||||||
|
* @return Audio interface
|
||||||
|
*/
|
||||||
|
GF_EXPORT gf_audio_t* gf_audio_create(gf_engine_t* engine);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @~english
|
||||||
|
* @brief Destroy audio interface
|
||||||
|
* @param audio Audio interface
|
||||||
|
*/
|
||||||
|
GF_EXPORT void gf_audio_destroy(gf_audio_t* audio);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @~english
|
||||||
|
* @brief Load and play file
|
||||||
|
* @param audio Audio interface
|
||||||
|
* @param path Path
|
||||||
|
* @return `0` if successful, otherwise `-1`
|
||||||
|
*/
|
||||||
|
int gf_audio_load_file(gf_audio_t* audio, const char* path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @~english
|
||||||
|
* @brief Load and play data
|
||||||
|
* @param audio Audio interface
|
||||||
|
* @param data Data
|
||||||
|
* @param size Data size
|
||||||
|
* @return `0` if successful, otherwise `-1`
|
||||||
|
*/
|
||||||
|
int gf_audio_load(gf_audio_t* audio, const void* data, size_t size);
|
||||||
|
|
||||||
|
#endif
|
@ -121,6 +121,14 @@
|
|||||||
#define GF_EXPOSE_INPUT
|
#define GF_EXPOSE_INPUT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef GF_EXPOSE_AUDIO
|
||||||
|
/**
|
||||||
|
* @~english
|
||||||
|
* @brief Expose audio interface properties
|
||||||
|
*/
|
||||||
|
#define GF_EXPOSE_AUDIO
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef GF_EXPOSE_GRAPHIC
|
#ifndef GF_EXPOSE_GRAPHIC
|
||||||
/**
|
/**
|
||||||
* @~english
|
* @~english
|
||||||
|
79
engine/include/gf_type/audio.h
Normal file
79
engine/include/gf_type/audio.h
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
/**
|
||||||
|
* @file gf_type/audio.h
|
||||||
|
* @~english
|
||||||
|
* @brief Type definitions related to audio interface
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GF_TYPE_AUDIO_H__
|
||||||
|
#define __GF_TYPE_AUDIO_H__
|
||||||
|
|
||||||
|
#include <gf_pre.h>
|
||||||
|
#include <gf_macro.h>
|
||||||
|
|
||||||
|
#ifdef GF_EXPOSE_AUDIO
|
||||||
|
typedef struct gf_audio_t gf_audio_t;
|
||||||
|
typedef struct gf_audio_decoder_t gf_audio_decoder_t;
|
||||||
|
|
||||||
|
/* External library */
|
||||||
|
#include <miniaudio.h>
|
||||||
|
|
||||||
|
/* Engine */
|
||||||
|
#include <gf_type/core.h>
|
||||||
|
|
||||||
|
/* Standard */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @~english
|
||||||
|
* @brief Max decoders audio interface can handle
|
||||||
|
*/
|
||||||
|
#define GF_AUDIO_MAX_DECODERS 64
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @struct gf_audio_decoder_t
|
||||||
|
* @~english
|
||||||
|
* @brief Audio decoder
|
||||||
|
*
|
||||||
|
* @var gf_audio_decoder_t::decoder_config
|
||||||
|
* @brief miniaudio decoder config
|
||||||
|
*
|
||||||
|
* @var gf_audio_decoder_t::decoder
|
||||||
|
* @brief miniaudio decoder
|
||||||
|
*
|
||||||
|
* @var gf_audio_decoder_t::used
|
||||||
|
* @brief `1` if used, otherwise `0`
|
||||||
|
*/
|
||||||
|
GF_DECLARE_TYPE(audio_decoder, {
|
||||||
|
ma_decoder_config decoder_config;
|
||||||
|
ma_decoder* decoder;
|
||||||
|
int used;
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @struct gf_audio_t
|
||||||
|
* @~english
|
||||||
|
* @brief Audio interface
|
||||||
|
*
|
||||||
|
* @var gf_audio_t::engine
|
||||||
|
* @brief Engine instance
|
||||||
|
*
|
||||||
|
* @var gf_audio_t::device_config
|
||||||
|
* @brief miniaudio device config
|
||||||
|
*
|
||||||
|
* @var gf_audio_t::device
|
||||||
|
* @brief miniaudio device
|
||||||
|
*
|
||||||
|
* @var gf_audio_t::decoder
|
||||||
|
* @brief Decoder
|
||||||
|
*/
|
||||||
|
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];
|
||||||
|
});
|
||||||
|
#else
|
||||||
|
typedef void gf_audio_decoder_t;
|
||||||
|
typedef void gf_audio_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@ -19,6 +19,7 @@ typedef struct gf_client_t gf_client_t;
|
|||||||
#include <gf_type/core.h>
|
#include <gf_type/core.h>
|
||||||
#include <gf_type/draw.h>
|
#include <gf_type/draw.h>
|
||||||
#include <gf_type/input.h>
|
#include <gf_type/input.h>
|
||||||
|
#include <gf_type/audio.h>
|
||||||
|
|
||||||
/* Standard */
|
/* Standard */
|
||||||
|
|
||||||
@ -35,11 +36,15 @@ typedef struct gf_client_t gf_client_t;
|
|||||||
*
|
*
|
||||||
* @var gf_client_t::input
|
* @var gf_client_t::input
|
||||||
* @brief Input interface
|
* @brief Input interface
|
||||||
|
*
|
||||||
|
* @var gf_client_t::audio
|
||||||
|
* @brief Audio interface
|
||||||
*/
|
*/
|
||||||
GF_DECLARE_TYPE(client, {
|
GF_DECLARE_TYPE(client, {
|
||||||
gf_engine_t* engine;
|
gf_engine_t* engine;
|
||||||
gf_draw_t* draw;
|
gf_draw_t* draw;
|
||||||
gf_input_t* input;
|
gf_input_t* input;
|
||||||
|
gf_audio_t* audio;
|
||||||
});
|
});
|
||||||
#else
|
#else
|
||||||
typedef void gf_client_t;
|
typedef void gf_client_t;
|
||||||
|
@ -43,7 +43,7 @@ typedef void (*gf_gui_callback_t)(gf_engine_t* engine, gf_draw_t* draw, gf_gui_i
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @~english
|
* @~english
|
||||||
* @brief Max components engine GUI can handle
|
* @brief Max components GUI can handle
|
||||||
*/
|
*/
|
||||||
#define GF_GUI_MAX_COMPONENTS 64
|
#define GF_GUI_MAX_COMPONENTS 64
|
||||||
|
|
||||||
|
@ -297,6 +297,9 @@ project("GoldFish")
|
|||||||
"external/lua/l*.h",
|
"external/lua/l*.h",
|
||||||
"external/lua/l*.c",
|
"external/lua/l*.c",
|
||||||
})
|
})
|
||||||
|
files({
|
||||||
|
"audio/*.c"
|
||||||
|
})
|
||||||
filter({
|
filter({
|
||||||
"system:windows",
|
"system:windows",
|
||||||
"options:engine=dynamic"
|
"options:engine=dynamic"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user