• ### Aftertouch last note priority

Hi, I am trying to implement this feature for a hardware synth. I decided to write notes and velocity into separate arrays - here could someone explain why I need to shift the note array -1 to have both of them in sync. This part of the patch works great.
Now imagine this scenario. On a 6 voice synth I hold for example 3 notes chord in the bottom and play monophonic lines on top, with the aftertouch effecting only the last top note. But as soon as I play two notes on top, than if I release last one of the top notes I want the previous one to take priority.
Here is the algorithm I am trying to achieve: if there is a noteoff message, go back in the array and compare stored notes to the noteoff number. If you find another noteoff message, store its number and go further back. This way it should be possible to to find the last note that you still hold and assign aftertouch to it. To ensure there wouldn’t be endless loop in case you release all note I added a counter object and it lets the algorithm run only 6 times (size of the arrays). Each new noteoff message resets the counter.
Right now the note numbers after a noteoff event either don’t come out at all or the result is wrong.
Can you see why the patch is faulty or maybe suggest a cleaner way to do this?

Here is a link to the patch

• Posts 22 | Views 7031
• @5tepan Here are two examples of how to possibly do it with [text]:

The first one will assign aftertouch to the last note that was played, the second one will assign it to the highest note that is currently held.

• @5tepan ......... note.... just fixed "clone out of range"......
maybe.zip
David.

• @5tepan Here is my stab, not quite complete, need to setup the logic to bang zero to the float when all notes are off, but that is simple enough, no time to do that now, time for work. This just stores the highest note and compares it to the incoming new notes instead of storing and comparing all notes. It is quick and efficient.
highnote.pd

