MIDI music and soundfonts work

This commit is contained in:
John Alanbrook 2022-07-10 18:04:24 +00:00
parent e57bf668c2
commit d8640bed5a
6 changed files with 63 additions and 45 deletions

View file

@ -91,7 +91,7 @@ void ds_openvideo(struct datastream *ds, const char *video, const char *adriver)
fir->in = astream_filter; 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_video_decode_callback(ds->plm, render_frame, ds);
plm_set_audio_decode_callback(ds->plm, render_audio, ds); plm_set_audio_decode_callback(ds->plm, render_audio, ds);

View file

@ -17,7 +17,11 @@ struct dsp_filter make_dsp(void *data, void (*in)(void *data, short *out, int n)
new.data = data; new.data = data;
new.filter = in; new.filter = in;
if (filters.len == 0) return new;
if (filters.len == 0) {
}
} }
void dsp_run(struct dsp_filter filter, short *out, int n) { 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; return;
for (int i = 0; i < filter.inputs; i++) 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); 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) { if (filter.inputs > 5) {
YughError("Too many inputs in filter.", 0); YughError("Too many inputs in filter.", 0);
} }
filter.in[filter.inputs++] = in; filter.in[filter.inputs++] = in;
return filter;
} }
void am_mod(struct dsp_ammod *mod, short *c, int n) void am_mod(struct dsp_ammod *mod, short *c, int n)

View file

@ -32,7 +32,7 @@ struct dsp_fir {
struct dsp_filter in; 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); struct dsp_filter lp_fir_make(float freq);

View file

