Refactored sound related api and implemented writing entity to particular file

dev
Shariq Shah 6 years ago
parent 65382c7d37
commit c0dc6a2c69
  1. 8
      src/game/console.c
  2. 156
      src/game/entity.c
  3. 1
      src/game/entity.h
  4. 6
      src/game/game.c
  5. 2
      src/game/game.h
  6. 2
      src/game/material.c
  7. 8
      src/game/model.c
  8. 47
      src/game/scene.c
  9. 2
      src/system/file_io.h
  10. 7
      src/system/main.c
  11. 252
      src/system/sound.c
  12. 94
      src/system/sound.h
  13. 2
      todo.txt

@ -159,9 +159,9 @@ void console_on_log_error(struct Console* console, const char* context, const ch
void console_command_entity_save(struct Console* console, const char* command)
{
char filename[64];
char filename[MAX_FILENAME_LEN];
char entity_name[MAX_ENTITY_NAME_LEN];
memset(filename, '\0', 64);
memset(filename, '\0', MAX_FILENAME_LEN);
memset(entity_name, '\0', MAX_ENTITY_NAME_LEN);
int params_read = sscanf(command, "%s %s", entity_name, filename);
@ -179,7 +179,9 @@ void console_command_entity_save(struct Console* console, const char* command)
return;
}
if(!entity_save(entity, filename, DIRT_INSTALL))
char full_filename[MAX_FILENAME_LEN];
snprintf(full_filename, MAX_FILENAME_LEN, "entities/%s.symtres", filename);
if(!entity_save(entity, full_filename, DIRT_INSTALL))
log_error("entity_save", "Command failed");
}

