expon

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;
}