General

do loop

Started by joebataz on .

Sign in or create an account to join the conversation.

21 posts

Topic starter
Has anyone used a do loop and had it work?
This works, I get the 'bah' message and then the 'humbug' message:

timeMark = floor(time) + time%0.25;
lastTime = floor(time) + time%0.25 + 4;
AAmsg = 'bah';
while(timeMark < lastTime)
{
timeMark = floor(time) + time%0.2;
}
AAmsg = 'humbug';


I never get 'humbug' with this. Why not?

timeMark = floor(time) + time%0.25;
lastTime = floor(time) + time%0.25 + 4;
AAmsg = 'bah';
do
{
timeMark = floor(time) + time%0.2;
}
while(timeMark < lastTime);
AAmsg = 'humbug';
And this never hits 'humbug' (changed lastTime to a local variable, removed the global)


decl lastTime;
AAmsg = 'bah';
lastTime = floor(time)+ time%.01 + 5;
while(1)
{
if(time>lastTime)break;
}
AAmsg = 'humbug';

Is this another Lemur bug that I spend hours (which I now have) banging my head against?
How do you figure that???
for example:
timeMark = floor(time) + time%0.25; timeMark is now equal 100
lastTime = floor(time) + time%0.25 + 4; lastTime is now equal to 104
AAmsg = 'bah';
do
{
timeMark = floor(time) + time%0.2; <<<<<< --------shouldn't THIS increment timeMark? time is running isn't it
}
while(timeMark < lastTime);
AAmsg = 'humbug';

I have also tried this with the internal time variable as in:

lastTime = floor(time) + time%0.25 + 4;
AAmsg = 'bah';
do
{
<<doesn't really matter what goes here. this do loop is just killing time
}
while(time < lastTime);
AAmsg = 'humbug';

I have a monitor that is watching time and it most certainly goes past the lastTime variable so why is it still looping?
Could you give me an example of how to kill time?
Hi Joe,

It seems you are hitting a limit in regards to the number of times a loop is executed. Look at the attached example. The onchange script contains a "classic" endless loop. The variable count countes the number of times the loop is ececuted. In this case count shows the value of 11110 after execution. That leaves me to suspect that the Lemur has inbuilt limits to stop the execution of a script if an abnormal situation is encountered. But I may be totally wrong about that :roll:

Regarding your specific issue with the do loop, take a look at the attachement. Btw. Have you tried to increase the increment of the varialbe timeMark? Just for the giggles 8-)

Cheers,
B.

endlessloop_test.jzml
This is about the third time I've gotten REALLY disgusted with Lemur. I don't see how I can ask a simpler question than this and get an actual answer. I am including EXACTLY the code and the template. Here is the code:

AAmsg = 'start';
lastTime = floor(time)+time%.25+4;
timeMark = floor(time)+time%.25;
while(timeMark<lastTime)
{
timeMark = floor(time)+time%.25;
}
AAmsg = 'end';

WHY does this loop not end? maccazia said something about timeMark never getting larger than lastTime. WHY NOT???? Isn't it incremented being set to the value of time in the while loop? And if not why not? I get absolutely frustrated when I'm spending hours and hours trying to make a simple loop work and it all comes down to WHY specifically does this never get to 'end'. I am including a simple template which I would appreciate someone modifying to show me how to get to 'end'.

dirtSimple.jzml
Hi
Sorry - I focused on the wrong part of my answer and got it wrong, scope and execution issues didn't help either . . .
But I overlooked the crucial issue - for 'time' to have passed, particularly 240 frames, we can't still be executing . . .
Damn even bxsj comment should have 'thrown the switch' - I am pretty sure there has always been an 'escape clause' to avoid those issues.
Remember we are not in a 'realtime rate' but instead a 'frame rate' environment and that sometimes that changes things drastically.
In 'realtime' the do whiles etc recipes you used work, but the can be used in the framed Lemur environment
Within the operation time of the script your test is not fulfilled and I think it's execution abandoned to avoid hanging

So what I did was give timeMark it definition at global level so it is always giving current time via your function
Custom Button.RunA - lastTime = timeMark+4; - sets lastTime to some value and that is all it does.
message -the Monitor object- has a script added
ie disp()

if(floor(timeMark)<lastTime)
AAmsg = 'start';

else
AAmsg = 'end';

The floor(timeMark) was needed to avoid bounce due to the modulo

Hope that makes sense.
MM

dirtySimple.jzml
I sort of understand what you mean but I still can't get this to work.
Here is the task I need.
I have 2 sequences of midi notes (anywhere from 0 to 31) in two arrays. For each pair of those notes I have a set number(time) as in:
A_SeqBank = {0,3,10,0,3,10,0,3,10,6,9,11}
A_SeqPreset = {3,1,1,6,2,2,9,3,3,2,8,6}
A_SeqTime = {1,1,1,2,2,2,3,3,3,4,4,4}