Edit; Anyone know why the [\$1( is needed before the [expr]? It throws stack overflows without it.
Edit2; Just noticed an error, the wire to [pack f f]'s left inlet should come from [notein]'s left outlet, not from [spigot] if you want to retain you note off data!
Edit3; This does not work, since if you release the high note the aftertouch does not drop down to the new high note, I forgot to account for that.

• @oid regarding edit1: without \$1 you send a list with three floats into expr, they are used as \$f1, \$f2, \$f3.
i would use an [unpack f f] after [notein].

• @oid I like the 3 episodes (edits)

• @Jona Ahh, so the stack that is overflowing in this case is a stack of three, \$f1, \$f2 and \$f3, or is it three stacks of one?, since they all get values direct at their inlets, the rest of the list overflows leaving us with the correct result and some overflow. I assumed that if [expr] worked on lists it would have stuck velocity into \$f2 and produce incorrect output, so I figured no lists to [expr], the actual number of stack overflows should have clued me in, makes perfect sense. As too using [unpack f f] insteald of [\$1(, is there a technical reason for this, or is it just because it tells explicitly that it is taking one value from a list of two instead of just one value from a list?

• @oid a stack of size three would not cause a stack overflow. here is something about stack overflow: https://forum.pdpatchrepo.info/topic/10805/struct-pointer-object-limitation/13
in short, in pd a stack > 1000 causes a stack oferflow.
i would use unpack, because i would split the list before spigot if i just need the first value afterwards, but it is not necessary.
but i would use a trigger after \$1 because the order of operations makes a difference in the result. on topic: the suggestions from @ingox and @whale-av should work as a solution

• @ingox thanks a lot, the aftertouch1 patch does exactly what I need. There is one thing left. If I release a key it sometimes "remembers" its polytouch value. I tried sending polytouchout with zero value after every noteoff but it didn't work (there might be a mistake in my patch or maybe the synth doesn't register the message at that time). Right now I use a workaround of sending touchout of value 0 every time there is a noteoff, however the disadvantage is that the note to which the aftertouch is applied is also affected for a short time. I have to look into it further.

• @5tepan I don't have the setup to actually test any of the stuff, but here i added that a zero is send before the aftertouch note is changed. Also added a [change] before the aftertouch note, so only when the note really changes, the aftertouch is updated. Not sure if any of this might help: aftertouch1.pd

Edit: Not sure about the [change]. It may prevent setting the aftertouch to zero if the last note is released. Maybe better to test it without the [change].

• @Jona Thanks for that link, very informative.

I confused myself with a false sense of understanding, the left outlet from [notein] only outputs one value at a time, it is serial just like midi, putting a [\$2( on its outlet throws an argument number out of range error as expected. So the original question still remains, why the need to unpack? The recursion in my patch does not cause the stack overflow, it still happens without it, the same exact number of overflows. Connecting a numberbox to [expr]'s \$f1 and \$f2 inlets works fine with no overflows, so this seems to be some weirdness with [notein]'s output.

• @oid you are right, notein only outputs single values at each outlet, so unpack and \$1 should not be needed.

• @oid I cannot see why there would be a stack overflow. The [\$1( should make no difference unless you changed the order of operations when you inserted it. [expr] only executes when something arrives at its left inlet, and there is no feedback loop......?
If you still have the patch which produces a stack overflow maybe you could post it?
David.

• @whale-av It was just the patch above without the [\$1(. I just tried to recreate it and tried every possible order of connecting the various inlets and outlets and have been unsucessful. I suspect it was an error with the connection between alsa and pd, which I have had before, but those always produced garbled midi in pd and aconnect hanging at 'connecting.' Pretty sure there is a bug in pd here, I have had this issue in both slackware and crux, it will crop up and not even a restart and or reinstall of pd/alsa will remedy it, and then for no known reason, everything works. Hopefully this is one step closer to finding the actual issue, I have had it with both the build files in slackware and crux and with my own builds on both systems and have seeked help on the IRC channel in the past with no luck.

• @oid It seems to me that there is a problem with your MIDI setup.
Two ideas that could help to localize the issue, just guessing because I do not know your setup:
If you have not already, I would install the newest PD version so that you do not have any PD bugs that are fixed already, and you need Jack to route ALSA MIDI:
"If the ALSA MIDI drivers are used, then JACK users can use the QJackctl application (available in most Linux distributions) to connect external MIDI devices and other MIDI applications running on the same computer to Pd."
Regarding your patch, if I am right you could theoretically replace your whole expr with a max object?

max.pd

• @Jona said:

and you need Jack to route ALSA MIDI:

`aconnect -l` in any terminal will list all available software and hardware midi ports and then you can connect any of them by name or port number `aconnect 'Pure Data:4' Blofeld` or `aconnect 128:4 28:0` will connect pd's midi out to my Blofeld and `aconnect -x` will disconnect everything or just one conenction if specified. Generally this sort of work is just handled by a script, so for me `midiup` will check what programs I have open and what hardware connected and figure out how they should be connected . For audio between applications we use the alsa loopback device to create a virtual soundcard to route the audio through using the `alsaloop` utility, with a script or through alsa configuration files. Alsa can do a great deal more than most think and often can do it better than Jack, Jack is just intuitive, alsa requires you to study up. The main drawback to alsa is that some applications have dropped alsa support, mainly DAWs, which is odd since they generally have no use for Jack since it is rare for a user to route audio between a DAW and another application, it is all internally connected in the DAW to the various plugins, everything is a plugin and Jack is often a redundant requirement that just consumes.

My setup is as simple as possible, midi controller to USB, alsa, pd, no jack. This problem has persisted through multiple pd versions and two different systems, the only commonalities between them are that both systems are source based and use old fashioned SysV. I have spent a fair amount of time in the past in both the alsa and pd IRC channels trouble shooting this and the best guess so far is that under certain circumstances pd does not clean up properly on shutdown and leaves alsa unable to make a proper midi connection into pd, midi out seems unaffected, aconnect -l shows the midi connection into pd hangs at 'connecting.' When this happens midi still works properly in all other applications, it is just pd and I have not been able to recreate the garbled midi in any other application.

Yes, [max], I have been learning [expr] lately and have become somewhat fixated on it, I often find myself using it for things which pd already offers a simple solution for, but I am getting better about that.

Edit; Forgot to mention, you can automate a great deal of the alsa connection, with the use of udev rules you can have the hardware to software connections made automaticaly when a device is plugged in and you can have a script that starts up all your programs and makes the connections between them, so one command or one click and everything is done for you. This works best for those that always use the same setup, but it can be worked to adapt to changing setups as well.

• @oid I don't know of such problems with Pd........ but....
Have you tried setting again the Midi as Pd opens...... rather than relying on its saved setup.
You can do it like this....... get_set_midi.pd
Maybe add a delay after loadbang as you are starting Pd with a script and it could need the ports already open.
David.

• @whale-av I have, I have also tried changing the number of midi ports or changing to OSS/Jack and back too alsa hoping it would reset things, but I did not think of trying to increase the number of ports and connecting to one of the new ports, will have to try that the next time it happens. As of now my solution has been to just leave pd open and never quit it, which mostly works as long as I remember to turn off DSP before putting the comuter into suspend/hibernate. The only time I have had the problem show up since, other than this recent stack overflow issue, was after I sent pd into an infinite loop and had to send it KILL, but that time the problem did not last long enough to search for a cause, it solved itself with in a minute or two. The first time it happened was right after pd got infinite undo and I updated, that lasted months and going back to the old version and deleting every file I could find related to pd did not solve it, later releases of pd did not solve it, and then it just worked one day. It seems to do something to 128:0, alsa's client number for pd midi in, one of my future tests for when this happens again is to see if I can change pd's alsa client number. I do not start pd with a script, the script just does the midi connections, connecting manually does not change anything and once aconnect gets too 'connecting,' it can not even be disconnected, it hangs forever. This suggests pd, alsa is waiting for pds input to become available, or so I was told.

• @oid Pd is only going to look for available midi inputs and outputs as it starts or when you open the midi settings dialog (I think). The Alsa service should make them available and then Pd can connect.
The "pins" have to be announced so that the other service can connect.
So I think you should restart Pd and open the required patch from your script, as thread connections have to be made again when restoring from sleep mode and Pd might not have such a mechanism.
David.

• @whale-av In the case of alsa, I do not think pd looks for midi i/o, just looks for alsa, if found it connects to alsa and tells it to create the specified midi ins and outs, perhaps that is what you said? These ports and connections seem to be quite stable once created or a successful connection is made and they do persist through sleep without problem. The DSP issue was an aside, it is just caused by pd restoring before alsa gets sound back up, turning DSP off then back on solves it, I have not gotten arround to installing any power management software or configuring things myself to make certain software is not restored until all system services are back since I switched distros. Midi is either restored before pd or pd does not care if midi is late, no isses there. The garbled midi only happen after pd is quit or killed and then started back up and only occasionally happens. Thanks for this exchange, I have a good number of new things to look for on the next occuurance, think I am getting closer to being able to file a bug report with enough information to actually be useful and to actually know who should get the bug report!

Just gave a look over the alsa C library reference, they have greatly improved it since my last look and I think I might have just enough C to find the issue myself.

• @oid More info....... Pd polls the system for midi I/O at start-up (and then it seems goes into a loop to continue polling)...... system dependant code in midi.c ....https://puredata.info/docs/developer/PdStartupOrder.
The Alsa service makes pins available but doesn't initiate connections to Pd.
A router does the same.
Pd has to poll for available pins in order to connect.

But this is probably not the cause of your problems. You should check out this issue thread which is probably relevant....... https://github.com/pure-data/pure-data/issues/895 and either provides a fix or will soon do so.
David.

Posts 22 | Views 7031
Internal error.

Oops! Looks like something went wrong!