MIDI unhappiness


#1

hi there,
I got a bit lost trying understand the way axo handles MIDI in an attempt to
find out how many notes are currently 'on hold'...

see the attached patch.
midi madness.axp (1.7 KB)

seems like 'data1' provides information about the last key active in any way,while
'data2' provides velocity information,regardless whether it's attack-velocity or release-velocity,am I right?

...with a device NOT sending release-velocity like the 'novation launchpad' , I get pretty good
results,but some annoying hanging notes when I play fast...
...with a 'korg mpk- mini' I don't get ANYWHERE, since it sends release-velocity...

what would be so good if 'data2' would provide attack-velocity and in addition,'data3' would provide release-velocity..


#2

no this is not how its works really,
the midi handler simply is passed the midi message (2 or 3 bytes) , 'raw'

the first byte, has the message type (and midi channel) and the data bytes are dependent on the message types;

this is detailed in the midi spec:
https://www.midi.org/specifications/item/table-1-summary-of-midi-message

the nice thing about using it this way, is its well documented :slight_smile:

(we always send 3 bytes, here data2 is 0, if not relevant which is like the usb midi spec)

i doubt the hanging notes are to do with release velocity... most controllers dont send release velocity but Ive tested if with a controller that does, and it seems fine.
you may also find that your controller sends note-on with velocity=0 for note-off, this is also allowed the midi standards. (as an alternative to sending note-off)

sorry, dont really have time to dig into your patch to see what your trying to do...

do you have a problem with the factory keyb objects?
I know of an issue with the way legato is working, or more to the point I think it works not as expected... there was a post about it somewhere on here. Ive got a replacement, but as its such a fundamental object and it required a pretty big change... Im kind of reluctant to release it... I might put it in my contrib lib.


#3

ahhh...thanks for putting me on track!
I'll have a look at the specs,then..

the 'keyb' - objects are working fine,but they're monophonic...
what I was trying to do is to write a bunch of notes to a table and display their state with a launchpad,
which pad is held down? which one not ??
this works OK,but since I misunderstood 'data1' and 'data2', I had the hanging-notes-effect.

while I was at it,it occured to me that this table is actually a 'busymap',
that I could use it to find out how many notes are currently on hold...
this could be an approach to get around the problem of 'hanging notes' in polyphonic subpatchers..
(once you 'run out of voices' , there will be hanging notes)


#4

you should not be getting hanging notes when running out of voices (afaik)
with a poly voice, it knows the last note played, as its stored... and since there is an instance per voice, all voices know which note is active.

my newer keyb, does however track notes in an array to deal with the monophonic legato issue. (tricky to explain why in few words :wink:)


#5

aaahh...it works nicely with the 'normal' 'keybzone' but ::
it doesn't work with 'keyb zone lru' !

I've always been using 'keyb zone lru' in polys because I like the behaviour (releasing a note jumps back to
the LRU..)
but thinking about it ,there probably aint nothing like LRU in a poly-context...
(or is it actually a bug?)


#6

I wouldn't call this a bug, because I can imagine this is how the object is intended to work, but I do change my MIDI OFF handling section to set _note to match the MIDI ON section.

Otherwise, if you are using a single midi object to handle simultaneous key presses, the note will be whatever was most recently pressed, unless you also set _note on the MIDI OFF section. I've found this useful when using something like a Novation Launchpad Mini, and I want to map all of the buttons in one patch. This is opposed to using the native Axoloti polyphony, in which case, using the standard MIDI objects and enabling polyphony in the sub patch is the easiest, best way to go.

if ((status == MIDI_NOTE_ON + attr_midichannel) && (data2)) 
{
  _velo = data2;
  _note = data1-64;
  _gate = 1<<27;
  _gate2 = 0;
  _channel = (status & 0x0F) + 1;
} 
else if (((status == MIDI_NOTE_ON + attr_midichannel) && (!data2))||
          (status == MIDI_NOTE_OFF + attr_midichannel)) 
{
    _note = data1-64;
    _rvelo = data2;
    _gate = 0;
 
} else if ((status == attr_midichannel + MIDI_CONTROL_CHANGE)&&(data1 == MIDI_C_ALL_NOTES_OFF)) 
{
  _gate = 0; 
}

#7

if you look at the original code, you can see why that does not make sense:

if ((status == MIDI_NOTE_ON + 0) && (data2)) {
  _velo = data2;
  _note = data1-64;
  _gate = 1<<27;
  _gate2 = 0;
} else if (((status == MIDI_NOTE_ON + 0) && (!data2))||
          (status == MIDI_NOTE_OFF + 0)) {
  if (_note == data1-64) {
    _rvelo = data2;
    _gate = 0;
  }
} else if ((status == 0 + MIDI_CONTROL_CHANGE)&&(data1 == MIDI_C_ALL_NOTES_OFF)) {
  _gate = 0;
}

this reads quite clearly... you don't process a note off, for a message that you didn't process the note on... but that only works if the rest of your patch tracks note allocation....

its not wrong, its just it has a different use-case to the one you want... but that is why Axoloti allows for users to create their own objects...

what I tend to do, is write objects for specific controllers, like push etc... whilst they might have things in common with keyboards, they are also different, and to get the most of out of them, its better to code of them.

back to the original thread, I did put together a new keyb implementation, but I didn't get enough feedback from users from testing etc, to decide if to promote it to release. obviously keyb is used by probably something like 75% of patches, so I have to play it 'conservative'... so as there was a lack of interest in improving it, I left it in my community library.