paraphonic

4 note paraphonic midi input. DISCLAIMER: "Paraphonic" does not mean "polyphonic". If you intend to build a real polyphonic patch, use the recommended "polyphonic subpatch" approach! This object is designed to build a so-called "paraphonic" synthesizer voice. The outlets note1-4 deliver the notes of up to four pressed keys. If only one key is pressed, all note outlets send the same note unisono. Up to three additionally pressed keys are distributed over the outlets. More keys than four are simply ignored. The gate outlet is high as long as any key is pressed. The "retrigger" checkbox turns on retriggering of the gate outlet with every additional keystroke. The velocity outlet delivers the velocity of the first hit key. If you just want to make a "duophonic" voice (2 pitches) or "triphonic" (3 pitches) just connect only note1-2 or note1-3 and leave the remaining notes unconnected. Set the receiving input midi channel with the MIDIchannel attribute. Channel 0 means "listen on all channels".
Author: Peter Witzel
License: CC0
Github: cpwitz/midi/paraphonic.axo

Inlets

None

Outlets

int32 notecount

frac32.bipolar note1

frac32.bipolar note2

frac32.bipolar note3

frac32.bipolar note4

frac32.positive velocity

bool32 gate

Parameters

bool32.tgl retrigger

Attributes

spinner MIDIchannel

Declaration
#define MAX_VOX 4
int8_t pressed_note[MAX_VOX];
int32_t pitches[MAX_VOX];
int notecount = 0;
int32_t velocity = 0;
int retrigger = 0;
int doretrigger = 0;
Init
for (int i = 0; i < MAX_VOX; i++) {
  pressed_note[i] = 0;
  pitches[i] = 0;
}
Control Rate
if (doretrigger) {
  doretrigger = 0;
  outlet_gate = 0;
} else {
  outlet_gate = notecount > 0 ? 1 : 0;
}
outlet_note1 = pitches[0];
outlet_note2 = pitches[1];
outlet_note3 = pitches[2];
outlet_note4 = pitches[3];
outlet_velocity = velocity;
outlet_notecount = notecount;
retrigger = param_retrigger;
Midi Handler
int channel = (status & 0xf) + 1;
int cmd = (status & 0x70) >> 4;

if ((channel != attr_MIDIchannel && attr_MIDIchannel > 0)) {
  return;
}

// some midi devices send note on with velocity 0 instead of note off
if (cmd == 1 && data2 == 0) {
  cmd = 0;
}

if (cmd == 1) {
  // note on
  if (notecount < MAX_VOX) {
    if (notecount == 0) {
      velocity = data2 << 20;
    }
    for (int i = 0; i < MAX_VOX; i++) {
      if (pressed_note[i] == 0) {
        pressed_note[i] = data1;
        notecount++;
        break;
      }
    }
  } else {
    pressed_note[MAX_VOX - 1] = data1;
  }
  if (retrigger) {
    doretrigger = 1;
  }
} else if (cmd == 0) {
  // note off
  for (int i = 0; i < MAX_VOX; i++) {
    if (pressed_note[i] == data1) {
      pressed_note[i] = 0;
      notecount--;
      break;
    }
  }
}

if ((cmd == 1 || cmd == 0) && notecount > 0) {
  // distribute pitches
  int notei = 0;
  for (int i = 0; i < MAX_VOX; i++) {
    while (pressed_note[notei] == 0) {
      notei = (notei + 1) % MAX_VOX;
    }
    pitches[i] = (pressed_note[notei] - 64) << 21;
    notei++;
  }
}
if ((cmd == 3) && (data1 == 123)) { // all notes off message
  for (int i = 0; i < MAX_VOX; i++) {
    pressed_note[i] = 0;
  }
  notecount = 0;
}

Privacy

© 2024 Zrna Research