diff --git a/source/engine/sound.c b/source/engine/sound.c index 3dfac30..7b0753e 100644 --- a/source/engine/sound.c +++ b/source/engine/sound.c @@ -9,6 +9,8 @@ #include "music.h" #include "stb_vorbis.h" +#include "stb_ds.h" + #include "mix.h" #include "dsp.h" @@ -28,6 +30,11 @@ #define TML_IMPLEMENTATION #include "tml.h" +static struct { + char *key; + struct wav *value; +} *wavhash = NULL; + const char *audioDriver; void new_samplerate(short *in, short *out, int n, int ch, int sr_in, int sr_out) @@ -150,20 +157,39 @@ void audio_close() //Mix_CloseAudio(); } -static struct wav mwav; - struct wav *make_sound(const char *wav) { + int index = shgeti(wavhash, wav); + if (index != -1) return wavhash[index].value; + + struct wav mwav; mwav.data = drwav_open_file_and_read_pcm_frames_s16(wav, &mwav.ch, &mwav.samplerate, &mwav.frames, NULL); - if (mwav.samplerate != SAMPLERATE) { + if (mwav->samplerate != SAMPLERATE) { YughInfo("Changing samplerate of %s.", wav); mwav = change_samplerate(mwav, 48000); } mwav.gain = 1.f; - return &mwav; + struct wav *newwav = malloc(sizeof(*newwav)); + *newwav = mwav; + + if (shlen(wavhash) == 0) sh_new_arena(wavhash); + + shput(wavhash, wav, newwav); + + return newwav; +} + +void free_sound(const char *wav) +{ + struct wav *w = shget(wavhash, wav); + if (w == NULL) return; + + free(w->data); + free(w); + shdel(wavhash, wav); } struct soundstream *soundstream_make() @@ -173,6 +199,14 @@ struct soundstream *soundstream_make() return new; } +void play_oneshot(struct wav *wav) { + struct sound *new = calloc(1, sizeof(*new)); + new->data = wav; + new->bus = first_free_bus(dsp_filter(new, sound_fillbuf)); + new->playing=1; + new->loop=0; +} + struct sound *play_sound(struct wav *wav) { struct sound *new = calloc(1, sizeof(*new)); diff --git a/source/engine/sound.h b/source/engine/sound.h index 43e5afb..ccc587d 100644 --- a/source/engine/sound.h +++ b/source/engine/sound.h @@ -29,9 +29,10 @@ struct soundconvstream { struct soundstream *soundstream_make(); +/* A playing sound; struct sound { int loop; - int frame; + unsigned int frame; int playing; float gain; @@ -39,6 +40,7 @@ struct sound { struct bus *bus; }; +/* Represents a sound file */ struct wav { unsigned int ch; unsigned int samplerate; @@ -62,6 +64,7 @@ void audio_close(); void sound_fillbuf(struct sound *s, short *buf, int n); struct wav *make_sound(const char *wav); +void free_sound(const char *wav); void wav_norm_gain(struct wav *w, double lv); struct sound *play_sound(struct wav *wav); @@ -73,7 +76,7 @@ void sound_pause(struct sound *s); void sound_resume(struct sound *s); void sound_stop(struct sound *s); -struct music make_music(const char *ogg); +struct music make_music(const char *mp3); const char *get_audio_driver(); diff --git a/source/engine/sound/mix.c b/source/engine/sound/mix.c index 5ec531e..8d36401 100644 --- a/source/engine/sound/mix.c +++ b/source/engine/sound/mix.c @@ -6,37 +6,62 @@ #include static struct bus bus[256]; +static int first = 0; /* First bus available */ +static int first_on = -1; short mastermix[BUF_FRAMES*CHANNELS]; -struct bus *first_free_bus(struct dsp_filter in) { +void mixer_init() { for (int i = 0; i < 256; i++) { - if (!bus[i].on) { - bus[i].on = 1; - bus[i].in = in; - return &bus[i]; - } + bus[i].next = i+1; + bus[i].on = 0; + bus[i].id = i; } - return NULL; + bus[255].next = -1; +} + +struct bus *first_free_bus(struct dsp_filter in) { + if (first == -1) return NULL; + struct bus *ret = bus[first]; + first = ret->next; + ret->on = 1; + ret->in = in; + + ret->next = first_on; + first_on = ret->id; + + return ret; } void bus_free(struct bus *bus) { + bus->next = first; bus->on = 0; + first = bus->id; } void bus_fill_buffers(short *master, int n) { + int curbus = first_one + memset(master, 0, BUF_FRAMES*CHANNELS*sizeof(short)); + while (bus[curbus].next != -1) { + dsp_run(bus[curbus].in, bus[curbus].buf, BUF_FRAMES); + for (int i = 0; i < BUF_FRAMES*CHANNELS; i++) + master[i] += bus[curbus].buf[i]; + + curbus = bus[curbus].next; + } + + /* for (int i = 0; i < 256; i++) { if (bus[i].on != 1) continue; dsp_run(bus[i].in, bus[i].buf, BUF_FRAMES); } - memset(master, 0, BUF_FRAMES*CHANNELS*sizeof(short)); - for (int j = 0; j < 256; j++) { if (!bus[j].on) continue; for (int i = 0; i < BUF_FRAMES*CHANNELS; i++) { master[i] += bus[j].buf[i]; } } + */ } diff --git a/source/engine/sound/mix.h b/source/engine/sound/mix.h index 9265154..e746341 100644 --- a/source/engine/sound/mix.h +++ b/source/engine/sound/mix.h @@ -7,22 +7,23 @@ struct sound; struct bus { - int on; struct dsp_filter in; short buf[BUF_FRAMES*CHANNELS]; float gain; -}; - -struct listener { - float x; - float y; - float z; + int on; + int next; /* Next available bus */ + int prev; + int id; }; extern short mastermix[BUF_FRAMES*CHANNELS]; +void mixer_init(); + struct bus *first_free_bus(struct dsp_filter in); void bus_fill_buffers(short *master, int n); + + void bus_free(struct bus *bus);