From afc38d91c3b6d89239350b5592e0de087445ec2b Mon Sep 17 00:00:00 2001 From: John Alanbrook Date: Tue, 12 Jul 2022 04:21:57 +0000 Subject: [PATCH] Mono & pan --- source/engine/datastream.c | 2 +- source/engine/dsp.c | 104 +++++++++++++++++++++++++++++++++++++ source/engine/dsp.h | 12 ++++- source/engine/mix.c | 6 --- source/engine/mix.h | 6 +++ source/engine/music.c | 8 ++- source/engine/music.h | 2 + source/engine/sound.c | 27 ++++++++-- source/engine/sound.h | 7 +++ 9 files changed, 161 insertions(+), 13 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 504cf80..0ea8f23 100644 --- a/source/engine/dsp.c +++ b/source/engine/dsp.c @@ -525,4 +525,108 @@ struct dsp_filter make_reverb() void dsp_reverb_fillbuf(struct dsp_reverb *r, short *out, int n) { +} + +struct dsp_filter dsp_make_compressor() +{ + struct dsp_filter filter; + struct dsp_compressor new; + + new.ratio = 4000; + new.atk = 50; + new.rls = 250; + new.target = 0.f; + new.threshold = -3.f; + new.atk_tau = tau2pole(new.atk / 3000.f); + new.rls_tau = tau2pole(new.rls / 3000.f); + + struct dsp_compressor *c = malloc(sizeof(*c)); + *c = new; + + filter.data = c; + filter.filter = dsp_compressor_fillbuf; + + return filter; +} + +void dsp_compressor_fillbuf(struct dsp_compressor *comp, short *out, int n) +{ + float val; + float db; + db = comp->target * (val - comp->threshold) / comp->ratio; + + for (int i = 0; i < n; i++) { + val = short2db(out[i*CHANNELS]); + + + if (val < comp->threshold) { + comp->target = comp->rls_tau * comp->target; + + val += db; + } else { + comp->target = (1 - comp->atk_tau) + comp->atk_tau * comp->target; // TODO: Bake in the 1 - atk_tau + + val -= db; + } + + + + // Apply same compression to both channels + out[i*CHANNELS] = out[i*CHANNELS+1] = db2short(val) * ( out[i*CHANNELS] > 0 ? 1 : -1); + } +} + +void dsp_pan(float *deg, short *out, int n) +{ + if (*deg < -100) *deg = -100.f; + else if (*deg > 100) *deg = 100.f; + + if (*deg == 0.f) return; + + float db1, db2; + float pct = *deg / 100.f; + + if (*deg > 0) { + db1 = pct2db(1 - pct); + db2 = pct2db(pct); + } else { + db1 = pct2db(1 + pct); + db2 = pct2db(-1*pct); + } + + + for (int i = 0; i < n; i++) { + double pct = *deg / 100.f; + short L = out[i*CHANNELS]; + short R = out[i*CHANNELS +1]; + + + if (*deg > 0) { + + + out[i*CHANNELS] = short_gain(L, db1); + out[i*CHANNELS+1] = (R + short_gain(L, db2)) / 2; + + continue; + } + + out[i*CHANNELS+1] = short_gain(R, db1); + out[i*CHANNELS] = short_gain(L, db1) + short_gain(R, db2); + + + + + } + + +} + +void dsp_mono(void *p, short *out, int n) +{ + for (int i = 0; i < n; i++) { + short val = (out[i*CHANNELS] + out[i*CHANNELS+1]) / 2; + + for (int j = 0; j < CHANNELS; j++) + out[i*CHANNELS+j] = val; + } } \ No newline at end of file diff --git a/source/engine/dsp.h b/source/engine/dsp.h index f388938..1b2d2bd 100644 --- a/source/engine/dsp.h +++ b/source/engine/dsp.h @@ -77,7 +77,13 @@ struct dsp_ammod { }; struct dsp_compressor { - + double ratio; + double threshold; + float target; + unsigned int atk; /* Milliseconds */ + double atk_tau; + unsigned int rls; /* MIlliseconds */ + double rls_tau; }; struct dsp_filter dsp_make_compressor(); @@ -137,4 +143,8 @@ struct dsp_reverb { struct dsp_filter make_reverb(); void dsp_reverb_fillbuf(struct dsp_reverb *r, short *out, int n); +void dsp_pan(float *deg, short *out, int n); + +void dsp_mono(void *p, short *out, int n); + #endif \ No newline at end of file diff --git a/source/engine/mix.c b/source/engine/mix.c index 17388b6..2c873cd 100644 --- a/source/engine/mix.c +++ b/source/engine/mix.c @@ -19,14 +19,10 @@ struct bus *first_free_bus(struct dsp_filter in) { } void bus_fill_buffers(short *master, int n) { - //clock_t sa = clock(); for (int i = 0; i < 256; i++) { if (bus[i].on != 1) continue; dsp_run(bus[i].in, bus[i].buf, BUF_FRAMES); } - //printf("DSP run took %f.\n", (double)(clock() - sa)/CLOCKS_PER_SEC); - - //sa = clock(); memset(master, 0, BUF_FRAMES*CHANNELS*sizeof(short)); @@ -36,6 +32,4 @@ void bus_fill_buffers(short *master, int n) { master[i] += bus[j].buf[i]; } } - - //printf("Mix took %f.\n", (double)(clock() - sa)/CLOCKS_PER_SEC); } \ No newline at end of file diff --git a/source/engine/mix.h b/source/engine/mix.h index 5e57648..6249f45 100644 --- a/source/engine/mix.h +++ b/source/engine/mix.h @@ -12,6 +12,12 @@ struct bus { short buf[BUF_FRAMES*CHANNELS]; }; +struct listener { + float x; + float y; + float z; +}; + extern short mastermix[BUF_FRAMES*CHANNELS]; struct bus *first_free_bus(struct dsp_filter in); diff --git a/source/engine/music.c b/source/engine/music.c index 90e874e..cfd37d5 100644 --- a/source/engine/music.c +++ b/source/engine/music.c @@ -11,6 +11,8 @@ struct dsp_filter cursong; struct dsp_midi_song gsong; +float music_pan = 0.f; + void dsp_midi_fillbuf(struct dsp_midi_song *song, void *out, int n) { short *o = (short*)out; @@ -54,12 +56,14 @@ void dsp_midi_fillbuf(struct dsp_midi_song *song, void *out, int n) } song->midi = midi; + + dsp_pan(&music_pan, out, n); } void play_song(const char *midi, const char *sf) { - gsong.midi = tml_load_filename("sounds/littlewonder.mid"); - gsong.sf = tsf_load_filename("sounds/ff7.sf2"); + gsong.midi = tml_load_filename("sounds/one-winged-angel.mid"); + gsong.sf = tsf_load_filename("sounds/mario.sf2"); gsong.time = 0.f; tsf_set_output(gsong.sf, TSF_STEREO_INTERLEAVED, SAMPLERATE, 0.f); diff --git a/source/engine/music.h b/source/engine/music.h index 409db42..ad02173 100644 --- a/source/engine/music.h +++ b/source/engine/music.h @@ -11,6 +11,8 @@ struct dsp_midi_song { tml_message *midi; }; +extern float music_pan; + void play_song(const char *midi, const char *sf); void dsp_midi_fillbuf(struct dsp_midi_song *song, void *out, int n); diff --git a/source/engine/sound.c b/source/engine/sound.c index 6a9ff80..e2efb0d 100755 --- a/source/engine/sound.c +++ b/source/engine/sound.c @@ -91,7 +91,7 @@ static PaStream *stream_def; void normalize_gain(struct wav *w, double lv) { - short tarmax = pow(10, lv/20.f) * SHRT_MAX; + short tarmax = db2short(lv); short max = 0; short *s = w->data; for (int i = 0; i < w->frames; i++) { @@ -180,7 +180,7 @@ void sound_init() dspammod.ina = s600; dspammod.inb = s20; - // first_free_bus(am_filter); + //first_free_bus(am_filter); struct dsp_filter wn; wn.filter = gen_pinknoise; @@ -227,7 +227,7 @@ void sound_init() - //play_song("", ""); + play_song("", ""); } void audio_open(const char *device) @@ -381,3 +381,24 @@ void soundstream_fillbuf(struct soundstream *s, short *buf, int n) } } +float short2db(short val) +{ + return 20*log10(abs((double)val) / SHRT_MAX); +} + +short db2short(float db) +{ + return pow(10, db/20.f) * SHRT_MAX; +} + +short short_gain(short val, float db) +{ + return (short)(pow(10, db/20.f) * val); +} + +float pct2db(float pct) +{ + if (pct <= 0) return -72.f; + + return 10*log2(pct); +} \ No newline at end of file diff --git a/source/engine/sound.h b/source/engine/sound.h index e4ac134..78963e7 100755 --- a/source/engine/sound.h +++ b/source/engine/sound.h @@ -67,6 +67,13 @@ void soundstream_fillbuf(struct soundstream *stream, short *buf, int n); void close_audio_device(int device); int open_device(const char *adriver); +float short2db(short val); +short db2short(float db); +float pct2db(float pct); +short short_gain(short val, float db); + void audio_init(); + + #endif