porres / pd-else

ELSE - EL Locus Solus' Externals for Pure Data
Do What The F*ck You Want To Public License
292 stars 36 forks source link

Some trouble with [voices] related to voice allocation #895

Closed alfonso73 closed 3 years ago

alfonso73 commented 3 years ago

Hi! Since the inclusion of Else in Camomile i'm doing some more extensive work with Else stuff. First of all many thanks for the Camomile Else project and hope to see more and more libraries included in Camomile and as soon as a tutorial on compiling Else with Camomile/libpd/Juce on Windows will be out i'll try to help building more stuff. I'm working on a little poly synth based on else/bl.vsaw~ and some randomness/drifting that is often part of my sound design for every modular platform or real hardware and plugins that i use. The patch synth works fine as a VST3 in Reaper (apart some "touch" automation mode problem that i've reported here https://github.com/pierreguillot/Camomile/issues/219. The synth uses Else's [voices] to deal with polyphony but i think that it has some little design problem that doesn't make it work very well. If my voice has a pretty long release time and i play one note after another the release phase is interrupted because the voice is stolen by the next note played. So i guess that voice allocation mechanism in [voices] is now taking the first available free voice. I think it should take the "next" free voice. So if i play a second note the first one can play for it's whole duration. Probably a "circular" voice allocation system should be the one that works better and can be totally included in the voice steal design already included in [voices]. I tried to send to [voices] a [rel $1( message with $1 being the release time of my voice [adsr~] but i often get stuck notes.

I attach the whole zipped folder of my patch (including some very smart abstractions by @pierreguillot that are super useful for Camomile stuff). The main patch is Varsaw-Edit.pd.

Varsaw.zip

porres commented 3 years ago

hi, can you provide me a minimal patch the reproduces the issue please? One patch should be enough, and that wouldn't include a patch and a cloned abstraction.

alfonso73 commented 3 years ago

Hi @porres! Sure. Here it is. With the radio button you can choose the [voices] solution or the [poly] solution. If you try to play an arpeggio you'll notice that [voices] behave like a """mono""" synth and that [poly] behaves correctly so at every note (even if it is the same or another one played after) a new voice is selected while [voices] select always the same voice.

voices.test.pd.zip

alfonso73 commented 3 years ago

In the previous patch there was a little error because i forgot that [poly] is 1 based and [voices] is 0 based (unless offset is used) I added a little sequencer so you can hear the effect of [voices] vs. [poly] more clearly.

voices.test.pd.zip

porres commented 3 years ago

I think I get your issue, please note that [voices] has a 'release' setting that will hold that voice allocated after it gets a note off message. Do you think that would help you?

alfonso73 commented 3 years ago

