expon
Overview
A (re)triggerable exponential line generator. Go from A to B in a exponential swell over some duration in seconds. When it reaches B, hold indefinitely until retriggered.
Note that values cannot be exactly 0.
Tangled files.
expon.h
and expon.c
. SK_EXPON_PRIV
exposes the
sk_expon
struct.
<<expon.h>>=
#ifndef SK_EXPON_H
#define SK_EXPON_H
#ifndef SKFLT
#define SKFLT float
#endif
<<typedefs>>
<<funcdefs>>
#ifdef SK_EXPON_PRIV
<<structs>>
#endif
#endif
<<expon.c>>=
#include <math.h>
#define SK_EXPON_PRIV
#include "expon.h"
<<static_funcdefs>>
<<funcs>>
Initialization
The expon state is managed in a struct called sk_expon
,
and initialized with sk_expon_init
. The sampling rate
sr
must be provided.
<<typedefs>>=
typedef struct sk_expon sk_expon;
<<structs>>=
struct sk_expon {
SKFLT a, dur, b;
SKFLT val, incr;
unsigned long sdur, stime;
int init;
int sr;
};
<<funcdefs>>=
void sk_expon_init(sk_expon *e, int sr);
<<funcs>>=
void sk_expon_init(sk_expon *e, int sr)
{
sk_expon_a(e, 0.000001);
sk_expon_b(e, 1);
sk_expon_dur(e, 1);
e->sr = sr;
e->init = 1;
expon_reinit(e);
}
Setting Parameters
A and B
Go from value A to value B.
<<funcdefs>>=
void sk_expon_a(sk_expon *e, SKFLT val);
void sk_expon_b(sk_expon *e, SKFLT val);
<<funcs>>=
void sk_expon_a(sk_expon *e, SKFLT val)
{
if (val != 0) e->a = val;
}
void sk_expon_b(sk_expon *e, SKFLT val)
{
if (val != 0) e->b = val;
}
Duration
Set the duration of the segment with sk_expon_dur
.
This is in units of seconds.
<<funcdefs>>=
void sk_expon_dur(sk_expon *e, SKFLT dur);
<<funcs>>=
void sk_expon_dur(sk_expon *e, SKFLT dur)
{
e->dur = dur;
}
Calculating Multipler
The function expon_reinit
will recalculate the multiplier
used to compute the exponential line.
<<static_funcdefs>>=
static void expon_reinit(sk_expon *e);
<<funcs>>=
static void expon_reinit(sk_expon *e)
{
SKFLT onedsr;
e->stime = 0;
e->sdur = e->dur * e->sr;
onedsr = 1.0 / e->sr;
if ((e->a * e->b) > 0.0) {
e->incr = pow((SKFLT)(e->b / e->a), onedsr / e->dur);
} else {
e->incr = 1;
e->val = e->a;
}
e->val = e->a;
}
Computing a Sample
<<funcdefs>>=
SKFLT sk_expon_tick(sk_expon *e, SKFLT trig);
<<funcs>>=
SKFLT sk_expon_tick(sk_expon *e, SKFLT trig)
{
SKFLT out;
out = 0;
if (trig != 0) {
expon_reinit(e);
e->init = 0;
}
if (e->init) {
out = 0;
}
if (e->stime < e->sdur) {
SKFLT val = e->val;
e->val *= e->incr;
e->stime++;
out = val;
} else {
out = e->b;
}
return out;
}