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. Mass
determines 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.
SKFLT inertia;
SKFLT mass;
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
.
typedef struct gestvm_weight gestvm_weight;
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
.
size_t gestvm_weight_sizeof(void);
size_t gestvm_weight_sizeof(void)
{
return sizeof(gestvm_weight);
}
void gestvm_weight_init(gestvm_weight *gw, gestvm *gvm, int sr);
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.
void gestvm_weight_amppos(gestvm_weight *gw, SKFLT amp);
void gestvm_weight_ampneg(gestvm_weight *gw, SKFLT amp);
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
.
SKFLT gestvm_weight_tick(gestvm_weight *gw);
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 void uxn_mass(gestvm *gvm, unsigned char val);
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 void uxn_inertia(gestvm *gvm, unsigned char val);
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