As i said in the first post in the first patch i posted using [rel $1( message to voices where $1 is my voice ADSR envelope release time gave me a lot of stuck notes. I'll try to reproduce it in this simpler stuff. BTW i think that polyphonic allocation should work with a kind of round robin mechanism so that the next voice is never more the lest one used. I think that with this change [voices] will be just perfect 'cause it's already more powerful than [poly].

alfonso73 commented 3 years ago

As i suspected there's anyway something strange. I added a -rel 2000 flag to [voices] so the release time is the same that i gave to the [adsr~] release time in the synth voices but... 1) If you use the sequencer the [voices] version does a "suspicious" pause and the [poly] version behave as expected. 2) And if you play several notes with a midi keyboard you'll have some stuck notes after a while usig the [voices] version. Everyhing works as expected with [poly]

voices.test.rel.pd.zip

porres commented 3 years ago

If you use the sequencer the [voices] version does a "suspicious" pause and the [poly] version behave as expected.

ok, we have a bug then to work on

alfonso73 commented 3 years ago

Yes probably is a bug in the [rel( message handling. But i think that probably the whole voice allocation system could probably be rethinked. Could we use [poly] as a main inspiration for voice allocation but probably all the beautiful and super useful -retrigger flag option in [voices] are based on this mechanism that assign the coming note to the "first" free voice available. Another thing that it's kind of strange is to use that 'release' setting. Given that every synth voice is switched off by [switch~] when [adsr~] goes over the release time it's quite strange to have a "double" mechanism to deal with this (one "internal" inside the actual synth voice and one "external" at the [voices] object level. BTW voice allocation is one of the most mind-boggling things in audio/midi programming :-D

porres commented 3 years ago

I see your point and I considered it, but I believe the most elegant way to deal with this is by also having [voices] deal with the release period. The other way works but it's kind of a hack. You just get free voices that you believe and that will probably be free, but there's no guarantee that the release and voice is over. This is specially true when you're playing with huge chords. So if the release message was working, and now I seem to encounter even more bugs and funny businees, it'd all be fine. But I'll consider giving the option of round robin anyway.

alfonso73 commented 3 years ago

Great, let me know if you need any help/testing.

porres commented 3 years ago

If you use the sequencer the [voices] version does a "suspicious" pause and the [poly] version behave as expected.

if you use -retrig 2 it works fine! But I'm thinking about revising -retrig 0, which seems stupid

alfonso73 commented 3 years ago

mhh...strange i just began the patch using -retrig 2 but i've got the same problem probably because i was using [suspedal] to...i'll go test again! BTW basically what is needed is an "expanded" version of vanilla's [poly] that can with an option retrigger when the same note number is received...so when the same note number is received is assigned to the same voice.

porres commented 3 years ago

anyway, I really don't see an issue with the defined behaviour of the object and your patch

you have a tempo of 500ms and voices that take 100 ms + 2000 ms for release. You also have retrig 0, which ignores retrigerred notes and that's what you get when you play the same note 2000ms later, when the voice is allocated for 2100ms

so all is fine

I may just change the default or the order of the modes, so it's not "ignore"... and also, "ignore" works by sending it to an "extra" voice outlet while not in list mode, and we don't have that in list mode. Anyway, I'm just thinking about the design and I might change/revise/add something, but I can't see a bug!

porres commented 3 years ago

I may just change the default or the order of the modes, so it's not "ignore"... and also, "ignore" works by sending it to an "extra" voice outlet while not in list mode, and we don't have that in list mode.

well, we actually do, so there's nothing to change. Well, you can try and send me another bug test patch to see if I can reproduce or find something funny, but it's all working fine really

maybe add a new request for the round robin option

porres commented 3 years ago

BTW basically what is needed is an "expanded" version of vanilla's [poly] that can with an option retrigger when the same note number is received...so when the same note number is received is assigned to the same voice.

that's "retrig 1"

alfonso73 commented 3 years ago

Here's a version with [suspedal] and if I play with a MIDI keyboard doing some notes and chords I have a lot of stuck/never ending notes even if [suspedal] is off. And btw i didn't talk about a bug but about some design things to get intended behavior. For example a guitar-like instrument does retrigger the voice when the same note is played (the string stop its vibration and restart) but trigger a new voice every time a different voice is played (the previous played string(s) continue(s) their vibration. (is this retrig 1 right?)

Obviously i'm only trying to help improve little things and bot criticizing your beautiful work on Else! voices.test.rel.trig_2.suspedal.pd.zip

porres commented 3 years ago

hi, sorry, this is still very confusing, vague and the provided patch seems more complictaed than it could be. I tried the example with the sequencer and it's fine. If it's something to do with suspedal+voices interaction, please provide a minimal patch with both objects and we can probably see what's going on just by checking the output of voices. There's no need to compare to poly as well

alfonso73 commented 3 years ago

Yeah, with the sequencer is fine. But with a MIDI keyboard is showing some strange hangin notes etc. I'll try to do a simple example where you can play a MIDI keyboard, use a sustain pedal and set the ADSR values. I can make a video to if you think is good to get a good idea...or make a CamomilElse example to share ;-)

alfonso73 commented 3 years ago

This is the simplest that i can do to show what's happening (tell me please if i can simplify more and how) I can make a video too if you need it. thanks voices.suspedal.test.pd.zip

porres commented 3 years ago

you could record some MIDI sequence so I can reproduce it and debug it. I actually have a MIDI keyboard, but it'll take a little while until I set it up and test this. here's my version of the patch

voices.suspedal.pd.zip

alfonso73 commented 3 years ago

How can i record a MIDI sequence in PD? Is there any object in ELSE?

porres commented 3 years ago

else/MIDI

alfonso73 commented 3 years ago

I'll send you some tomorrow. Thanks for your help!

alfonso73 commented 3 years ago

Hi @porres ! Sorry for the huge delay. I'm back to the Else (and Camomile) bench. I've realized several things that can be the cause of some unexpected (obviously from my humble point of view) behavior of [voices] and [suspedal].

  1. My Novation Remote 61SL MIDI controller sends out Midi Note Off events that have note off velocity values.

  2. The "retrig 1" flag in [voices] works fine with retriggered notes when the note number is the same (i.e. i play a C note several times in a row) but because it uses the first available free voice it doesn't work as expected when different note numbers are played in a row (i.e. i play C E G in a row). I would expect a guitar-like behavior so that when i play different notes in a row the play for the whole duration of the envelope and if i play the very same note several times in a row everytime i play it the envelope retrigger (as the actual strings of a guitar if you play different strings they play until their amp envelope is over and if you play the same string twice or more the amp envelope retriggers from the beginning).

  3. I'm doing a MIDI file to show the [suspedal] hanging notes thing ( could it be related to my controller's note off midi messages that PD doesn't handle...but probably your cyclone version has some Max-like MIDI external that allows to deal with it (BTW not usable in Camomile as it is now) thanks and I wish you a happy new year (hope it will be better that this shitty 2020)

porres commented 3 years ago

My Novation Remote 61SL MIDI controller sends out Midi Note Off events that have note off velocity values.

that's awesome, does it have polyphonic aftertouch as well? I mean in the keys not pads...

probably your cyclone version has some Max-like MIDI external that allows to deal with it

yeah, but else/note.in handles it too!

about "2", I still can't get it...

happy 2021!!!

alfonso73 commented 3 years ago

My Novation Remote 61SL MIDI controller sends out Midi Note Off events that have note off velocity values.

that's awesome, does it have polyphonic aftertouch as well? I mean in the keys not pads...

No it's a "old" style controller but i have Roli Block Seaboard too and as soon i solve this complicated poly allocation problems i'll try to do some MPE controlled Camomile/Else instrument.

probably your cyclone version has some Max-like MIDI external that allows to deal with it

yeah, but else/note.in handles it too!

Thanks! Basically i've seen that vanilla notein transform all raw midi note off events in note on events with velocity = 0.

about "2", I still can't get it...

I'm doing some drawing to try to explain better what i mean and i'm doing some [voices] patches to show the problems i find. For the moment i'm keeping out [suspedal] from the test bench beacuse even with [voices] only i have some troubles. Basicly i've seen that in -list mode several note on with velocity = 0 events go out form the [voices] second outlet instead of the first one so some notes are hanging. Sending to [voices] flush or clear messages does not stop the hangin' notes. When i'll resolve this problems (if i am able to do it) i'll send you the example patches. BTW i still think that is "conceptually" not a very good idea to use that -rel flag. The duration of the actual voice should be in charge of the actual voice envelope at the inner voice level and not at the voice allocation algorithm level. In a polyphonic voice allocation algorithm i think that a new note should be always assigned to a new voice slot unless the note has the very same midi note number (for example several C4 in a row). In the case of a repeated note with the same midi note number the retriggering logic can be of two types. 1- Use another voice slot (as in vanilla [poly] and as in the majority of virtual synth...but not all) 2- Use the same voice slot. Sorry for the mess but polyphony and voice allocation is truly a complicated topic.

alfonso73 commented 3 years ago

In the mean time two images that deal with the two modes that i think are the only one really useful in a polyphonic context. In my humble opinion the [poly] mode should be implemented in [voices] as -retrig 0 and the other in the other image should be implemented in [voices] as -retrig 1. The topic about voice stealing is interesting to and i think that would be great to have for modes in [voices]. Mode 1 = ignore any new note if maximun polyphony is reached. Mode 2 = steal oldest voice. Mode 3 = steal lower pitch voice. Mode 4 = steal higher pitch voice. poly  No retrigger when repeated notes with same number Possible new mode for  voices  - Retrigger when repeated notes with same number arrive

porres commented 3 years ago

sorry, this only gets more confusing to me :) I'm completely lost and have no idea anymore what you're talking about anymore. I'm giving up and I'll close this issue for the second time, but you're welcome to open new issues again, more than one if needed, reorganize things that were discussed here. I just need something clear, more straight to the point, with a clear issue title and with an example. Sorry, but I can't work with this :/

porres commented 3 years ago

maybe you can find some tips here https://www.softwaretestinghelp.com/how-to-write-good-bug-report/

alfonso73 commented 3 years ago

Hi @porres . I'm very sorry not to be able to explain in a simple way. Voice allocation is a truly complex matter. I'll try the "divide and conquer" strategy and try to report all my findings about [voices]. If i can give you my humble suggestion...can you update all the [voices] and [suspedal] help files with some actual MIDI input? As the help patches are now they tend not to create the "real life" situation for those externals. Using a MIDI input (with some sort of musical keyboard controller) and a litte simple sine oscillator synth abstraction with an adsr would be very useful to do some testing for [voices] and [suspedal]. I can help if you want, to make some proposal for [voices] and [suspedal] help patches. Thanks and all the best.

porres commented 3 years ago

you can suggest whatever you want, but please make different issue reports for everything

alfonso73 commented 3 years ago

sure. thanks