13. Weight

13.1. Overview

This is an optional signal generator used to influence parameters in the external conductor signal. This is known as temporal weight.

13.2. Weight and Mass

Weight has two parameters: mass, and inertia. Massdetermines how much to warp the tempo. Postive values indicate a faster tempo. Negative values indicate a slower tempo. Zero is neutral. The inertia value determines the overal responsiveness to the temporal weight changes.

Ranges are TBD. In Gest, mass had a range of (-120,120), and could be scaled to some arbirtrary amount (120 was chosen for it's division properties). Inertia was usually in tau units for a smoothing filter.

<<gestvm>>=
SKFLT inertia;
SKFLT mass;
<<init>>=
gvm->mass = 0;
gvm->inertia = 0;

13.3. Weight DSP algorithm

The weight signal can be implemented as a control signal with adjustable range, put through a 1-pole smoothing filter.

This will be called gestvm_weight.

<<typedefs>>=
typedef struct gestvm_weight gestvm_weight;
<<structs>>=
struct gestvm_weight {
    gestvm *gvm;
    int sr;
    SKFLT a;
    SKFLT inertia;
    SKFLT prev;
    SKFLT scale;
    SKFLT ampneg;
    SKFLT amppos;
};

Since it is used opaquely, the size is returned via gestvm_weight_sizeof.

<<funcdefs>>=
size_t gestvm_weight_sizeof(void);
<<funcs>>=
size_t gestvm_weight_sizeof(void)
{
    return sizeof(gestvm_weight);
}
<<funcdefs>>=
void gestvm_weight_init(gestvm_weight *gw, gestvm *gvm, int sr);
<<funcs>>=
void gestvm_weight_init(gestvm_weight *gw, gestvm *gvm, int sr)
{
    gw->sr = sr;
    gw->gvm = gvm;
    gw->prev = 0;
    gw->a = 0.0;
    gw->scale = 1.0 / 120;
    gestvm_weight_amppos(gw, 20);
    gestvm_weight_ampneg(gw, 20);
}

Weight will scale differently depending on if it is negative or postive. These are set with gestvm_weight_amppos and gestvm_weight_ampneg.

NOTE: a negative amp is stored as a positive value, but will end up being negative.

<<funcdefs>>=
void gestvm_weight_amppos(gestvm_weight *gw, SKFLT amp);
void gestvm_weight_ampneg(gestvm_weight *gw, SKFLT amp);
<<funcs>>=
void gestvm_weight_amppos(gestvm_weight *gw, SKFLT amp)
{
    gw->amppos = amp;
}

void gestvm_weight_ampneg(gestvm_weight *gw, SKFLT amp)
{
    gw->ampneg = amp;
}

A sample of audio is computed with gestvm_weight_tick.

<<funcdefs>>=
SKFLT gestvm_weight_tick(gestvm_weight *gw);
<<funcs>>=
SKFLT gestvm_weight_tick(gestvm_weight *gw)
{
    SKFLT i;
    SKFLT mass;
    gestvm *gvm;
    SKFLT out;

    gvm = gw->gvm;

    mass = gvm->mass;
    i = gvm->inertia;

    if (i != gw->inertia) {
        gw->inertia = i;
        if (i == 0) {
            gw->a = 0;
            gw->prev = 0;
        } else {
            gw->a = exp(-1.0 / (gw->sr * i));
        }
    }


    out =
        (1 - gw->a) * mass * gw->scale +
        gw->a * gw->prev;

    if (out > 1) out = 1;
    if (out < -1) out = -1;

    gw->prev = out;

    if (out >= 0) {
        out *= gw->amppos;
    } else {
        out *= gw->ampneg;
    }

    return out;
}

13.4. Setting mass/inertia from Uxn

Since Uxn can only communicate with 8 bit values, some scaling has to be done to make meaningful weight values.

For weight, the range of 0x00-0xff will represent -120,120.

A value of 0x7f will be a neutral (0) value.

<<static_funcdefs>>=
static void uxn_mass(gestvm *gvm, unsigned char val);
<<funcs>>=
static void uxn_mass(gestvm *gvm, unsigned char val)
{
    SKFLT m;
    val &= 0xFF;

    m = (SKFLT)(val - 0x7F) / 0x7F;
    m *= 120.0;

    if (m < -120) m = -120;
    if (m > 120) m = 120;

    gvm->mass = m;
}
<<static_funcdefs>>=
static void uxn_inertia(gestvm *gvm, unsigned char val);
<<funcs>>=
static void uxn_inertia(gestvm *gvm, unsigned char val)
{
    SKFLT i;
    val &= 0xFF;

    i = (SKFLT)val / 0xFF;
    i *= 0.3;

    gvm->inertia = i;
}



prev | home | next