Optimize busses; add samplerate changing library

This commit is contained in:
John Alanbrook 2023-01-16 05:27:28 +00:00
parent 8f6c8774de
commit 5da19ec407
8 changed files with 93 additions and 57 deletions

View file

@ -84,7 +84,7 @@ ifeq ($(OS), WIN32)
EXT = .exe EXT = .exe
else else
LINKER_FLAGS = $(QFLAGS) -L/usr/local/lib LINKER_FLAGS = $(QFLAGS) -L/usr/local/lib
ELIBS = engine pthread yughc portaudio asound glfw3 c m dl ELIBS = engine pthread yughc portaudio asound glfw3 c m dl samplerate
CLIBS = CLIBS =
endif endif

View file

@ -120,11 +120,11 @@ duk_ret_t duk_cmd(duk_context *duk) {
break; break;
case 14: case 14:
play_sound(make_sound(duk_to_string(duk, 1))); play_oneshot(make_sound(duk_to_string(duk, 1)));
break; break;
case 15: case 15:
music_stop();
break; break;
case 16: case 16:

View file

@ -9,6 +9,8 @@
#include "music.h" #include "music.h"
#include "stb_vorbis.h" #include "stb_vorbis.h"
#include "samplerate.h"
#include "stb_ds.h" #include "stb_ds.h"
#include "mix.h" #include "mix.h"
@ -47,27 +49,53 @@ void new_samplerate(short *in, short *out, int n, int ch, int sr_in, int sr_out)
*/ */
} }
struct wav change_samplerate(struct wav w, int rate) static struct wav change_channels(struct wav w, int ch)
{ {
//int samples = sizeof(short) * w.ch * w.frames; short *data = w.data;
//short *new = malloc(samples); int samples = ch * w.frames;
//new_samplerate(w.data, new, short *new = malloc(sizeof(short)*samples);
if (ch > w.ch) {
/* Sets all new channels equal to the first one */
for (int i = 0; i < w.frames; i++) {
for (int j = 0; j < ch; j++)
new[i*ch+j] = data[i];
}
} else {
/* Simple method; just use first N channels present in wav */
for (int i = 0; i < w.frames; i++)
for (int j = 0; j < ch; j++)
new[i*ch+j] = data[i*ch+j];
}
free (w.data);
w.data = new;
return w;
}
//SDL_AudioStream *stream = SDL_NewAudioStream(AUDIO_S16, w.ch, w.samplerate, AUDIO_S16, w.ch, rate); static struct wav change_samplerate(struct wav w, int rate)
//SDL_AudioStreamPut(stream, w.data, w.frames*w.ch*sizeof(short)); {
float ratio = (float)rate/w.samplerate;
int outframes = w.frames * ratio;
SRC_DATA ssrc;
float floatdata[w.frames*w.ch];
src_short_to_float_array(w.data, floatdata, w.frames*w.ch);
float resampled[w.ch*outframes];
int oldframes = w.frames; ssrc.data_in = floatdata;
w.frames *= (float)rate/w.samplerate; ssrc.data_out = resampled;
int samples = sizeof(short) * w.ch * w.frames; ssrc.input_frames = w.frames;
w.samplerate = rate; ssrc.output_frames = outframes;
short *new = malloc(samples); ssrc.src_ratio = ratio;
//SDL_AudioStreamGet(stream, new, samples);
src_simple(&ssrc, SRC_SINC_BEST_QUALITY, w.ch);
short *newdata = malloc(sizeof(short)*outframes*w.ch);
src_float_to_short_array(resampled, newdata, outframes*w.ch);
free(w.data); free(w.data);
w.data = new; w.data = newdata;
//SDL_FreeAudioStream(stream); w.samplerate = rate;
return w; return w;
} }
@ -165,11 +193,17 @@ struct wav *make_sound(const char *wav)
struct wav mwav; struct wav mwav;
mwav.data = drwav_open_file_and_read_pcm_frames_s16(wav, &mwav.ch, &mwav.samplerate, &mwav.frames, NULL); mwav.data = drwav_open_file_and_read_pcm_frames_s16(wav, &mwav.ch, &mwav.samplerate, &mwav.frames, NULL);
if (mwav->samplerate != SAMPLERATE) {
YughInfo("Changing samplerate of %s.", wav); if (mwav.samplerate != SAMPLERATE) {
YughInfo("Changing samplerate of %s from %d to %d.", wav, mwav.samplerate, 48000);
mwav = change_samplerate(mwav, 48000); mwav = change_samplerate(mwav, 48000);
} }
if (mwav.ch != CHANNELS) {
YughInfo("Changing channels of %s from %d to %d.", wav, mwav.ch, CHANNELS);
//mwav = change_channels(mwav, CHANNELS);
}
mwav.gain = 1.f; mwav.gain = 1.f;
struct wav *newwav = malloc(sizeof(*newwav)); struct wav *newwav = malloc(sizeof(*newwav));
@ -205,6 +239,7 @@ void play_oneshot(struct wav *wav) {
new->bus = first_free_bus(dsp_filter(new, sound_fillbuf)); new->bus = first_free_bus(dsp_filter(new, sound_fillbuf));
new->playing=1; new->playing=1;
new->loop=0; new->loop=0;
new->frame = 0;
} }
struct sound *play_sound(struct wav *wav) struct sound *play_sound(struct wav *wav)
@ -301,9 +336,7 @@ void sound_fillbuf(struct sound *s, short *buf, int n)
short *in = s->data->data; short *in = s->data->data;
for (int i = 0; i < n; i++) { for (int i = 0; i < n; i++) {
for (int j = 0; j < 2; j++) { for (int j = 0; j < CHANNELS; j++) buf[i*CHANNELS+j] = in[s->frame+j] * gainmult;
buf[i*2+j] = in[s->frame+j] * gainmult;
}
s->frame++; s->frame++;
if (s->frame == s->data->frames) { if (s->frame == s->data->frames) {
@ -313,6 +346,7 @@ void sound_fillbuf(struct sound *s, short *buf, int n)
s->frame = 0; s->frame = 0;
} else { } else {
bus_free(s->bus); bus_free(s->bus);
return;
} }
} }
} }

