General
Midiout delay?
Started by kraftf on .
Sign in or create an account to join the conversation.
How can a midiout message be delayed in a script?
I guess the time function has to be used. Can someone please help me out this?
I guess the time function has to be used. Can someone please help me out this?
Haven't play with that yet, but basically you need an OnFrame script, which is called about 60 times per second, but depends of the complexity of the project.
Then some variables (expression) to store the time you want the midi out and one to store the midi out message.
It can become a little tricky if you excpect more than one message to be delayed and at different time.
Then some variables (expression) to store the time you want the midi out and one to store the midi out message.
It can become a little tricky if you excpect more than one message to be delayed and at different time.
I just want to delay the noteoff message that is attached to the noteon in a script.
In other words I want to define the hold/decay parameter of the note on. Still I can't see how I can use the frame function. It would have been a lot easier if there was a function to stall the script for a specific amount of time.
Maybe I should give a look at the sequencer examples. They surely use time functions.
In other words I want to define the hold/decay parameter of the note on. Still I can't see how I can use the frame function. It would have been a lot easier if there was a function to stall the script for a specific amount of time.
Maybe I should give a look at the sequencer examples. They surely use time functions.
You'll have to figure out the syntax, but you should be able to do something like this:
on a noteon event
...send a noteon
...oldTime = time
...trigger = true
if trigger == true and time-oldTime >= hold
...send a noteoff
...trigger = false
You probably can also do it with a multiball using its adsr.
Hope this helps.
on a noteon event
...send a noteon
...oldTime = time
...trigger = true
if trigger == true and time-oldTime >= hold
...send a noteoff
...trigger = false
You probably can also do it with a multiball using its adsr.
Hope this helps.
Hi
Wouldn't it be better to use the time function which would allow you to set i more accurately?
MM
Wouldn't it be better to use the time function which would allow you to set i more accurately?
MM
Thanks very nuch for the suggestions.
I'll try them and let you know about the results.
I'll try them and let you know about the results.
Well I didn't actually try your suggestions.
I would like to decribe my situation a little bit more.
I am having a for loop sending out midiout sysex events in a script.
It's a button which scans a multislider's vector values and sends 16 different sysex messages. What I am asking is if it is possible to dealy the actual for loop. Instead of sending instantly all the 16 messages to pause for an amount of time inside the for loop.
Is it possible to di this with the time function.
Any ideas?
I am attatching this multislider.
Another problem I have is that I cannot send simultaneously more than fader because one variable inside the sysex message that corresponds to the midi channel gets stuck to the prevailing fader that moves.
I know I can setup 16 different messages and assign expicitly all the items of the vector but I don't want to do that.
Multislider auto to sysex.zip
I would like to decribe my situation a little bit more.
I am having a for loop sending out midiout sysex events in a script.
It's a button which scans a multislider's vector values and sends 16 different sysex messages. What I am asking is if it is possible to dealy the actual for loop. Instead of sending instantly all the 16 messages to pause for an amount of time inside the for loop.
Is it possible to di this with the time function.
Any ideas?
I am attatching this multislider.
Another problem I have is that I cannot send simultaneously more than fader because one variable inside the sysex message that corresponds to the midi channel gets stuck to the prevailing fader that moves.
I know I can setup 16 different messages and assign expicitly all the items of the vector but I don't want to do that.
Multislider auto to sysex.zip
AFAIK there is no sleep function in Lemur.
The only option I see as I stated before is to use an OnFrame script. You can use it together with the time function.
So instead of having your for loop, create a variable and set it to 16 when you need to send your sysex.
Decrease this value by one each time until it reaches 0.
Actually instaed of using the on expression trigger it's better to do everything in the on frame script taking care yourself of what has changed.
OnFrame
if( (time- prevtime) < delay) return;
d = A -x;
i = firstof(d);
if(i < sizeof(x))
{
//send your sysex for i;
A = x;
prevtime = time; // reset the timer
}
The only option I see as I stated before is to use an OnFrame script. You can use it together with the time function.
So instead of having your for loop, create a variable and set it to 16 when you need to send your sysex.
Decrease this value by one each time until it reaches 0.
Actually instaed of using the on expression trigger it's better to do everything in the on frame script taking care yourself of what has changed.
OnFrame
if( (time- prevtime) < delay) return;
d = A -x;
i = firstof(d);
if(i < sizeof(x))
{
//send your sysex for i;
A = x;
prevtime = time; // reset the timer
}
Thanks man for the script.
I am getting into the time scripting idea slowly.
The script works overy well for delaying a message.
However it relys on the timing of Lemur.
To get more specific I am trying to build some pads that send continuus midi notes delayed according to a bpm setting and note value. Like mpc has the note repeat function.
Regarding timing and the delay method that you've kindly suggested it works fine but the problem is that I can't trigger the notes the time that I press the pad. THe notes get triggered according to the internal timimg of Lemur.
How could possibly trgger for eg a sequence of 16th midi notes from pad as long as the pad is being held. I guess I have to find out how the sequencer tempates work. I tried but I couldn't make it.
Any help would be highly appreciated.
I am getting into the time scripting idea slowly.
The script works overy well for delaying a message.
However it relys on the timing of Lemur.
To get more specific I am trying to build some pads that send continuus midi notes delayed according to a bpm setting and note value. Like mpc has the note repeat function.
Regarding timing and the delay method that you've kindly suggested it works fine but the problem is that I can't trigger the notes the time that I press the pad. THe notes get triggered according to the internal timimg of Lemur.
How could possibly trgger for eg a sequence of 16th midi notes from pad as long as the pad is being held. I guess I have to find out how the sequencer tempates work. I tried but I couldn't make it.
Any help would be highly appreciated.
The idea is the same, if you have a tempo of 100 bpm this means that a beat is played every 0.6 sec (60/100) and as a 1/16 is a quarter of a beat your delay is then 0.15 sec.
The other option is to sync to an external midi clock, in this case you need to watch incoming midi clock values. I made a small template that shows how it works somewhere in this forum. As there are 24 midi ticks per beat, trigger a note every 6 ticks for 1/16 th. Note that this method is not very good due to midi jitter, normally a sequencer will use it's internal clock and adjust smoothly to the incomming midi clocks.
To trigger notes only when you press a button, in the on frame script check the state of your button, if it's value is one then send the note(s), otherwise just leave the procedure. But don't forget to send note off or you may have hanging notes.
The other option is to sync to an external midi clock, in this case you need to watch incoming midi clock values. I made a small template that shows how it works somewhere in this forum. As there are 24 midi ticks per beat, trigger a note every 6 ticks for 1/16 th. Note that this method is not very good due to midi jitter, normally a sequencer will use it's internal clock and adjust smoothly to the incomming midi clocks.
To trigger notes only when you press a button, in the on frame script check the state of your button, if it's value is one then send the note(s), otherwise just leave the procedure. But don't forget to send note off or you may have hanging notes.
Thabks again for your help.mbncp wrote:The idea is the same, if you have a tempo of 100 bpm this means that a beat is played every 0.6 sec (60/100) and as a 1/16 is a quarter of a beat your delay is then 0.15 sec.
The other option is to sync to an external midi clock, in this case you need to watch incoming midi clock values. I made a small template that shows how it works somewhere in this forum. As there are 24 midi ticks per beat, trigger a note every 6 ticks for 1/16 th. Note that this method is not very good due to midi jitter, normally a sequencer will use it's internal clock and adjust smoothly to the incomming midi clocks.
To trigger notes only when you press a button, in the on frame script check the state of your button, if it's value is one then send the note(s), otherwise just leave the procedure. But don't forget to send note off or you may have hanging notes.
I have to get myself a little more clear.
I have aready dane what you suggest regarding the on/switch.
I have ascript running on Frame which sends a midi noteon and off and I have set a delay time set to 60/BPM
value for generating delayed 1/4 notes as long as the pad is held. It is working but the timing of the second is not correct because it is generated according to the fixed xlock of Lemur. How can I extrapolate the internal timing to start from the time I press the button. Tried using new time variables with no success. There should be a similar way to do this like when constructing a sequencer start stop but I can't connect them.
I also don't want to sync to a midi clock.
Not sure I get this right, but when you hit the button you should set some variable to the current time as you probably want the first note right away.
triggertime = time;
Given that the function is called every 1/60 sec, to compensate, you could write:
triggertime = time-1/120;
Then, in the on frame scrip:
if(mybutton.x == 0) return;
if(triggertime > time) return;
// send your note
triggertime+=60/BPM;
triggertime = time;
Given that the function is called every 1/60 sec, to compensate, you could write:
triggertime = time-1/120;
Then, in the on frame scrip:
if(mybutton.x == 0) return;
if(triggertime > time) return;
// send your note
triggertime+=60/BPM;
No its not working like the way you suggest. However I am not sure where you put the triggertime variable inside or outside the script.mbncp wrote:Not sure I get this right, but when you hit the button you should set some variable to the current time as you probably want the first note right away.
triggertime = time;
Given that the function is called every 1/60 sec, to compensate, you could write:
triggertime = time-1/120;
Then, in the on frame scrip:
if(mybutton.x == 0) return;
if(triggertime > time) return;
// send your note
triggertime+=60/BPM;
Also I think that time is returning ms and not second as you suggest. Still trying but no success.
My problem is how to define the limited conditions. Its nit vflear for me yet.
NoteOnTime.jzml.zip
It's working here, the triggertime variable has to be outside the script as I assume local variables get cleared. Also yo wouldn't be able to access a variable declared in another script.
And the time is indeed in seconds.
It's working here, the triggertime variable has to be outside the script as I assume local variables get cleared. Also yo wouldn't be able to access a variable declared in another script.
And the time is indeed in seconds.
Well yes its working!!
I didn't put the "triggertime = time-1/120;" in another script!It was not clear from your message.
I tried all combinations except that.
Thanks a lot. Your help is valuable!
I didn't put the "triggertime = time-1/120;" in another script!It was not clear from your message.
I tried all combinations except that.
Thanks a lot. Your help is valuable!
Hi
I have not had much time to look into this but have given it some thought and a possible solution . .
I don't think 'On Frame' is the best way to go -due to jitter and granularity, frame rate can possibly vary depending on graphic complexity and 16.66r msec frame rate . . .
The time() function actually returns time to microsecond resolution (with precision set to 6) not that we need delays that fine-grained . .
time%1 will give a 0 -.999999 second ramp from which you can capture the press time=now which becomes the 'offset' within any given second . . .
1/4 note delay @60bpm = .25 sec, therefore the note and delayed notes equals 'now' (offset), (offset+.25)%1, (offset+.5)%1, (offset+.75)%1,
Of course the BPMs etc would do with numeric representations linked to time definitions for programmatic ease of use by calculating mSec delay value
Hope that explains it well enough, have not had time to code up solid examples but the principle is sound imho
Cheers
MM
I have not had much time to look into this but have given it some thought and a possible solution . .
I don't think 'On Frame' is the best way to go -due to jitter and granularity, frame rate can possibly vary depending on graphic complexity and 16.66r msec frame rate . . .
The time() function actually returns time to microsecond resolution (with precision set to 6) not that we need delays that fine-grained . .
time%1 will give a 0 -.999999 second ramp from which you can capture the press time=now which becomes the 'offset' within any given second . . .
1/4 note delay @60bpm = .25 sec, therefore the note and delayed notes equals 'now' (offset), (offset+.25)%1, (offset+.5)%1, (offset+.75)%1,
Of course the BPMs etc would do with numeric representations linked to time definitions for programmatic ease of use by calculating mSec delay value
Hope that explains it well enough, have not had time to code up solid examples but the principle is sound imho
Cheers
MM
Sounds good and indeed there is jitter with the onframe approach.Macciza wrote:Hi
I have not had much time to look into this but have given it some thought and a possible solution . .
I don't think 'On Frame' is the best way to go -due to jitter and granularity, frame rate can possibly vary depending on graphic complexity and 16.66r msec frame rate . . .
The time() function actually returns time to microsecond resolution (with precision set to 6) not that we need delays that fine-grained . .
time%1 will give a 0 -.999999 second ramp from which you can capture the press time=now which becomes the 'offset' within any given second . . .
1/4 note delay @60bpm = .25 sec, therefore the note and delayed notes equals 'now' (offset), (offset+.25)%1, (offset+.5)%1, (offset+.75)%1,
Of course the BPMs etc would do with numeric representations linked to time definitions for programmatic ease of use by calculating mSec delay value
Hope that explains it well enough, have not had time to code up solid examples but the principle is sound imho
Cheers
MM
Anyway I have completely no idea on how to use in a script the time values produced in by the time%1 expression.
I can understand the approach with the offset but have no idea how to speak to Lemur!
Help needed.
@Macciza
??? I don't see a time() function, there is a time in-built variable, which I use in the example above.
triggertime = time-1/120;
...
if(triggertime > time) return;
...
triggertime+=60/BPM;
The OnFrame is not used to calculate the timing, it's just there to trigger the event as I don't see a better way to do it as there is no way to send a midi event at a specific time.
Off course there will be some jitter due to the OnFrame lack of precision (not even speaking about midi over wifi), but globally things should stay in (internal) sync over time.
??? I don't see a time() function, there is a time in-built variable, which I use in the example above.
triggertime = time-1/120;
...
if(triggertime > time) return;
...
triggertime+=60/BPM;
The OnFrame is not used to calculate the timing, it's just there to trigger the event as I don't see a better way to do it as there is no way to send a midi event at a specific time.
Off course there will be some jitter due to the OnFrame lack of precision (not even speaking about midi over wifi), but globally things should stay in (internal) sync over time.
I tried the time%1 option and put it in the trigger of a custom midi message in the form of x*time%1. It produces the time varying triggers of the midi message but again it's fixed on the Lemur internal timing. I can't think of a way to set repeating triggers of a midi message relative to the time variable.mbncp wrote:@Macciza
??? I don't see a time() function, there is a time in-built variable, which I use in the example above.
triggertime = time-1/120;
...
if(triggertime > time) return;
...
triggertime+=60/BPM;
The OnFrame is not used to calculate the timing, it's just there to trigger the event as I don't see a better way to do it as there is no way to send a midi event at a specific time.
Off course there will be some jitter due to the OnFrame lack of precision (not even speaking about midi over wifi), but globally things should stay in (internal) sync over time.
I have to study the sequencer start/stop that are available. Maybe the answer is there.
Thanks for this, I've been working on output timing as well.
mbncp wrote:AFAIK there is no sleep function in Lemur.
The only option I see as I stated before is to use an OnFrame script. You can use it together with the time function.
So instead of having your for loop, create a variable and set it to 16 when you need to send your sysex.
Decrease this value by one each time until it reaches 0.
Actually instaed of using the on expression trigger it's better to do everything in the on frame script taking care yourself of what has changed.