frac32.bipolar note number (-64..63)
int32 tonic note number (0-11)
int32 note input offset (0-128)
bool32 latch to record scale notes
frac32.bipolar note number (-64..63)
bin12 b12
int32_t _scaleVal;
int8_t _scale[12];
int8_t _nscale;
int32_t _note;
int32_t _tonic;
int32_t _offset;
int32_t _out;
int32_t _latch;
_note = 0;
_scaleVal = 0;
_nscale = 0;
_tonic = 0;
_offset = 0;
for (int i = 0; i < 12; i++) {
_scale[i] = 0;
}
_latch = inlet_latch;
if (_scaleVal != param_b12) {
// calculate new scale parameters as they changed
// optimize for evaluation
int x = 0;
for (int i = 0; i < 12; i++) {
if (param_b12 & (1 << i)) {
_scale[x++] = i;
}
}
_nscale = x;
}
if (_note != inlet_note || _offset != inlet_offset || _scaleVal != param_b12 ||
_tonic != inlet_tonic) {
_note = inlet_note;
_tonic = inlet_tonic;
_offset = inlet_offset;
_scaleVal = param_b12;
int mn = (inlet_note >> 21) + 64 - _offset;
int8_t oct = mn / _nscale;
int8_t n = mn % _nscale;
_out = ((oct * 12 + _scale[n] + _tonic) - 64) << 21;
}
outlet_note = _out;
if (_latch && (status == MIDI_NOTE_ON + attr_midichannel) && (data2)) {
int16_t note = data1 % 12;
int16_t mask = 1 << note;
int16_t nval = _scaleVal ^ mask;
PExParameterChange(&parent->PExch[PARAM_INDEX_attr_legal_name_b12], nval,
0xFFFD);
}