diff --git a/Makefile b/Makefile index f7934737..2b778bea 100755 --- a/Makefile +++ b/Makefile @@ -79,7 +79,7 @@ COMPINCLUDE = $(edirs) $(eddirs) $(pindirs) $(bsdirs) -WARNING_FLAGS = #-Wall -Wwrite-strings -Wunsupported -Wall -Wextra -Wwrite-strings -Wno-unused-parameter -Wno-unused-function -Wno-missing-braces -Wno-incompatible-function-pointer-types -Wno-gnu-statement-expression -Wno-complex-component-init -pedantic +WARNING_FLAGS = -Wno #-Wall -Wwrite-strings -Wunsupported -Wall -Wextra -Wwrite-strings -Wno-unused-parameter -Wno-unused-function -Wno-missing-braces -Wno-incompatible-function-pointer-types -Wno-gnu-statement-expression -Wno-complex-component-init -pedantic diff --git a/source/engine/datastream.c b/source/engine/datastream.c index c4b94cd4..95beabc6 100755 --- a/source/engine/datastream.c +++ b/source/engine/datastream.c @@ -11,6 +11,7 @@ #include #include "mix.h" #include "limits.h" +#include "iir.h" struct mShader *vid_shader; @@ -90,7 +91,7 @@ void ds_openvideo(struct datastream *ds, const char *video, const char *adriver) fir->in = astream_filter; */ - first_free_bus(hpf); + 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 bfeeb255..76259ac3 100644 --- a/source/engine/dsp.c +++ b/source/engine/dsp.c @@ -5,19 +5,42 @@ #include "math.h" #include "stdlib.h" #include "iir.h" +#include "log.h" +#include "vec.h" #define PI 3.14159265 +struct vec filters; + struct dsp_filter make_dsp(void *data, void (*in)(void *data, short *out, int n)) { struct dsp_filter new; new.data = data; new.filter = in; + + if (filters.len == 0) } void dsp_run(struct dsp_filter filter, short *out, int n) { + filter.dirty = 1; // Always on for testing + + if (!filter.dirty) + return; + + for (int i = 0; i < filter.inputs; i++) + 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) +{ + if (filter.inputs > 5) { + YughError("Too many inputs in filter.", 0); + } + + filter.in[filter.inputs++] = in; +} + void am_mod(struct dsp_ammod *mod, short *c, int n) { dsp_run(mod->ina, mod->abuf, n); @@ -133,9 +156,8 @@ void dsp_filter(short *in, short *out, int samples, struct dsp_delay *d) void dsp_rectify(short *in, short *out, int n) { - for (int i = 0; i < n; i++) { + for (int i = 0; i < n; i++) out[i] = abs(in[i]); - } } struct phasor phasor_make(unsigned int sr, float freq) @@ -245,25 +267,27 @@ void gen_pinknoise(void *data, short *out, int n) */ } -short iir_filter(struct dsp_iir *iir, short val) +short iir_filter(struct dsp_iir *miir, short val) { + struct dsp_iir iir = *miir; + float a = 0.f; - iir->dx[0] = (float)val/SHRT_MAX; - for (int i = 0; i < iir->n; i++) - a += iir->ccof[i] * iir->dx[i]; + iir.dx[0] = (float)val/SHRT_MAX; + for (int i = 0; i < iir.n; i++) + a += iir.ccof[i] * iir.dx[i]; - for (int i = iir->n-1; i > 0; i--) - iir->dx[i] = iir->dx[i-1]; + for (int i = iir.n-1; i > 0; i--) + iir.dx[i] = iir.dx[i-1]; - for (int i =0; i < iir->n; i++) - a -= iir->dcof[i] * iir->dy[i]; + for (int i =0; i < iir.n; i++) + a -= iir.dcof[i] * iir.dy[i]; - iir->dy[0] = a; + iir.dy[0] = a; - for (int i = iir->n-1; i > 0; i--) - iir->dy[i] = iir->dy[i-1]; + for (int i = iir.n-1; i > 0; i--) + iir.dy[i] = iir.dy[i-1]; @@ -283,46 +307,31 @@ void dsp_iir_fillbuf(struct dsp_iir *iir, short *out, int n) } } -struct dsp_iir new_iir(int poles, float freq) -{ - struct dsp_iir new; - new.poles = poles; - new.freq = freq; - new.n = new.poles+1; - new.ccof = malloc(new.n*sizeof(float)); - new.dcof = malloc(new.n*sizeof(float)); - new.dy = malloc(new.n*sizeof(float)); - new.dx = malloc(new.n*sizeof(float)); - return new; -} - struct dsp_filter lpf_make(int poles, float freq) { struct dsp_iir *new = malloc(sizeof(*new)); - *new = new_iir(poles, freq); + (*new) = make_iir(3, 1); double fcf = new->freq*2/SAMPLERATE; + double sf = sf_bwlp(poles, fcf); printf("Making LPF filter, fcf: %f, coeffs: %i, scale %1.15lf\n", fcf, new->n, sf); - int *ccof = ccof_bwlp(new->poles); - double *dcof = dcof_bwlp(new->poles, fcf); + int *ccof = ccof_bwlp(new->n); + new->dcof = dcof_bwlp(new->n, fcf); - for (int i = 0; i < new->n; i++) { - new->ccof[i] = ccof[i] * sf; - new->dcof[i] = dcof[i]; - } + for (int i = 0; i < new->n; i++) + new->ccof[i] = (float)ccof[i] * sf; new->dcof[0] = 0.f; free(ccof); - free(dcof); printf("LPF coefficients are:\n"); for (int i = 0; i < new->n; i++) { - printf("%f, %f\n", new->ccof[i], new->dcof[i]); + YughInfo("%f, %f\n", new->ccof[i], new->dcof[i]); } struct dsp_filter lpf; @@ -335,25 +344,22 @@ struct dsp_filter lpf_make(int poles, float freq) struct dsp_filter hpf_make(int poles, float freq) { struct dsp_iir *new = malloc(sizeof(*new)); - *new = new_iir(poles, freq); + *new = make_iir(3, 1); double fcf = new->freq*2/SAMPLERATE; - double sf = sf_bwhp(new->poles, fcf); + double sf = sf_bwhp(new->n, fcf); - int *ccof = ccof_bwhp(new->poles); - double *dcof = dcof_bwhp(new->poles, fcf); + int *ccof = ccof_bwhp(new->n); + new->dcof = dcof_bwhp(new->n, fcf); - for (int i = 0; i < new->n; i++) { + for (int i = 0; i < new->n; i++) new->ccof[i] = ccof[i] * sf; - new->dcof[i] = dcof[i]; - } for (int i = 0; i < new->n; i++) { printf("%f, %f\n", new->ccof[i], new->dcof[i]); } free(ccof); - free(dcof); struct dsp_filter hpf; hpf.data = new; diff --git a/source/engine/dsp.h b/source/engine/dsp.h index 7c83fbeb..70787790 100644 --- a/source/engine/dsp.h +++ b/source/engine/dsp.h @@ -14,19 +14,12 @@ void dsp_rectify(short *in, short *out, int n); struct dsp_filter { void (*filter)(void *data, short *out, int samples); void *data; -}; -struct dsp_iir { - float freq; - int poles; - int n; // Amount of constants - int order; // How many times it's applied - float *ccof; - float *dcof; - float *dx; - float *dy; + int inputs; + struct dsp_filter *in[6]; - struct dsp_filter in; + short cache[CHANNELS*SAMPLERATE]; + int dirty; }; struct dsp_fir { @@ -39,6 +32,8 @@ struct dsp_fir { struct dsp_filter in; }; +void dsp_filter_addin(struct dsp_filter filter, struct dsp_filter in); + struct dsp_filter lp_fir_make(float freq); void dsp_iir_fillbuf(struct dsp_iir *iir, short *out, int n); diff --git a/source/engine/iir.c b/source/engine/iir.c index 834e0b51..f49e7a87 100644 --- a/source/engine/iir.c +++ b/source/engine/iir.c @@ -43,6 +43,35 @@ #include "limits.h" #include "iir.h" #include "dsp.h" +#include "log.h" + +struct dsp_iir make_iir(int cofs, int order) +{ + struct dsp_iir new; + 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); + new.order = order; + new.n = cofs; + + return new; +} + + +struct dsp_iir biquad_iir() +{ + struct dsp_iir new = make_iir(3, 1); + return new; +} + +struct dsp_iir p2_iir_order(int order) +{ + struct dsp_iir new = make_iir(3, order); + new.order = order; + + return new; +} /********************************************************************** binomial_mult - multiplies a series of binomials together and returns @@ -641,26 +670,105 @@ float *fir_bpf(int n, double fcf1, double fcf2) +struct dsp_iir sp_lp(double fcf) +{ + struct dsp_iir new = make_iir(2, 1); + double x = exp(-2*M_PI*fcf); + new.ccof[0] = 1 - x; + new.ccof[1] = 0.f; + new.dcof[0] = 0.f; + new.dcof[1] = x; + + return new; +} + +struct dsp_iir sp_hp(double fcf) +{ + struct dsp_iir new = make_iir(2, 1); + double x = exp(-2*M_PI*fcf); + + new.ccof[0] = (1 + x)/2; + new.ccof[1] = -new.ccof[0]; + + new.dcof[0] = 0.f; + new.dcof[1] = x; + + return new; +} + +/* http://www.dspguide.com/ch19/3.htm */ +struct dsp_iir sp_bp(double fcf, double bw) +{ + double R = 1 - 3*bw; + double K = (1 - 2*R*cos(2*M_PI*fcf)+pow(R, 2)) / (2 - 2*cos(2*M_PI*fcf)); + + struct dsp_iir new = make_iir(3, 1); + + new.ccof[0] = 1-K; + new.ccof[1] = 2*(K-R)*cos(2*M_PI*fcf); + new.ccof[2] = pow(R, 2) - K; + + new.dcof[0] = 0.f; + new.dcof[1] = 2*R*cos(2*M_PI*fcf); + new.dcof[2] = -1 * pow(R, 2); + + return new; +} + +struct dsp_iir sp_notch(double fcf, double bw) +{ + double R = 1 - 3*bw; + double K = (1 - 2*R*cos(2*M_PI*fcf)+pow(R, 2)) / (2 - 2*cos(2*M_PI*fcf)); + + struct dsp_iir new = make_iir(3, 1); + + new.ccof[0] = K; + new.ccof[1] = -2*K*cos(2*M_PI*fcf); + new.ccof[2] = K; + + new.dcof[0] = 0.f; + new.dcof[1] = 2*R*cos(2*M_PI*fcf); + new.dcof[2] = -1 * pow(R, 2); + + return new; +} + +double chevy_pct_to_e(double pct) +{ + if (pct > 0.292 || pct < 0) { + YughWarn("Gave a percentage out of range. Should be between 0.0 and 0.292 to get a proper value. Gave %f.", pct); + pct = pct > 0.292 ? 0.292 : 0.f; + } + + double e = pow(1/(1-pct), 2) - 1; + + return e; +} + +/* Four stage single pole low pass, similar to gauss */ +/* http://www.dspguide.com/ch19/2.htm */ +struct dsp_iir sp_lp_gauss(double fcf) +{ + struct dsp_iir new = make_iir(5, 1); + double x = exp(-14.445*fcf); + + new.ccof[0] = pow((1 - x), 4); + + new.dcof[0] = 0.f; + new.dcof[1] = 4*x; + new.dcof[2] = -6 * pow(x, 2); + new.dcof[3] = 4 * pow(x, 3); + new.dcof[4] = -1 * pow(x,4); + + return new; +} /* Biquad filters */ - -struct dsp_iir biquad_iir() -{ - 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.poles = 2; - return new; -} - void biquad_iir_fill(struct dsp_iir bq, double *a, double *b) { bq.ccof[0] = (b[0] / a[0]); @@ -843,7 +951,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]; @@ -913,19 +1021,7 @@ struct dsp_iir p2_beshp(double fcf) return new; } -struct dsp_iir p2_iir_order(int order) -{ - struct dsp_iir new; - new.n = 3; - new.order = order; - new.ccof = calloc(sizeof(float), 3 * order); - new.dcof = calloc(sizeof(float), 3 * order); - new.dx = calloc(sizeof(float), 3 * order); - new.dy = calloc(sizeof(float), 3 * order); - - return new; -} short p2_filter(struct dsp_iir iir, short val) { @@ -963,8 +1059,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; @@ -974,7 +1070,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); @@ -995,8 +1091,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; @@ -1006,7 +1102,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); @@ -1020,31 +1116,32 @@ struct dsp_iir che_hp(int order, double fcf, double e) return new; } -struct dsp_iir che_bp(int order, double fcf1, double fcf2, double e) +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 = make_iir(5, order); - double a = cos(M_PI*(fcf1+fcf2)/2) / cos(M_PI*(fcf2-fcf1)); - double a2 = pow2(a); - double b = tan(M_PI*(fcf2-fcf1)); - double b2 = pow2(b); - double u = log((1.f+sqrt(1.f+pow2(e)))/e); + double a = cos(M_PI*(fcf1+fcf2)/s) / cos(M_PI*(fcf2-fcf1)/s); + double a2 = pow(a, 2); + double b = tan(M_PI*(fcf2-fcf1)/s); + 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); - double r, c, s; + double r, c; + double ep = 2.f/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; 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*(1.f+b*r)/s; new.dcof[2*i] = ep * 2.f*(b2*c-2.f*a2-1.f)/s; new.dcof[3*i] = ep * 4.f*a*(1.f-b*r)/s; @@ -1054,31 +1151,32 @@ struct dsp_iir che_bp(int order, 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) { - struct dsp_iir new = p2_iir_order(order); + struct dsp_iir new = make_iir(5, order); - double a = cos(M_PI*(fcf1+fcf2)/2) / cos(M_PI*(fcf2-fcf1)); - double a2 = pow2(a); - double b = tan(M_PI*(fcf2-fcf1)); - double b2 = pow2(b); - double u = log((1.f+sqrt(1.f+pow2(e)))/e); - double su = sinh(2.f*u/n); - double cu = cosh(2.f*u/n); + double a = cos(M_PI*(fcf1+fcf2)/s) / cos(M_PI*(fcf2-fcf1)/s); + double a2 = pow(a, 2); + double b = tan(M_PI*(fcf2-fcf1)/s); + double b2 = pow(b, 2); + double u = log((1.f+sqrt(1.f+pow(e, 2)))/e); + double su = sinh(2.f*u/new.n); + double cu = cosh(2.f*u/new.n); double A = b2/(4.f*s); - double r, c, s; + double r, c; + double ep = 2.f/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)/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/iir.h b/source/engine/iir.h index 95a3aff4..c30bdbd5 100644 --- a/source/engine/iir.h +++ b/source/engine/iir.h @@ -1,6 +1,22 @@ #ifndef IIR_H #define IIR_H +#include "dsp.h" + +struct dsp_iir { + float freq; + int n; // Amount of constants + int order; // How many times it's applied + float *ccof; + float *dcof; + float *dx; + float *dy; + + struct dsp_filter in; +}; + +struct dsp_iir make_iir(int cofs, int order); + double *binomial_mult( int n, double *p ); double *trinomial_mult( int n, double *b, double *c ); @@ -23,6 +39,11 @@ float *fir_lp(int n, double fcf); float *fir_hp(int n, double fcf); float *fir_bpf(int n, double fcf1, double fcf2); +struct dsp_iir sp_lp(double fcf); +struct dsp_iir sp_hp(double fcf); + +double chevy_pct_to_e(double pct); + struct dsp_iir bqlp_dcof(double fcf, float Q); struct dsp_iir bqhp_dcof(double fcf, float Q); struct dsp_iir bqbpq_dcof(double fcf, float Q); @@ -42,7 +63,7 @@ struct dsp_iir p2_beshp(double fcf); struct dsp_iir che_lp(int order, double fcf, double e); struct dsp_iir che_hp(int order, double fcf, double e); -struct dsp_iir che_bp(int order, double fcf1, double fcf2, double e); -struct dsp_iir che_notch(int order, double fcf1, double fcf2, double e); +struct dsp_iir che_bp(int order, double s, double fcf1, double fcf2, double e); +struct dsp_iir che_notch(int order, double s, double fcf1, double fcf2, double e); #endif diff --git a/source/engine/sound.c b/source/engine/sound.c index 8a3a4869..5e87bd00 100755 --- a/source/engine/sound.c +++ b/source/engine/sound.c @@ -16,6 +16,9 @@ #define TSF_IMPLEMENTATION #include "tsf.h" +#define TML_IMPLEMENTATION +#include "tml.h" + #define DR_WAV_IMPLEMENTATION #include "dr_wav.h" @@ -222,6 +225,9 @@ void sound_init() + + tsf *tsf_load_filename("sounds/ff7.sf2"); + tml_message *tml_load_filename("sounds/one_winged_angel.mid"); } void audio_open(const char *device)