diff --git a/source/engine/dsp.c b/source/engine/dsp.c index 8ce06b4..9c51135 100644 --- a/source/engine/dsp.c +++ b/source/engine/dsp.c @@ -43,8 +43,6 @@ void dsp_filter_addin(struct dsp_filter filter, struct dsp_filter *in) } filter.in[filter.inputs++] = in; - - return filter; } void am_mod(struct dsp_ammod *mod, short *c, int n) @@ -52,10 +50,8 @@ void am_mod(struct dsp_ammod *mod, short *c, int n) dsp_run(mod->ina, mod->abuf, n); dsp_run(mod->inb, mod->bbuf, n); - for (int i = 0; i < n*2; i++) { + for (int i = 0; i < n*CHANNELS; i++) c[i] = (mod->abuf[i]*mod->bbuf[i])>>15; - //c[i] = mod->abuf[i]; - } } static struct wav make_wav(float freq, int sr, int ch) { @@ -334,11 +330,10 @@ struct dsp_filter lpf_make(int poles, float freq) free(ccof); - printf("LPF coefficients are:\n"); + YughInfo("LPF coefficients are:", 0); - for (int i = 0; i < new->n; i++) { - YughInfo("%f, %f\n", new->ccof[i], new->dcof[i]); - } + for (int i = 0; i < new->n; i++) + YughInfo("%f, %f", new->ccof[i], new->dcof[i]); struct dsp_filter lpf; lpf.data = new; @@ -361,9 +356,8 @@ struct dsp_filter hpf_make(int poles, float freq) for (int i = 0; i < new->n; i++) new->ccof[i] = ccof[i] * sf; - for (int i = 0; i < new->n; i++) { - printf("%f, %f\n", new->ccof[i], new->dcof[i]); - } + for (int i = 0; i < new->n; i++) + YughInfo("%f, %f", new->ccof[i], new->dcof[i]); free(ccof); @@ -449,4 +443,78 @@ void dsp_delay_filbuf(struct dsp_delay *delay, short *buf, int n) cbuf_push(&delay->buf, cache[i] / 2); buf[i] = cache[i] + cbuf_shift(&delay->buf); } +} + +/* Get decay constant for a given pole */ +/* Samples to decay 1 time constant is exp(-1/timeconstant) */ +double tau2pole(double tau) +{ + return exp(-1/(tau*SAMPLERATE)); +} + +void dsp_adsr_fillbuf(struct dsp_adsr *adsr, short *out, int n) +{ + short val; + + for (int i = 0; i < n; i++) { + if (adsr->time > adsr->rls) { + // Totally decayed + adsr->out = 0.f; + + goto fin; + } + + if (adsr->time > adsr->sus) { + // Release phase + adsr->out = adsr->rls_t * adsr->out; + + goto fin; + } + + if (adsr->time > adsr->dec) { + // Sustain phase + adsr->out = adsr->sus_pwr; + + goto fin; + } + + if (adsr->time > adsr->atk) { + // Decay phase + adsr->out = (1 - adsr->dec_t) * adsr->sus_pwr + adsr->dec_t * adsr->out; + + goto fin; + } + + // Attack phase + adsr->out = (1-adsr->atk_t) + adsr->atk_t * adsr->out; + + + + fin: + + val = SHRT_MAX * adsr->out; + out[i*CHANNELS] = out[i*CHANNELS+1] = val; + adsr->time += (double)(1000.f / SAMPLERATE); + } +} + + + +struct dsp_filter make_adsr(unsigned int atk, unsigned int dec, unsigned int sus, unsigned int rls) +{ + struct dsp_adsr *adsr = calloc(sizeof(*adsr), 1); + adsr->atk = atk; + /* decay to 3 tau */ + adsr->atk_t = tau2pole(atk / 3000.f); + + adsr->dec = dec + adsr->atk; + adsr->dec_t = tau2pole(dec / 3000.f); + + adsr->sus = sus + adsr->dec; + adsr->sus_pwr = 0.8f; + + adsr->rls = rls + adsr->sus; + adsr->rls_t = tau2pole(rls / 3000.f); + + return make_dsp(adsr, dsp_adsr_fillbuf); } \ No newline at end of file diff --git a/source/engine/dsp.h b/source/engine/dsp.h index 81850ac..79dbcee 100644 --- a/source/engine/dsp.h +++ b/source/engine/dsp.h @@ -18,7 +18,7 @@ struct dsp_filter { int inputs; struct dsp_filter *in[6]; - short cache[CHANNELS*SAMPLERATE]; + short cache[CHANNELS*BUF_FRAMES]; int dirty; }; @@ -42,6 +42,24 @@ struct dsp_filter lpf_make(int poles, float freq); struct dsp_filter bpf_make(int poles, float freq1, float freq2); struct dsp_filter npf_make(int poles, float freq1, float freq2); +/* atk, dec, sus, rls specify the time, in miliseconds, the phase begins */ +struct dsp_adsr { + unsigned int atk; + double atk_t; + unsigned int dec; + double dec_t; + unsigned int sus; + float sus_pwr; // Between 0 and 1 + unsigned int rls; + double rls_t; + + double time; /* Current time of the filter */ + float out; +}; + +void dsp_adsr_fillbuf(struct dsp_adsr *adsr, short *out, int n); +struct dsp_filter make_adsr(unsigned int atk, unsigned int dec, unsigned int sus, unsigned int rls); + struct dsp_delay { unsigned int ms_delay; struct circbuf buf; @@ -54,18 +72,23 @@ void dsp_delay_filbuf(struct dsp_delay *delay, short *buf, int n); struct dsp_ammod { struct dsp_filter ina; struct dsp_filter inb; - short abuf[BUF_FRAMES*2]; - short bbuf[BUF_FRAMES*2]; + short abuf[BUF_FRAMES*CHANNELS]; + short bbuf[BUF_FRAMES*CHANNELS]; }; struct dsp_compressor { }; +struct dsp_filter dsp_make_compressor(); +void dsp_compressor_fillbuf(struct dsp_compressor *comp, short *out, int n); + struct dsp_limiter { }; +struct dsp_filter dsp_make_limiter(); +void dsp_limiter_fillbuf(struct dsp_limiter *lim, short *out, int n); struct phasor { diff --git a/source/engine/log.c b/source/engine/log.c index 62e3ee6..1e621ed 100755 --- a/source/engine/log.c +++ b/source/engine/log.c @@ -23,8 +23,8 @@ void mYughLog(int category, int priority, int line, const char *file, const char va_end(args); char buffer[ERROR_BUFFER] = { '\0' }; - snprintf(buffer, ERROR_BUFFER, "LEVEL %d :: %s [ %s:%d ] %s\n", - priority, msgbuffer, file, line, dt); + snprintf(buffer, ERROR_BUFFER, "%s\n[ %s:%d ] %s\n", + msgbuffer, file, line, dt); printf("%s", buffer); fflush(stdout); diff --git a/source/engine/music.c b/source/engine/music.c index cc992ce..90e874e 100644 --- a/source/engine/music.c +++ b/source/engine/music.c @@ -58,7 +58,7 @@ 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/stickerbrush.mid"); + gsong.midi = tml_load_filename("sounds/littlewonder.mid"); gsong.sf = tsf_load_filename("sounds/ff7.sf2"); gsong.time = 0.f; diff --git a/source/engine/sound.c b/source/engine/sound.c index 587ac04..b917453 100755 --- a/source/engine/sound.c +++ b/source/engine/sound.c @@ -164,8 +164,7 @@ void sound_init() struct dsp_filter am_filter; - dspammod.ina = s600; - dspammod.inb = s20; + am_filter.filter = am_mod; am_filter.data = &dspammod; @@ -176,7 +175,12 @@ void sound_init() del_filter.filter = dsp_delay_filbuf; del_filter.data = &dspdel; - //first_free_bus(s600); + struct dsp_filter ad = make_adsr(50, 200, 500, 100); + + dspammod.ina = s600; + dspammod.inb = ad; + + first_free_bus(am_filter); struct dsp_filter wn; wn.filter = gen_pinknoise;