add mod/xm
This commit is contained in:
parent
c7678eaeab
commit
1af31757fd
15 changed files with 499 additions and 47 deletions
|
|
@ -69,14 +69,23 @@ int main(int argc, char** argv){
|
|||
GSInit();
|
||||
|
||||
if((engine = GSEngineCreate(¶m)) != NULL){
|
||||
GSSound sound;
|
||||
|
||||
signal(SIGINT, shutdown_engine);
|
||||
signal(SIGTERM, shutdown_engine);
|
||||
|
||||
model = GSModelOpen(engine, "game:/mdl/fish.gsm");
|
||||
|
||||
GSClientToggleSkybox(GSEngineGetClient(engine), GSTrue);
|
||||
|
||||
if((sound = GSSoundOpen(GSClientGetSoundEngine(GSEngineGetClient(engine)), "game:/fracture.mod")) != NULL){
|
||||
GSSoundToggleLoop(sound, 1);
|
||||
GSSoundStart(sound);
|
||||
}
|
||||
|
||||
GSEngineLoop(engine);
|
||||
|
||||
if(sound != NULL) GSSoundClose(sound);
|
||||
GSEngineDestroy(engine);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,11 +8,12 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
GSDECL GSClient GSClientCreate(GSEngine engine);
|
||||
GSDECL void GSClientDestroy(GSClient client);
|
||||
GSDECL void GSClientStep(GSClient client);
|
||||
GSDECL GSGL GSClientGetGL(GSClient client);
|
||||
GSDECL void GSClientToggleSkybox(GSClient client, GSBool toggle);
|
||||
GSDECL GSClient GSClientCreate(GSEngine engine);
|
||||
GSDECL void GSClientDestroy(GSClient client);
|
||||
GSDECL void GSClientStep(GSClient client);
|
||||
GSDECL GSGL GSClientGetGL(GSClient client);
|
||||
GSDECL GSSoundEngine GSClientGetSoundEngine(GSClient client);
|
||||
GSDECL void GSClientToggleSkybox(GSClient client, GSBool toggle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@
|
|||
#include <GearSrc/SkyBox.h>
|
||||
#include <GearSrc/CRC.h>
|
||||
#include <GearSrc/Model.h>
|
||||
#include <GearSrc/SoundDriver.h>
|
||||
#include <GearSrc/SoundEngine.h>
|
||||
#include <GearSrc/Sound.h>
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -8,10 +8,22 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define GSSoundRate 48000
|
||||
|
||||
GSDECL GSSound GSSoundOpen(GSClient client);
|
||||
/* sound.c */
|
||||
GSDECL GSSound GSSoundNew(GSSoundEngine sengine);
|
||||
GSDECL GSSound GSSoundOpen(GSSoundEngine sengine, const char* path);
|
||||
GSDECL void GSSoundClose(GSSound sound);
|
||||
GSDECL void GSSoundToggleLoop(GSSound sound, GSBool toggle);
|
||||
GSDECL void GSSoundStart(GSSound sound);
|
||||
GSDECL void GSSoundResume(GSSound sound);
|
||||
GSDECL void GSSoundPause(GSSound audio);
|
||||
GSDECL void GSSoundLock(GSSound sound);
|
||||
GSDECL void GSSoundUnlock(GSSound sound);
|
||||
|
||||
/* snd_xm.c */
|
||||
GSDECL GSSound GSSoundOpenXM(GSSoundEngine sengine, GSFile file);
|
||||
|
||||
/* snd_mod.c */
|
||||
GSDECL GSSound GSSoundOpenMOD(GSSoundEngine sengine, GSFile file);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
20
engine/include/GearSrc/SoundDriver.h
Normal file
20
engine/include/GearSrc/SoundDriver.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef __GEARSRC_SOUNDDRIVER_H__
|
||||
#define __GEARSRC_SOUNDDRIVER_H__
|
||||
|
||||
#include <GearSrc/MachDep.h>
|
||||
#include <GearSrc/TypeDefs.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define GSSoundDriverRate 48000
|
||||
|
||||
GSDECL GSSoundDriver GSSoundDriverOpen(GSClient client, GSSoundDriverReadCallback callback, void* opaque);
|
||||
GSDECL void GSSoundDriverClose(GSSoundDriver sound);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
20
engine/include/GearSrc/SoundEngine.h
Normal file
20
engine/include/GearSrc/SoundEngine.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
#ifndef __GEARSRC_SOUNDENGINE_H__
|
||||
#define __GEARSRC_SOUNDENGINE_H__
|
||||
|
||||
#include <GearSrc/MachDep.h>
|
||||
#include <GearSrc/TypeDefs.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
GSDECL GSSoundEngine GSSoundEngineCreate(GSClient client);
|
||||
GSDECL void GSSoundEngineDestroy(GSSoundEngine sengine);
|
||||
GSDECL void GSSoundEngineLock(GSSoundEngine sengine);
|
||||
GSDECL void GSSoundEngineUnlock(GSSoundEngine sengine);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -46,15 +46,17 @@ typedef struct _GSEngineParam GSEngineParam;
|
|||
typedef struct _GSResourceKV GSResourceKV;
|
||||
typedef struct _GSBox GSBox;
|
||||
#ifdef _GEARSRC
|
||||
typedef struct _GSClient* GSClient;
|
||||
typedef struct _GSServer* GSServer;
|
||||
typedef struct _GSEngine* GSEngine;
|
||||
typedef struct _GSFile* GSFile;
|
||||
typedef struct _GSResource* GSResource;
|
||||
typedef struct _GSGL* GSGL;
|
||||
typedef struct _GSSkyBox* GSSkyBox;
|
||||
typedef struct _GSModel* GSModel;
|
||||
typedef struct _GSSound* GSSound;
|
||||
typedef struct _GSClient* GSClient;
|
||||
typedef struct _GSServer* GSServer;
|
||||
typedef struct _GSEngine* GSEngine;
|
||||
typedef struct _GSFile* GSFile;
|
||||
typedef struct _GSResource* GSResource;
|
||||
typedef struct _GSGL* GSGL;
|
||||
typedef struct _GSSkyBox* GSSkyBox;
|
||||
typedef struct _GSModel* GSModel;
|
||||
typedef struct _GSSoundDriver* GSSoundDriver;
|
||||
typedef struct _GSSoundEngine* GSSoundEngine;
|
||||
typedef struct _GSSound* GSSound;
|
||||
|
||||
typedef struct _GSModelFace GSModelFace;
|
||||
typedef struct _GSModelMaterial GSModelMaterial;
|
||||
|
|
@ -69,6 +71,8 @@ typedef void* GSResource;
|
|||
typedef void* GSGL;
|
||||
typedef void* GSSkyBox;
|
||||
typedef void* GSModel;
|
||||
typedef void* GSSoundDriver;
|
||||
typedef void* GSSoundEngine;
|
||||
typedef void* GSSound;
|
||||
#endif
|
||||
typedef float GSNumber;
|
||||
|
|
@ -85,6 +89,12 @@ typedef void (*GSSleepCallback)(int ms);
|
|||
typedef void (*GSRenderCallback)(GSEngine engine);
|
||||
typedef void (*GSAfterRenderCallback)(GSEngine engine);
|
||||
|
||||
typedef void (*GSSoundDriverReadCallback)(void* opaque, GSI16* out, int frame);
|
||||
|
||||
typedef void (*GSSoundResetCallback)(GSSound audio);
|
||||
typedef int (*GSSoundReadCallback)(GSSound audio, GSI16* out, int frame);
|
||||
typedef void (*GSSoundCloseCallback)(GSSound audio);
|
||||
|
||||
struct _GSBox {
|
||||
GSVector3 a;
|
||||
GSVector3 b;
|
||||
|
|
@ -162,8 +172,41 @@ struct _GSModel {
|
|||
struct _GSSound {
|
||||
GSEngine engine;
|
||||
|
||||
GSBool paused;
|
||||
GSBool loop;
|
||||
|
||||
ma_mutex mutex;
|
||||
|
||||
GSFile file;
|
||||
|
||||
void* opaque1;
|
||||
void* opaque2;
|
||||
|
||||
GSSoundResetCallback reset;
|
||||
GSSoundReadCallback read;
|
||||
GSSoundCloseCallback close;
|
||||
};
|
||||
|
||||
struct _GSSoundDriver {
|
||||
GSEngine engine;
|
||||
|
||||
ma_device device;
|
||||
ma_device_config config;
|
||||
|
||||
int ready;
|
||||
|
||||
GSSoundDriverReadCallback callback;
|
||||
void* opaque;
|
||||
};
|
||||
|
||||
struct _GSSoundEngine {
|
||||
GSEngine engine;
|
||||
|
||||
GSSoundDriver driver;
|
||||
|
||||
ma_mutex mutex;
|
||||
|
||||
GSSound* sound;
|
||||
};
|
||||
|
||||
struct _GSClient {
|
||||
|
|
@ -189,7 +232,7 @@ struct _GSClient {
|
|||
GSSkyBox skybox;
|
||||
GSBool skybox_enabled;
|
||||
|
||||
GSSound sound;
|
||||
GSSoundEngine sengine;
|
||||
};
|
||||
|
||||
struct _GSServer {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
#include <GearSrc/Math.h>
|
||||
#include <GearSrc/Model.h>
|
||||
#include <GearSrc/Version.h>
|
||||
#include <GearSrc/Sound.h>
|
||||
#include <GearSrc/SoundEngine.h>
|
||||
|
||||
#include <stb_ds.h>
|
||||
|
||||
|
|
@ -50,9 +50,9 @@ GSClient GSClientCreate(GSEngine engine) {
|
|||
|
||||
client->skybox_enabled = GSFalse;
|
||||
|
||||
if((client->sound = GSSoundOpen(client)) == NULL) {
|
||||
if((client->sengine = GSSoundEngineCreate(client)) == NULL) {
|
||||
GSLog(engine, GSLogError, "Failed to create sound engine");
|
||||
GSClientDestroy(client);
|
||||
GSLog(engine, GSLogError, "Failed to create client");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -89,7 +89,7 @@ void GSClientDestroy(GSClient client) {
|
|||
|
||||
GSGLDestroy(client->gl);
|
||||
|
||||
if(client->sound != NULL) GSSoundClose(client->sound);
|
||||
if(client->sengine != NULL) GSSoundEngineDestroy(client->sengine);
|
||||
|
||||
GSLog(client->engine, GSLogInfo, "Destroyed client");
|
||||
|
||||
|
|
@ -252,6 +252,10 @@ GSGL GSClientGetGL(GSClient client) {
|
|||
return client->gl;
|
||||
}
|
||||
|
||||
GSSoundEngine GSClientGetSoundEngine(GSClient client) {
|
||||
return client->sengine;
|
||||
}
|
||||
|
||||
void GSClientToggleSkybox(GSClient client, GSBool toggle) {
|
||||
client->skybox_enabled = toggle;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -270,7 +270,7 @@ GSModel GSModelOpen(GSEngine engine, const char* path) {
|
|||
|
||||
GSEngineUnregisterResource(engine, "model-ws");
|
||||
|
||||
GSLog(engine, GSLogInfo, "Opened model %s, %d vertexes, %d faces", path, arrlen(model->vertex), arrlen(model->face));
|
||||
GSLog(engine, GSLogInfo, "%s: %d vertexes, %d faces", path, arrlen(model->vertex), arrlen(model->face));
|
||||
|
||||
/* TODO: check for animation */
|
||||
if(gl != NULL) {
|
||||
|
|
|
|||
74
engine/src/snd_mod.c
Normal file
74
engine/src/snd_mod.c
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
#include <GearSrc/Sound.h>
|
||||
|
||||
#include <GearSrc/SoundDriver.h>
|
||||
#include <GearSrc/File.h>
|
||||
|
||||
#include <jar_mod.h>
|
||||
|
||||
static const char* sig[] = {"M!K!", "M.K.", "FLT4", "FLT8", "4CHN", "6CHN", "8CHN", "10CH", "12CH", "14CH", "16CH", "18CH", "20CH", "22CH", "24CH", "26CH", "28CH", "30CH", "32CH"};
|
||||
|
||||
static void snd_reset(GSSound sound) {
|
||||
jar_mod_seek_start(sound->opaque1);
|
||||
}
|
||||
|
||||
static int snd_read(GSSound sound, GSI16* out, int frame) {
|
||||
if(((jar_mod_context_t*)sound->opaque1)->loopcount > 0) return 0;
|
||||
|
||||
jar_mod_fillbuffer(sound->opaque1, out, frame, NULL);
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
static void snd_close(GSSound sound) {
|
||||
if(sound->opaque1 != NULL) {
|
||||
jar_mod_unload(sound->opaque1);
|
||||
free(sound->opaque1);
|
||||
}
|
||||
free(sound->opaque2);
|
||||
}
|
||||
|
||||
static GSBool compare(void* buf) {
|
||||
int i;
|
||||
for(i = 0; i < sizeof(sig) / sizeof(sig[0]); i++) {
|
||||
if(memcmp(((unsigned char*)buf) + 1080, sig[i], 4) == 0) return GSTrue;
|
||||
}
|
||||
|
||||
return GSFalse;
|
||||
}
|
||||
|
||||
GSSound GSSoundOpenMOD(GSSoundEngine sengine, GSFile file) {
|
||||
GSSound sound = GSSoundNew(sengine);
|
||||
int size;
|
||||
|
||||
GSFileSeek(file, 0);
|
||||
|
||||
size = GSFileSize(file);
|
||||
sound->opaque2 = malloc(size);
|
||||
GSFileRead(file, sound->opaque2, size);
|
||||
|
||||
sound->reset = snd_reset;
|
||||
sound->read = snd_read;
|
||||
sound->close = snd_close;
|
||||
|
||||
if(size < 1084 || !compare(sound->opaque2)) {
|
||||
GSSoundClose(sound);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sound->opaque1 = malloc(sizeof(jar_mod_context_t));
|
||||
jar_mod_init(sound->opaque1);
|
||||
|
||||
if(!jar_mod_load(sound->opaque1, sound->opaque2, size)) {
|
||||
free(sound->opaque1);
|
||||
sound->opaque1 = NULL;
|
||||
|
||||
GSSoundClose(sound);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
jar_mod_setcfg(sound->opaque1, GSSoundDriverRate, 16, 1, 1, 0);
|
||||
|
||||
return sound;
|
||||
}
|
||||
52
engine/src/snd_xm.c
Normal file
52
engine/src/snd_xm.c
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
#include <GearSrc/Sound.h>
|
||||
|
||||
#include <GearSrc/SoundDriver.h>
|
||||
#include <GearSrc/File.h>
|
||||
|
||||
#include <jar_xm.h>
|
||||
|
||||
static void snd_reset(GSSound sound) {
|
||||
jar_xm_reset(sound->opaque1);
|
||||
}
|
||||
|
||||
static int snd_read(GSSound sound, GSI16* out, int frame) {
|
||||
if(jar_xm_get_loop_count(sound->opaque1) == 1) return 0;
|
||||
|
||||
jar_xm_generate_samples_16bit(sound->opaque1, out, frame);
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
static void snd_close(GSSound sound) {
|
||||
if(sound->opaque1 != NULL) jar_xm_free_context(sound->opaque1);
|
||||
free(sound->opaque2);
|
||||
}
|
||||
|
||||
GSSound GSSoundOpenXM(GSSoundEngine sengine, GSFile file) {
|
||||
GSSound sound = GSSoundNew(sengine);
|
||||
int size;
|
||||
|
||||
GSFileSeek(file, 0);
|
||||
|
||||
size = GSFileSize(file);
|
||||
sound->opaque2 = malloc(size);
|
||||
GSFileRead(file, sound->opaque2, size);
|
||||
|
||||
sound->reset = snd_reset;
|
||||
sound->read = snd_read;
|
||||
sound->close = snd_close;
|
||||
|
||||
if(size < 37 || memcmp(sound->opaque2, "Extended Module: ", 17) != 0 || ((unsigned char*)sound->opaque2)[37] != 0x1a) {
|
||||
GSSoundClose(sound);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(jar_xm_create_context_safe((jar_xm_context_t**)&sound->opaque1, sound->opaque2, size, GSSoundDriverRate) != 0) {
|
||||
GSSoundClose(sound);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return sound;
|
||||
}
|
||||
|
|
@ -1,48 +1,108 @@
|
|||
#include <GearSrc/Sound.h>
|
||||
|
||||
#include <GearSrc/File.h>
|
||||
#include <GearSrc/SoundEngine.h>
|
||||
#include <GearSrc/Sound.h>
|
||||
#include <GearSrc/Log.h>
|
||||
|
||||
#include <stb_ds.h>
|
||||
#include <miniaudio.h>
|
||||
|
||||
static void data_callback(ma_device* device, void* output, const void* input, ma_uint32 frame) {
|
||||
}
|
||||
|
||||
GSSound GSSoundOpen(GSClient client) {
|
||||
GSSound GSSoundNew(GSSoundEngine sengine) {
|
||||
GSSound sound = malloc(sizeof(*sound));
|
||||
|
||||
memset(sound, 0, sizeof(*sound));
|
||||
|
||||
sound->engine = client->engine;
|
||||
sound->engine = sengine->engine;
|
||||
|
||||
sound->config = ma_device_config_init(ma_device_type_playback);
|
||||
sound->config.playback.format = ma_format_s16;
|
||||
sound->config.playback.channels = 2;
|
||||
sound->config.sampleRate = GSSoundRate;
|
||||
sound->config.dataCallback = data_callback;
|
||||
sound->config.pUserData = sound;
|
||||
sound->paused = 1;
|
||||
sound->loop = 0;
|
||||
|
||||
if(ma_device_init(NULL, &sound->config, &sound->device) != MA_SUCCESS) {
|
||||
free(sound);
|
||||
GSLog(client->engine, GSLogInfo, "Failed to open sound");
|
||||
return NULL;
|
||||
}
|
||||
ma_mutex_init(&sound->mutex);
|
||||
|
||||
if(ma_device_start(&sound->device) != MA_SUCCESS) {
|
||||
ma_device_uninit(&sound->device);
|
||||
free(sound);
|
||||
GSLog(client->engine, GSLogInfo, "Failed to open sound");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GSLog(client->engine, GSLogInfo, "Opened sound");
|
||||
GSSoundEngineLock(sengine);
|
||||
arrput(sengine->sound, sound);
|
||||
GSSoundEngineUnlock(sengine);
|
||||
|
||||
return sound;
|
||||
}
|
||||
|
||||
void GSSoundClose(GSSound sound) {
|
||||
ma_device_uninit(&sound->device);
|
||||
GSSound GSSoundOpen(GSSoundEngine sengine, const char* path) {
|
||||
GSSound s;
|
||||
GSFile f;
|
||||
|
||||
GSLog(sound->engine, GSLogInfo, "Closed sound");
|
||||
if((f = GSFileOpen(sengine->engine, path)) == NULL) return NULL;
|
||||
if((s = GSSoundOpenXM(sengine, f)) != NULL) {
|
||||
s->file = f;
|
||||
GSLog(sengine->engine, GSLogInfo, "%s: Opened as XM", path);
|
||||
return s;
|
||||
}
|
||||
|
||||
if((s = GSSoundOpenMOD(sengine, f)) != NULL) {
|
||||
s->file = f;
|
||||
GSLog(sengine->engine, GSLogInfo, "%s: Opened as MOD", path);
|
||||
return s;
|
||||
}
|
||||
|
||||
GSLog(sengine->engine, GSLogError, "%s: Unrecognized format", path);
|
||||
|
||||
GSFileClose(f);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void GSSoundClose(GSSound sound) {
|
||||
int i;
|
||||
GSSoundEngine sengine = sound->engine->client->sengine;
|
||||
|
||||
GSSoundEngineLock(sengine);
|
||||
for(i = 0; i < arrlen(sengine->sound); i++) {
|
||||
if(sengine->sound[i] == sound) {
|
||||
arrdel(sengine->sound, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
GSSoundEngineUnlock(sengine);
|
||||
|
||||
if(sound->close != NULL) sound->close(sound);
|
||||
|
||||
ma_mutex_uninit(&sound->mutex);
|
||||
|
||||
if(sound->file != NULL) GSFileClose(sound->file);
|
||||
|
||||
free(sound);
|
||||
}
|
||||
|
||||
void GSSoundToggleLoop(GSSound sound, GSBool toggle) {
|
||||
GSSoundLock(sound);
|
||||
sound->loop = toggle;
|
||||
GSSoundUnlock(sound);
|
||||
}
|
||||
|
||||
void GSSoundStart(GSSound sound) {
|
||||
GSSoundLock(sound);
|
||||
if(sound->reset != NULL) sound->reset(sound);
|
||||
GSSoundUnlock(sound);
|
||||
|
||||
GSSoundResume(sound);
|
||||
}
|
||||
|
||||
void GSSoundResume(GSSound sound) {
|
||||
GSSoundLock(sound);
|
||||
sound->paused = 0;
|
||||
GSSoundUnlock(sound);
|
||||
}
|
||||
|
||||
void GSSoundPause(GSSound sound) {
|
||||
GSSoundLock(sound);
|
||||
sound->paused = 1;
|
||||
GSSoundUnlock(sound);
|
||||
}
|
||||
|
||||
void GSSoundLock(GSSound sound) {
|
||||
ma_mutex_lock(&sound->mutex);
|
||||
}
|
||||
|
||||
void GSSoundUnlock(GSSound sound) {
|
||||
ma_mutex_unlock(&sound->mutex);
|
||||
}
|
||||
|
|
|
|||
61
engine/src/sounddriver.c
Normal file
61
engine/src/sounddriver.c
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
#include <GearSrc/SoundDriver.h>
|
||||
|
||||
#include <GearSrc/Log.h>
|
||||
|
||||
#include <miniaudio.h>
|
||||
|
||||
static void data_callback(ma_device* device, void* output, const void* input, ma_uint32 frame) {
|
||||
GSSoundDriver driver = device->pUserData;
|
||||
|
||||
driver->callback(driver->opaque, output, frame);
|
||||
}
|
||||
|
||||
GSSoundDriver GSSoundDriverOpen(GSClient client, GSSoundDriverReadCallback callback, void* opaque) {
|
||||
GSSoundDriver driver = malloc(sizeof(*driver));
|
||||
|
||||
memset(driver, 0, sizeof(*driver));
|
||||
|
||||
driver->engine = client->engine;
|
||||
|
||||
driver->callback = callback;
|
||||
driver->opaque = opaque;
|
||||
|
||||
driver->config = ma_device_config_init(ma_device_type_playback);
|
||||
driver->config.playback.format = ma_format_s16;
|
||||
driver->config.playback.channels = 2;
|
||||
driver->config.sampleRate = GSSoundDriverRate;
|
||||
driver->config.dataCallback = data_callback;
|
||||
driver->config.pUserData = driver;
|
||||
|
||||
driver->ready = 0;
|
||||
|
||||
if(ma_device_init(NULL, &driver->config, &driver->device) != MA_SUCCESS) {
|
||||
GSLog(client->engine, GSLogInfo, "Failed to initialize sound driver");
|
||||
|
||||
GSSoundDriverClose(driver);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
driver->ready = 1;
|
||||
|
||||
if(ma_device_start(&driver->device) != MA_SUCCESS) {
|
||||
GSLog(client->engine, GSLogInfo, "Failed to start sound driver");
|
||||
|
||||
GSSoundDriverClose(driver);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GSLog(client->engine, GSLogInfo, "Opened sound driver");
|
||||
|
||||
return driver;
|
||||
}
|
||||
|
||||
void GSSoundDriverClose(GSSoundDriver driver) {
|
||||
if(driver->ready) ma_device_uninit(&driver->device);
|
||||
|
||||
GSLog(driver->engine, GSLogInfo, "Closed sound driver");
|
||||
|
||||
free(driver);
|
||||
}
|
||||
94
engine/src/soundengine.c
Normal file
94
engine/src/soundengine.c
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
#include <GearSrc/SoundEngine.h>
|
||||
|
||||
#include <GearSrc/SoundDriver.h>
|
||||
#include <GearSrc/Log.h>
|
||||
#include <GearSrc/Sound.h>
|
||||
|
||||
#include <miniaudio.h>
|
||||
#include <stb_ds.h>
|
||||
|
||||
static void read_callback(void* opaque, GSI16* out, int frame) {
|
||||
GSSoundEngine sengine = opaque;
|
||||
int i;
|
||||
GSNumber* buffer = malloc(sizeof(*buffer) * frame * 2);
|
||||
GSI16* result = malloc(sizeof(*result) * frame * 2);
|
||||
|
||||
for(i = 0; i < frame * 2; i++) buffer[i] = 0;
|
||||
|
||||
GSSoundEngineLock(sengine);
|
||||
for(i = 0; i < arrlen(sengine->sound); i++) {
|
||||
int s;
|
||||
|
||||
GSSoundLock(sengine->sound[i]);
|
||||
if(sengine->sound[i]->paused || sengine->sound[i]->read == NULL) {
|
||||
GSSoundUnlock(sengine->sound[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
memset(result, 0, sizeof(*result) * frame * 2);
|
||||
s = sengine->sound[i]->read(sengine->sound[i], result, frame);
|
||||
if(s > 0) {
|
||||
int j;
|
||||
for(j = 0; j < s * 2; j++) buffer[j] += (GSNumber)result[j] / 32767;
|
||||
} else if(sengine->sound[i]->loop && sengine->sound[i]->reset != NULL) {
|
||||
sengine->sound[i]->reset(sengine->sound[i]);
|
||||
} else {
|
||||
sengine->sound[i]->paused = GSTrue;
|
||||
}
|
||||
GSSoundUnlock(sengine->sound[i]);
|
||||
}
|
||||
GSSoundEngineUnlock(sengine);
|
||||
|
||||
for(i = 0; i < frame * 2; i++) out[i] = buffer[i] * 32767;
|
||||
|
||||
free(result);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
GSSoundEngine GSSoundEngineCreate(GSClient client) {
|
||||
GSSoundEngine sengine = malloc(sizeof(*sengine));
|
||||
|
||||
memset(sengine, 0, sizeof(*sengine));
|
||||
|
||||
sengine->engine = client->engine;
|
||||
|
||||
ma_mutex_init(&sengine->mutex);
|
||||
|
||||
sengine->sound = NULL;
|
||||
|
||||
if((sengine->driver = GSSoundDriverOpen(client, read_callback, sengine)) == NULL) {
|
||||
GSLog(client->engine, GSLogError, "Failed to open sound driver");
|
||||
GSSoundEngineDestroy(sengine);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GSLog(client->engine, GSLogInfo, "Created sound engine");
|
||||
|
||||
return sengine;
|
||||
}
|
||||
|
||||
void GSSoundEngineDestroy(GSSoundEngine sengine) {
|
||||
int i;
|
||||
|
||||
if(sengine->driver != NULL) GSSoundDriverClose(sengine->driver);
|
||||
|
||||
ma_mutex_uninit(&sengine->mutex);
|
||||
|
||||
for(i = 0; i < arrlen(sengine->sound); i++) {
|
||||
GSSoundClose(sengine->sound[i]);
|
||||
}
|
||||
arrfree(sengine->sound);
|
||||
|
||||
GSLog(sengine->engine, GSLogInfo, "Destroyed sound engine");
|
||||
|
||||
free(sengine);
|
||||
}
|
||||
|
||||
void GSSoundEngineLock(GSSoundEngine sengine) {
|
||||
ma_mutex_lock(&sengine->mutex);
|
||||
}
|
||||
|
||||
void GSSoundEngineUnlock(GSSoundEngine sengine) {
|
||||
ma_mutex_unlock(&sengine->mutex);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue