|
|
@ -4,125 +4,114 @@ |
|
|
|
#include "../common/hashmap.h" |
|
|
|
#include "../common/hashmap.h" |
|
|
|
#include "../common/variant.h" |
|
|
|
#include "../common/variant.h" |
|
|
|
#include "../common/string_utils.h" |
|
|
|
#include "../common/string_utils.h" |
|
|
|
#include "file_io.h" |
|
|
|
|
|
|
|
|
|
|
|
#include "../game/entity.h" |
|
|
|
|
|
|
|
#include "../game/transform.h" |
|
|
|
|
|
|
|
|
|
|
|
#include <assert.h> |
|
|
|
#include <assert.h> |
|
|
|
#include <stdio.h> |
|
|
|
#include <stdio.h> |
|
|
|
#include <stdlib.h> |
|
|
|
#include <stdlib.h> |
|
|
|
|
|
|
|
#include <string.h> |
|
|
|
|
|
|
|
|
|
|
|
#include <soloud_c.h> |
|
|
|
#include <soloud_c.h> |
|
|
|
|
|
|
|
|
|
|
|
struct Sound_Source_Buffer |
|
|
|
bool sound_init(struct Sound* sound) |
|
|
|
{ |
|
|
|
|
|
|
|
int type; |
|
|
|
|
|
|
|
union |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Wav* wav; |
|
|
|
|
|
|
|
WavStream* wavstream; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct Sound_State |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Soloud* soloud_context; |
|
|
|
|
|
|
|
float volume; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static struct Sound_State sound_state = |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
.soloud_context = NULL, |
|
|
|
|
|
|
|
.volume = 1.f |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static struct Hashmap* sound_sources = NULL; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool sound_init(void) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
sound_sources = hashmap_new(); |
|
|
|
sound->soloud_context = Soloud_create(); |
|
|
|
|
|
|
|
|
|
|
|
sound_state.soloud_context = Soloud_create(); |
|
|
|
if(!sound->soloud_context) |
|
|
|
|
|
|
|
|
|
|
|
if(!sound_state.soloud_context) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
log_error("sound:init", "Failed to create sound context"); |
|
|
|
log_error("sound:init", "Failed to create sound context"); |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Soloud_initEx(sound_state.soloud_context, SOLOUD_CLIP_ROUNDOFF | SOLOUD_ENABLE_VISUALIZATION, SOLOUD_SDL2, SOLOUD_AUTO, SOLOUD_AUTO, SOLOUD_AUTO); |
|
|
|
Soloud_initEx(sound->soloud_context, SOLOUD_CLIP_ROUNDOFF | SOLOUD_ENABLE_VISUALIZATION, SOLOUD_SDL2, SOLOUD_AUTO, SOLOUD_AUTO, SOLOUD_AUTO); |
|
|
|
Soloud_setGlobalVolume(sound_state.soloud_context, 4); |
|
|
|
Soloud_setGlobalVolume(sound->soloud_context, 4); |
|
|
|
|
|
|
|
|
|
|
|
Soloud_set3dListenerParameters(sound_state.soloud_context, |
|
|
|
Soloud_set3dListenerParameters(sound->soloud_context, |
|
|
|
0.f, 0.f, 0.f, // Position
|
|
|
|
0.f, 0.f, 0.f, // Position
|
|
|
|
0.f, 0.f, -1.f, // At
|
|
|
|
0.f, 0.f, -1.f, // At
|
|
|
|
0.f, 1.f, 0.f); // Up
|
|
|
|
0.f, 1.f, 0.f); // Up
|
|
|
|
|
|
|
|
sound->listener = NULL; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
log_message("Sound initialized with %s", Soloud_getBackendString(sound->soloud_context)); |
|
|
|
|
|
|
|
|
|
|
|
log_message("Sound initialized with %s", Soloud_getBackendString(sound_state.soloud_context)); |
|
|
|
for(int i = 0; i < MAX_SOUND_BUFFERS; i++) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
sound->sound_buffers[i].type = ST_NONE; |
|
|
|
|
|
|
|
memset(sound->sound_buffers[i].filename, '\0', MAX_FILENAME_LEN); |
|
|
|
|
|
|
|
sound->sound_buffers[i].wav = NULL; |
|
|
|
|
|
|
|
} |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void sound_listener_update(float apos_x, float apos_y, float apos_z, |
|
|
|
void sound_listener_update(struct Sound* sound) |
|
|
|
float afwd_x, float afwd_y, float afwd_z, |
|
|
|
|
|
|
|
float aup_x, float aup_y, float aup_z) |
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
Soloud_set3dListenerParameters(sound_state.soloud_context, |
|
|
|
vec3 position = { 0.f, 0.f, 0.f }; |
|
|
|
apos_x, apos_y, apos_z, // Position
|
|
|
|
vec3 at = { 0.f, 0.f, -1.f }; |
|
|
|
afwd_x, afwd_y, afwd_z, // At
|
|
|
|
vec3 up = { 0.f, 1.f, 0.f }; |
|
|
|
aup_x, aup_y, aup_z); // Up
|
|
|
|
if(sound->listener) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
transform_get_absolute_position(sound->listener, &position); |
|
|
|
|
|
|
|
transform_get_absolute_forward(sound->listener, &at); |
|
|
|
|
|
|
|
transform_get_absolute_up(sound->listener, &up); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Soloud_set3dListenerParameters(sound->soloud_context, |
|
|
|
|
|
|
|
position.x, position.y, position.z, // Position
|
|
|
|
|
|
|
|
at.x, at.y, at.z, // At
|
|
|
|
|
|
|
|
up.x, up.y, up.z); // Up
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void sound_volume_set(float volume) |
|
|
|
void sound_master_volume_set(struct Sound* sound, float volume) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if(volume < 0.f) volume = 0.f; |
|
|
|
if(volume < 0.f) volume = 0.f; |
|
|
|
sound_state.volume = volume; |
|
|
|
sound->master_volume = volume; |
|
|
|
Soloud_setGlobalVolume(sound_state.soloud_context, sound_state.volume); |
|
|
|
Soloud_setGlobalVolume(sound->soloud_context, sound->master_volume); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void sound_update_3d(void) |
|
|
|
void sound_update_3d(struct Sound* sound) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Soloud_update3dAudio(sound_state.soloud_context); |
|
|
|
Soloud_update3dAudio(sound->soloud_context); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void sound_cleanup(void) |
|
|
|
void sound_cleanup(struct Sound* sound) |
|
|
|
{ |
|
|
|
{ |
|
|
|
char* key = NULL; |
|
|
|
for(int i = 0; i < MAX_SOUND_BUFFERS; i++ ) |
|
|
|
struct Variant* value = NULL; |
|
|
|
|
|
|
|
HASHMAP_FOREACH(sound_sources, key, value) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
struct Sound_Source_Buffer* source = value->val_voidptr; |
|
|
|
struct Sound_Source_Buffer* source = &sound->sound_buffers[i]; |
|
|
|
sound_source_stop_all(source); |
|
|
|
sound_source_stop_all(sound, source); |
|
|
|
switch(source->type) |
|
|
|
switch(source->type) |
|
|
|
{ |
|
|
|
{ |
|
|
|
case ST_WAV: Wav_destroy(source->wav); break; |
|
|
|
case ST_WAV: Wav_destroy(source->wav); break; |
|
|
|
case ST_WAV_STREAM: WavStream_destroy(source->wavstream); break; |
|
|
|
case ST_WAV_STREAM: WavStream_destroy(source->wavstream); break; |
|
|
|
} |
|
|
|
} |
|
|
|
free(source); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
hashmap_free(sound_sources); |
|
|
|
Soloud_deinit(sound->soloud_context); |
|
|
|
Soloud_deinit(sound_state.soloud_context); |
|
|
|
Soloud_destroy(sound->soloud_context); |
|
|
|
Soloud_destroy(sound_state.soloud_context); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sound_state.volume = 0.f; |
|
|
|
sound->master_volume = 0.f; |
|
|
|
sound_state.soloud_context = NULL; |
|
|
|
sound->soloud_context = NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void sound_source_instance_destroy(uint source_instance) |
|
|
|
void sound_source_instance_destroy(struct Sound* sound, uint source_instance) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Soloud_stop(sound_state.soloud_context, source_instance); |
|
|
|
Soloud_stop(sound->soloud_context, source_instance); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void sound_source_instance_update_position(uint source_instance, float apos_x, float apos_y, float apos_z) |
|
|
|
void sound_source_instance_update_position(struct Sound* sound, uint source_instance, vec3 abs_pos) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Soloud_set3dSourceParameters(sound_state.soloud_context, source_instance, apos_x, apos_y, apos_z); |
|
|
|
Soloud_set3dSourceParameters(sound->soloud_context, source_instance, abs_pos.x, abs_pos.y, abs_pos.z); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
uint sound_source_instance_create(struct Sound_Source_Buffer* source, bool is3d) |
|
|
|
uint sound_source_instance_create(struct Sound* sound, struct Sound_Source_Buffer* source, bool is3d) |
|
|
|
{ |
|
|
|
{ |
|
|
|
assert(source); |
|
|
|
assert(source); |
|
|
|
uint source_instance = 0; |
|
|
|
uint source_instance = 0; |
|
|
|
if(is3d) |
|
|
|
if(is3d) |
|
|
|
{ |
|
|
|
{ |
|
|
|
source_instance = Soloud_play3dEx(sound_state.soloud_context, |
|
|
|
source_instance = Soloud_play3dEx(sound->soloud_context, |
|
|
|
source->type == ST_WAV ? source->wav : source->wavstream, |
|
|
|
source->type == ST_WAV ? source->wav : source->wavstream, |
|
|
|
0.f, 0.f, 0.f, |
|
|
|
0.f, 0.f, 0.f, |
|
|
|
0.f, 0.f, 0.f, |
|
|
|
0.f, 0.f, 0.f, |
|
|
@ -132,88 +121,104 @@ uint sound_source_instance_create(struct Sound_Source_Buffer* source, bool is3d) |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
source_instance = Soloud_playEx(sound_state.soloud_context, source->type == ST_WAV ? source->wav : source->wavstream, 1.f, 0.0f, true, 0); |
|
|
|
source_instance = Soloud_playEx(sound->soloud_context, source->type == ST_WAV ? source->wav : source->wavstream, 1.f, 0.0f, true, 0); |
|
|
|
} |
|
|
|
} |
|
|
|
return source_instance; |
|
|
|
return source_instance; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void sound_source_instance_volume_set(uint source_instance, float volume) |
|
|
|
void sound_source_instance_volume_set(struct Sound* sound, uint source_instance, float volume) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if(volume < 0.f) volume = 0.f; |
|
|
|
if(volume < 0.f) volume = 0.f; |
|
|
|
Soloud_setVolume(sound_state.soloud_context, source_instance, volume); |
|
|
|
Soloud_setVolume(sound->soloud_context, source_instance, volume); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void sound_source_instance_loop_set(uint source_instance, bool loop) |
|
|
|
void sound_source_instance_loop_set(struct Sound* sound, uint source_instance, bool loop) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Soloud_setLooping(sound_state.soloud_context, source_instance, loop); |
|
|
|
Soloud_setLooping(sound->soloud_context, source_instance, loop); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void sound_source_instance_play(uint source_instance) |
|
|
|
void sound_source_instance_play(struct Sound* sound, uint source_instance) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Soloud_setPause(sound_state.soloud_context, source_instance, false); |
|
|
|
Soloud_setPause(sound->soloud_context, source_instance, false); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void sound_source_instance_pause(uint source_instance) |
|
|
|
void sound_source_instance_pause(struct Sound* sound, uint source_instance) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Soloud_setPause(sound_state.soloud_context, source_instance, true); |
|
|
|
Soloud_setPause(sound->soloud_context, source_instance, true); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void sound_source_instance_rewind(uint source_instance) |
|
|
|
void sound_source_instance_rewind(struct Sound* sound, uint source_instance) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Soloud_seek(sound_state.soloud_context, source_instance, 0.0); |
|
|
|
Soloud_seek(sound->soloud_context, source_instance, 0.0); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void sound_source_instance_stop(uint source_instance) |
|
|
|
void sound_source_instance_stop(struct Sound* sound, uint source_instance) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Soloud_stop(sound_state.soloud_context, source_instance); |
|
|
|
Soloud_stop(sound->soloud_context, source_instance); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void sound_source_instance_min_max_distance_set(uint source_instance, float min_distance, float max_distance) |
|
|
|
void sound_source_instance_min_max_distance_set(struct Sound* sound, uint source_instance, float min_distance, float max_distance) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Soloud_set3dSourceMinMaxDistance(sound_state.soloud_context, source_instance, min_distance, max_distance); |
|
|
|
Soloud_set3dSourceMinMaxDistance(sound->soloud_context, source_instance, min_distance, max_distance); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void sound_source_instance_attenuation_set(uint source_instance, int attenuation_type, float rolloff_factor) |
|
|
|
void sound_source_instance_attenuation_set(struct Sound* sound, uint source_instance, int attenuation_type, float rolloff_factor) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Soloud_set3dSourceAttenuation(sound_state.soloud_context, source_instance, attenuation_type, rolloff_factor); |
|
|
|
Soloud_set3dSourceAttenuation(sound->soloud_context, source_instance, attenuation_type, rolloff_factor); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
float sound_source_instance_volume_get(uint source_instance) |
|
|
|
float sound_source_instance_volume_get(struct Sound* sound, uint source_instance) |
|
|
|
{ |
|
|
|
{ |
|
|
|
return Soloud_getVolume(sound_state.soloud_context, source_instance); |
|
|
|
return Soloud_getVolume(sound->soloud_context, source_instance); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool sound_source_instance_loop_get(uint source_instance) |
|
|
|
bool sound_source_instance_loop_get(struct Sound* sound, uint source_instance) |
|
|
|
{ |
|
|
|
{ |
|
|
|
return Soloud_getLooping(sound_state.soloud_context, source_instance); |
|
|
|
return Soloud_getLooping(sound->soloud_context, source_instance); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool sound_source_instance_is_paused(uint source_instance) |
|
|
|
bool sound_source_instance_is_paused(struct Sound* sound, uint source_instance) |
|
|
|
{ |
|
|
|
{ |
|
|
|
return Soloud_getPause(sound_state.soloud_context, source_instance); |
|
|
|
return Soloud_getPause(sound->soloud_context, source_instance); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
struct Sound_Source_Buffer* sound_source_create(const char* filename, int type) |
|
|
|
struct Sound_Source_Buffer* sound_source_create(struct Sound* sound, const char* filename, int type) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if(!filename) return NULL; |
|
|
|
if(!filename)
|
|
|
|
|
|
|
|
return NULL; |
|
|
|
|
|
|
|
|
|
|
|
struct Sound_Source_Buffer* source = NULL; |
|
|
|
struct Sound_Source_Buffer* source = sound_source_get(sound, filename); |
|
|
|
|
|
|
|
|
|
|
|
//See if we've already loaded this file
|
|
|
|
// See if we've already loaded this file otherwise, get the next empty slot.
|
|
|
|
if(hashmap_value_exists(sound_sources, filename)) |
|
|
|
// If we can't find an empty slot, print error and return NULL
|
|
|
|
|
|
|
|
if(source) |
|
|
|
{ |
|
|
|
{ |
|
|
|
source = (struct Sound_Source_Buffer*)hashmap_ptr_get(sound_sources, filename); |
|
|
|
|
|
|
|
return source; |
|
|
|
return source; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
for(int i = 0; i < MAX_SOUND_BUFFERS; i++) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if(sound->sound_buffers[i].type == ST_NONE) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
source = &sound->sound_buffers[i]; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(!source) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
log_error("sound:source_create", "Could not find empty sound source slot for '%s'", filename); |
|
|
|
|
|
|
|
return source; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
long size = 0L; |
|
|
|
long size = 0L; |
|
|
|
unsigned char* memory = io_file_read(DIRT_INSTALL, filename, "rb", &size); |
|
|
|
unsigned char* memory = io_file_read(DIRT_INSTALL, filename, "rb", &size); |
|
|
|
|
|
|
|
if(!memory) |
|
|
|
source = malloc(sizeof(*source)); |
|
|
|
|
|
|
|
if(!source) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
log_error("sound:source_create", "Out of memory!"); |
|
|
|
log_error("sound:source_create", "Failed to read file"); |
|
|
|
return NULL; |
|
|
|
return source; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
switch(type) |
|
|
|
switch(type) |
|
|
@ -224,8 +229,8 @@ struct Sound_Source_Buffer* sound_source_create(const char* filename, int type) |
|
|
|
int rc = Wav_loadMem(wave, memory, (uint)size); |
|
|
|
int rc = Wav_loadMem(wave, memory, (uint)size); |
|
|
|
if(rc != 0) |
|
|
|
if(rc != 0) |
|
|
|
{ |
|
|
|
{ |
|
|
|
log_error("sound:source_create", "Failed to load %s, Soloud: %s", filename, Soloud_getErrorString(sound_state.soloud_context, rc)); |
|
|
|
log_error("sound:source_create", "Failed to load %s, Soloud: %s", filename, Soloud_getErrorString(sound->soloud_context, rc)); |
|
|
|
free(source); |
|
|
|
free(memory); |
|
|
|
return 0; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |
|
|
|
source->type = ST_WAV; |
|
|
|
source->type = ST_WAV; |
|
|
@ -238,8 +243,8 @@ struct Sound_Source_Buffer* sound_source_create(const char* filename, int type) |
|
|
|
int rc = WavStream_loadMem(wave_stream, memory, (uint)size); |
|
|
|
int rc = WavStream_loadMem(wave_stream, memory, (uint)size); |
|
|
|
if(rc != 0) |
|
|
|
if(rc != 0) |
|
|
|
{ |
|
|
|
{ |
|
|
|
log_error("sound:source_create", "Failed to load %s, Soloud: %s", filename, Soloud_getErrorString(sound_state.soloud_context, rc)); |
|
|
|
log_error("sound:source_create", "Failed to load %s, Soloud: %s", filename, Soloud_getErrorString(sound->soloud_context, rc)); |
|
|
|
free(source); |
|
|
|
free(memory); |
|
|
|
return 0; |
|
|
|
return 0; |
|
|
|
} |
|
|
|
} |
|
|
|
source->type = ST_WAV_STREAM; |
|
|
|
source->type = ST_WAV_STREAM; |
|
|
@ -248,38 +253,45 @@ struct Sound_Source_Buffer* sound_source_create(const char* filename, int type) |
|
|
|
default: log_error("sound:source_create", "Invalid source type %d", type); break; |
|
|
|
default: log_error("sound:source_create", "Invalid source type %d", type); break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
hashmap_ptr_set(sound_sources, filename, (void*)source); |
|
|
|
strncpy(source->filename, filename, MAX_FILENAME_LEN); |
|
|
|
if(memory) free(memory); |
|
|
|
free(memory); |
|
|
|
return source; |
|
|
|
return source; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
struct Sound_Source_Buffer* sound_source_get(const char* name) |
|
|
|
struct Sound_Source_Buffer* sound_source_get(struct Sound* sound, const char* name) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct Sound_Source_Buffer* source = NULL; |
|
|
|
struct Sound_Source_Buffer* source = NULL; |
|
|
|
if(hashmap_value_exists(sound_sources, name)) |
|
|
|
for(int i = 0; i < MAX_SOUND_BUFFERS; i++) |
|
|
|
{ |
|
|
|
{ |
|
|
|
source = (struct Sound_Source_Buffer*)hashmap_ptr_get(sound_sources, name); |
|
|
|
if(sound->sound_buffers[i].type == ST_NONE) |
|
|
|
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(strncmp(name, sound->sound_buffers[i].filename, MAX_FILENAME_LEN) == 0) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
source = &sound->sound_buffers[i]; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return source; |
|
|
|
return source; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void sound_source_destroy(const char* name) |
|
|
|
void sound_source_destroy(struct Sound* sound, const char* name) |
|
|
|
{ |
|
|
|
{ |
|
|
|
struct Sound_Source_Buffer* source = sound_source_get(name); |
|
|
|
struct Sound_Source_Buffer* source = sound_source_get(sound, name); |
|
|
|
if(source) |
|
|
|
if(source) |
|
|
|
{ |
|
|
|
{ |
|
|
|
sound_source_stop_all(source); |
|
|
|
sound_source_stop_all(sound, source); |
|
|
|
switch(source->type) |
|
|
|
switch(source->type) |
|
|
|
{ |
|
|
|
{ |
|
|
|
case ST_WAV: Wav_destroy(source->wav); break; |
|
|
|
case ST_WAV: Wav_destroy(source->wav); source->wav = NULL; break; |
|
|
|
case ST_WAV_STREAM: WavStream_destroy(source->wavstream); break; |
|
|
|
case ST_WAV_STREAM: WavStream_destroy(source->wavstream); source->wavstream = NULL; break; |
|
|
|
} |
|
|
|
} |
|
|
|
free(source); |
|
|
|
source->type = ST_NONE; |
|
|
|
|
|
|
|
memset(source->filename, '\0', MAX_FILENAME_LEN); |
|
|
|
} |
|
|
|
} |
|
|
|
hashmap_value_remove(sound_sources, name); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void sound_source_volume_set(struct Sound_Source_Buffer* source, float volume) |
|
|
|
void sound_source_volume_set(struct Sound* sound, struct Sound_Source_Buffer* source, float volume) |
|
|
|
{ |
|
|
|
{ |
|
|
|
assert(source); |
|
|
|
assert(source); |
|
|
|
switch(source->type) |
|
|
|
switch(source->type) |
|
|
@ -289,7 +301,7 @@ 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_loop_set(struct Sound* sound, struct Sound_Source_Buffer* source, bool loop) |
|
|
|
{ |
|
|
|
{ |
|
|
|
assert(source); |
|
|
|
assert(source); |
|
|
|
switch(source->type) |
|
|
|
switch(source->type) |
|
|
@ -299,17 +311,17 @@ 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_stop_all(struct Sound* sound, struct Sound_Source_Buffer* source) |
|
|
|
{ |
|
|
|
{ |
|
|
|
assert(source); |
|
|
|
assert(source); |
|
|
|
switch(source->type) |
|
|
|
switch(source->type) |
|
|
|
{ |
|
|
|
{ |
|
|
|
case ST_WAV: Soloud_stopAudioSource(sound_state.soloud_context, source->wav); break; |
|
|
|
case ST_WAV: Soloud_stopAudioSource(sound->soloud_context, source->wav); break; |
|
|
|
case ST_WAV_STREAM: Soloud_stopAudioSource(sound_state.soloud_context, source->wavstream); break; |
|
|
|
case ST_WAV_STREAM: Soloud_stopAudioSource(sound->soloud_context, source->wavstream); break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void sound_source_min_max_distance_set(struct Sound_Source_Buffer* source, float min_distance, float max_distance) |
|
|
|
void sound_source_min_max_distance_set(struct Sound* sound, struct Sound_Source_Buffer* source, float min_distance, float max_distance) |
|
|
|
{ |
|
|
|
{ |
|
|
|
assert(source); |
|
|
|
assert(source); |
|
|
|
switch(source->type) |
|
|
|
switch(source->type) |
|
|
|