Optimize busses; add samplerate changing library
This commit is contained in:
parent
8f6c8774de
commit
5da19ec407
2
Makefile
2
Makefile
|
@ -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
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
||||
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);
|
||||
//SDL_AudioStreamPut(stream, w.data, w.frames*w.ch*sizeof(short));
|
||||
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];
|
||||
|
||||
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);
|
||||
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 = new;
|
||||
//SDL_FreeAudioStream(stream);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue