Monkeymonkey35 Posted March 25, 2018 Share Posted March 25, 2018 Like the title says, I'd like to modify this script to randomly choose different rhythmic values from an array. Not sure why it's not working... var NeedsTimingInfo = true; var beatArray = ['1','3','1.5']; var randomBeat = beatArray[Math.floor(Math.random() * beatArray.length)]; function HandleMIDI(e) { var info = GetTimingInfo(); if (e instanceof NoteOn) { randomBeat = beatArray[Math.floor(Math.random() * beatArray.length)]; e.sendAtBeat(Math.ceil(info.blockStartBeat) + randomBeat); } else if (e instanceof NoteOff) e.sendAtBeat(Math.ceil(info.blockStartBeat) + randomBeat); else e.send(); } Quote Link to comment Share on other sites More sharing options...
Dewdman42 Posted March 25, 2018 Share Posted March 25, 2018 First problem I see is that you are defining your array of beat offsets, as strings rather then as numbers. So later on when you add the random beat offset to blockStartBeat, a string concatenation occurs, resulting in very large beat offsets. The + operator in javascript concatenates strings if there are any strings on either side of it, and it will convert numbers to strings on the fly if it has to... So for example, if you had a midi note at beat 1 and run it through your script, let's say the random value selected for it is '3', then the resulting operation would result in beat 13, not 4, because 1+'3' = 13. So for starters... var beatArray = [1,3,1.5]; Beyond that I see a few potential problems with what you're doing, so just want to comment about that a little bit. Not entirely sure exactly what you're trying to accomplish. But anyway, I just want to point out you can use the event.beatPos attribute of the event object to determine the exact time location of the incoming beat you're wanting to move. Basing your math off the start of the processing block is a little odd, the processing block has no bearing on the meter whatsoever. Also, since you're rounding it off, and sometimes downwards, you could be rounding it so far down, that its too late to schedule the resulting number you plan to use for the AtBeat function. The number passed into AtBeat needs to be at least as big as info.blockStartBeat. If you pass something smaller, you won't hear it. Next, your Noteoff's have the potential to get confused by making the randomly produced note off occur before the actual NoteOn that was meant to turn off. Keeping track of note on's that require note off's kind of has to be done at the global level and can get complicated. Quote Link to comment Share on other sites More sharing options...
Monkeymonkey35 Posted March 25, 2018 Author Share Posted March 25, 2018 Wow, thanks for that! Now it makes some noise This is a simple a human (playing keyboard) + scripter hybrid sequencer, for idea generation. Noteoff is definitely a problem.. hmmm... Quote Link to comment Share on other sites More sharing options...
Dewdman42 Posted April 3, 2018 Share Posted April 3, 2018 If you’re ok with all notes having the same duration, you can schedule the note off to happen right after you do the event.send. Sendatbeat(). Then block all incoming noteoff’s Quote Link to comment Share on other sites More sharing options...
Monkeymonkey35 Posted April 3, 2018 Author Share Posted April 3, 2018 That's a good idea. There are a bunch of ways to go about this that have slightly different musical effects, but this one is a good standard behavior. Now to figure out how to code it... Will post back if I do! Quote Link to comment Share on other sites More sharing options...
Dewdman42 Posted April 4, 2018 Share Posted April 4, 2018 in HandleMIDI do this: function HandleMIDI(event) { if(event instanceof NoteOff) { return; } } the above will ignore NoteOff events... Then you need code to send NoteOff's so something like this: function HandleMIDI(event) { event.sendAtBeat(A); event.velocity = 0; event.sendAtBeat(A+.5); } Setting velocity to zero is same as sending noteoff. so for each of your notes you send, just send it, add some amount of time (in the above its half a beat) and then send the same event with velocity zero. Quote Link to comment Share on other sites More sharing options...
Monkeymonkey35 Posted April 4, 2018 Author Share Posted April 4, 2018 Not really sure why, but I was able to make this work based on your suggestion: ResetParameterDefaults = true; var NeedsTimingInfo = true; var beatArray = [1,1.5,2,2.3,3]; var cutArray = [.5,2.3,3.3,3.6,4.3,4.6]; var randomBeat = beatArray[Math.floor(Math.random() * beatArray.length)]; var randomCut = cutArray[Math.floor(Math.random() * cutArray.length)]; function HandleMIDI(e) { var info = GetTimingInfo(); var Pos = e.beatPos; if (e instanceof NoteOn) { randomBeat = beatArray[Math.floor(Math.random() * beatArray.length)]; e.sendAtBeat(Math.ceil(Pos) + randomBeat); } else if (e instanceof NoteOff) e.sendAtBeat(Math.ceil(Pos) + randomBeat + randomCut); } Trace("Random Beat: " + randomBeat); Trace("Random Cuttoff: " + randomCut); Maybe because the NoteOff message coming in tells the script to hold that and send it out later? In any event, thanks for the help Quote Link to comment Share on other sites More sharing options...
Dewdman42 Posted April 4, 2018 Share Posted April 4, 2018 Yep as long as the delayed noteoff is always delayed just a little longer then the matching note on.flad you got it working! 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.