I need to fire the notes in a set a minimum of 40ms apart so I press a custom button for set 1 and I need the following to happen
noteout(0,0,127,15);
delay
noteout(0,3,127,16);
delay
noteout(0,3,127,15);
delay
noteout(0,1,127,16);
delay
noteout(0,10,127,15);
delay
noteout(0,1,127,16);

Of course the above happens in a loop (which is the whole point of this loop stuff) and I just can't ever get this to work. Here's what the code should look like:
if(A_CurFrame < sizeof(A_SeqBank))
{
if(A_CurFrame == 0)
{
noteout(0,A_SeqBank[A_CurFrame],127,15);
DELAY GOES HERE!!
noteout(0,A_SeqPreset[A_CurFrame],127,16);
DELAY GOES HERE!!
A_CurFrame++;
}
do
{
noteout(0,A_SeqBank[A_CurFrame],127,15);
DELAY GOES HERE!!
noteout(0,A_SeqPreset[A_CurFrame],127,16);
DELAY GOES HERE!!
A_CurFrame++;
}
while ((A_SeqTime[A_CurFrame-1] == A_SeqTime[A_CurFrame]) && (A_CurFrame < sizeof(A_SeqBank)));
}

Does that make sense? Everything else I sent in the last template is now working (with a few added functions). And it works extremely well. Just need a better way to save the sequences once I get past this timing issue.

Thanks,

joeb
it is absolutely beyond frustrating that it is so hard to get a 40ms delay between 2 events, frame based or whatever. I'm done with banging my head against this. 5 days of roughly 16 hours a day. I have come to the conclusion that Lemur CAN'T control everything. Understand I have spent several weeks setting up an enormous amount of DMX scenes based on being able to turn them on in sets or individually. The whole silly things works EXCEPT I can't get playing to work because of an inability to get midi to come out in 40ms intervals. Since I can't do that I'm going to have to go back in and reset all my DMX work to individual scenes instead of mixing masked scenes. This means taking the 260 or so DMX scenes and changing them to several thousand scenes. What a HUGE price to pay for 40ms.
Hi
I understand your frustration and have experienced similar over my time as well . . .
Often it can be worse when we are so used to doing things a particular way and it suddenly doesn't work the way we expect . .
Or we get so caught up in making our way work that we forget about the environment in which we are working, I' did that earlier. . .
All I can say is Don't give up - take a break and let inspiration come after some thought - other solutions will be possible . .
Anyway enough psuedo-psycho-babble . . .

I am sure you understand what I mean - it is a Granularity problem, a do while can't exceed it's execution time/frame boundary, I don't think.
Now 40ms is a different thing to 4 sec as was used earlier, and makes it all a lot easier I think.

I would suggest forgetting about 'time' as a reference point for what you want to do
Use 'Frames' as your reference and count/compare frames not time. This is because of the 'Granularity' mentioned earlier - things happen 'per frame'.
At the nominal 60 frames a second which I believe is fairly consistent, (despite disclaimer from the Legacy documentation) frames occur ever 16.66r msecs.
This grain-size means a 1 frame delay is 16.6msec,2-33.2,3-49.8 etc co for your purposes choose either a 1 or 2 frame delay and implement that.

Rather than creating a looping as you would in a realtime environment, make use of the OnFrame 60hz loop implicit to Lemur, makes sense?

Will have a look at this problem - I did have a look at the project you posted and the timing issue there but did not solve anything, not knowing what some of the expected values were and scope of operation etc. The circularity of the various time definitions kept getting me, I think a reference time variable is what is need possibly similar to what I did in the earlier post, or a frame-based approached for short delays.

Hope this makes sense - will have a look at problem and see what comes to mind
Cheers
MM
For every frame displayed, all Lemur scripts are executed. Things happen synchronously, so while a script executes time doesn't "move". The time variable is evaluated at each frame, which typically happens 60 times per second, and less with very heavy templates or lots of scripts. So a loop in a script that waits for time to cross a certain mark will never exit, since time is "frozen" in a way. (Actually there's a watchdog that makes sure script eventually exit and the app is not stuck indefinitely).
Maybe this is not made clear enough in the manual ?
Thanks Macciza and axel_line. My season is coming up and having this template work would vastly simplify what I need to do and replace the tedium with more time for creativity. A couple of things. First I would definitely supplement the manual in regards to how time "works" in the Lemur environment. Even with all the discussions about this point I am still a little fuzzy as to how to implement it effectively. In light of that I would include somewhere on this forum a tutorial topic which contains nothing but Liine generated help content and selected user videos/methods. There are gems of knowledge spread throughout the forum but just about all of them I have found accidentally while searching through for other topics. Same for code. I realize its a lot of effort to do this but I think would help immensely.

