This commit is contained in:
John Alanbrook 2022-07-10 22:59:15 +00:00
parent d8640bed5a
commit c52509a9d7
5 changed files with 116 additions and 21 deletions

View file

@ -43,8 +43,6 @@ void dsp_filter_addin(struct dsp_filter filter, struct dsp_filter *in)
} }
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)
@ -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->ina, mod->abuf, n);
dsp_run(mod->inb, mod->bbuf, 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]*mod->bbuf[i])>>15;
//c[i] = mod->abuf[i];
}
} }
static struct wav make_wav(float freq, int sr, int ch) { 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); free(ccof);
printf("LPF coefficients are:\n"); YughInfo("LPF coefficients are:", 0);
for (int i = 0; i < new->n; i++) { for (int i = 0; i < new->n; i++)
YughInfo("%f, %f\n", new->ccof[i], new->dcof[i]); YughInfo("%f, %f", new->ccof[i], new->dcof[i]);
}
struct dsp_filter lpf; struct dsp_filter lpf;
lpf.data = new; lpf.data = new;
@ -361,9 +356,8 @@ struct dsp_filter hpf_make(int poles, float freq)
for (int i = 0; i < new->n; i++) for (int i = 0; i < new->n; i++)
new->ccof[i] = ccof[i] * sf; new->ccof[i] = ccof[i] * sf;
for (int i = 0; i < new->n; i++) { for (int i = 0; i < new->n; i++)
printf("%f, %f\n", new->ccof[i], new->dcof[i]); YughInfo("%f, %f", new->ccof[i], new->dcof[i]);
}
free(ccof); free(ccof);
@ -450,3 +444,77 @@ void dsp_delay_filbuf(struct dsp_delay *delay, short *buf, int n)
buf[i] = cache[i] + cbuf_shift(&delay->buf); 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);
}

View file

@ -18,7 +18,7 @@ struct dsp_filter {
int inputs; int inputs;
struct dsp_filter *in[6]; struct dsp_filter *in[6];
short cache[CHANNELS*SAMPLERATE]; short cache[CHANNELS*BUF_FRAMES];
int dirty; 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 bpf_make(int poles, float freq1, float freq2);
struct dsp_filter npf_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 { struct dsp_delay {
unsigned int ms_delay; unsigned int ms_delay;
struct circbuf buf; struct circbuf buf;
@ -54,18 +72,23 @@ void dsp_delay_filbuf(struct dsp_delay *delay, short *buf, int n);
struct dsp_ammod { struct dsp_ammod {
struct dsp_filter ina; struct dsp_filter ina;
struct dsp_filter inb; struct dsp_filter inb;
short abuf[BUF_FRAMES*2]; short abuf[BUF_FRAMES*CHANNELS];
short bbuf[BUF_FRAMES*2]; short bbuf[BUF_FRAMES*CHANNELS];
}; };
struct dsp_compressor { 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_limiter {
}; };
struct dsp_filter dsp_make_limiter();
void dsp_limiter_fillbuf(struct dsp_limiter *lim, short *out, int n);
struct phasor { struct phasor {

View file

@ -23,8 +23,8 @@ void mYughLog(int category, int priority, int line, const char *file, const char
va_end(args); va_end(args);
char buffer[ERROR_BUFFER] = { '\0' }; char buffer[ERROR_BUFFER] = { '\0' };
snprintf(buffer, ERROR_BUFFER, "LEVEL %d :: %s [ %s:%d ] %s\n", snprintf(buffer, ERROR_BUFFER, "%s\n[ %s:%d ] %s\n",
priority, msgbuffer, file, line, dt); msgbuffer, file, line, dt);
printf("%s", buffer); printf("%s", buffer);
fflush(stdout); fflush(stdout);

View file

@ -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) 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.sf = tsf_load_filename("sounds/ff7.sf2");
gsong.time = 0.f; gsong.time = 0.f;

View file

@ -164,8 +164,7 @@ void sound_init()
struct dsp_filter am_filter; struct dsp_filter am_filter;
dspammod.ina = s600;
dspammod.inb = s20;
am_filter.filter = am_mod; am_filter.filter = am_mod;
am_filter.data = &dspammod; am_filter.data = &dspammod;
@ -176,7 +175,12 @@ void sound_init()
del_filter.filter = dsp_delay_filbuf; del_filter.filter = dsp_delay_filbuf;
del_filter.data = &dspdel; 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; struct dsp_filter wn;
wn.filter = gen_pinknoise; wn.filter = gen_pinknoise;