From d8640bed5ae5d4fbfc3ff7da604d056ac6e6ae8d Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Sun, 10 Jul 2022 18:04:24 +0000 Subject: [PATCH] MIDI music and soundfonts work --- source/engine/datastream.c | 2 +- source/engine/dsp.c | 12 ++++++-- source/engine/dsp.h | 2 +- source/engine/iir.c | 60 ++++++++++++++++++++++---------------- source/engine/music.c | 20 ++++++++----- source/engine/sound.c | 12 +++----- 6 files changed, 63 insertions(+), 45 deletions(-) diff --git a/source/engine/datastream.c b/source/engine/datastream.c index 95beabc..cea9a5f 100755 --- a/source/engine/datastream.c +++ b/source/engine/datastream.c @@ -91,7 +91,7 @@ void ds_openvideo(struct datastream *ds, const char *video, const char *adriver) fir->in = astream_filter; */ - first_free_bus(astream_filter); + //first_free_bus(astream_filter); plm_set_video_decode_callback(ds->plm, render_frame, ds); plm_set_audio_decode_callback(ds->plm, render_audio, ds); diff --git a/source/engine/dsp.c b/source/engine/dsp.c index 76259ac..8ce06b4 100644 --- a/source/engine/dsp.c +++ b/source/engine/dsp.c @@ -17,7 +17,11 @@ struct dsp_filter make_dsp(void *data, void (*in)(void *data, short *out, int n) new.data = data; new.filter = in; - if (filters.len == 0) + return new; + + if (filters.len == 0) { + + } } void dsp_run(struct dsp_filter filter, short *out, int n) { @@ -27,18 +31,20 @@ void dsp_run(struct dsp_filter filter, short *out, int n) { return; for (int i = 0; i < filter.inputs; i++) - dsp_run(filter.in[i], out, n); + dsp_run(*(filter.in[i]), out, n); filter.filter(filter.data, out, n); } -struct dsp_filter_addin(struct dsp_filter filter, struct dsp_filter in) +void dsp_filter_addin(struct dsp_filter filter, struct dsp_filter *in) { if (filter.inputs > 5) { YughError("Too many inputs in filter.", 0); } filter.in[filter.inputs++] = in; + + return filter; } void am_mod(struct dsp_ammod *mod, short *c, int n) diff --git a/source/engine/dsp.h b/source/engine/dsp.h index 7078779..81850ac 100644 --- a/source/engine/dsp.h +++ b/source/engine/dsp.h @@ -32,7 +32,7 @@ struct dsp_fir { struct dsp_filter in; }; -void dsp_filter_addin(struct dsp_filter filter, struct dsp_filter in); +void dsp_filter_addin(struct dsp_filter filter, struct dsp_filter *in); struct dsp_filter lp_fir_make(float freq); diff --git a/source/engine/iir.c b/source/engine/iir.c index 22adf0c..3a503a2 100644 --- a/source/engine/iir.c +++ b/source/engine/iir.c @@ -43,6 +43,7 @@ #include "limits.h" #include "iir.h" #include "dsp.h" +#include "log.h" /********************************************************************** binomial_mult - multiplies a series of binomials together and returns @@ -649,17 +650,25 @@ float *fir_bpf(int n, double fcf1, double fcf2) /* Biquad filters */ -struct dsp_iir biquad_iir() +struct dsp_iir make_iir(int cofs, int order) { struct dsp_iir new; - new.dcof = malloc(sizeof(float) * 3); - new.ccof = malloc(sizeof(float) * 3); - new.dx = malloc(sizeof(float) * 3); - new.dy = malloc(sizeof(float) * 3); - new.n = 3; + new.n = cofs; + new.order = order; + + new.dcof = calloc(sizeof(float), cofs *order); + new.ccof = calloc(sizeof(float), cofs *order); + new.dx = calloc(sizeof(float), cofs *order); + new.dy = calloc(sizeof(float), cofs *order); + return new; } +struct dsp_iir biquad_iir() +{ + return make_iir(3, 1); +} + void biquad_iir_fill(struct dsp_iir bq, double *a, double *b) { bq.ccof[0] = (b[0] / a[0]); @@ -842,7 +851,7 @@ void p2_ccalc(double fcf, double p, double g, double *a, double *b) double w0 = tan(M_PI * fcf); double k[2]; k[0] = p * w0; - k[1] = g * pow2(w0); + k[1] = g * pow(w0, 2); a[0] = k[1] / (1 + k[0] + k[1]); a[1] = 2 * a[0]; @@ -962,8 +971,8 @@ struct dsp_iir che_lp(int order, double fcf, double e) double a = tan(M_PI * fcf); - double a2 = pow2(a); - double u = log((1.f + sqrt(1.f + pow2(e)))/e); + double a2 = pow(a, 2); + double u = log((1.f + sqrt(1.f + pow(e, 2)))/e); double su = sinh(u/new.order); double cu = cosh(u/new.order); double b, c, s; @@ -973,7 +982,7 @@ struct dsp_iir che_lp(int order, double fcf, double e) { b = sin(M_PI * (2.f*i + 1.f)/(2.f*new.order)) * su; c = cos(M_PI * (2.f*i + 1.f)/(2.f*new.order)) * cu; - c = pow2(b) + pow2(c); + c = pow(b, 2) + pow(c, 2); s = a2*c + 2.f*a*b + 1.f; double A = a2/(4.f); @@ -994,8 +1003,8 @@ struct dsp_iir che_hp(int order, double fcf, double e) struct dsp_iir new = che_lp(order, fcf, e); double a = tan(M_PI * fcf); - double a2 = pow2(a); - double u = log((1.f + sqrt(1.f + pow2(e)))/e); + double a2 = pow(a, 2); + double u = log((1.f + sqrt(1.f + pow(e, 2)))/e); double su = sinh(u/new.order); double cu = cosh(u/new.order); double b, c, s; @@ -1005,7 +1014,7 @@ struct dsp_iir che_hp(int order, double fcf, double e) { b = sin(M_PI * (2.f*i + 1.f)/(2.f*new.order)) * su; c = cos(M_PI * (2.f*i + 1.f)/(2.f*new.order)) * cu; - c = pow2(b) + pow2(c); + c = pow(b, 2) + pow(c, 2); s = a2*c + 2.f*a*b + 1.f; double A = 1.f/(4.f); @@ -1031,10 +1040,10 @@ struct dsp_iir che_bp(int order, double s, double fcf1, double fcf2, double e) struct dsp_iir new = p2_iir_order(order); double a = cos(M_PI*(fcf1+fcf2)/2) / cos(M_PI*(fcf2-fcf1)/s); - double a2 = pow2(a); + double a2 = pow(a, 2); double b = tan(M_PI*(fcf2-fcf1)/s); - double b2 = pow2(b); - double u = log((1.f+sqrt(1.f+pow2(e)))/e); + double b2 = pow(b, 2); + double u = log((1.f+sqrt(1.f+pow(e, 2)))/e); double su = sinh(2.f*u/new.order); double cu = cosh(2.f*u/new.order); double A = b2/(4.f); @@ -1043,7 +1052,7 @@ struct dsp_iir che_bp(int order, double s, double fcf1, double fcf2, double e) for (int i = 0; i < new.order; ++i) { r = sin(M_PI*(2.f*i+1.f)/new.order)*su; c = cos(M_PI*(2.f*i+1.f)/new.order)*su; - c = pow2(r) + pow2(c); + c = pow(r, 2) + pow(c, 2); s = b2*c + 2.f*b*r + 1.f; new.ccof[0*i] = ep * 1.f/A; @@ -1060,7 +1069,7 @@ struct dsp_iir che_bp(int order, double s, double fcf1, double fcf2, double e) return new; } -struct dsp_iir che_notch(int order, double fcf1, double fcf2, double e) +struct dsp_iir che_notch(int order, double s, double fcf1, double fcf2, double e) { if (order %4 != 0) { YughWarn("Tried to make a filter with wrong order. Given order was %d, but order should be 4, 8, 12, ...", order); @@ -1068,29 +1077,30 @@ struct dsp_iir che_notch(int order, double fcf1, double fcf2, double e) int n = order / 4; +double ep = 2.f/e; struct dsp_iir new = p2_iir_order(order); double a = cos(M_PI*(fcf1+fcf2)/2) / cos(M_PI*(fcf2-fcf1)/s); - double a2 = pow2(a); + double a2 = pow(a, 2); double b = tan(M_PI*(fcf2-fcf1)/s); - double b2 = pow2(b); - double u = log((1.f+sqrt(1.f+pow2(e)))/e); + double b2 = pow(b, 2); + double u = log((1.f+sqrt(1.f+pow(e, 2)))/e); double su = sinh(2.f*u/n); double cu = cosh(2.f*u/n); double A = b2/(4.f*s); - double r, c, s; + double r, c; for (int i = 0; i < new.order; ++i) { r = sin(M_PI*(2.f*i+1.f)/new.order)*su; - c = cos(M_PI*(2.f*i+1.f)/ew.order)*su; - c = pow2(r) + pow2(c); + c = cos(M_PI*(2.f*i+1.f)/new.order)*su; + c = pow(r, 2) + pow(c, 2); s = b2*c + 2.f*b*r + 1.f; new.ccof[0*i] = ep * 1.f/A; new.ccof[1*i] = ep * -2.f/A; new.ccof[2*i] = ep * 1.f/A; - new.ddof[0*i] = 0.f; + new.dcof[0*i] = 0.f; new.dcof[1*i] = ep * 4.f*a*(c+b*r)/s; new.dcof[2*i] = ep * 2.f*(b2-2.f*a2*c-c)/s; new.dcof[3*i] = ep * 4.f*a*(c-b*r)/s; diff --git a/source/engine/music.c b/source/engine/music.c index 20e2458..cc992ce 100644 --- a/source/engine/music.c +++ b/source/engine/music.c @@ -6,7 +6,7 @@ #include "mix.h" #include "sound.h" -#define TSF_BLOCK 64 +#define TSF_BLOCK 32 struct dsp_filter cursong; struct dsp_midi_song gsong; @@ -16,10 +16,10 @@ void dsp_midi_fillbuf(struct dsp_midi_song *song, void *out, int n) short *o = (short*)out; tml_message *midi = song->midi; - for (int i = TSF_BLOCK; n; n -= i, o += n*CHANNELS) { - if (i > n) i = n; + for (int i = 0; i < n; i += TSF_BLOCK) { + + while (midi && song->time >= midi->time) { - for (song->time += i * (1000.f / SAMPLERATE); midi && song->time >= midi->time; midi = midi->next) { switch (midi->type) { case TML_PROGRAM_CHANGE: @@ -42,9 +42,15 @@ void dsp_midi_fillbuf(struct dsp_midi_song *song, void *out, int n) tsf_channel_midi_control(song->sf, midi->channel, midi->control, midi->control_value); break; } + + + midi = midi->next; } - tsf_render_short(song->sf, o, i, 0); + + tsf_render_short(song->sf, o, TSF_BLOCK, 0); + o += TSF_BLOCK*2; + song->time += TSF_BLOCK * (1000.f/SAMPLERATE); } song->midi = midi; @@ -52,8 +58,8 @@ void dsp_midi_fillbuf(struct dsp_midi_song *song, void *out, int n) void play_song(const char *midi, const char *sf) { - gsong.midi = tml_load_filename("sounds/one-winged-angel.mid"); - gsong.sf = tsf_load_filename("sounds/mario.sf2"); + gsong.midi = tml_load_filename("sounds/stickerbrush.mid"); + gsong.sf = tsf_load_filename("sounds/ff7.sf2"); gsong.time = 0.f; tsf_set_output(gsong.sf, TSF_STEREO_INTERLEAVED, SAMPLERATE, 0.f); diff --git a/source/engine/sound.c b/source/engine/sound.c index e24157f..587ac04 100755 --- a/source/engine/sound.c +++ b/source/engine/sound.c @@ -8,19 +8,11 @@ #include "time.h" #include "music.h" - #include "SDL2/SDL.h" #include "mix.h" #include "dsp.h" -#define TSF_IMPLEMENTATION -#include "tsf.h" - -#define TML_IMPLEMENTATION -#include "tml.h" - - #define DR_WAV_IMPLEMENTATION #include "dr_wav.h" @@ -31,7 +23,11 @@ #include "circbuf.h" +#define TSF_IMPLEMENTATION +#include "tsf.h" +#define TML_IMPLEMENTATION +#include "tml.h" const char *audioDriver;