This repository has been archived on 2022-05-21. You can view files and clone it, but cannot push or open issues or pull requests.
LEFTONE/core/loresource/sound.c

264 lines
7.3 KiB
C
Raw Normal View History

#include "./sound.h"
#include <assert.h>
#include <stddef.h>
#include <string.h>
#include "util/jukebox/amp.h"
#include "util/jukebox/composite.h"
#include "util/jukebox/delay.h"
#include "util/jukebox/format.h"
#include "util/jukebox/mixer.h"
#include "util/jukebox/sound.h"
#include "util/math/algorithm.h"
#include "util/math/rational.h"
#include "util/memory/memory.h"
/* resources */
#include "anysrc/sound/bomb.mp3.h"
#include "anysrc/sound/enemy_shoot.mp3.h"
#include "anysrc/sound/enemy_trigger.mp3.h"
#include "anysrc/sound/damage.mp3.h"
#include "anysrc/sound/dodge.mp3.h"
#include "anysrc/sound/dying.mp3.h"
#include "anysrc/sound/guard.mp3.h"
#include "anysrc/sound/player_shoot.mp3.h"
#include "anysrc/sound/player_trigger.mp3.h"
#include "anysrc/sound/reflection.mp3.h"
#include "anysrc/sound/touch_gate.mp3.h"
#define LORESOURCE_SOUND_DECL_(PROC) \
PROC(bomb); \
PROC(enemy_shoot); \
PROC(enemy_trigger); \
PROC(damage); \
PROC(dodge); \
PROC(dying); \
PROC(guard); \
PROC(player_shoot); \
PROC(player_trigger); \
PROC(reflection); \
PROC(touch_gate);
#define LORESOURCE_SOUND_EACH_(PROC) do { \
LORESOURCE_SOUND_DECL_(PROC) \
} while (0)
struct loresource_sound_t {
struct {
# define each_(n) \
jukebox_sound_buffer_t* n
LORESOURCE_SOUND_DECL_(each_);
# undef each_
} buffers;
struct {
# define each_(n) \
jukebox_sound_t* n
LORESOURCE_SOUND_DECL_(each_);
# undef each_
} sounds;
struct {
jukebox_delay_t* delay;
jukebox_composite_t* compo;
} combat;
struct {
jukebox_delay_t* delay;
jukebox_composite_t* compo;
} env;
struct {
jukebox_composite_t* compo;
} direction;
struct {
jukebox_amp_t amp;
jukebox_composite_t* compo;
} root;
};
#define LORESOURCE_SOUND_MAX_CONCURRENT_PLAY 32
static void loresource_sound_initialize_combat_(
loresource_sound_t* sound,
jukebox_mixer_t* mixer,
const jukebox_format_t* format) {
assert(sound != NULL);
assert(mixer != NULL);
assert(jukebox_format_valid(format));
typeof(sound->sounds)* s = &sound->sounds;
typeof(sound->combat)* c = &sound->combat;
c->delay = jukebox_delay_new(format, &rational(5, 100), .1f, .4f);
c->compo = jukebox_composite_new(format, 7);
jukebox_composite_add_effect(c->compo, (jukebox_effect_t*) s->damage);
jukebox_composite_add_effect(c->compo, (jukebox_effect_t*) s->dodge);
jukebox_composite_add_effect(c->compo, (jukebox_effect_t*) s->guard);
jukebox_composite_add_effect(c->compo, (jukebox_effect_t*) s->player_shoot);
jukebox_composite_add_effect(c->compo, (jukebox_effect_t*) s->player_trigger);
jukebox_composite_add_effect(c->compo, (jukebox_effect_t*) s->reflection);
jukebox_composite_add_effect(c->compo, (jukebox_effect_t*) c->delay);
jukebox_composite_play(c->compo);
}
static void loresource_sound_deinitialize_combat_(loresource_sound_t* sound) {
assert(sound != NULL);
typeof(sound->combat)* c = &sound->combat;
jukebox_composite_delete(c->compo);
jukebox_delay_delete(c->delay);
}
static void loresource_sound_initialize_env_(
loresource_sound_t* sound,
jukebox_mixer_t* mixer,
const jukebox_format_t* format) {
assert(sound != NULL);
assert(mixer != NULL);
assert(jukebox_format_valid(format));
typeof(sound->sounds)* s = &sound->sounds;
typeof(sound->env)* e = &sound->env;
e->delay = jukebox_delay_new(format, &rational(1, 10), .3f, .4f);
e->compo = jukebox_composite_new(format, 5);
jukebox_composite_add_effect(e->compo, (jukebox_effect_t*) s->bomb);
jukebox_composite_add_effect(e->compo, (jukebox_effect_t*) s->enemy_shoot);
jukebox_composite_add_effect(e->compo, (jukebox_effect_t*) s->enemy_trigger);
jukebox_composite_add_effect(e->compo, (jukebox_effect_t*) s->touch_gate);
jukebox_composite_add_effect(e->compo, (jukebox_effect_t*) e->delay);
jukebox_composite_play(e->compo);
}
static void loresource_sound_deinitialize_env_(loresource_sound_t* sound) {
assert(sound != NULL);
typeof(sound->env)* e = &sound->env;
jukebox_composite_delete(e->compo);
jukebox_delay_delete(e->delay);
}
static void loresource_sound_initialize_direction_(
loresource_sound_t* sound,
jukebox_mixer_t* mixer,
const jukebox_format_t* format) {
assert(sound != NULL);
assert(mixer != NULL);
assert(jukebox_format_valid(format));
typeof(sound->sounds)* s = &sound->sounds;
typeof(sound->direction)* d = &sound->direction;
d->compo = jukebox_composite_new(format, 1);
jukebox_composite_add_effect(d->compo, (jukebox_effect_t*) s->dying);
jukebox_composite_play(d->compo);
}
static void loresource_sound_deinitialize_direction_(loresource_sound_t* sound) {
assert(sound != NULL);
typeof(sound->direction)* d = &sound->direction;
jukebox_composite_delete(d->compo);
}
loresource_sound_t* loresource_sound_new(
jukebox_mixer_t* mixer, const jukebox_format_t* format) {
assert(mixer != NULL);
assert(jukebox_format_valid(format));
loresource_sound_t* sound = memory_new(sizeof(*sound));
*sound = (typeof(*sound)) {0};
# define each_(n) do { \
sound->buffers.n = jukebox_sound_buffer_new_from_memory_mp3( \
format, \
loresource_sound_##n##_mp3_, \
sizeof(loresource_sound_##n##_mp3_)); \
sound->sounds.n = jukebox_sound_new( \
sound->buffers.n, LORESOURCE_SOUND_MAX_CONCURRENT_PLAY); \
} while (0)
LORESOURCE_SOUND_EACH_(each_);
# undef each_
sound->root.compo = jukebox_composite_new(format, 4);
loresource_sound_initialize_combat_(sound, mixer, format);
jukebox_composite_add_effect(
sound->root.compo, (jukebox_effect_t*) sound->combat.compo);
loresource_sound_initialize_env_(sound, mixer, format);
jukebox_composite_add_effect(
sound->root.compo, (jukebox_effect_t*) sound->env.compo);
loresource_sound_initialize_direction_(sound, mixer, format);
jukebox_composite_add_effect(
sound->root.compo, (jukebox_effect_t*) sound->direction.compo);
jukebox_amp_initialize(&sound->root.amp, format);
jukebox_composite_add_effect(sound->root.compo, &sound->root.amp.super);
jukebox_amp_change_volume(&sound->root.amp, 1, &rational(1, 1));
jukebox_composite_play(sound->root.compo);
jukebox_mixer_add_effect(mixer, (jukebox_effect_t*) sound->root.compo);
return sound;
}
void loresource_sound_delete(loresource_sound_t* sound) {
if (sound == NULL) return;
jukebox_composite_delete(sound->root.compo);
jukebox_amp_deinitialize(&sound->root.amp);
loresource_sound_deinitialize_combat_(sound);
loresource_sound_deinitialize_env_(sound);
loresource_sound_deinitialize_direction_(sound);
# define each_(n) do { \
jukebox_sound_delete(sound->sounds.n); \
jukebox_sound_buffer_delete(sound->buffers.n); \
} while (0)
LORESOURCE_SOUND_EACH_(each_);
# undef each_
memory_delete(sound);
}
void loresource_sound_play(loresource_sound_t* sound, const char* name) {
assert(sound != NULL);
# define each_(n) do { \
if (strcmp(name, #n) == 0) { \
jukebox_sound_play(sound->sounds.n); \
return; \
} \
} while (0)
LORESOURCE_SOUND_EACH_(each_);
# undef each_
}
void loresource_sound_change_master_volume(
loresource_sound_t* sound, float v, const rational_t* duration) {
assert(sound != NULL);
assert(MATH_FLOAT_VALID(v));
assert(rational_valid(duration));
jukebox_amp_change_volume(&sound->root.amp, v, duration);
}