adsr
This commit is contained in:
parent
d8640bed5a
commit
c52509a9d7
|
@ -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);
|
||||||
|
|
||||||
|
@ -449,4 +443,78 @@ void dsp_delay_filbuf(struct dsp_delay *delay, short *buf, int n)
|
||||||
cbuf_push(&delay->buf, cache[i] / 2);
|
cbuf_push(&delay->buf, cache[i] / 2);
|
||||||
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);
|
||||||
}
|
}
|
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue