int32.positive note
int32.positive velo
int32.positive note number to stop
int32.positive startnote
bool32.rising stop it!
bool32.rising start
int32.positive note
int32.positive velo
int32.positive target
bool32.tgl kill notes on release
bool32.tgl ignoreZeroSlots
combo polyphony
combo blocksize
objref playmode
spinner loopFlag
spinner index
int8_t _note;
uint8_t _velo;
uint8_t pren;
uint8_t prev;
bool trig;
bool trigoff;
bool stop;
bool start;
uint8_t i;
uint8_t ii;
bool doit;
uint8_t target;
bool latch;
static const uint8_t LENGTHPOW = 5;
static const uint8_t POLY = attr_polyphony;
static const uint8_t BITS = 8;
static const uint8_t GAIN = 20;
uint8_t Rhold[POLY];
uint8_t Rrelease[POLY];
uint8_t Snote[POLY];
uint8_t Svelo[POLY];
uint8_t old_voice[POLY];
uint8_t old_voice_length;
pren = 0;
prev = 0;
_note = 0;
_velo = 0;
stop = 0;
start = 0;
trig = 0;
trigoff = 0;
for (i = 0; i < old_voice_length; i++)
if (!Rrelease[old_voice[i] - 1] || !old_voice[i]) {
old_voice_length--;
for (ii = i; ii < old_voice_length; ii++)
old_voice[ii] = old_voice[ii + 1];
break;
}
if ((inlet_note != pren) || (inlet_velo != prev)) {
pren = inlet_note;
prev = inlet_velo;
_velo = inlet_velo;
_note = inlet_note;
latch = (attr_playmode.array[(_note << attr_blocksize) + attr_index]) >=
attr_loopFlag;
if (_velo && ((attr_playmode.array[(_note << attr_blocksize) + attr_index]) ||
!param_ignoreZeroSlots))
trig = 1;
if (!latch && !_velo)
trigoff = 1;
}
TRIGGER : if (trig) {
// FIRST,check if this is a retrigger-event or a latched note that's being
// toggled
for (i = 0; i < POLY; i++) {
// is this note latched?
if (latch) {
if (Rhold[i] == (_note + 1)) {
target = i;
_velo = 0;
doit = 1;
}
if (Rrelease[i] == (_note + 1)) {
target = i;
doit = 1;
}
}
// is this note on release an will be retriggered?
else if (Rrelease[i] == (_note + 1)) {
target = i;
// remove this voice from the old voices list
for (ii = 0; ii < old_voice_length; ii++)
if (old_voice[ii] == (target + 1))
old_voice[ii] = 0;
doit = 1;
}
}
// if it's NOT a retrigger or a toggle-event,try to start a 'normal' voice..
if (!doit) {
for (i = 0; i < POLY; i++)
if ((!Rhold[i]) && (!Rrelease[i])) {
target = i;
doit = 1;
}
}
// if there are no empty voices available,try to STEAL a voice that's on
// release
if ((!doit && param_steal) && old_voice_length) {
// set the target to the oldest voice
target = old_voice[0] - 1;
// remove that voice from the old voices list
old_voice[0] = 0;
doit = 1;
}
}
// trigger off
if (trigoff) {
for (i = 0; i < POLY; i++)
if (Rhold[i] == (_note + 1)) {
target = i;
doit = 1;
if (!latch) {
// add the voice to the old voices list if it's NOT a loop
old_voice[old_voice_length] = target + 1;
old_voice_length++;
}
}
}
// stop
if (inlet_stop && (!stop)) {
_note = inlet_stopnote;
_velo = 0;
pren = _note;
prev = _velo;
stop = 1;
trigoff = 1;
goto TRIGGER;
}
if (!inlet_stop)
stop = 0;
// start
if (inlet_start && (!start)) {
_note = inlet_startnote;
_velo = 127;
pren = _note;
prev = _velo;
start = 1;
trig = 1;
latch = 0;
goto TRIGGER;
}
if (!inlet_start)
start = 0;
if (doit) {
doit = 0;
Snote[target] = _note + 1;
Svelo[target] = _velo;
if (_velo)
Rhold[target] = _note + 1;
else
Rhold[target] = 0;
}
outlet_note = _note;
outlet_velo = _velo;
outlet_target = target;