ClassiCube/src/Audio_Web.c
2025-06-09 10:57:28 +10:00

161 lines
7.1 KiB
C

#include "Core.h"
#if defined CC_BUILD_WEBAUDIO
struct AudioContext { int contextID, count, rate; void* data; };
#define AUDIO_OVERRIDE_SOUNDS
#define AUDIO_OVERRIDE_ALLOC
#include "_AudioBase.h"
extern int interop_InitAudio(void);
extern int interop_AudioCreate(void);
extern void interop_AudioClose(int contextID);
extern int interop_AudioPlay(int contextID, const void* name, int rate);
extern int interop_AudioPoll(int contextID, int* inUse);
extern int interop_AudioVolume(int contextID, int volume);
extern int interop_AudioDescribe(int res, char* buffer, int bufferLen);
cc_bool AudioBackend_Init(void) {
cc_result res = interop_InitAudio();
if (res) { Audio_Warn(res, "initing WebAudio context"); return false; }
return true;
}
void AudioBackend_Tick(void) { }
void AudioBackend_Free(void) { }
cc_result Audio_Init(struct AudioContext* ctx, int buffers) {
ctx->count = buffers;
ctx->contextID = interop_AudioCreate();
ctx->data = NULL;
ctx->rate = 100;
return 0;
}
void Audio_Close(struct AudioContext* ctx) {
if (ctx->contextID) interop_AudioClose(ctx->contextID);
ctx->contextID = 0;
ctx->count = 0;
}
cc_result Audio_SetFormat(struct AudioContext* ctx, int channels, int sampleRate, int playbackRate) {
ctx->rate = playbackRate; return 0;
}
void Audio_SetVolume(struct AudioContext* ctx, int volume) {
interop_AudioVolume(ctx->contextID, volume);
}
cc_result Audio_QueueChunk(struct AudioContext* ctx, struct AudioChunk* chunk) {
ctx->data = chunk->data; return 0;
}
cc_result Audio_Play(struct AudioContext* ctx) {
return interop_AudioPlay(ctx->contextID, ctx->data, ctx->rate);
}
cc_result Audio_Poll(struct AudioContext* ctx, int* inUse) {
return interop_AudioPoll(ctx->contextID, inUse);
}
/*########################################################################################################################*
*------------------------------------------------------Stream context-----------------------------------------------------*
*#########################################################################################################################*/
cc_result StreamContext_SetFormat(struct AudioContext* ctx, int channels, int sampleRate, int playbackRate) {
return Audio_SetFormat(ctx, channels, sampleRate, playbackRate);
}
cc_result StreamContext_Enqueue(struct AudioContext* ctx, struct AudioChunk* chunk) {
return Audio_QueueChunk(ctx, chunk);
}
cc_result StreamContext_Play(struct AudioContext* ctx) {
return Audio_Play(ctx);
}
cc_result StreamContext_Pause(struct AudioContext* ctx) {
return Audio_Pause(ctx);
}
cc_result StreamContext_Update(struct AudioContext* ctx, int* inUse) {
return Audio_Poll(ctx, inUse);
}
/*########################################################################################################################*
*------------------------------------------------------Sound context------------------------------------------------------*
*#########################################################################################################################*/
cc_bool SoundContext_FastPlay(struct AudioContext* ctx, struct AudioData* data) {
/* Channels/Sample rate is per buffer, not a per source property */
return true;
}
cc_result SoundContext_PlayData(struct AudioContext* ctx, struct AudioData* data) {
return interop_AudioPlay(ctx->contextID, data->chunk.data, data->rate);
}
cc_result SoundContext_PollBusy(struct AudioContext* ctx, cc_bool* isBusy) {
int inUse = 1;
cc_result res;
if ((res = Audio_Poll(ctx, &inUse))) return res;
*isBusy = inUse > 0;
return 0;
}
/*########################################################################################################################*
*--------------------------------------------------------Audio misc-------------------------------------------------------*
*#########################################################################################################################*/
cc_bool Audio_DescribeError(cc_result res, cc_string* dst) {
char buffer[NATIVE_STR_LEN];
int len = interop_AudioDescribe(res, buffer, NATIVE_STR_LEN);
String_AppendUtf8(dst, buffer, len);
return len > 0;
}
/*########################################################################################################################*
*----------------------------------------------------------Sounds---------------------------------------------------------*
*#########################################################################################################################*/
static const struct SoundID { int group; const char* name; } sounds_list[] =
{
{ SOUND_CLOTH, "step_cloth1" }, { SOUND_CLOTH, "step_cloth2" }, { SOUND_CLOTH, "step_cloth3" }, { SOUND_CLOTH, "step_cloth4" },
{ SOUND_GRASS, "step_grass1" }, { SOUND_GRASS, "step_grass2" }, { SOUND_GRASS, "step_grass3" }, { SOUND_GRASS, "step_grass4" },
{ SOUND_GRAVEL, "step_gravel1" }, { SOUND_GRAVEL, "step_gravel2" }, { SOUND_GRAVEL, "step_gravel3" }, { SOUND_GRAVEL, "step_gravel4" },
{ SOUND_SAND, "step_sand1" }, { SOUND_SAND, "step_sand2" }, { SOUND_SAND, "step_sand3" }, { SOUND_SAND, "step_sand4" },
{ SOUND_SNOW, "step_snow1" }, { SOUND_SNOW, "step_snow2" }, { SOUND_SNOW, "step_snow3" }, { SOUND_SNOW, "step_snow4" },
{ SOUND_STONE, "step_stone1" }, { SOUND_STONE, "step_stone2" }, { SOUND_STONE, "step_stone3" }, { SOUND_STONE, "step_stone4" },
{ SOUND_WOOD, "step_wood1" }, { SOUND_WOOD, "step_wood2" }, { SOUND_WOOD, "step_wood3" }, { SOUND_WOOD, "step_wood4" },
{ SOUND_NONE, NULL },
{ SOUND_CLOTH, "dig_cloth1" }, { SOUND_CLOTH, "dig_cloth2" }, { SOUND_CLOTH, "dig_cloth3" }, { SOUND_CLOTH, "dig_cloth4" },
{ SOUND_GRASS, "dig_grass1" }, { SOUND_GRASS, "dig_grass2" }, { SOUND_GRASS, "dig_grass3" }, { SOUND_GRASS, "dig_grass4" },
{ SOUND_GLASS, "dig_glass1" }, { SOUND_GLASS, "dig_glass2" }, { SOUND_GLASS, "dig_glass3" },
{ SOUND_GRAVEL, "dig_gravel1" }, { SOUND_GRAVEL, "dig_gravel2" }, { SOUND_GRAVEL, "dig_gravel3" }, { SOUND_GRAVEL, "dig_gravel4" },
{ SOUND_SAND, "dig_sand1" }, { SOUND_SAND, "dig_sand2" }, { SOUND_SAND, "dig_sand3" }, { SOUND_SAND, "dig_sand4" },
{ SOUND_SNOW, "dig_snow1" }, { SOUND_SNOW, "dig_snow2" }, { SOUND_SNOW, "dig_snow3" }, { SOUND_SNOW, "dig_snow4" },
{ SOUND_STONE, "dig_stone1" }, { SOUND_STONE, "dig_stone2" }, { SOUND_STONE, "dig_stone3" }, { SOUND_STONE, "dig_stone4" },
{ SOUND_WOOD, "dig_wood1" }, { SOUND_WOOD, "dig_wood2" }, { SOUND_WOOD, "dig_wood3" }, { SOUND_WOOD, "dig_wood4" },
};
/* TODO this is a terrible solution */
void AudioBackend_LoadSounds(void) {
struct Soundboard* board = &stepBoard;
struct SoundGroup* group;
int i;
for (i = 0; i < Array_Elems(sounds_list); i++) {
if (sounds_list[i].group == SOUND_NONE) {
board = &digBoard;
} else {
group = &board->groups[sounds_list[i].group];
group->sounds[group->count++].chunk.data = sounds_list[i].name;
}
}
}
#endif