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
else
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 =
endif

View file

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

View file

@ -9,6 +9,8 @@
#include "music.h"
#include "stb_vorbis.h"
#include "samplerate.h"
#include "stb_ds.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 *new = malloc(samples);
//new_samplerate(w.data, new,
short *data = w.data;
int samples = ch * w.frames;
short *new = malloc(sizeof(short)*samples);
//SDL_AudioStream *stream = SDL_NewAudioStream(AUDIO_S16, w.ch, w.samplerate, AUDIO_S16, w.ch, rate);
//SDL_AudioStreamPut(stream, w.data, w.frames*w.ch*sizeof(short));
int oldframes = w.frames;
w.frames *= (float)rate/w.samplerate;
int samples = sizeof(short) * w.ch * w.frames;
w.samplerate = rate;
short *new = malloc(samples);
//SDL_AudioStreamGet(stream, new, 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;
//SDL_FreeAudioStream(stream);
return w;
}
static struct wav change_samplerate(struct wav w, int rate)
{
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];
ssrc.data_in = floatdata;
ssrc.data_out = resampled;
ssrc.input_frames = w.frames;
ssrc.output_frames = outframes;
ssrc.src_ratio = ratio;
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);
w.data = newdata;
w.samplerate = rate;
return w;
}
@ -165,11 +193,17 @@ struct wav *make_sound(const char *wav)
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) {
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);
}
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;
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->playing=1;
new->loop=0;
new->frame = 0;
}
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;
for (int i = 0; i < n; i++) {
for (int j = 0; j < 2; j++) {
buf[i*2+j] = in[s->frame+j] * gainmult;
}
for (int j = 0; j < CHANNELS; j++) buf[i*CHANNELS+j] = in[s->frame+j] * gainmult;
s->frame++;
if (s->frame == s->data->frames) {
@ -313,6 +346,7 @@ void sound_fillbuf(struct sound *s, short *buf, int n)
s->frame = 0;
} else {
bus_free(s->bus);
return;
}
}
}

View file

@ -2,7 +2,6 @@
#define SOUND_H
struct circbuf;
struct SDL_AudioStream;
struct Mix_Chunk {
int i;
@ -23,16 +22,15 @@ struct soundstream {
};
struct soundconvstream {
// SDL_AudioStream *srconv;
void *data;
};
struct soundstream *soundstream_make();
/* A playing sound;
/* A playing sound */
struct sound {
int loop;
unsigned int frame;
int loop; /* How many times to loop */
unsigned int frame; /* Pointing to the current frame on the wav */
int playing;
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;
new.data = data;
new.filter = filter;
new.inputs = 0;
return new;
}

View file

@ -4,10 +4,12 @@
#include "sound.h"
#include "dsp.h"
#include <string.h>
#include "log.h"
static struct bus bus[256];
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];
void mixer_init() {
@ -22,46 +24,44 @@ void mixer_init() {
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;
int ret = first;
first = bus[ret].next;
ret->next = first_on;
first_on = ret->id;
bus[ret].on = 1;
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;
bus->on = 0;
first = bus->id;
if (first_on == b->id) first_on = b->next;
if (b->next != -1) bus[b->next].prev = b->prev;
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) {
int curbus = first_one
int curbus = first_on;
if (curbus == -1) return;
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);
for (int i = 0; i < BUF_FRAMES*CHANNELS; 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);
}
struct bus *musicbus;
void play_song(const char *midi, const char *sf)
{
gsong.midi = tml_load_filename(midi);
@ -85,7 +87,7 @@ void play_song(const char *midi, const char *sf)
cursong.data = &gsong;
cursong.filter = dsp_midi_fillbuf;
first_free_bus(cursong);
musicbus = first_free_bus(cursong);
}
@ -96,7 +98,7 @@ void music_play()
void music_stop()
{
bus_free(musicbus);
}
void music_volume()

View file

@ -14,6 +14,7 @@ struct dsp_midi_song {
extern float music_pan;
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);
#endif