endub Posted November 16 Share Posted November 16 I have a synth that gets stuck notes with polyphony >4, or when it receives too many midi notes in a short time. Does anyone know of a script to limit simultaneous notes to a maximum of 4 in this case? Ideally with most recent note priority. I tried to ChatGPT this but no luck! 😅 Quote Link to comment Share on other sites More sharing options...
David Nahmani Posted November 16 Share Posted November 16 You could use the Voice Limiter object set to 4 voices and priority = last in the MIDI Environment:Â 2 Quote Link to comment Share on other sites More sharing options...
Dewdman42 Posted November 16 Share Posted November 16 (edited) edit, see next message...stay tuned Edited November 16 by Dewdman42 1 Quote Link to comment Share on other sites More sharing options...
Dewdman42 Posted November 16 Share Posted November 16 oh actually, never mind....the script I just did is not quite what you asked for, you wanted to keep the last 4 notes, throwing away the oldest ones...I have to think that through some more... stay tuned. 2 Quote Link to comment Share on other sites More sharing options...
Dewdman42 Posted November 16 Share Posted November 16 (edited) ok...I had nothing better to do this morning.. Â here is a try at a scripter script for this, in case you want to avoid the environment, though David's simple environment solution should also work perfectly well.... Â its also an opportunity to share scripter tricks. Â I don't have a mac to test this, and it's a bit complicated so let me know if it actually works or not. Â it could be enhanced to have a GUI slider for the MAX value also. caveat...note that this is also kind of simplistic in that if you were to have two overlapping notes of the same pitch (which is unlikely anyway), then it would probably cut things off prematurely. Â Â var queue = []; var offAlreadySent= []; var MAX = 4; var offEvent = new NoteOff; offEvent.velocity = 100; function HandleMIDI(event) { if(event instanceof NoteOn) { queue.push(event.pitch); // If queue bigger then MAX, then send NoteOff's early while (queue.length > MAX) { offEvent.pitch = queue.shift(); offEvent.send(); offAlreadySent.push(offEvent.pitch); } } else if (event instanceof NoteOff || (event instanceof NoteOn && event.velocity < 1)) { // First check to see if we already sent NoteOff for this pitch for(let i=0; i<offAlreadySent.length; i++) { if(offAlreadySent[i] == event.pitch) { // we already sent this NoteOff early, get out offAlreadySent.splice(i,1); return; } } // Legit NoteOff so look for first matching pitch in queue to remove it for(let i=0; i<queue.length; i++) { if(queue[i] == event.pitch) { queue.splice(i, 1); break; } } } event.send(); } Â Edited November 16 by Dewdman42 1 Quote Link to comment Share on other sites More sharing options...
endub Posted November 16 Author Share Posted November 16 Thanks for the code! It seems like it may not cut off the notes correctly; at least upon first testing the note lengths seem to be too long. Quote Link to comment Share on other sites More sharing options...
Dewdman42 Posted November 16 Share Posted November 16 alright, well I really should not have tried it without being able to test it myself, which unfortunately I cannot from the foreseeable future. Â But anyway, maybe someone else may be able to figure out the exact tweak to get it working.. Â or just use the environment thing David showed 1 Quote Link to comment Share on other sites More sharing options...
Solution Atlas007 Posted November 16 Solution Share Posted November 16 (edited) Although it’s not meant to address your issue, you might find interesting the Mono2Poly script… Edited November 16 by Atlas007 3 Quote Link to comment Share on other sites More sharing options...
endub Posted November 17 Author Share Posted November 17 The environment Voice Limiter works well. @Atlas007 And your script seems even better - will definitely use that 🙂 2 Quote Link to comment Share on other sites More sharing options...
Dewdman42 Posted November 27 Share Posted November 27 Had a minute to tweak on that script above to see if I could get it working, here it is in case its of any interest......its actually working for me even as is originally, so I'm not sure why it didn't work before, but anyway here it is with a gui to set the amount of polyphony. Â The only thing I can figure is that its possible that the destination synth needs to see a bit of delay between the forced NoteOff and the next note that needs to use the voice..not really sure on that...would be interested to get it working though for the mental exercise... So I added a 5ms delay here, but you can changed it to a different value, larger or smaller or zero or whatever, see the DROPDELAY variable at the top of the script. var queue = []; var offAlreadySent= []; var offEvent = new NoteOff; offEvent.velocity = 100; const DROPDELAY = 5; // ms function HandleMIDI(event) { if(event instanceof NoteOn) { queue.push(event.pitch); // If queue bigger then MAX, then send NoteOff's early while (queue.length > GuiParameters.get(0)) { offEvent.pitch = queue.shift(); offEvent.send(); offAlreadySent.push(offEvent.pitch); } event.sendAfterMilliseconds(DROPDELAY); return; } else if (event instanceof NoteOff || (event instanceof NoteOn && event.velocity < 1)) { // First check to see if we already sent NoteOff for this pitch for(let i=0; i<offAlreadySent.length; i++) { if(offAlreadySent[i] == event.pitch) { // we already sent this NoteOff early, get out offAlreadySent.splice(i,1); return; } } // Legit NoteOff so look for first matching pitch in queue to remove it for(let i=0; i<queue.length; i++) { if(queue[i] == event.pitch) { queue.splice(i, 1); break; } } } event.send(); } /********* * GUI *********/ var PluginParameters = [{ name: "Max Polyphony", type: "lin", minValue: 1, maxValue: 127, numberOfSteps: 126, defaultValue: 16, automation: true, hidden: false }]; /************************** * More efficient GUI read **************************/ var GuiParameters = { data: [], set: function(id, val) { if(typeof id != "string") id = PluginParameters[id].name; this.data[id] = val; }, get: function(id) { if(typeof id != "string") id = PluginParameters[id].name; if(this.data[id] == undefined) { this.data[id] = GetParameter(id); } return this.data[id]; } }; function ParameterChanged(id, val) { GuiParameters.set(id, val); } Â 3 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.