View file

@ -2,7 +2,6 @@
#define SOUND_H #define SOUND_H
struct circbuf; struct circbuf;
struct SDL_AudioStream;
struct Mix_Chunk { struct Mix_Chunk {
int i; int i;
@ -23,16 +22,15 @@ struct soundstream {
}; };
struct soundconvstream { struct soundconvstream {
// SDL_AudioStream *srconv;
void *data; void *data;
}; };
struct soundstream *soundstream_make(); struct soundstream *soundstream_make();
/* A playing sound; /* A playing sound */
struct sound { struct sound {
int loop; int loop; /* How many times to loop */
unsigned int frame; unsigned int frame; /* Pointing to the current frame on the wav */
int playing; int playing;
float gain; float gain;

View file

@ -160,6 +160,7 @@ struct dsp_filter dsp_filter(void *data, void (*filter)(void *data, short *out,
struct dsp_filter new; struct dsp_filter new;
new.data = data; new.data = data;
new.filter = filter; new.filter = filter;
new.inputs = 0;
return new; return new;
} }

View file

@ -4,10 +4,12 @@
#include "sound.h" #include "sound.h"
#include "dsp.h" #include "dsp.h"
#include <string.h> #include <string.h>
#include "log.h"
static struct bus bus[256]; static struct bus bus[256];
static int first = 0; /* First bus available */ static int first = 0; /* First bus available */
static int first_on = -1; //static struct bus *first_on = NULL;
static int first_on = -1; /* First bus to fill buffer with */
short mastermix[BUF_FRAMES*CHANNELS]; short mastermix[BUF_FRAMES*CHANNELS];
void mixer_init() { void mixer_init() {
@ -22,46 +24,44 @@ void mixer_init() {
struct bus *first_free_bus(struct dsp_filter in) { struct bus *first_free_bus(struct dsp_filter in) {
if (first == -1) return NULL; if (first == -1) return NULL;
struct bus *ret = bus[first]; int ret = first;
first = ret->next; first = bus[ret].next;
ret->on = 1;
ret->in = in;
ret->next = first_on; bus[ret].on = 1;
first_on = ret->id; bus[ret].in = in;
return ret; if (first_on != -1) bus[first_on].prev = ret;
bus[ret].next = first_on;
bus[ret].prev = -1;
first_on = ret;
return &bus[ret];
} }
void bus_free(struct bus *bus) void bus_free(struct bus *b)
{ {
bus->next = first; if (first_on == b->id) first_on = b->next;
bus->on = 0; if (b->next != -1) bus[b->next].prev = b->prev;
first = bus->id; if (b->prev != -1) bus[b->prev].next = b->next;
b->next = first;
first = b->id;
b->on = 0;
} }
void bus_fill_buffers(short *master, int n) { void bus_fill_buffers(short *master, int n) {
int curbus = first_one int curbus = first_on;
if (curbus == -1) return;
memset(master, 0, BUF_FRAMES*CHANNELS*sizeof(short)); memset(master, 0, BUF_FRAMES*CHANNELS*sizeof(short));
while (bus[curbus].next != -1) {
while (curbus != -1) {
int nextbus = bus[curbus].next; /* Save this in case busses get changed during fill */
dsp_run(bus[curbus].in, bus[curbus].buf, BUF_FRAMES); dsp_run(bus[curbus].in, bus[curbus].buf, BUF_FRAMES);
for (int i = 0; i < BUF_FRAMES*CHANNELS; i++) for (int i = 0; i < BUF_FRAMES*CHANNELS; i++)
master[i] += bus[curbus].buf[i]; master[i] += bus[curbus].buf[i];
curbus = bus[curbus].next; curbus = nextbus;
} }
/*
for (int i = 0; i < 256; i++) {
if (bus[i].on != 1) continue;
dsp_run(bus[i].in, bus[i].buf, BUF_FRAMES);
}
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];
}
}
*/
} }

View file

@ -61,6 +61,8 @@ void dsp_midi_fillbuf(struct dsp_midi_song *song, void *out, int n)
dsp_pan(&music_pan, out, n); dsp_pan(&music_pan, out, n);
} }
struct bus *musicbus;
void play_song(const char *midi, const char *sf) void play_song(const char *midi, const char *sf)
{ {
gsong.midi = tml_load_filename(midi); gsong.midi = tml_load_filename(midi);
@ -85,7 +87,7 @@ void play_song(const char *midi, const char *sf)
cursong.data = &gsong; cursong.data = &gsong;
cursong.filter = dsp_midi_fillbuf; cursong.filter = dsp_midi_fillbuf;
first_free_bus(cursong); musicbus = first_free_bus(cursong);
} }
@ -96,7 +98,7 @@ void music_play()
void music_stop() void music_stop()
{ {
bus_free(musicbus);
} }
void music_volume() void music_volume()

View file

@ -14,6 +14,7 @@ struct dsp_midi_song {
extern float music_pan; extern float music_pan;
void play_song(const char *midi, const char *sf); void play_song(const char *midi, const char *sf);
void music_stop();
void dsp_midi_fillbuf(struct dsp_midi_song *song, void *out, int n); void dsp_midi_fillbuf(struct dsp_midi_song *song, void *out, int n);
#endif #endif