@ -52,20 +52,18 @@ void entity_reset(struct Entity * entity, int id)
bool entity_write(struct Entity* entity, struct Parser_Object* object)
{
//if(!object)
//{
// log_error("entity:write", "Invalid object");
// return false;
//}
if(!object)
{
log_error("entity:write", "Invalid object");
return false;
}
///* First write all properties common to all entity types */
//struct Hashmap* entity_data = object->data;
/* First write all properties common to all entity types */
struct Hashmap* entity_data = object->data;
//hashmap_str_set(entity_data, "name", entity->name);
//hashmap_int_set(entity_data, "type", entity->type);
//hashmap_bool_set(entity_data, "is_listener", entity->is_listener);
//hashmap_bool_set(entity_data, "renderable", entity->renderable);
//hashmap_bool_set(entity_data, "has_collision", entity->has_collision);
hashmap_str_set(entity_data, "name", entity->name);
hashmap_int_set(entity_data, "type", entity->type);
hashmap_bool_set(entity_data, "active", entity->active);
//if(entity->has_collision)
//{
@ -125,72 +123,71 @@ bool entity_write(struct Entity* entity, struct Parser_Object* object)
//hashmap_vec3_set(entity_data, "position", &entity->transform.position);
//hashmap_vec3_set(entity_data, "scale", &entity->transform.scale);
//hashmap_quat_set(entity_data, "rotation", &entity->transform.rotation);
//switch(entity->type)
//{
//case ET_CAMERA:
//{
// struct Camera* camera = &entity->camera;
// hashmap_bool_set(entity_data, "ortho", camera->ortho);
// hashmap_bool_set(entity_data, "resizeable", camera->resizeable);
// hashmap_float_set(entity_data, "fov", camera->fov);
// hashmap_float_set(entity_data, "zoom", camera->zoom);
// hashmap_float_set(entity_data, "nearz", camera->nearz);
// hashmap_float_set(entity_data, "farz", camera->farz);
// hashmap_vec4_set(entity_data, "clear_color", &camera->clear_color);
// if(entity->camera.fbo != -1)
// {
// hashmap_bool_set(entity_data, "has_fbo", true);
// hashmap_int_set(entity_data, "fbo_height", framebuffer_height_get(camera->fbo));
// hashmap_int_set(entity_data, "fbo_width", framebuffer_width_get(camera->fbo));
// hashmap_bool_set(entity_data, "fbo_has_render_tex", camera->render_tex == -1 ? false : true);
// hashmap_bool_set(entity_data, "fbo_has_depth_tex", camera->depth_tex == -1 ? false : true);
// }
// else
// {
// hashmap_bool_set(entity_data, "has_fbo", true);
// }
// break;
//}
//case ET_STATIC_MODEL:
//{
// /* TODO: Change this after adding proper support for exported models from blender */
// struct Material* material = material_get(entity->model.material);
// struct Geometry* geom = geom_get(entity->model.geometry_index);
// hashmap_str_set(entity_data, "material", material->name);
// hashmap_str_set(entity_data, "geometry", geom->filename);
// break;
//}
//case ET_LIGHT:
//{
// struct Light* light = &entity->light;
// hashmap_int_set(entity_data, "light_type", light->type);
// hashmap_float_set(entity_data, "outer_angle", light->outer_angle);
// hashmap_float_set(entity_data, "inner_angle", light->inner_angle);
// hashmap_float_set(entity_data, "falloff", light->falloff);
// hashmap_float_set(entity_data, "radius", light->radius);
// hashmap_float_set(entity_data, "intensity", light->intensity);
// hashmap_float_set(entity_data, "depth_bias", light->depth_bias);
// hashmap_bool_set(entity_data, "valid", light->valid);
// hashmap_bool_set(entity_data, "cast_shadow", light->cast_shadow);
// hashmap_bool_set(entity_data, "pcf_enabled", light->pcf_enabled);
// hashmap_vec3_set(entity_data, "color", &light->color);
// break;
//}
//case ET_SOUND_SOURCE:
//{
// 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;
//}
//};
switch(entity->type)
{
case ET_CAMERA:
{
struct Camera* camera = (struct Camera*)entity;
hashmap_bool_set(entity_data, "ortho", camera->ortho);
hashmap_bool_set(entity_data, "resizeable", camera->resizeable);
hashmap_float_set(entity_data, "fov", camera->fov);
hashmap_float_set(entity_data, "zoom", camera->zoom);
hashmap_float_set(entity_data, "nearz", camera->nearz);
hashmap_float_set(entity_data, "farz", camera->farz);
hashmap_vec4_set(entity_data, "clear_color", &camera->clear_color);
if(camera->fbo != -1)
{
hashmap_bool_set(entity_data, "has_fbo", true);
hashmap_int_set(entity_data, "fbo_height", framebuffer_height_get(camera->fbo));
hashmap_int_set(entity_data, "fbo_width", framebuffer_width_get(camera->fbo));
hashmap_bool_set(entity_data, "fbo_has_render_tex", camera->render_tex == -1 ? false : true);
hashmap_bool_set(entity_data, "fbo_has_depth_tex", camera->depth_tex == -1 ? false : true);
}
else
{
hashmap_bool_set(entity_data, "has_fbo", true);
}
break;
}
case ET_STATIC_MESH:
{
struct Static_Mesh* mesh = (struct Static_Mesh*)entity;
struct Geometry* geom = geom_get(mesh->model.geometry_index);
hashmap_int_set(entity_data, "material", mesh->model.material->type);
hashmap_str_set(entity_data, "geometry", geom->filename);
break;
}
case ET_LIGHT:
{
struct Light* light = (struct Light*)entity;
hashmap_int_set(entity_data, "light_type", light->type);
hashmap_float_set(entity_data, "outer_angle", light->outer_angle);
hashmap_float_set(entity_data, "inner_angle", light->inner_angle);
hashmap_float_set(entity_data, "falloff", light->falloff);
hashmap_float_set(entity_data, "radius", light->radius);
hashmap_float_set(entity_data, "intensity", light->intensity);
hashmap_float_set(entity_data, "depth_bias", light->depth_bias);
hashmap_bool_set(entity_data, "valid", light->valid);
hashmap_bool_set(entity_data, "cast_shadow", light->cast_shadow);
hashmap_bool_set(entity_data, "pcf_enabled", light->pcf_enabled);
hashmap_vec3_set(entity_data, "color", &light->color);
break;
}
case ET_SOUND_SOURCE:
{
struct Sound_Source* sound_source = (struct Sound_Source*)entity;
hashmap_str_set(entity_data, "source_filename", sound_source->source_buffer->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;
}
};
return true;
}
@ -209,6 +206,7 @@ bool entity_save(struct Entity* entity, const char* filename, int directory_type
if(!entity_write(entity, object))
{
log_error("entity:save", "Failed to save entity : %s to file : %s", entity->name, filename);
parser_free(parser);
fclose(entity_file);
return false;
}
@ -218,7 +216,7 @@ bool entity_save(struct Entity* entity, const char* filename, int directory_type
parser_free(parser);
fclose(entity_file);
return false;
return true;
}
struct Entity* entity_read(struct Parser_Object* object)

@ -8,7 +8,6 @@
#include "material.h"
#define MAX_ENTITY_NAME_LEN 128
#define MAX_SOUND_SOURCE_BUFFERS 5
struct Entity;

@ -77,6 +77,7 @@ bool game_init(struct Window* window, struct Hashmap* cvars)
game_state->editor = calloc(1, sizeof(*game_state->editor));
game_state->gui = calloc(1, sizeof(*game_state->gui));
game_state->event_manager = calloc(1, sizeof(*game_state->event_manager));
game_state->sound = calloc(1, sizeof(*game_state->sound));
log_message_callback_set(game_on_log_message);
log_warning_callback_set(game_on_log_warning);
@ -105,6 +106,7 @@ bool game_init(struct Window* window, struct Hashmap* cvars)
physics_gravity_set(0.f, -9.8f, 0.f);
physics_body_set_moved_callback(entity_rigidbody_on_move);
physics_body_set_collision_callback(entity_rigidbody_on_collision);
sound_init(game_state->sound);
scene_init(game_state->scene);
editor_init(game_state->editor);
@ -545,7 +547,7 @@ void game_post_update(float dt)
{
input_post_update();
scene_post_update(game_state->scene);
sound_update_3d();
sound_update_3d(game_state->sound);
}
void game_debug_gui(float dt)
@ -1887,6 +1889,7 @@ void game_cleanup(void)
framebuffer_cleanup();
texture_cleanup();
shader_cleanup();
sound_cleanup(game_state->sound);
event_manager_cleanup(game_state->event_manager);
free(game_state->editor);
@ -1895,6 +1898,7 @@ void game_cleanup(void)
free(game_state->renderer);
free(game_state->event_manager);
free(game_state->gui);
free(game_state->sound);
}
free(game_state);
game_state = NULL;

@ -13,6 +13,7 @@ struct Gui;
struct Event_Manager;
struct Editor;
struct Hashmap;
struct Sound;
enum Game_Mode
{
@ -32,6 +33,7 @@ struct Game_State
struct Event_Manager* event_manager;
struct Editor* editor;
struct Hashmap* cvars;
struct Sound* sound;
};

@ -130,12 +130,14 @@ bool material_register_static_mesh(struct Material* material, struct Static_Mesh
variant_assign_int(&mesh->model.material_params[MMP_DIFFUSE_TEX], texture_create_from_file("default.tga", TU_DIFFUSE));
variant_assign_float(&mesh->model.material_params[MMP_SPECULAR], 1.f);
variant_assign_float(&mesh->model.material_params[MMP_SPECULAR_STRENGTH], 50.f);
mesh->model.material = material;
}
break;
case MAT_UNSHADED:
{
variant_assign_vec4f(&mesh->model.material_params[MMP_DIFFUSE_COL], 1.f, 0.f, 1.f, 1.f);
variant_assign_int(&mesh->model.material_params[MMP_DIFFUSE_TEX], texture_create_from_file("default.tga", TU_DIFFUSE));
mesh->model.material = material;
}
break;
default:

@ -18,15 +18,15 @@ void model_init(struct Model* model, struct Static_Mesh* mesh, const char* geome
assert(model && material_type > -1 && material_type < MAT_MAX);
/* if no name is given for geometry, use default */
int geo_index = geom_create_from_file(geometry_name ? geometry_name : "default.pamesh");
int geo_index = geom_create_from_file(geometry_name ? geometry_name : "default.symbres");
if(geo_index == -1)
{
log_error("model:init", "Failed to load model %s", geometry_name);
geo_index = geom_create_from_file("default.pamesh");
geo_index = geom_create_from_file("default.symbres");
if(geo_index == -1)
{
log_error("model:init", "Could not load default model 'default.pamesh' ");
log_error("model:init", "Could not load default model 'default.symbres' ");
return;
}
}
@ -35,7 +35,7 @@ void model_init(struct Model* model, struct Static_Mesh* mesh, const char* geome
struct Material* material = &game_state_get()->renderer->materials[material_type];
if(!material_register_static_mesh(material, mesh))
{
log_error("model:create", "Unable to register model with Unshaded material, component not added");
log_error("model:create", "Unable to register model with Unshaded material");
model_reset(model, mesh);
}
}

@ -96,6 +96,7 @@ void scene_update(struct Scene* scene, float dt)
void scene_post_update(struct Scene* scene)
{
assert(scene);
struct Sound* sound = game_state_get()->sound;
for(int i = 0; i < MAX_ENTITIES; i++)
{
@ -144,7 +145,7 @@ void scene_post_update(struct Scene* scene)
{
vec3 abs_pos = { 0.f, 0.f, 0.f };
transform_get_absolute_position(&sound_source->base, &abs_pos);
sound_source_instance_update_position(sound_source->source_instance, abs_pos.x, abs_pos.y, abs_pos.z);
sound_source_instance_update_position(sound, sound_source->source_instance, abs_pos);
sound_source->base.transform.is_modified = false;
}
}
@ -198,16 +199,7 @@ void scene_post_update(struct Scene* scene)
if(scene->player.base.transform.is_modified)
{
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_position(&scene->player, &abs_pos);
transform_get_absolute_forward(&scene->player, &abs_fwd);
transform_get_absolute_up(&scene->player, &abs_up);
sound_listener_update(abs_pos.x, abs_pos.y, abs_pos.z,
abs_fwd.x, abs_fwd.y, abs_fwd.z,
abs_up.x, abs_up.y, abs_up.z);
sound_listener_update(sound);
scene->player.base.transform.is_modified = false;
}
}
@ -329,6 +321,7 @@ struct Static_Mesh* scene_static_mesh_create(struct Scene* scene, const char* na
struct Sound_Source* scene_sound_source_create(struct Scene* scene, const char* name, struct Entity* parent, const char* filename, int type, bool loop, bool play)
{
assert(scene && filename);
struct Sound* sound = game_state_get()->sound;
struct Sound_Source* new_sound_source = NULL;
for(int i = 0; i < MAX_SOUND_SOURCES; i++)
{
@ -346,7 +339,7 @@ struct Sound_Source* scene_sound_source_create(struct Scene* scene, const char*
new_sound_source->base.type = ET_SOUND_SOURCE;
struct Entity* entity = &new_sound_source->base;
new_sound_source->source_buffer = sound_source_create(filename, type);
new_sound_source->source_buffer = sound_source_create(sound, filename, type);
if(!new_sound_source->source_buffer)
{
log_error("entity:sync_sound_params", "Failed to load file '%s' to provide sound source for entity %s", filename, entity->name);
@ -354,14 +347,10 @@ struct Sound_Source* scene_sound_source_create(struct Scene* scene, const char*
return new_sound_source;
}
new_sound_source->source_instance = sound_source_instance_create(new_sound_source->source_buffer, true);
new_sound_source->source_instance = sound_source_instance_create(sound, new_sound_source->source_buffer, 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_position(entity, &abs_pos);
transform_get_absolute_forward(entity, &abs_fwd);
transform_get_absolute_up(entity, &abs_up);
sound_source_instance_update_position(new_sound_source->source_instance, abs_pos.x, abs_pos.y, abs_pos.z);
sound_source_instance_update_position(sound, new_sound_source->source_instance, abs_pos);
new_sound_source->loop = loop;
new_sound_source->min_distance = 0.f;
@ -372,13 +361,13 @@ struct Sound_Source* scene_sound_source_create(struct Scene* scene, const char*
new_sound_source->volume = 1.f;
new_sound_source->type = type;
sound_source_instance_loop_set(new_sound_source->source_instance, new_sound_source->loop);
sound_source_instance_min_max_distance_set(new_sound_source->source_instance, new_sound_source->min_distance, new_sound_source->max_distance);
sound_source_instance_attenuation_set(new_sound_source->source_instance, new_sound_source->attenuation_type, new_sound_source->rolloff_factor);
sound_source_instance_volume_set(new_sound_source->source_instance, new_sound_source->volume);
sound_source_instance_loop_set(sound, new_sound_source->source_instance, new_sound_source->loop);
sound_source_instance_min_max_distance_set(sound, new_sound_source->source_instance, new_sound_source->min_distance, new_sound_source->max_distance);
sound_source_instance_attenuation_set(sound, new_sound_source->source_instance, new_sound_source->attenuation_type, new_sound_source->rolloff_factor);
sound_source_instance_volume_set(sound, new_sound_source->source_instance, new_sound_source->volume);
sound_update_3d();
if(new_sound_source->playing) sound_source_instance_play(new_sound_source->source_instance);
sound_update_3d(sound);
if(new_sound_source->playing) sound_source_instance_play(sound, new_sound_source->source_instance);
}
else
{
@ -429,7 +418,7 @@ void scene_sound_source_remove(struct Scene* scene, struct Sound_Source* source)
{
assert(scene && source);
sound_source_instance_destroy(source->source_instance);
sound_source_instance_destroy(game_state_get()->sound, source->source_instance);
source->source_instance = 0;
scene_entity_remove(scene, &source->base);
}
@ -456,7 +445,7 @@ struct Light* scene_light_find(struct Scene* scene, const char* name)
assert(scene && name);
struct Light* light = NULL;
for(int i = 0; i < MAX_ENTITIES; i++)
for(int i = 0; i < MAX_LIGHTS; i++)
{
if(strncmp(name, scene->lights[i].base.name, MAX_ENTITY_NAME_LEN) == 0)
{
@ -473,7 +462,7 @@ struct Camera* scene_camera_find(struct Scene* scene, const char* name)
assert(scene && name);
struct Camera* camera = NULL;
for(int i = 0; i < MAX_ENTITIES; i++)
for(int i = 0; i < MAX_CAMERAS; i++)
{
if(strncmp(name, scene->cameras[i].base.name, MAX_ENTITY_NAME_LEN) == 0)
{
@ -490,7 +479,7 @@ struct Static_Mesh* scene_static_mesh_find(struct Scene* scene, const char* name
assert(scene && name);
struct Static_Mesh* static_mesh = NULL;
for(int i = 0; i < MAX_ENTITIES; i++)
for(int i = 0; i < MAX_STATIC_MESHES; i++)
{
if(strncmp(name, scene->static_meshes[i].base.name, MAX_ENTITY_NAME_LEN) == 0)
{
@ -507,7 +496,7 @@ struct Sound_Source* scene_sound_source_find(struct Scene* scene, const char* na
assert(scene && name);
struct Sound_Source* sound_source = NULL;
for(int i = 0; i < MAX_ENTITIES; i++)
for(int i = 0; i < MAX_SOUND_SOURCES; i++)
{
if(strncmp(name, scene->sound_sources[i].base.name, MAX_ENTITY_NAME_LEN) == 0)
{

@ -4,6 +4,8 @@
#include <stdbool.h>
#include <stdio.h>
#define MAX_FILENAME_LEN 128
enum Directory_Type
{
DIRT_USER, /* User directory or preferences directory */

@ -87,12 +87,6 @@ bool init(void)
return false;
}
if(!sound_init())
{
log_error("main:init", "Failed to initialize sound");
return false;
}
return true;
}
@ -101,7 +95,6 @@ void cleanup(void)
game_cleanup();
if(window) window_destroy(window);
log_reset_all_callbacks(); // Now that the game library has been unloaded, reset all callbacks to stubs so we don't crash on exit
sound_cleanup();
platform_unload_gl();
platform_cleanup();
config_vars_cleanup(cvars);

@ -4,125 +4,114 @@
#include "../common/hashmap.h"
#include "../common/variant.h"
#include "../common/string_utils.h"
#include "file_io.h"
#include "../game/entity.h"
#include "../game/transform.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <soloud_c.h>
struct Sound_Source_Buffer
{
int type;
union
{
Wav* wav;
WavStream* wavstream;
};
};
struct Sound_State
bool sound_init(struct Sound* sound)
{
Soloud* soloud_context;
float volume;
};
sound->soloud_context = Soloud_create();
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_state.soloud_context = Soloud_create();
if(!sound_state.soloud_context)
if(!sound->soloud_context)
{
log_error("sound:init", "Failed to create sound context");
return false;
}
Soloud_initEx(sound_state.soloud_context, SOLOUD_CLIP_ROUNDOFF | SOLOUD_ENABLE_VISUALIZATION, SOLOUD_SDL2, SOLOUD_AUTO, SOLOUD_AUTO, SOLOUD_AUTO);
Soloud_setGlobalVolume(sound_state.soloud_context, 4);
Soloud_initEx(sound->soloud_context, SOLOUD_CLIP_ROUNDOFF | SOLOUD_ENABLE_VISUALIZATION, SOLOUD_SDL2, SOLOUD_AUTO, SOLOUD_AUTO, SOLOUD_AUTO);
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, -1.f, // At
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;
}
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_listener_update(struct Sound* sound)
{
vec3 position = { 0.f, 0.f, 0.f };
vec3 at = { 0.f, 0.f, -1.f };
vec3 up = { 0.f, 1.f, 0.f };
if(sound->listener)
{
Soloud_set3dListenerParameters(sound_state.soloud_context,
apos_x, apos_y, apos_z, // Position
afwd_x, afwd_y, afwd_z, // At
aup_x, aup_y, aup_z); // Up
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;
sound_state.volume = volume;
Soloud_setGlobalVolume(sound_state.soloud_context, sound_state.volume);
sound->master_volume = 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;
struct Variant* value = NULL;
HASHMAP_FOREACH(sound_sources, key, value)
for(int i = 0; i < MAX_SOUND_BUFFERS; i++ )
{
struct Sound_Source_Buffer* source = value->val_voidptr;
sound_source_stop_all(source);
struct Sound_Source_Buffer* source = &sound->sound_buffers[i];
sound_source_stop_all(sound, source);
switch(source->type)
{
case ST_WAV: Wav_destroy(source->wav); break;
case ST_WAV_STREAM: WavStream_destroy(source->wavstream); break;
}
free(source);
}
hashmap_free(sound_sources);
Soloud_deinit(sound_state.soloud_context);
Soloud_destroy(sound_state.soloud_context);
Soloud_deinit(sound->soloud_context);
Soloud_destroy(sound->soloud_context);
sound_state.volume = 0.f;
sound_state.soloud_context = NULL;
sound->master_volume = 0.f;
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);
uint source_instance = 0;
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,
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
{
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;
}
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;
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 otherwise, get the next empty slot.
// If we can't find an empty slot, print error and return NULL
if(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;
}
}
//See if we've already loaded this file
if(hashmap_value_exists(sound_sources, filename))
if(!source)
{
source = (struct Sound_Source_Buffer*)hashmap_ptr_get(sound_sources, filename);
log_error("sound:source_create", "Could not find empty sound source slot for '%s'", filename);
return source;
}
}
long size = 0L;
unsigned char* memory = io_file_read(DIRT_INSTALL, filename, "rb", &size);
source = malloc(sizeof(*source));
if(!source)
if(!memory)
{
log_error("sound:source_create", "Out of memory!");
return NULL;
log_error("sound:source_create", "Failed to read file");
return source;
}
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);
if(rc != 0)
{
log_error("sound:source_create", "Failed to load %s, Soloud: %s", filename, Soloud_getErrorString(sound_state.soloud_context, rc));
free(source);
log_error("sound:source_create", "Failed to load %s, Soloud: %s", filename, Soloud_getErrorString(sound->soloud_context, rc));
free(memory);
return 0;
}
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);
if(rc != 0)
{
log_error("sound:source_create", "Failed to load %s, Soloud: %s", filename, Soloud_getErrorString(sound_state.soloud_context, rc));
free(source);
log_error("sound:source_create", "Failed to load %s, Soloud: %s", filename, Soloud_getErrorString(sound->soloud_context, rc));
free(memory);
return 0;
}
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;
}
hashmap_ptr_set(sound_sources, filename, (void*)source);
if(memory) free(memory);
strncpy(source->filename, filename, MAX_FILENAME_LEN);
free(memory);
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;
if(hashmap_value_exists(sound_sources, name))
for(int i = 0; i < MAX_SOUND_BUFFERS; i++)
{
if(sound->sound_buffers[i].type == ST_NONE)
continue;
if(strncmp(name, sound->sound_buffers[i].filename, MAX_FILENAME_LEN) == 0)
{
source = (struct Sound_Source_Buffer*)hashmap_ptr_get(sound_sources, name);
source = &sound->sound_buffers[i];
break;
}
}
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)
{
sound_source_stop_all(source);
sound_source_stop_all(sound, source);
switch(source->type)
{
case ST_WAV: Wav_destroy(source->wav); break;
case ST_WAV_STREAM: WavStream_destroy(source->wavstream); break;
case ST_WAV: Wav_destroy(source->wav); source->wav = NULL; 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);
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);
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);
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;
case ST_WAV: Soloud_stopAudioSource(sound->soloud_context, source->wav); 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);
switch(source->type)

@ -2,10 +2,19 @@
#define SOUND_H
#include "../common/num_types.h"
#include "../common/linmath.h"
#include "file_io.h"
#define MAX_SOUND_BUFFERS 128
typedef void* Wav;
typedef void* WavStream;
typedef void* Soloud;
enum Sound_Source_Type
{
ST_WAV = 0,
ST_NONE = 0,
ST_WAV,
ST_WAV_STREAM
};
@ -17,40 +26,53 @@ enum Sound_Attenuation_Type
SA_EXPONENTIAL // Exponential distance attenuation model
};
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_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);
struct Sound_Source_Buffer
{
int type;
char filename[MAX_FILENAME_LEN];
union
{
Wav* wav;
WavStream* wavstream;
};
};
struct Sound
{
Soloud* soloud_context;
struct Entity* listener;
float master_volume;
struct Sound_Source_Buffer sound_buffers[MAX_SOUND_BUFFERS];
};
bool sound_init(struct Sound* sound);
void sound_cleanup(struct Sound* sound);
void sound_master_volume_set(struct Sound* sound, float volume);
void sound_update_3d(struct Sound* sound);
void sound_listener_update(struct Sound* sound);
void sound_source_instance_update_position(struct Sound* sound, uint source_instance, vec3 abs_pos);
uint sound_source_instance_create(struct Sound* sound, struct Sound_Source_Buffer* source, bool is3d);
void sound_source_instance_destroy(struct Sound* sound, uint source_instance);
void sound_source_instance_volume_set(struct Sound* sound, uint source_instance, float volume);
void sound_source_instance_loop_set(struct Sound* sound, uint source_instance, bool loop);
void sound_source_instance_play(struct Sound* sound, uint source_instance);
void sound_source_instance_pause(struct Sound* sound, uint source_instance);
void sound_source_instance_rewind(struct Sound* sound, uint source_instance);
void sound_source_instance_stop(struct Sound* sound, uint source_instance);
void sound_source_instance_min_max_distance_set(struct Sound* sound, uint source_instance, float min_distance, float max_distance);
void sound_source_instance_attenuation_set(struct Sound* sound, uint source_instance, int attenuation_type, float rolloff_factor);
float sound_source_instance_volume_get(struct Sound* sound, uint source_instance);
bool sound_source_instance_loop_get(struct Sound* sound, uint source_instance);
bool sound_source_instance_is_paused(struct Sound* sound, uint source_instance);
struct Sound_Source_Buffer* sound_source_create(struct Sound* sound, const char* filename, int type);
struct Sound_Source_Buffer* sound_source_get(struct Sound* sound, const char* name);
void sound_source_destroy(struct Sound* sound, const char* buffer_name);
void sound_source_volume_set(struct Sound* sound, struct Sound_Source_Buffer* source, float volume);
void sound_source_loop_set(struct Sound* sound, struct Sound_Source_Buffer* source, bool loop);
void sound_source_stop_all(struct Sound* sound, struct Sound_Source_Buffer* source);
void sound_source_min_max_distance_set(struct Sound* sound, struct Sound_Source_Buffer* source, float min_distance, float max_distance);
#endif

@ -50,6 +50,8 @@ Todo:
- Move Gui_State and Editor_State into game_state and modify usage as needed
- Get editor camera speed and other settings from config file
- Recompile Soloud on windows to use static sdl2 backend
- Refactor input sub-system to be the same as other sub-systems embedded
in game state.
- Figure out a way to reduce of remove snprintf calls from render code
- Re-Implement saving/loading scene to/from files
- Implement storing console's scroll location and restore it when console is toggled

Loading…
Cancel
Save