Choke group processor
-
@Christoph-Hart I sense you're working on a percussion plugin. Tell us more about this new processor. :)
-
I'll add this later to the docs, but:
The ChokeGroup processor is a MIDI processor that automatically kills all notes when a note is played on another sound generator that has a ChokeGroup processor with the same
ChokeGroup
index (if the ChokeGroup is zero then it's disabled so you can dynamically reassign it to work in different configurations)The most obvious use case for this is when you have drum samples that should stop other drum samples, eg. a closed hi-hat stopping a open hi-hat sound.
In order for this to work, you have to assign a valid MIDI range using the
LoKey
andHiKey
parameters where the samples are mapped (otherwise everything would choke each other). This processor will then also mute every note that lies outside that range.Lastly you can decide whether you want to kill the voices using the SoundGenerator's
KillFadeTime
parameter or if you just want to send a note off to let the envelopes ring out naturally.Example:
A sine wave mapped to the lower half of the keyboard and a saw mapped to the upper half. They will choke each other, but allow polyphonic playing inside the same group.
HiseSnippet 878.3oc6X0rTaCCDVlD0BSaYZ6.sbzG501IIk9yMBDR.FHfGLE5MFU6EhFrkRkkoMuc8QnOB8Qf2fVIaRsTmLYBdJ+Nja62pU5a0tq9L3I3APRBWfblYuA8Ajyiw9CXxds5QnLzFqhblE2kjHAgaNzJC5SRRfPjiSk0z.NyTEk86rkVgDQXAPADBsOmF.aQioxBTulaRih5PBg8nwFqdwlaDvYs3Q7TEepfqg5SBNgbLrMQurovHmGzNjJ4BeIQBIp0rBObfeO92X4qeeZB8KQf1nNxWsQ4vnV8nQgdCy0DjZi7Jx7J4Y9b3tzP5ewKtAdZlC2hHLuCblZbTp9jSIjAiplyH0AyCSiHRa1nu1O2AkaWQ1fIAVBUNvrrbAnXs+KT7YXOpLn2n43TifipBxkAGOuv9Db6iNBBjEDrJtymKaUbxO9YyO9Gg8oLHapJ6veQls6AjSA20.FHzWd0Gyf0OmzAq9S7f0NAR0wumfvR5ySr1XeHltGmouEJ.+TBzQ.ecWc0zDuEmHFoqyVpiJIGYL9DYpHqsX4XdJSZ0FTwtNTcxllrmHLV+Hl7qdML4O9dFGGCJ8vbJMOtUO9IvZBdZ+BuZNsPtG2LWETytApHXyRxV7MAqot0oV.4OLm0YUx2Ot0+DmUsXlgbzmF2OBZyNEh3JDMGeNdU3HRZjbHpcAnKmw62iynAl226BRA83iAgI2GYBsrTpz9JPlq4tPDPLGUeUysTiXDg5d5xobYcWLt50B3b55pe1w81qzTk61RS6xSkT1wcIplvuibvamF6qTDB.0oyXPjZywNSoeUO2tl1NWRfElY7a0uycVWa6bty5CcZlhyOT9SqzUH+Mel8QbQ7ME0u5l67+3qgouUAYJyd44PVqRmdcTomw5lt4PvFlfdDl0lors1ot5xzPyesTaFQUn8AU1DtSRfJY02cliSdoQIvAzPYu5lAV.2vDdchHTUWBthEfevcSA3FWbAXul1Bv+3v6EfKu.bi6EfuW.91xea33m9TO7eytJ9RrR.pgaVoz85oVdU70LWEmQLIPvOTooKE7H8P+zYHp7lk8u8ZFbWssaczojnTE.FW6M0PwJcwCCBz8quVIyN5XZThXdaIhYwRDy6JQLuuDw7gRDyGGaL5OIY4TIONumWA30dUhjnZ5y+Dsr1ezezDoK5M
-
@Christoph-Hart it is wonderful that you implementing this as a hard-coded script.
-
Implementing this as ScriptProcessor is rather trivial as long as all notes are received by all script processors. In my case I have MIDI players sitting on each channel so the MIDI notes from the MIDI player will only be sent into a single channel and the other ones have no idea that a "choke note" was played. I implemented this at first using global variables and even passing around a broadcaster as global object, but then I realised that a smart man once said "globals suck big time". (Me. It was me who said that.)
-
@Christoph-Hart I've really fine-combed through the forum and docs for a solution and I can't for the life of me figure out how the choke group processor is intended to work.
My goal: I have 8 samplers with individual drum sounds. They can and should be able to be triggered at different pitches. If two sounds are set to the same choke group, they should choke each other. Think basically any drum sampler in history. Every sampler has different fx configurations et cetera so they're essentially acting as voices of one drum sampler.
Tried my own solutions with script processors on each sampler; artificial events, event IDs, noteOffByEventId etc. on them, and every possible combination of settings with choke group processors on each sampler. It just will not work. The closest I've gotten with the Choke group processor is either one sound choking the other but not vice versa, and both choking each other but only when they're playing at two specific midi notes.
So I need to be able to tell each sampler exactly which note to play, and regardless of which note any of them are playing they should bidirectionally choke each other if they're part of the same choke group.
Any ideas on what a solution for this could be?
-
@audiolyf I think you should be able to accomplish this by using 2 choke scripts on two samplers.
Sampler 1
Trigger: Note A
Target: Note BSamplers 2
Trigger: Note B
Target: Note A -
@gorangrooves Thanks for replying!
Don't really get it though, where do you set the trigger and target in the Choke group processor?
All I have is the group (set to 1 on all), the range (LoKey and HiKey which I don't really get what they actually do in practice despite Christoph's explanation above), and KillVoices.
Do I limit the range to one specific note? 2 or more samplers don't always play the same note since they can be set to different pitches.
And where does it leave 3 samplers choking each other?
-
Choke script
Content.setHeight(50); Content.setWidth(600); const var target = Content.getComponent("target"); const var trigger = Content.getComponent("trigger"); const var trigger2 = Content.getComponent("trigger2"); const var decay = Content.getComponent("decay"); // An Array is also a constant, even if it will be populated later on const var evtList = []; // make sure it has enough storage to avoid allocation during the noteOn callback evtList.reserve(1200);function onNoteOn() { local number = Message.getNoteNumber() + 1; if(number == trigger.getValue() || number == trigger2.getValue()) { local decayValue = decay.getValue(); if(decayValue == 0) { // Always use the for ... in loop if you don't need the index for(eventId in evtList) { // Send the note off command for the given event id Synth.noteOffByEventId(eventId); } } else { // Always use the for ... in loop if you don't need the index for(eventId in evtList) { // Fade out the note Console.print("Choke 9 event no is:" + eventId + " and is artificial:" + Message.isArtificial()); if (!Message.isArtificial()) if (Globals.auditionSusNotes.indexOf(eventId) == -1) //not an auditioning note Synth.addVolumeFade(eventId, decayValue, -100); } } // Clear all notes evtList.clear(); } else if (number == target.getValue()) { // This is necessary because you will kill the note artificially and HISE // can only kill artifical notes for stability reasons Message.makeArtificial(); // Add this ID to the list (it'll add the artificial event ID) evtList.push(Message.getEventId()); } } function onNoteOff() { local v = Message.getNoteNumber() + 1; if(v == target.getValue()) { // We need to ignore the note-off message // for the open triangle so it will keep ringing... Message.ignoreEvent(true); } } function onController() { } function onTimer() { } function onControl(number, value) { }
Don't use the built-in voice choke for this to work.
If you have two instruments that should choke each other, create two samplers for them and put one into each.
Add MIDI script for each sampler by copying and pasting the above script.The choke script above has 1 target and 2 triggers, so you will need to set the same note for both triggers.
Set the values for the MIDI script for both samplers in the manner I described previously and this should work.
-
@gorangrooves Thank you so much for the tips!
It didn't really work for my exact purpose but it gave me a very refreshing angle, in case anyone else has the same use case here's my modified version:HiseSnippet 2569.3oc6b0siaabElZ2kIdU+AIM9hd4.ihDJ30ZkHY1D.Cir+ZmEwq8BKam9CJL3RNRZ5RMiJI0ZK2XfbYQaA5qPeD5ifeD5iRtt2zdNbHkFthRhq7FuVNjXgf3Ylyb9lyblYNmOK3iCDtzvPQfVk0e7v9TsJ+b8VC4Qc2qqCiqc39ZU9Pc2thSoZ6NruSXH0SqRkUuG1Xk0WSK94G9pcc7c3tzwhzzdpf4RuOqGKZrzi29aX9920wi9XVOkdau8gtB9dBew..Hqp2Pqui6oNcnOvA61J5ZU9fC7XQhfVQNQzPsJqsqvaXqthmyk8+orP1I9T7klZsfARJ9tBeODwnTs85x78NNcBGpoU4ZGOd5upb5ec8iXdrQxG6F9n3FHi0P0eTYkrva0LvqoJ7Zn.ubfTEEHslDRerdK2.V+nwsf34moeHOhFz1wM6RiruZq7u+P88DPO3Q064bJ8tAvKizvXqFM1f.eT61Uq1wWbhiOoOKxsaSxcHMtcFQlSJxZRQ1RQoxDChvgp4sUDXddAVmWfsTPpjn.VGbT1ZrsPQ33rUyLhvQZKyLhvwZKKXvpBgVgQjybBHeCWbBNfoNlNzn8D85K3vKF2Ht0a.djrJXNSELmTAqYpf0jJXOSErQEpx39LNkzd.2MhI3DAOFtnZABeC2Tc1.FU+AzZU+KUWezJZrnaW8Uv3Lyod8PTZ7Htmiu+IvlPirFBgxTvh47whYQwh4rvh47wh0kHVrlEVrlOVruDwh8rvhsJVFGgA6q5K2Ml+3lzd1vRoPy4njYdJYMGkrxSI64njbSPNd3DzOSebxgQy0COxSjuONqoxeSYheYdvwr3vwb1vwr.vwZdvwp3vwZ1vwp.vwddvwt3vwd1vIyVB4iBbdfHh9PtQrYq9ppjy2T6141VxX5SCxsYL0lfYonAePuSnApSZriv88YShPe5IQnliiqz8nzQA+PNK5g8o7ok4iVhOEyAJAUPWihS23WljtQKelGMPi4go.FeGfVLfUSxSqvJa9lnr04U9ZaWbksWLKutdx98yq9O7UWD0MWLnmpt0al5SN22V6IGtuSjClpYRP.DXzmFDwvXtJ6SOCxaWl34556SCOMRzONJIYmG784Fm7B0T6Gp9ROlmmO8XQHC2SntlDFQ62h8xLN5dpUYPdcOGkAlfNhBiISEL85Sd2.SVJX56+yuafIaEL8uFdUiow6AmVD0ua6dYqD8b1Iejk+73itfnZ5wTWknZ5QUWknZ5wUWxnZxxmgB2EdC7chxVMORgQRC3XnVBMVlLGF6gp17RqD+hBwOV+Xr1f7w3J4fQ3H8eLvXBwH+B8CZ2l5FMFfqoe2e6ONrfnZ9OI076LviItu.uqJ17WWJgfhHG66LjFzbFjT8eJJIU8KLIUsFxcgkmLglwqYON.RBkw6n1.ByC3Nv72SEAORHhvjMUIIqkSu99TvKFDACeldSOiFDlcDtKyOgmLO8MeRHz9l+IAGthm2ywu2lGMHj4tobHIHsZgat+NO3dG7nm76IsDC3dmxhHmLjrqO8kujrK0IJbyCghyBFzC1am7cx85JBip+bmyzh2spWAsb7NU8J+2OQWyGlcw.NsM+3oqWZ6UVcV720bA4uaskX96tljV0l4Rd2e+Z5iJGFJu4qorNciL9bjtNU4eKyKpqg4WFKuJIf1g.AH7nFPAT2pYrrwEZCqNPETJ0Y634gW4abiGG2xM1fz.9SNTxNi13QN7NTiF0arQSyu.+r9Dc4oXNlFwr0U6bF0i55LLOatO1.Xxl1iLZbeyZRyFJFbyMIjc3jcBBfgjERb7CEDGowbvhHw4Ng0l.AzOG1BSNAB3E8wSOodD7y.nHLUzQOK59rPzm7G9iol.IKkDNHfhCSWmPBEpkrSWRHDd3zgRh.adlf4Al2W3FevLwaP.ramD0kR3w0TRbSpDsZpMpGPgslmQMZZhrtleUnD3AGTehrDQ.XGAQLfYwhewN9fX4F0tIt5BOScQ.dh+HUeVGtHfd.Fc.cBJ6ToOfKyH0f2IcH6jNj0pE2II5vGvI83tf+G9iSwHZmfgfu10YPHkLTLP57OE+H0iPfSFXsYtLvsLj3v8He8gsNPcDccPeAzXrdIcGcDf1gj1h.XAv4DlObiGDm6DBqgJpmNKwEucFYJijII9LZeQ7+5F06C2Wf9yj48MkTkhg3J5L5KPzanvmVuOrLGknRd8ClG634AyZv0b39XnB5.7wPLCVzmgSr3lU8GRjAculBVkgL8GD10PB7Dq8pj0KCCImV2Qxq9m9oDk0Ojh7Zju66HpcxZxNYMQmrmrS10pQN25uLBMd2ZbDB3TkacGGxjiuA.spJ2A1zOpswicpWz+4NCCIX.E5svk+50qSXbBduBFvhwYdB9mEAwfToOkw8nuHyHA5I8eG5g5l3WqkoOYsch8aQ4diCdEsaCGZzqGF2hPAanCCOrQt1w7lXLjQYbIKR6N7.IHRAih+Y7pZ1uQ8CouC5eVWNwfv3mJ7gLDvzjRGhMThI1.t+oQiBLOU26rmOENTFNhPtqeh8CtX6Fi1J7povW23Xzyl9AnjaRZl4HPiyJ5geeKMwmJHxSUGEobKLRomzfpZjFz.4txwcUv8aPxXvsWo2TcJk1mf2g.+AKjizcNmdm0G79EujqT.ZttltL0kyyx0CJH8fwIgjC8fKDEYqnTP7GLeH+hzLkGl9kbqzUoX3W+rLEc+AychEah+wEwDZrkgJnyjj85oXrECKw4.9YTeXwJFi+JvQz1YfeTpzrYaejfK52UvYtYqwBu2qCMPE64Ng1IJBRwarjqu8invQTgJt2ey12mwgSsNeYhW.eQyKbAG4td8q0kvkfmCPVdY9X02uY93QPZXvk.G4.Ag39W39JnJ8.WJXcNGxJ.2JuBdRo78FoaswTVhe4+AOIM1DeuRRiMSabQYWwrjckR1UVtXWwLW1U9mKorqXVxtxUO6JlWT1UJoXQghEykKJVLSHFo4jDizbD6IlEghEyYRwRICKkLrTxvRICKKKLr78kLrTxvRtLrXVxvxaNCKqUr0sYW+1aQ1Vtzw6hy7xkCTdGlEFqRVXJYgY4hEFqbYg4uc0xByBxAi0aBGLkrvbYwBiU4uwkEi.FqkKBXrJBALVE4GBiUIALkDvTR.SIALue7Sb4gkDvTR.SdDvXUR.S4OwkxehKKF4J1uyRthl1aAxUVQOGpORY5XZTeDGaVR8Q9TeXmK0G+0kRpOrK+4mb0S7gcIwG+jf3C6hP7gcQH9vdV+7TJI9nj3iRhOJI9X44WdRIwGkDejKwG1kDeTR7wO4I93sgM543FHdlq7T33+ezMVBLu4wzHrt9Q36jQ+WmltNTumVOn.8m45ht3a0TSKecLW.crV.crW.c97EPmsV.c9hEPmubl5fbiryfHQO4VNPvwGDeMXkJinTpxpZ+e.5Zc0tA
In this example, there are 4 samplers (Audio Loop Players in this case), set their MIDI trigger with trig1-4 in the interface script. Each sample can be pitched using the interface, and if two or more channels are set to the same output they will choke each other. If you need more channels you will need to add more variables for pitch, out & trig and add them to the conditions for each midi processor. Maybe not the cleanest solution and could definitely be more dynamic but it works!
-
@audiolyf That's awesome. I am happy to know that it was able to give you some clues and that you managed to get it going in the end.