@ -43,6 +43,7 @@
#include "limits.h" #include "limits.h"
#include "iir.h" #include "iir.h"
#include "dsp.h" #include "dsp.h"
#include "log.h"
/********************************************************************** /**********************************************************************
binomial_mult - multiplies a series of binomials together and returns 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 */ /* Biquad filters */
struct dsp_iir biquad_iir() struct dsp_iir make_iir(int cofs, int order)
{ {
struct dsp_iir new; struct dsp_iir new;
new.dcof = malloc(sizeof(float) * 3); new.n = cofs;
new.ccof = malloc(sizeof(float) * 3); new.order = order;
new.dx = malloc(sizeof(float) * 3);
new.dy = malloc(sizeof(float) * 3); new.dcof = calloc(sizeof(float), cofs *order);
new.n = 3; new.ccof = calloc(sizeof(float), cofs *order);
new.dx = calloc(sizeof(float), cofs *order);
new.dy = calloc(sizeof(float), cofs *order);
return new; return new;
} }
struct dsp_iir biquad_iir()
{
return make_iir(3, 1);
}
void biquad_iir_fill(struct dsp_iir bq, double *a, double *b) void biquad_iir_fill(struct dsp_iir bq, double *a, double *b)
{ {
bq.ccof[0] = (b[0] / a[0]); 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 w0 = tan(M_PI * fcf);
double k[2]; double k[2];
k[0] = p * w0; 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[0] = k[1] / (1 + k[0] + k[1]);
a[1] = 2 * a[0]; 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 a = tan(M_PI * fcf);
double a2 = pow2(a); double a2 = pow(a, 2);
double u = log((1.f + sqrt(1.f + pow2(e)))/e); double u = log((1.f + sqrt(1.f + pow(e, 2)))/e);
double su = sinh(u/new.order); double su = sinh(u/new.order);
double cu = cosh(u/new.order); double cu = cosh(u/new.order);
double b, c, s; 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; 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 = 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; s = a2*c + 2.f*a*b + 1.f;
double A = a2/(4.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); struct dsp_iir new = che_lp(order, fcf, e);
double a = tan(M_PI * fcf); double a = tan(M_PI * fcf);
double a2 = pow2(a); double a2 = pow(a, 2);
double u = log((1.f + sqrt(1.f + pow2(e)))/e); double u = log((1.f + sqrt(1.f + pow(e, 2)))/e);
double su = sinh(u/new.order); double su = sinh(u/new.order);
double cu = cosh(u/new.order); double cu = cosh(u/new.order);
double b, c, s; 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; 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 = 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; s = a2*c + 2.f*a*b + 1.f;
double A = 1.f/(4.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); struct dsp_iir new = p2_iir_order(order);
double a = cos(M_PI*(fcf1+fcf2)/2) / cos(M_PI*(fcf2-fcf1)/s); 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 b = tan(M_PI*(fcf2-fcf1)/s);
double b2 = pow2(b); double b2 = pow(b, 2);
double u = log((1.f+sqrt(1.f+pow2(e)))/e); double u = log((1.f+sqrt(1.f+pow(e, 2)))/e);
double su = sinh(2.f*u/new.order); double su = sinh(2.f*u/new.order);
double cu = cosh(2.f*u/new.order); double cu = cosh(2.f*u/new.order);
double A = b2/(4.f); 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) { for (int i = 0; i < new.order; ++i) {
r = sin(M_PI*(2.f*i+1.f)/new.order)*su; 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 = 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; s = b2*c + 2.f*b*r + 1.f;
new.ccof[0*i] = ep * 1.f/A; 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; 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) { 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); 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; int n = order / 4;
double ep = 2.f/e;
struct dsp_iir new = p2_iir_order(order); struct dsp_iir new = p2_iir_order(order);
double a = cos(M_PI*(fcf1+fcf2)/2) / cos(M_PI*(fcf2-fcf1)/s); 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 b = tan(M_PI*(fcf2-fcf1)/s);
double b2 = pow2(b); double b2 = pow(b, 2);
double u = log((1.f+sqrt(1.f+pow2(e)))/e); double u = log((1.f+sqrt(1.f+pow(e, 2)))/e);
double su = sinh(2.f*u/n); double su = sinh(2.f*u/n);
double cu = cosh(2.f*u/n); double cu = cosh(2.f*u/n);
double A = b2/(4.f*s); double A = b2/(4.f*s);
double r, c, s; double r, c;
for (int i = 0; i < new.order; ++i) { for (int i = 0; i < new.order; ++i) {
r = sin(M_PI*(2.f*i+1.f)/new.order)*su; 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 = 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; s = b2*c + 2.f*b*r + 1.f;
new.ccof[0*i] = ep * 1.f/A; new.ccof[0*i] = ep * 1.f/A;
new.ccof[1*i] = ep * -2.f/A; new.ccof[1*i] = ep * -2.f/A;
new.ccof[2*i] = ep * 1.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[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[2*i] = ep * 2.f*(b2-2.f*a2*c-c)/s;
new.dcof[3*i] = ep * 4.f*a*(c-b*r)/s; new.dcof[3*i] = ep * 4.f*a*(c-b*r)/s;

View file

@ -6,7 +6,7 @@
#include "mix.h" #include "mix.h"
#include "sound.h" #include "sound.h"
#define TSF_BLOCK 64 #define TSF_BLOCK 32
struct dsp_filter cursong; struct dsp_filter cursong;
struct dsp_midi_song gsong; 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; short *o = (short*)out;
tml_message *midi = song->midi; tml_message *midi = song->midi;
for (int i = TSF_BLOCK; n; n -= i, o += n*CHANNELS) { for (int i = 0; i < n; i += TSF_BLOCK) {
if (i > n) i = n;
while (midi && song->time >= midi->time) {
for (song->time += i * (1000.f / SAMPLERATE); midi && song->time >= midi->time; midi = midi->next) {
switch (midi->type) switch (midi->type)
{ {
case TML_PROGRAM_CHANGE: 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); tsf_channel_midi_control(song->sf, midi->channel, midi->control, midi->control_value);
break; 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; 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) void play_song(const char *midi, const char *sf)
{ {
gsong.midi = tml_load_filename("sounds/one-winged-angel.mid"); gsong.midi = tml_load_filename("sounds/stickerbrush.mid");
gsong.sf = tsf_load_filename("sounds/mario.sf2"); gsong.sf = tsf_load_filename("sounds/ff7.sf2");
gsong.time = 0.f; gsong.time = 0.f;
tsf_set_output(gsong.sf, TSF_STEREO_INTERLEAVED, SAMPLERATE, 0.f); tsf_set_output(gsong.sf, TSF_STEREO_INTERLEAVED, SAMPLERATE, 0.f);

View file

@ -8,19 +8,11 @@
#include "time.h" #include "time.h"
#include "music.h" #include "music.h"
#include "SDL2/SDL.h" #include "SDL2/SDL.h"
#include "mix.h" #include "mix.h"
#include "dsp.h" #include "dsp.h"
#define TSF_IMPLEMENTATION
#include "tsf.h"
#define TML_IMPLEMENTATION
#include "tml.h"
#define DR_WAV_IMPLEMENTATION #define DR_WAV_IMPLEMENTATION
#include "dr_wav.h" #include "dr_wav.h"
@ -31,7 +23,11 @@
#include "circbuf.h" #include "circbuf.h"
#define TSF_IMPLEMENTATION
#include "tsf.h"
#define TML_IMPLEMENTATION
#include "tml.h"
const char *audioDriver; const char *audioDriver;