Back to my nemesis issue; if I understand this correctly I need 3 frames to achieve my target delay. This would be equivalent to 3 different ascending values of;
floor(time) + time%.25
The following would be in an OnFrame script
cFrame would be equal to
floor(time) + time%.25
playing would be equal to saying I'm in an execution state and I need to start counting frames.
I grab the current cFrame, set fCount (count of cFrames) to 1
When I get to fCount = 3 I execute my noteout, check for termination conditions and reset if not done playing

There is a lot to develop here but I think this is a base concept to work from.

Thanks again,

joeb
Counting frames would be the way to handle it indeed. Achevieving timing precision better than the "frame" unit (which is 60fps, so 16ms) is something we want to enable at some point, but there's no ETA on this.
I am so close now it is actually painful!
Attached is a template which has the very basic elements I need to FINALLY get this working. As a matter of fact it's probably 60% there but as usual just when you think it's safe to dive back in you're missing a large chunk of butt. Here's the problem now:
This is an OnFrame script (PlaySet):

if(playing == 1 && curNote < sizeof(NoteSet))
{
if(frameCounter())
{
noteout(0,A_Notes[curNote],127,15);
noteout(0,B_Notes[curNote],127,16);
curNote++;
frameCount = 0;
if(NoteSet[curNote-1] != NoteSet[curNote])playing = 0;
}
}
else if(curNote == sizeof(NoteSet)) playing = 0;

This is another OnFrame script (frameCounter):

if(playing == 1)
{
if(frameCount == delayFrames)
{
return 1;
}
else
{
frameCount++;
return 0;
}
}

delayFrames is the variable to tweak timing

The issue is the 2 noteout lines next to each other. Sometimes they step on each other. I tried doing this inside the if(frameCounter() statement:
if(curChannel == 'B')
{
noteout(0,A_Notes[curNote],127,15);
curChannel = 'P'
frameCount = 0;
}
else
{
noteout(0,B_Notes[curNote],127,16);
curNote++;
frameCount = 0;
if(NoteSet[curNote-1] != NoteSet[curNote])playing = 0;
curChannel = 'B';
}

But all I get is the A_Notes midi getting sent out in a loop and I never seem to hit the else part which makes zero sense to me. I took the advice of ignoring ANY time references and just going by Lemur frame which seems to have gotten me a lot closer.

TIA for any help/ideas. joeb

basicSend.jzml
Sometimes they step on each other.
Are the notes send out or not? Have you tried a midi monitor to see what gets send out?

Btw, is it really necessary to have multiple "on frame" scripts? When defining two of them (were one even calls the other) they both are called in the "same" Lemur frame. Which can lead to situations were the frame counter is incremented twice in one frame.

B.
One should try avoiding complexity in an already highly complex environment 8-)
OMG!! Could it be??????
Yes, after considerable head banging (as you've all witnessed) and a few temper tantrums. The wise teachings of macciza and axel_line finally got through my thick skull and I have it working, the midi sends at least. I'm now at 95% accuracy (which I can live with) and got the added benefit of being able to control speed for free. Although its a teeny bit slower than I'd like (but I'm a perfectionist) a delay of 6 frames makes everything happy. I totally threw out all the time code and just went with frames. I was pretty DUHHH for awhile but it finally sunk in. I still want to finish the fader based timeline display/controller and want to add back in the sequencer saver (only 12 this time) but I should be able to get a full working version out in time for the May theatre season.

Many thanks to all the forum members who contributed. If you were in AZ we could go shoot scorpions and drink Coronas in the back yard.

Thanks and I'll be less present while I finish up the code!

joeb
bxsj,

Just saw your post as I was writing the last one. Yes, the notes were getting sent, just too fast for the hardware to process them. I only have 2 OnFrame loops and the entire app is at about 4%. Nothing else is really time based so I think I'll be OK. The proof will come when I go out to scope a couple of gigs. I'll be running a couple of Audio apps as well as the DMX application but that'll pretty much be it.

thanks for the comments and help
I haven't followed exactly the whole thread.
At some point I read that you need a delay inside the execution of your code.
Have a look at my implementation in Ambivalent beats of presets. The problem I had that was the execution of the script loading/storing the values which had to scroll a 16 pad object was too fast and it did not produce the right results. So I had to delay it. I've put a hidden button which performs the script action with a delay that has been set explicitly.
Here is the thread:
http://liine.net/forum/viewtopic.php?f=26&t=1154&hilit=Ambivalent&start=10
and the attachment is the Ambivalent Beats-Mod.zip.
I hope it can help you