From e2fd8e2411a4e848d4395e64535c4de84d502648 Mon Sep 17 00:00:00 2001 From: Shariq Shah Date: Fri, 20 Oct 2017 19:46:32 +0500 Subject: [PATCH] Separated sound source from sound source's instance --- README.md | 2 +- src/common/common.h | 42 +++++-- src/game/main.c | 35 ++++-- src/game/sound.c | 245 +++++++++++++++++++++++++++------------ src/game/sound.h | 40 ++++--- src/libsymmetry/entity.c | 132 ++++++++++++++++----- src/libsymmetry/entity.h | 18 ++- src/libsymmetry/game.c | 45 +++---- 8 files changed, 385 insertions(+), 174 deletions(-) diff --git a/README.md b/README.md index 07ba845..45aa30d 100644 --- a/README.md +++ b/README.md @@ -155,7 +155,6 @@ - ## TODO - - Replace OpenAL with Soloud - Store Materials in new format supported by parser - Add model description file which has the same syntax supported by parser and modify old blender exporter to conform to new standards - Implement sound/listener loading from scene file @@ -331,3 +330,4 @@ * Implmented writing to file through the new Parser and Parser_Objects * Changed Config to read/write using new Parser and Parser_Objects * Implemented Reading/Writing keybindings using new parser object + * Replaced OpenAL with Soloud with SDL2 backend \ No newline at end of file diff --git a/src/common/common.h b/src/common/common.h index 8a8acbe..01a35d5 100644 --- a/src/common/common.h +++ b/src/common/common.h @@ -15,6 +15,7 @@ extern struct Game_Api game; struct Window; struct Hashmap; +struct Sound_Source_Buffer; // Function Pointer decls typedef void (*Keyboard_Event_Func) (int key, int scancode, int state, int repeat, int mod_ctrl, int mod_shift, int mod_alt); @@ -38,21 +39,44 @@ enum Sound_Source_Type ST_WAV_STREAM }; +enum Sound_Attenuation_Type +{ + SA_NONE = 0, // No attenuation + SA_INVERSE, // Inverse distance attenuation model + SA_LINEAR, // Linear distance attenuation model + SA_EXPONENTIAL // Exponential distance attenuation model +}; + struct Sound_Api { + void (*update_3d)(void); void (*volume_set)(float volume); void (*listener_update)(float apos_x, float apos_y, float apos_z, float afwd_x, float afwd_y, float afwd_z, float aup_x, float aup_y, float aup_z); - void (*source_update)(uint source_handle, float apos_x, float apos_y, float apos_z); - uint (*source_create)(bool relative, const char* filename, int type); - void (*source_destroy)(uint source_handle); - void (*source_volume_set)(uint source_handle, float volume); - void (*source_loop_set)(uint source_handle, bool loop); - void (*source_play)(uint source_handle); - void (*source_pause)(uint source_handle); - void (*source_rewind)(uint source_handle); - void (*source_stop)(uint source_handle); + + void (*source_instance_update_position)(uint source_instance, float apos_x, float apos_y, float apos_z); + uint (*source_instance_create)(struct Sound_Source_Buffer* source, bool is3d); + void (*source_instance_destroy)(uint source_instance); + void (*source_instance_volume_set)(uint source_instance, float volume); + void (*source_instance_loop_set)(uint source_instance, bool loop); + void (*source_instance_play)(uint source_instance); + void (*source_instance_pause)(uint source_instance); + void (*source_instance_rewind)(uint source_instance); + void (*source_instance_stop)(uint source_instance); + void (*source_instance_min_max_distance_set)(uint source_instance, float min_distance, float max_distance); + void (*source_instance_attenuation_set)(uint source_instance, int attenuation_type, float rolloff_factor); + float (*source_instance_volume_get)(uint source_instance); + bool (*source_instance_loop_get)(uint source_instance); + bool (*source_instance_is_paused)(uint source_instance); + + struct Sound_Source_Buffer* (*source_create)(const char* filename, int type); + struct Sound_Source_Buffer* (*source_get)(const char* name); + void (*source_destroy)(const char* buffer_name); + void (*source_volume_set)(struct Sound_Source_Buffer* source, float volume); + void (*source_loop_set)(struct Sound_Source_Buffer* source, bool loop); + void (*source_stop_all)(struct Sound_Source_Buffer* source); + void (*source_min_max_distance_set)(struct Sound_Source_Buffer* source, float min_distance, float max_distance); }; struct Window_Api diff --git a/src/game/main.c b/src/game/main.c index 81ee03d..a70a74a 100644 --- a/src/game/main.c +++ b/src/game/main.c @@ -64,17 +64,30 @@ int main(int argc, char** args) .reload_game_lib = &game_lib_reload, .sound = { - .volume_set = &sound_volume_set, - .listener_update = &sound_listener_update, - .source_update = &sound_source_update, - .source_create = &sound_source_create, - .source_destroy = &sound_source_destroy, - .source_volume_set = &sound_source_volume_set, - .source_loop_set = &sound_source_loop_set, - .source_play = &sound_source_play, - .source_pause = &sound_source_pause, - .source_rewind = &sound_source_rewind, - .source_stop = &sound_source_stop + .update_3d = &sound_update_3d, + .volume_set = &sound_volume_set, + .listener_update = &sound_listener_update, + .source_instance_update_position = &sound_source_instance_update_position, + .source_instance_create = &sound_source_instance_create, + .source_instance_destroy = &sound_source_instance_destroy, + .source_instance_volume_set = &sound_source_instance_volume_set, + .source_instance_loop_set = &sound_source_instance_loop_set, + .source_instance_play = &sound_source_instance_play, + .source_instance_pause = &sound_source_instance_pause, + .source_instance_rewind = &sound_source_instance_rewind, + .source_instance_stop = &sound_source_instance_stop, + .source_instance_min_max_distance_set = &sound_source_instance_min_max_distance_set, + .source_instance_attenuation_set = &sound_source_instance_attenuation_set, + .source_instance_volume_get = &sound_source_instance_volume_get, + .source_instance_loop_get = &sound_source_instance_loop_get, + .source_instance_is_paused = &sound_source_instance_is_paused, + .source_create = &sound_source_create, + .source_get = &sound_source_get, + .source_destroy = &sound_source_destroy, + .source_volume_set = &sound_source_volume_set, + .source_loop_set = &sound_source_loop_set, + .source_stop_all = &sound_source_stop_all, + .source_min_max_distance_set = &sound_source_min_max_distance_set }, .window = { diff --git a/src/game/sound.c b/src/game/sound.c index 21d48c3..46fcae9 100644 --- a/src/game/sound.c +++ b/src/game/sound.c @@ -11,7 +11,7 @@ #include -struct Sound_Buffer +struct Sound_Source_Buffer { int type; union @@ -33,11 +33,11 @@ static struct Sound_State sound_state = .volume = 1.f }; -static struct Hashmap* sound_buffers = NULL; +static struct Hashmap* sound_sources = NULL; bool sound_init(void) { - sound_buffers = hashmap_new(); + sound_sources = hashmap_new(); sound_state.soloud_context = Soloud_create(); @@ -55,8 +55,6 @@ bool sound_init(void) 0.f, 0.f, -1.f, // At 0.f, 1.f, 0.f); // Up - Soloud_update3dAudio(sound_state.soloud_context); - log_message("Sound initialized with %s", Soloud_getBackendString(sound_state.soloud_context)); return true; } @@ -69,7 +67,6 @@ void sound_listener_update(float apos_x, float apos_y, float apos_z, apos_x, apos_y, apos_z, // Position afwd_x, afwd_y, afwd_z, // At aup_x, aup_y, aup_z); // Up - Soloud_update3dAudio(sound_state.soloud_context); } void sound_volume_set(float volume) @@ -77,23 +74,30 @@ void sound_volume_set(float volume) if(volume < 0.f) volume = 0.f; sound_state.volume = volume; Soloud_setGlobalVolume(sound_state.soloud_context, sound_state.volume); +} + +void sound_update_3d(void) +{ + Soloud_update3dAudio(sound_state.soloud_context); } void sound_cleanup(void) { char* key = NULL; struct Variant* value = NULL; - HASHMAP_FOREACH(sound_buffers, key, value) + HASHMAP_FOREACH(sound_sources, key, value) { - struct Sound_Buffer* buffer = value->val_voidptr; - switch(buffer->type) + struct Sound_Source_Buffer* source = value->val_voidptr; + sound_source_stop_all(source); + switch(source->type) { - case ST_WAV: Wav_destroy(buffer->wav); break; - case ST_WAV_STREAM: WavStream_destroy(buffer->wavstream); break; + case ST_WAV: Wav_destroy(source->wav); break; + case ST_WAV_STREAM: WavStream_destroy(source->wavstream); break; } + free(source); } - hashmap_free(sound_buffers); + hashmap_free(sound_sources); Soloud_deinit(sound_state.soloud_context); Soloud_destroy(sound_state.soloud_context); @@ -101,36 +105,114 @@ void sound_cleanup(void) sound_state.soloud_context = NULL; } -uint sound_source_create(bool relative, const char* filename, int type) +void sound_source_instance_destroy(uint source_instance) +{ + Soloud_stop(sound_state.soloud_context, source_instance); +} + +void sound_source_instance_update_position(uint source_instance, float apos_x, float apos_y, float apos_z) +{ + Soloud_set3dSourceParameters(sound_state.soloud_context, source_instance, apos_x, apos_y, apos_z); +} + +uint sound_source_instance_create(struct Sound_Source_Buffer* source, bool is3d) +{ + assert(source); + uint source_instance = 0; + if(is3d) + { + source_instance = Soloud_play3dEx(sound_state.soloud_context, + source->type == ST_WAV ? source->wav : source->wavstream, + 0.f, 0.f, 0.f, + 0.f, 0.f, 0.f, + 1.f, + true, + 0); + } + else + { + source_instance = Soloud_playEx(sound_state.soloud_context, source->type == ST_WAV ? source->wav : source->wavstream, 1.f, 0.0f, true, 0); + } + return source_instance; +} + +void sound_source_instance_volume_set(uint source_instance, float volume) { - uint handle = 0; - struct Sound_Buffer* buffer = NULL; + if(volume < 0.f) volume = 0.f; + Soloud_setVolume(sound_state.soloud_context, source_instance, volume); +} + +void sound_source_instance_loop_set(uint source_instance, bool loop) +{ + Soloud_setLooping(sound_state.soloud_context, source_instance, loop); +} + +void sound_source_instance_play(uint source_instance) +{ + Soloud_setPause(sound_state.soloud_context, source_instance, false); +} + +void sound_source_instance_pause(uint source_instance) +{ + Soloud_setPause(sound_state.soloud_context, source_instance, true); +} + +void sound_source_instance_rewind(uint source_instance) +{ + Soloud_seek(sound_state.soloud_context, source_instance, 0.0); +} + +void sound_source_instance_stop(uint source_instance) +{ + Soloud_stop(sound_state.soloud_context, source_instance); +} + +void sound_source_instance_min_max_distance_set(uint source_instance, float min_distance, float max_distance) +{ + Soloud_set3dSourceMinMaxDistance(sound_state.soloud_context, source_instance, min_distance, max_distance); +} + +void sound_source_instance_attenuation_set(uint source_instance, int attenuation_type, float rolloff_factor) +{ + Soloud_set3dSourceAttenuation(sound_state.soloud_context, source_instance, attenuation_type, rolloff_factor); +} + +float sound_source_instance_volume_get(uint source_instance) +{ + return Soloud_getVolume(sound_state.soloud_context, source_instance); +} + +bool sound_source_instance_loop_get(uint source_instance) +{ + return Soloud_getLooping(sound_state.soloud_context, source_instance); +} + +bool sound_source_instance_is_paused(uint source_instance) +{ + return Soloud_getPause(sound_state.soloud_context, source_instance); +} + +struct Sound_Source_Buffer* sound_source_create(const char* filename, int type) +{ + if(!filename) return NULL; + + struct Sound_Source_Buffer* source = NULL; long size = 0L; char* memory = io_file_read(DIRT_INSTALL, filename, "rb", &size); //See if we've already loaded this file - if(hashmap_value_exists(sound_buffers, filename)) + if(hashmap_value_exists(sound_sources, filename)) { - buffer = (struct Sound_Buffer*)hashmap_ptr_get(sound_buffers, filename); - if(relative) - { - handle = Soloud_play3dEx(sound_state.soloud_context, - type == ST_WAV ? buffer->wav : buffer->wavstream, - 0.f, 0.f, 0.f, - 0.f, 0.f, 0.f, - 1.f, - true, - 0); - return handle; - } + source = (struct Sound_Source_Buffer*)hashmap_ptr_get(sound_sources, filename); + return source; } - buffer = malloc(sizeof(*buffer)); - if(!buffer) + source = malloc(sizeof(*source)); + if(!source) { log_error("sound:source_create", "Out of memory!"); - return 0; + return NULL; } switch(type) @@ -142,12 +224,11 @@ uint sound_source_create(bool relative, const char* filename, int type) if(rc != 0) { log_error("sound:source_create", "Failed to load %s, Soloud: %s", filename, Soloud_getErrorString(sound_state.soloud_context, rc)); - free(buffer); + free(source); return 0; } - buffer->type = ST_WAV; - buffer->wav = wave; - Wav_set3dAttenuation(wave, 1, 0.9f); + source->type = ST_WAV; + source->wav = wave; } break; case ST_WAV_STREAM: @@ -157,67 +238,81 @@ uint sound_source_create(bool relative, const char* filename, int type) if(rc != 0) { log_error("sound:source_create", "Failed to load %s, Soloud: %s", filename, Soloud_getErrorString(sound_state.soloud_context, rc)); - free(buffer); + free(source); return 0; } - buffer->type = ST_WAV_STREAM; - buffer->wavstream = wave_stream; + source->type = ST_WAV_STREAM; } break; default: log_error("sound:source_create", "Invalid source type %d", type); return 0; } - hashmap_ptr_set(sound_buffers, filename, (void*)buffer); - handle = Soloud_play3dEx(sound_state.soloud_context, - type == ST_WAV ? buffer->wav : buffer->wavstream, - 0.f, 0.f, 0.f, - 0.f, 0.f, 0.f, - 1.f, - true, - 0); - - return handle; -} - -void sound_source_destroy(uint source_handle) -{ - Soloud_stop(sound_state.soloud_context, source_handle); -} - - -void sound_source_update(uint source_handle, float apos_x, float apos_y, float apos_z) -{ - Soloud_set3dSourceParameters(sound_state.soloud_context, source_handle, apos_x, apos_y, apos_z); - Soloud_update3dAudio(sound_state.soloud_context); + hashmap_ptr_set(sound_sources, filename, (void*)source); + return source; } -void sound_source_volume_set(uint source_handle, float volume) +struct Sound_Source_Buffer* sound_source_get(const char* name) { - if(volume < 0.f) volume = 0.f; - Soloud_setVolume(sound_state.soloud_context, source_handle, volume); + struct Sound_Source_Buffer* source = NULL; + if(hashmap_value_exists(sound_sources, name)) + { + source = (struct Sound_Source_Buffer*)hashmap_ptr_get(sound_sources, name); + } + return source; } -void sound_source_loop_set(uint source_handle, bool loop) +void sound_source_destroy(const char* name) { - Soloud_setLooping(sound_state.soloud_context, source_handle, loop); + struct Sound_Source_Buffer* source = sound_source_get(name); + if(source) + { + sound_source_stop_all(source); + switch(source->type) + { + case ST_WAV: Wav_destroy(source->wav); break; + case ST_WAV_STREAM: WavStream_destroy(source->wavstream); break; + } + free(source); + } + hashmap_value_remove(sound_sources, name); } -void sound_source_play(uint source_handle) +void sound_source_volume_set(struct Sound_Source_Buffer* source, float volume) { - Soloud_setPause(sound_state.soloud_context, source_handle, false); + assert(source); + switch(source->type) + { + case ST_WAV: Wav_setVolume(source->wav, volume); break; + case ST_WAV_STREAM: WavStream_setVolume(source->wavstream, volume); break; + } } -void sound_source_pause(uint source_handle) +void sound_source_loop_set(struct Sound_Source_Buffer* source, bool loop) { - Soloud_setPause(sound_state.soloud_context, source_handle, true); + assert(source); + switch(source->type) + { + case ST_WAV: Wav_setLooping(source->wav, loop); break; + case ST_WAV_STREAM: WavStream_setLooping(source->wavstream, loop); break; + } } -void sound_source_rewind(uint source_handle) +void sound_source_stop_all(struct Sound_Source_Buffer* source) { - Soloud_seek(sound_state.soloud_context, source_handle, 0.0); + assert(source); + switch(source->type) + { + case ST_WAV: Soloud_stopAudioSource(sound_state.soloud_context, source->wav); break; + case ST_WAV_STREAM: Soloud_stopAudioSource(sound_state.soloud_context, source->wavstream); break; + } } -void sound_source_stop(uint source_handle) -{ - Soloud_stop(sound_state.soloud_context, source_handle); -} +void sound_source_min_max_distance_set(struct Sound_Source_Buffer* source, float min_distance, float max_distance) +{ + assert(source); + switch(source->type) + { + case ST_WAV: Wav_set3dMinMaxDistance(source->wav, min_distance, max_distance); break; + case ST_WAV_STREAM: WavStream_set3dMinMaxDistance(source->wavstream, min_distance, max_distance); break; + } +} \ No newline at end of file diff --git a/src/game/sound.h b/src/game/sound.h index 95b9ae6..5c1cb68 100644 --- a/src/game/sound.h +++ b/src/game/sound.h @@ -3,28 +3,40 @@ #include "../common/num_types.h" -#ifdef AL_DEBUG - #define al_check(expr) expr; -#else - #define al_check(expr) expr; -#endif +struct Sound_Source_Buffer; bool sound_init(void); void sound_cleanup(void); void sound_volume_set(float volume); +void sound_update_3d(void); void sound_listener_update(float apos_x, float apos_y, float apos_z, float afwd_x, float afwd_y, float afwd_z, float aup_x, float aup_y, float aup_z); -void sound_source_update(uint source_handle, float apos_x, float apos_y, float apos_z); -uint sound_source_create(bool relative, const char* filename, int type); -void sound_source_destroy(uint handle); -void sound_source_volume_set(uint handle, float volume); -void sound_source_loop_set(uint handle, bool loop); -void sound_source_play(uint handle); -void sound_source_pause(uint handle); -void sound_source_rewind(uint handle); -void sound_source_stop(uint handle); + +void sound_source_instance_update_position(uint source_instance, float apos_x, float apos_y, float apos_z); +uint sound_source_instance_create(struct Sound_Source_Buffer* source, bool is3d); +void sound_source_instance_destroy(uint source_instance); +void sound_source_instance_volume_set(uint source_instance, float volume); +void sound_source_instance_loop_set(uint source_instance, bool loop); +void sound_source_instance_play(uint source_instance); +void sound_source_instance_pause(uint source_instance); +void sound_source_instance_rewind(uint source_instance); +void sound_source_instance_stop(uint source_instance); +void sound_source_instance_min_max_distance_set(uint source_instance, float min_distance, float max_distance); +void sound_source_instance_attenuation_set(uint source_instance, int attenuation_type, float rolloff_factor); + +float sound_source_instance_volume_get(uint source_instance); +bool sound_source_instance_loop_get(uint source_instance); +bool sound_source_instance_is_paused(uint source_instance); + +struct Sound_Source_Buffer* sound_source_create(const char* filename, int type); +struct Sound_Source_Buffer* sound_source_get(const char* name); +void sound_source_destroy(const char* buffer_name); +void sound_source_volume_set(struct Sound_Source_Buffer* source, float volume); +void sound_source_loop_set(struct Sound_Source_Buffer* source, bool loop); +void sound_source_stop_all(struct Sound_Source_Buffer* source); +void sound_source_min_max_distance_set(struct Sound_Source_Buffer* source, float min_distance, float max_distance); #endif diff --git a/src/libsymmetry/entity.c b/src/libsymmetry/entity.c index a50dd1f..4c67855 100644 --- a/src/libsymmetry/entity.c +++ b/src/libsymmetry/entity.c @@ -162,7 +162,7 @@ void entity_post_update(void) transform_get_absolute_forward(entity, &abs_fwd); transform_get_absolute_up(entity, &abs_up); - platform->sound.source_update(entity->sound_source.source_handle, abs_pos.x, abs_pos.y, abs_pos.z); + platform->sound.source_instance_update_position(entity->sound_source.source_instance, abs_pos.x, abs_pos.y, abs_pos.z); } if(entity->is_listener) @@ -270,11 +270,16 @@ bool entity_write(struct Entity* entity, struct Parser_Object* object) } case ET_SOUND_SOURCE: { - hashmap_bool_set(entity_data, "active", entity->sound_source.active); - hashmap_bool_set(entity_data, "relative", entity->sound_source.relative); - hashmap_int_set(entity_data, "sound_type", entity->sound_source.type); - hashmap_str_set(entity_data, "wav_filename", entity->sound_source.wav_filename); - hashmap_bool_set(entity_data, "loop", entity->sound_source.loop); + struct Sound_Source* sound_source = &entity->sound_source; + hashmap_str_set(entity_data, "source_filename", sound_source->source_filename); + hashmap_bool_set(entity_data, "playing", sound_source->playing); + hashmap_int_set(entity_data, "sound_type", sound_source->type); + hashmap_bool_set(entity_data, "loop", sound_source->loop); + hashmap_float_set(entity_data, "volume", sound_source->volume); + hashmap_float_set(entity_data, "sound_min_distance", sound_source->min_distance); + hashmap_float_set(entity_data, "sound_max_distance", sound_source->max_distance); + hashmap_float_set(entity_data, "rolloff_factor", sound_source->rolloff_factor); + hashmap_int_set(entity_data, "sound_attenuation_type", sound_source->attenuation_type); break; } }; @@ -439,31 +444,61 @@ struct Entity* entity_read(struct Parser_Object* object) case ET_SOUND_SOURCE: { struct Sound_Source* sound_source = &entity->sound_source; - sound_source->active = false; - sound_source->relative = false; - sound_source->loop = false; - sound_source->source_handle = 0; - sound_source->wav_filename = NULL; - sound_source->type = ST_WAV; - - if(hashmap_value_exists(object->data, "active")) sound_source->active = hashmap_bool_get(object->data, "active"); - if(hashmap_value_exists(object->data, "relative")) sound_source->relative = hashmap_bool_get(object->data, "relative"); - if(hashmap_value_exists(object->data, "loop")) sound_source->loop = hashmap_bool_get(object->data, "loop"); - if(hashmap_value_exists(object->data, "wav_filename")) sound_source->wav_filename = str_new(hashmap_str_get(object->data, "wav_filename")); - if(hashmap_value_exists(object->data, "sound_type")) sound_source->type = hashmap_int_get(object->data, "sound_type"); - if(sound_source->wav_filename) + sound_source->type = ST_WAV; + sound_source->playing = false; + sound_source->loop = false; + sound_source->source_instance = 0; + sound_source->min_distance = 1.f; + sound_source->max_distance = 1000.f; + sound_source->volume = 1.f; + sound_source->rolloff_factor = 1.f; + sound_source->attenuation_type = SA_EXPONENTIAL; + sound_source->source = NULL; + sound_source->source_filename = NULL; + + if(hashmap_value_exists(object->data, "playing")) sound_source->playing = hashmap_bool_get(object->data, "playing"); + if(hashmap_value_exists(object->data, "loop")) sound_source->loop = hashmap_bool_get(object->data, "loop"); + if(hashmap_value_exists(object->data, "sound_min_distance")) sound_source->min_distance = hashmap_float_get(object->data, "sound_min_distance"); + if(hashmap_value_exists(object->data, "sound_max_distance")) sound_source->max_distance = hashmap_float_get(object->data, "sound_max_distance"); + if(hashmap_value_exists(object->data, "volume")) sound_source->volume = hashmap_float_get(object->data, "volume"); + if(hashmap_value_exists(object->data, "rolloff_factor")) sound_source->rolloff_factor = hashmap_float_get(object->data, "rolloff_factor"); + if(hashmap_value_exists(object->data, "source_filename")) sound_source->source_filename = str_new(hashmap_str_get(object->data, "source_filename")); + if(hashmap_value_exists(object->data, "sound_type")) sound_source->type = hashmap_int_get(object->data, "sound_type"); + if(hashmap_value_exists(object->data, "sound_attenuation_type")) sound_source->attenuation_type = hashmap_int_get(object->data, "sound_attenuation_type"); + if(sound_source->source_filename) { - sound_source->source_handle = platform->sound.source_create(sound_source->relative, sound_source->wav_filename, sound_source->type); - platform->sound.source_loop_set(sound_source->source_handle, sound_source->loop); + sound_source->source = platform->sound.source_create(sound_source->source_filename, sound_source->type); + if(sound_source->source) + { + sound_source->source_instance = platform->sound.source_instance_create(sound_source->source, true); + + vec3 abs_pos = {0.f, 0.f, 0.f}; + vec3 abs_fwd = {0.f, 0.f, -1.f}; + vec3 abs_up = {0.f, 1.f, 0.f}; + transform_get_absolute_pos(entity, &abs_pos); + transform_get_absolute_forward(entity, &abs_fwd); + transform_get_absolute_up(entity, &abs_up); + platform->sound.source_instance_update_position(entity->sound_source.source_instance, abs_pos.x, abs_pos.y, abs_pos.z); + + platform->sound.source_instance_loop_set(sound_source->source_instance, sound_source->loop); + platform->sound.source_instance_min_max_distance_set(sound_source->source_instance, sound_source->min_distance, sound_source->max_distance); + platform->sound.source_instance_attenuation_set(sound_source->source_instance, sound_source->attenuation_type, sound_source->rolloff_factor); + platform->sound.source_instance_volume_set(sound_source->source_instance, sound_source->volume); + + platform->sound.update_3d(); + if(sound_source->playing) platform->sound.source_instance_play(sound_source->source_instance); + } + else + { + log_error("Failed to create sound source from '%s'", sound_source->source_filename); + free(sound_source->source_filename); + sound_source->source_filename = NULL; + } + } + else + { + log_error("entity:read", "No filename provided for sound source for entity '%s'", entity->name); } - - vec3 abs_pos = {0.f, 0.f, 0.f}; - vec3 abs_fwd = {0.f, 0.f, -1.f}; - vec3 abs_up = {0.f, 1.f, 0.f}; - transform_get_absolute_pos(entity, &abs_pos); - transform_get_absolute_forward(entity, &abs_fwd); - transform_get_absolute_up(entity, &abs_up); - platform->sound.source_update(entity->sound_source.source_handle, abs_pos.x, abs_pos.y, abs_pos.z); } break; case ET_PLAYER: @@ -572,4 +607,43 @@ const char* entity_type_name_get(struct Entity* entity) default: typename = "Unknown"; break; }; return typename; +} + +void entity_apply_sound_params(struct Entity* entity) +{ + if(entity->type != ET_SOUND_SOURCE) return; + + struct Sound_Source* sound_source = &entity->sound_source; + + // Check if sound source has no buffer attached but filename exists, this would mean we have to load the file first + if(!sound_source->source && sound_source->source_filename) + { + sound_source->source = platform->sound.source_create(sound_source->source_filename, sound_source->type); + if(!sound_source->source) + { + log_error("entity:sync_sound_params", "Failed to load file '%s' to provide sound source for entity %s", sound_source->source_filename, entity->name); + free(sound_source->source_filename); + sound_source->source_filename = NULL; + sound_source->source_instance = 0; + return; + } + } + + if(sound_source->source_instance == 0) sound_source->source_instance = platform->sound.source_instance_create(sound_source->source, true); + + vec3 abs_pos = {0.f, 0.f, 0.f}; + vec3 abs_fwd = {0.f, 0.f, -1.f}; + vec3 abs_up = {0.f, 1.f, 0.f}; + transform_get_absolute_pos(entity, &abs_pos); + transform_get_absolute_forward(entity, &abs_fwd); + transform_get_absolute_up(entity, &abs_up); + platform->sound.source_instance_update_position(entity->sound_source.source_instance, abs_pos.x, abs_pos.y, abs_pos.z); + + platform->sound.source_instance_loop_set(sound_source->source_instance, sound_source->loop); + platform->sound.source_instance_min_max_distance_set(sound_source->source_instance, sound_source->min_distance, sound_source->max_distance); + platform->sound.source_instance_attenuation_set(sound_source->source_instance, sound_source->attenuation_type, sound_source->rolloff_factor); + platform->sound.source_instance_volume_set(sound_source->source_instance, sound_source->volume); + + platform->sound.update_3d(); + if(sound_source->playing) platform->sound.source_instance_play(sound_source->source_instance); } diff --git a/src/libsymmetry/entity.h b/src/libsymmetry/entity.h index 2d4cbb9..3116c77 100644 --- a/src/libsymmetry/entity.h +++ b/src/libsymmetry/entity.h @@ -52,12 +52,17 @@ struct Model struct Sound_Source { - bool active; - int type; - bool relative; - bool loop; - char* wav_filename; - uint source_handle; + int type; + bool playing; + bool loop; + char* source_filename; + uint source_instance; + float min_distance; + float max_distance; + float rolloff_factor; + float volume; + int attenuation_type; + struct Sound_Source_Buffer* source; }; struct Camera @@ -134,6 +139,7 @@ bool entity_load(const char* filename, int directory_type); bool entity_write(struct Entity* entity, struct Parser_Object* object); struct Entity* entity_read(struct Parser_Object* object); const char* entity_type_name_get(struct Entity* entity); +void entity_apply_sound_params(struct Entity* entity); // Convenience function to sync the data set in entity's sound_source with the actual sound source's instance #endif diff --git a/src/libsymmetry/game.c b/src/libsymmetry/game.c index c70d698..9a8cb03 100644 --- a/src/libsymmetry/game.c +++ b/src/libsymmetry/game.c @@ -218,38 +218,24 @@ void scene_setup(void) struct Entity* suz = entity_find("Suzanne"); struct Entity* sound_ent = scene_add_as_child("Sound_Ent", ET_SOUND_SOURCE, suz->id); - sound_ent->sound_source.source_handle = platform->sound.source_create(true, "sounds/teh_beatz.wav", ST_WAV); - platform->sound.source_loop_set(sound_ent->sound_source.source_handle, true); - platform->sound.source_play(sound_ent->sound_source.source_handle); + struct Sound_Source* sound_source = &sound_ent->sound_source; + sound_source->source_filename = str_new("sounds/teh_beatz.wav"); + sound_source->type = ST_WAV; + sound_source->attenuation_type = SA_LINEAR; + sound_source->rolloff_factor = 0.95f; + sound_source->loop = true; + sound_source->volume = 1.f; + sound_source->min_distance = 1.f; + sound_source->max_distance = 50.f; + sound_source->playing = true; + + sound_source->source_instance = 0; + sound_source->source = NULL; + + entity_apply_sound_params(sound_ent); //scene_save("parser_write.symtres", DIRT_INSTALL); } - - /* - FILE* obj_file = platform->file.open(DIRT_INSTALL, "obj_test.symtres", "rb"); - if(obj_file) - { - struct Parser* parsed_file = parser_load_objects(obj_file, "obj_test.symtres"); - log_message("%d objects read from %s", array_len(parsed_file->objects), "obj_test.symtres"); - for(int i = 0; i < array_len(parsed_file->objects); i++) - { - struct Parser_Object* object = &parsed_file->objects[i]; - if(object->type == PO_UNKNOWN) - log_message("Type : Unknown"); - else if(object->type == PO_ENTITY) - log_message("Type : Entity"); - else if(object->type == PO_MATERIAL) - log_message("Type : Material"); - else if(object->type == PO_MODEL) - log_message("Type : Model"); - hashmap_debug_print(object->data); - } - fclose(obj_file); - } - else - { - log_warning("Failed to open obj_test.symtres"); - }*/ } void debug(float dt) @@ -398,6 +384,7 @@ bool run(void) render(); platform->window.swap_buffers(game_state->window); entity_post_update(); + platform->sound.update_3d(); } return true; }