Timing, Timing, Timing......
-
OK so I'm trying to build a sequencer, and its slipping out of time pretty badly....
Its a huge (already) script otherwise I'd post a snippet but instead here's some explanation...
OK so everything is currently running in the interface...which might be bad but I cant easily see how I can display the sequencers progress in the UI without running those updates from the sequencer itself...more than willing to be put right on this...
There are three samplers all "playing" at the same time...
The sequencer itself "just" has a simple timer that runs on "start" button, for each timer event it moves a cursor across the screen and checks to see if there's a playing note (noteID ) and if so turns it off then is there is another note to play issues a playNote command.
Its doing some envelope and FX parameter changing in each step too, but that's it.
Nothing is deferred in any way... but it slowly slips out of time...(lag) and seems inconsistent between steps too.
Am I approaching this wrong? Is there a better place to run the sequencer? If so how would I show its "state" in the UI?
Heres a quick look at the (unfinished obviously) UI:
Any suggestions appreciated...
-
@Lindon said in Timing, Timing, Timing......:
OK so everything is currently running in the interface...which might be bad but I cant easily see how I can display the sequencers progress in the UI without running those updates from the sequencer itself...more than willing to be put right on this...
Shouldn't be a problem because the timer is in the non-realtime thread. I always defer callbacks in the interface script by default.
How are you checking the accuracy of the timer? I mean, how do you know it's lagging or going out of time?
-
Actually I'm wrong. Turns out the timer callback is real-time, or at least the main
onTimer
callback is, so I assume individual timers are also real-time.I definitely recommend splitting the real-time stuff from the UI stuff. This won't necessarily be straightforward, depending on how entangled they already are in your project, but I'm 90% sure it's doable. I've had a few situations where I've had to re-think my script logic in order to achieve this. Deferring the UI script by default forces me to think of alternate ways to achieve a desired effect.
-
@d-healey er so are you saying I should be deferring the interface script?
I know its slipping out of thime with that old fashioned appraoch:
I compiled it as a VST,
loaded in to Reaper
ran the plug-in (seq set up to play a note on every beat a)
recorde its output
imported its output back into reaper
--- and saw it didnt line up with the beat markers. it did at the start but after about 2 bars began to slip out of time... -
@d-healey OK more than willing to do that - separating it out (its all in called functions anyway) wont be a big deal....
I can start run and stop the sequencer in the container...but I guess I cant see an obvious way to reflect the seq state in the UI
-
I can start run and stop the sequencer in the container...but I guess I cant see an obvious way to reflect the seq state in the UI
Use the real-time script to update a global variable. In your UI script's deferred timer callback you can read this variable to update the UI.
I'm not sure about the timer drift, I think we'll need some input from @Christoph-Hart - although making the realtime/non-realtime change might fix the issue.
-
@d-healey said in Timing, Timing, Timing......:
I can start run and stop the sequencer in the container...but I guess I cant see an obvious way to reflect the seq state in the UI
Use the real-time script to update a global variable. In your UI script's deferred timer callback you can read this variable to update the UI.
I'm not sure about the timer drift, I think we'll need some input from @Christoph-Hart
yeah thats the only way I could think of doing it....its all a bit sloppy tho (well subject to "visual slop" at least)... but if thats the only way...
-
If you want precise musical timing you need to use the
onTimer
callback, the other ones will run in the UI thread.If you want 100% sample accurate timing, take the timestamp of the timer callback into account (
Message.getTimestamp()
works there also)... -
@Christoph-Hart said in Timing, Timing, Timing......:
If you want precise musical timing you need to use the
onTimer
callback, the other ones will run in the UI thread.So I was half right :)
-
@Christoph-Hart said in Timing, Timing, Timing......:
If you want precise musical timing you need to use the
onTimer
callback, the other ones will run in the UI thread.If you want 100% sample accurate timing, take the timestamp of the timer callback into account (
Message.getTimestamp()
works there also)...OK great - I understand the first part of what you said, but not the second... how would getting the current time(stamp) help me ?
-
@Lindon I assume you can put
Message.getTimestamp()
inside the timer callback to get an accurate timestamp. You can then useSynth.addNote()
instead ofplayNote
to generate a MIDI note with that timestamp. -
@d-healey said in Timing, Timing, Timing......:
@Lindon I assume you can put
Message.getTimestamp()
inside the timer callback to get an accurate timestamp. You can then useSynth.addNote()
instead ofplayNote
to generate a MIDI note with that timestamp.OK well Im still a bit lost in what you are saying about Synth.addNote:
So I'm in my timer call back....
I check Message.getTimestamp()
-- so now I know what time it is (and if I'm late for the party (because - lets say - I worked out the required timestamp value in the last step)
-- let assume I'm late - nothing I can do about it now (cant go back in time) gotta just play the note I need to play...
-- at this point I can tell the timer to "hurry up to the next step" with startTimer(mySeqStepLength minus how_late_I_am)
How does Synth.AddNote() help me here?
--- incidentally I moved the seq to the Engine.getTimer (told you it'd be quick) and that sounds like its fixed it...so I'm really asking these questions in an attempt to have a better understanding...
-
I think Christoph's idea with using the timestamp is that it will prevent notes triggering early, but this won't help if the notes are triggering late. Yeah moving the GUI stuff out should make a big difference :)
-
@d-healey said in Timing, Timing, Timing......:
I think Christoph's idea with using the timestamp is that it will prevent notes triggering early, but this won't help if the notes are triggering late. Yeah moving the GUI stuff out should make a big difference :)
Oh yeah - of course. Thanks for your help (and you too Christoph...)