|
Post by joebataz on Mar 1, 2019 6:15:12 GMT
This is my dilemma currently. I am using a DMXIS box to control my lighting. Works great, you program a bunch lights and you save them as a Preset. Presets belong to Banks. Banks are selected on channel 15, Presets on 16. All the code for this works pretty well. But lighting designers like lots of looks, especially concert lighting. So I have roughly 20 Banks and up to 32 Presets under each Bank. Now we're into an awful lot of lighting Preset, 640. No I don't have that many, I hover around 225 to 250. But that's a hell of a lot to search for a couple of Presets. Right now my app handles the lights by using the following code:
noteout(0,BNote,127,15); bank on noteout(0,BNote,0,15); bank off noteout(0,PNote,127,16); preset on noteout(0,PNote,0,16); preset off
I set the note off messages because the hardware doesn't like it when all you're sending are note on messages.Still with me? Good... Because of the number of Presets I thought that it would be easier to be able to send Bank and Presets using Sets, groups of Bank/Presets so:
if(subarray(a,0,1) != 99) <== this is a check to see if the set has Bank/Presets in it 99 means a blank set. { noteout(0,subarray(a,0,1),127,15); noteout(0,subarray(a,0,1),0,15); noteout(0,subarray(a,1,1),127,16); noteout(0,subarray(a,1,1),0,16); }
Now comes the fun. Lemur merrily pumps out these noteout messages BUT the box can't receive them as fast as they're being sent. I wind up getting only the first, the rest of them still transmit but the box doesn't do anything when the codes are coming at these speeds.
fc = 0; if (fc >c){ if(subarray(a,0,1) != 99) { noteout(0,subarray(a,0,1),127,15); noteout(0,subarray(a,0,1),0,15); noteout(0,subarray(a,1,1),127,16); noteout(0,subarray(a,1,1),0,16); } }
fc is a variable thats sits in an "on Frame". The code in there is fc++
So the real issue I have is how to slowup the rate RELIABILY. Thanks
joeb
|
|
|
Post by xPsycHoWasPx on Mar 1, 2019 19:27:55 GMT
Is the note-offs necessary for the DMX box to receive the next input? Ain't the note on enough?
As a alternative try execute the note-ons first then note offs Normal I would say it was only needed if the node both turned something on and off.
But why subarray if you only want 1 value?
if(subarray(a,0,1) != 99) { noteout(0,subarray(a,0,1),127,15); noteout(0,subarray(a,0,1),0,15); noteout(0,subarray(a,1,1),127,16); noteout(0,subarray(a,1,1),0,16); }
Could easy have been written like this.
if (a[0] !=99) { noteout(a[0], 127,15); Etc.... }
|
|
|
Post by quartzite on Mar 1, 2019 19:30:44 GMT
My strategy for this in the past has been to put the later send messages in a script that runs on frame, inside an if statement that only sends if a timer is past a certain time and a boolean trigger has been turned on. Then when they send they turn the trigger off.
I'd like to know a better strategy for this myself.
For example, this onFrame script:
if(startTimerTrigger == 1 && (startTimer + .5 < time)) { noteout(0,5,0,16); startTimerTrigger = 0 }
The startTimer and startTimerTrigger are both set by the "initial" script that sends the messages that don't need to be delayed
|
|
|
Post by xPsycHoWasPx on Mar 2, 2019 15:57:17 GMT
onframe executing could be the answer only problem is now u got a script running all the time I know the first if rule will make the script ignore everything but its still being triggered 60 times every sec. but after abit of fooling around I might cooked another solution: delayed_actions.jzlib (6.98 KB) this method does need a few expressions to run, and a trigger script + the script that execute all the actions but its only triggers as long the enable expression is 1 and time is under or equal to the new time u want it 2 trigger on. it rely on these 2 scripts write(): decl a; 'Writes the delay index'; for (a=0;a<max;a++) { new[a]=time+((delay/1000)*(a+1)); } count = 0; 'resets the counter for the delayed script'
enable = 1; 'once enable becomes 1 , the delayed_action script will start to trigger, because it are using a if rule as trigger then it wont run unless time is (under or =) the delay array created in new we could call this a (passive time trigger)' delayed_actions(): instead of using onframe we will use this trigger code instead :
(enable==1 & (time<=new[count])) ? time : 0 based on the "a?b:c" from lemur manual its same as if rule but can be used in triggers so it will check if A statement is true and if true it will use b as trigger in this case time as trigger if A is false it will use C as trigger and 0 won't trigger the script. and u can mix [] into the statement 2, so count will first check first val in delay array once script changes count to 1 it will now use 2nd value to compare time ect.. making the trigger now a somewhat dynamic trigger. if (time>=new[count]) { 'action after delay' Monitor.value='action '+(count+1)+': '+floor( (time-old)*1000 )+ ' ms has passed';
count += 1; }
if (count == max) { 'do something when done' Pad.x=0; //Monitor.value=time; //(this was used to test if the trigger would still trigger after time has passed "new", and yes it only updates it the current time on next frame and no more) } for your needs : if (time>=new[count]) { 'action after delay'; Monitor.value='action '+(count+1)+': '+floor( (time-old)*1000 )+ ' ms has passed';
count += 1; } can be replace with if (time>=new[0]) { noteout(0,subarray(a,0,1),127,15); } if (time>=new[1]) { noteout(0,subarray(a,0,1),0,15); } if (time>=new[2]) { noteout(0,subarray(a,1,1),127,16); } if (time>=new[3]) { noteout(0,subarray(a,1,1),0,16); }
if you only want to trigger 4 commands each time the script is activated then set the max expression to 4. As a standard the delay expression is set to "100" ms but u can change it whatever u want, just note that lemur only updates 60 times a sec, so its accuracy is +16.6 ms meaning the trigger will start anywhere between 100ms and 116.6ms if delay is set to 100 but this is the same deal with onframe executing 2. hope this is what you are looking for. kinda happy u asked that question, because I puzzled in the past to do something like this, but no clue how.. but time passes and u get smarter :-)
|
|
|
Post by xPsycHoWasPx on Mar 2, 2019 18:27:54 GMT
I checked out the DMXiS So it's a app controlling a box that sends DMX outputs.
May I ask why u haven't considered using the buildin OSC server ? I did a quick check with a OSC monitor and I see controlling it by OSC is pretty straight forward. It even sends the names of presets when u pick a bank.
It also skips the need of using the lemur daemon since OSC can send directly from iPad lemur to the DMXIS app. If u need help with osc part I could easy sniff the OSC addresses for you.
|
|
|
Post by joebataz on Mar 3, 2019 6:23:09 GMT
Thanks guys, I have had a few harrowing days at work and I've got a little time to respond; First, BIG THANKS for all the new insights. I'll be jumping on them staring Monday.
At one point in time I was running the DMXIS app in plug-in mode in Abelton Lite it was there I discovered the note off issue and was never really sure if it was Abelton or DMXIS. I actually had it working REALLY well and went kind of nuts. Programmed about 20 tunes (Classic rock mostly) but the programming was long and tedious and I wasn't really thrilled with the overhead of Abelton.
The way I had it working is that the DMXIS plugin was sitting in a midi track by itself. The first track was a purely Audio channel where I put the song itself. In track 2 and 3 were midi out ports, one going to, 2 sending the bank (channel 15) and 3 sending the preset (channel 16). CAVEAT 1: First problem I ran into was that channel 15 and 16 both have the same range of notes, so I couldn't have them stepping on each other. I was using step input so my first bank note would go to where it was supposed to but the next preset note would go in 2 octaves higher. The step value was set to 1/64. Meaning each send to the midi tracks of 2 1/64 notes were a 1/32 note.So my minimum spacing between changes was 1/32. Hopefully you're following this. Of course we still have aa note sittin 2 octaves too high. The reason behind this was that I could save the midi track and not worry about confusing banks from presets. Between the send from track 3 and the input to the DMXIS plugin i put a keymapping filter that took track 3 back down. Great theory and execution until I started doing gigs using this setup. Abelton, although there are those that differ, is NOT a DJ application so it was difficult to cue up the music and lighting tracks quickly enough. So after all this initial work I added 100s of scenes (Banks + Presets) and realized how difficult it would be to maintain so I packed up the entire setup and went back to just putting together a Lemur Touch interface. But I was missing fades and building up sets from different scenes. These are the guitar note bends, a brilliantly lit stage dropping to just a couple of focused lights. The art of lighting. Over the 5 years of using the system I tried maybe 2 dozen different versions of the app but was never happy (damn perfectionist)
|
|
|
Post by joebataz on Mar 3, 2019 6:48:39 GMT
The key was always being able to build up a look by "layering" individual sets together rapidly which brings me closer to my current project. A couple of years ago I got frame based timing working so I could really make things pop how I wanted. An event precluded me from finishing and cost me time and money. Now I'm back to having the ability to pound this thing together, most of the interface is done but I'm needing to get the framing working again. To give you an idea of how far I push lighting Santana's Black Magic Woman had over 400 preset points in it. I think I'm going to try to go the OSC route this time. But unfortunately that will have to be after one more day in the salt mines. Going to try to post an old (5+ years ago) example of what my lighting set was. It's actually a little bigger and with a lot more movement. Thanks again!!! joeb
this is a led strip controller I designed and built. I have eight of these strips setup in a fan that opens
|
|
|
Post by joebataz on Mar 4, 2019 7:14:13 GMT
OK, still trying to figure out the whole expression as a trigger. Seems elegant and I think I sort of understand it but got something wrong with the delay value. I've cranked it as high as 50000 and the notes still come flying out. Here how I have it setup. write() decl a; for (a=0;a<max;a++) { new =time+((delay/1000)*(a+1)); } count = 0; enable = 1;
delay_action
decl a = SSet;
if (time>=new[0]) { AAmsg = '#1'; if(a[0] != 99){ noteout(0,a[0],127,15); noteout(0,a[0],0,15); noteout(0,a[1],127,16); noteout(0,a[1],0,16); }} if (time>=new[1]) { AAmsg = '#2'; if(a[0] != 99){ noteout(0,a[2],127,15); noteout(0,a[2],0,15); noteout(0,a[3],127,16); noteout(0,a[3],0,16); }} if (time>=new[2]) { AAmsg = '#3'; if(a[0] != 99){ noteout(0,a[4],127,15); noteout(0,a[4],0,15); noteout(0,a[5],127,16); noteout(0,a[5],0,16); }} if (time>=new[3]) { AAmsg = '#4'; if(a[0] != 99){ noteout(0,a[6],127,15); noteout(0,a[6],0,15); noteout(0,a[7],127,16); noteout(0,a[7],0,16); }} if (time>=new[4]) { AAmsg = '#5'; if(a[0] != 99){ noteout(0,a[8],127,15); noteout(0,a[8],0,15); noteout(0,a[9],127,16); noteout(0,a[9],0,16); }} if (time>=new[5]) { AAmsg = '#6'; if(a[0] != 99){ noteout(0,a[10],127,15); noteout(0,a[10],0,15); noteout(0,a[11],127,16); noteout(0,a[11],0,16); }} enable = 0;
|
|
|
Post by xPsycHoWasPx on Mar 4, 2019 10:11:36 GMT
I also posted one mistake in the script
if (time>=new[0]) { noteout(0,subarray(a,0,1),127,15); } if (time>=new[1]) { noteout(0,subarray(a,0,1),0,15); } if (time>=new[2]) { noteout(0,subarray(a,1,1),127,16); } if (time>=new[3]) { noteout(0,subarray(a,1,1),0,16); } should have been this , because we don't want delay before executing the first hideout only after, my bad.
noteout(0,subarray(a,0,1),127,15); if (time>=new[0]) { noteout(0,subarray(a,0,1),0,15); } if (time>=new[1]) { noteout(0,subarray(a,1,1),127,16); } if (time>=new[2]) { noteout(0,subarray(a,1,1),0,16); }
Wasnt the idea to put a delay between the 4 noteouts ?
Because the way you setup the timing then it will wait the delay And now instant trigger all 4 x noteouts
But before I can tell you how to execute it right I need bit info
As far as I understand your problem is if u send out a noteon/noteoff to pick Bank then a noteon/off to pick Preset in the bank and then somewhere along the way the DMXIS skips some of the msgs like its to slow to receive them ?
1. so a delay between sending the note to pick bank and note that picks preset is needed right ? or you need delay between each time you sended out bank/preset because you are going to send 4-5 bank/preset each trigger
as I understood it you wanted to do
noteout(bank) - on delay (100 ms) noteout(bank) - off delay (100 ms) noteout(preset) - on delay (100 ms) noteout(preset) - off delay (100 ms) but the code u posted does :
delay (100 ms) noteout(bank) - on noteout(bank) - off noteout(preset) - on noteout(preset) - off
2. if u only going to send out 1 x preset/bank, then your if(a[0] != 99){ } is not enough, and actually it should just be used 1 time surrounding all of your coding, not every time u want execute a part of it, because != is more a global IF rule since it allows everything to pass but 99 also:
enable = 0; MUST be contained by
if (count == max) { enable=0; } else it will run the script for 1 frame and instant disable it.
and what exactly does SSet contain when script is triggered ? looks like an Array what is the data ? {bank0,preset0,bank0,preset1,bank0,preset1,bank0,preset2} ect?
if you can clarify this abit more then I could properly quickly write the code needed for all of this.
|
|
|
Post by joebataz on Mar 4, 2019 17:05:31 GMT
Getting closer... A delay is only needed between pairs of notes, not each note/ Sending a set over consists of sending from 1 to 6 pairs of notes with both on and off so we have (the following is not code)
START OF SET note on B note off B note on P note off P DELAY ( time from 100 to adjustable ms) note on B note off B note on P note off P DELAY ( time from 100 to adjustable ms) note on B note off B note on P note off P DELAY ( time from 100 to adjustable ms) note on B note off B note on P note off P DELAY ( time from 100 to adjustable ms) ... ... ... END OF SET
You are correct SSet does carry the array but in this format {bank0,preset0,bank1,preset1,bank2,preset2,bank3,preset3....} When I initialize a set all members of the set have 99 as in {99,99,99,99,99,99,99,99,99,99,99,99} which is the reason for if(a[0] != 99){ } But as you can see below in the midi log the 99's are still getting sent. Also note the times are all the same and that is where the issue is. They MUST be different for the box to work. Again, BIG THANKS!!! joeb
613334819030751 From Session 1 Note On 15 C♯-1 127 613334819030751 From Session 1 Note Off 15 C♯-1 0 613334819030751 From Session 1 Note On 16 C♯-1 127 613334819030751 From Session 1 Note Off 16 C♯-1 0 613334819030751 From Session 1 Note On 15 D-1 127 613334819030751 From Session 1 Note Off 15 D-1 0 613334819030751 From Session 1 Note On 16 C♯-1 127 613334819030751 From Session 1 Note Off 16 C♯-1 0 613334819030751 From Session 1 Note On 15 D♯-1 127 613334819030751 From Session 1 Note Off 15 D♯-1 0 613334819030751 From Session 1 Note On 16 C♯-1 127 613334819030751 From Session 1 Note Off 16 C♯-1 0 613334819030751 From Session 1 Note On 15 D♯7 127 613334819030751 From Session 1 Note Off 15 D♯7 0 613334819030751 From Session 1 Note On 16 D♯7 127 613334819030751 From Session 1 Note Off 16 D♯7 0 613334819030751 From Session 1 Note On 15 D♯7 127 613334819030751 From Session 1 Note Off 15 D♯7 0 613334819030751 From Session 1 Note On 16 D♯7 127 613334819030751 From Session 1 Note Off 16 D♯7 0 613334819030751 From Session 1 Note On 15 D♯7 127 613334819030751 From Session 1 Note Off 15 D♯7 0 613334819030751 From Session 1 Note On 16 D♯7 127 613334819030751 From Session 1 Note Off 16 D♯7 0
|
|
|
Post by joebataz on Mar 4, 2019 17:20:58 GMT
WHOOPS... The times must be different between PAIRS. The first 4 entries are OK at the same time but the next 4 must be at a different time, etc.
sorry 'bot that
joeb
|
|
|
Post by joebataz on Mar 5, 2019 0:43:31 GMT
So 7 hours later, 2 with Apple and Audio Midi Setup, here is where I am:
write()
decl a; for (a=0;a<max;a++) { new=time+((delay/1000)*(a+1)); }
SendSet() same as Delayed action
decl a = SSet; if (time>=new[0]){ if(a[0] != 99){ noteout(0,a[0],127,15); noteout(0,a[1],127,16); }} if (time>=new[1]){ if(a[2] != 99){ noteout(0,a[2],127,15); noteout(0,a[3],127,16); }} ... ... if (time>=new[5]){ if(a[10] != 99){ noteout(0,a[10],127,15); noteout(0,a[11],127,16); }} if (count == max){ enable = 0; AAmsg = 'finish'; }
MIDI LOG with time between
12766423538138 From Daemon Input 1 Note On 15 C♯-1 127 5858 12766423543996 From Daemon Input 1 Note On 16 D-1 127 278 12766423544274 From Daemon Input 1 Note On 15 D-1 127 146 12766423544420 From Daemon Input 1 Note On 16 A-1 127 115 12766423544535 From Daemon Input 1 Note On 15 D♯-1 127 132 12766423544667 From Daemon Input 1 Note On 16 A-1 127
|
|
|
Post by xPsycHoWasPx on Mar 5, 2019 9:32:20 GMT
I have properly also done a mistake For one moment forgot myself how the concept was working its like a loop based meaning u can't put more if (time >= new [count]) into it because the rule only is trigger when its = or over the delayed time, it must also have, count += 1; because once time is passed the first delay then it must use the next else it just have a reason to trigger always. can't do if (time == new [count]) because each frame is 16,6 ms so u will never hit the time 100% with frames of course u could but then u must always remember how much delay 3 frames is (3x16.6ms) then it have to be changed to frame instead of time in the trigger ect **Edit frame doesn't work like the time so frames can't be used after all..** but as I see your script then between each if rule u just jump from 0 to 1 and 1 - 2 and I guess it because SSet will changed each time u call it so u you just want it from 0 - 15 whatever.. meaning all of this can be done with just 1 IF rule: decl a = SSet;
if (time >= new [count]) { if (a[count] != 99) { noteout (0, a[count * 2], 127, 15); noteout (0, a[count * 2 + 1], 127, 16); } count += 1; }
if (count == max) {
enable = 0;
} and if I get this right then SSet will always be {bank,preset} meaning it always becomes 2x what how many times it must run so u can just do in the max expression: sizeof=(SSet)/2 and with delay setting of 200 ms I also did a mistake in the write() new[a]=time+((delay/1000)*(a+1)); should just be new[a]=time+((delay/1000)*(a));
so the first run don't have a predelay because the script does delay(time+100ms) before action I added a new version of delay_testing that does what u want to do: Try this standalone first : delay testing v.2.jzml (7.61 KB) or just import this one into your own, and try see if it works with your SSet (delete the SSet I added, I just did it so script didn't cry about SSet missing) delay testing v.2.jzlib (7.09 KB)
|
|
|
Post by joebataz on Mar 5, 2019 20:06:33 GMT
AAAAAAAAAAAAAAAAaaaaaaaaaaaaaaaaa............... I am SO FRUSTRATED by this! I don't see where I am going wrong. Translations first: You Me Delayed_Actions Sets delayed_actions SendSet
max is always = 5 SSet always has 6 pairs of numbers {B0,P0,B1,P1,B2,P2,B3,P3,B4,P4,B5,P5} Sets is a 4X4 switches array on the Live_Mixer page. Banks is a 1X10 switches array Presets is a 4X6 pads array B_Pads is a 1X8 pads array There are multiple other objects but what we are trying to do exists ONLY in the Sets array. I have used variables and scripts from Delayed_Actions and recreated them under the Sets array. The issue I'm having is SendSet() never executes unless I call it. The "(enable==1 & (time<=new[count])) ? time : 0" doesn't seem to work. Instead of continuing to waste your time and drive myself crazy I'm just going to send the whole damn thing over. Is that OK? thanks, joeb
|
|
|
Post by xPsycHoWasPx on Mar 5, 2019 21:25:09 GMT
Sure just send me, and i take a look
|
|