Hi Alexey,
As i´m beginning to understand and implement the power of "states", i came up with an idea that i could not implement now.
Perhaps it´s already possible in some way, but i did not find a solution?
Example: i have a sw-state "shift", which has not 2, but 3 states (off, 1-time, locked).
So pressing shift causes the next action to be a "shifted" action, while pressing shift a second time will lock the shift-state until it´s pressed again.
Of course i have now more states than button-leds, so my idea was to use blinking leds to show different states.
I tried some things, but could not find a way. I think it could be possible, if function-calls could be executed after some time (as it´s now in triggers: x cycles, 1 second,..).
I would even use different blink-rates (slow/fast) to show more conditions.
E.g. you could have the "Play-Led" to indicate Loop-Mode with slow blinking, while fast blinking would show "Record".
Or the mode switch Tracks/Bus/ACT could be shown that way.
What do you think?
If it´s not already possible - could this be implemented?
I´m thinking of new values in the feedback, where you would choose instead of "value" - "blink-slow", "blink-fast".
And again, i have to thank you for this masterstroke and remind that i really want to donate something ;)
Hi,
I attach "PlayLed" preset so I do not have to type it here and you do not have to follow my text...
It should produce:
* no light in stop (loop independent)
* continuous light in play without loop
* slow blinking in play with loop
* fast blinking in record (loop independent)
To test it, reassign MIDI for PlayLED control (in the Hardware tab, select PlayLED, "Forget MIDI", press your pad, "Assign MIDI"). This button does nothing in that example (but it can do whatever it should). Note that example use one Pad with LED, MIDI signal to light is the same as the MIDI signal it sends when pressed. Just modify MIDI sends if required (4 actions in PlayLED Monitor).
And here is the explanation:
* Transport System control (without MIDI assignments) just has 2 Monitors, for Transport and Loop. They both have the same action: trigger PlayLED Timer Monitor. We could skip Loop monitor, but in case you turn on Loop during playing LED will not start blink. Every time Transport or Loop states are changed, I simply ask PlayLED Monitor to react (note "now" option, "as usual" will produce no effect, since usually that "timer" never triggers,).
* PlayLED has MIDI assigned. That is not a requirement, but "<Use Ctrl MIDI>" was handy in my case. The control has just one timer. That "Timer" has speed "Once". It is not triggered periodically, we do not want it triggers when we do not need blinking (in stop and not looped play).
* In the PlayLED Timer (which is not really a timer as I have explained), I:
1) check "Stop" state, and turn off LED. Final state. No other monitoring will go on till triggered from Transport Monitor.
2) check "Play" with Loop Off, and turn LED on. Final state. No other monitoring will go on till triggered from Transport Monitor.
3) Turn LED on/off dependent on "Play LED State". It is user defined State Set with just 2 states, On and Off.
4) Change "Play LED State" to opposite, note "Loop" and "Set engine state" flags (without first it will not move from On, without second it will not be saved between monitor calls).
5) Dependent either we are in "Play" or in "Rec" (we already know we are in "Loop" if we are in "Play", since "Play" "Without loop" was already configured, with "Final" flag) we retrigger ourself(!) with required delay.
I guess you need as many such configurations as blinking buttons in your setup. MIDI signals, conditions to blink, may be even blinking speed are going to be different.
If you "Tweak configuration..." to the Faderport preset, you can see how I do "Shift". I distinguish between "Shift"+Something (ShiftUsed StateSet) and "just" Shift (which Lock/Unlock). That way it is possible "temporarily unshift" as well. A kind of combined in one key Shift and CapsLock solution.
You are really GENIUS!!!
This is exactly what i was trying to do.
Although i assumed it should be possible in a similar way, i did not find it.
Now i have to spend some more hours trying to completely understand how you are doing it.
I think i´m still missing something about the event-flow and what/when gets triggered.
But with your explanations (i have to re-read them very slowly) i hope to get it.
I also had a look at your "Shift" implementation, i´ve seen details there that will also need some time to make it into my brain ;)
If i may ask for just a little change - that´s the blink-frequency.
I changed it to 1/2 cycles, because 1 sec was to slow for me, but that is also not optimal, maybe just adding options for 3,4 cycles would be nice.
Many, many thanks again for the best ever ControlSurface and also the time you spent on my wish.
Quote from: MarKo on April 25, 2015, 07:12:38 PM
Now i have to spend some more hours trying to completely understand how you are doing it.
I think i´m still missing something about the event-flow and what/when gets triggered.
But with your explanations (i have to re-read them very slowly) i hope to get it.
SONAR call plug-in under 2 conditions only:
- Some MIDI event is received
- ~13 times per second, independent from the MIDI input
"Logic" actions list is what is executed on MIDI events (in the first case).
13 times per second I check system states (what transport is doing, etc) and then execute Monitors (Feedback) which are "armed". State monitors are armed for next cycle once the state is changed and not armed otherwise. Other monitors arm "cycles" are configured in the Action. And there is "Reset Monitor", which arm Monitor explicitly.
I forgot to mention (and set) other important parameter. Priority. Set priority of Transport monitors to 0 and priority of PlayLED to 1. That way you can be sure that in case the transport state is changed, LED start light within 1/13 of second, not 2/13 ( 1/13 till I detect the change + 1/13 after Monitor reset, in case LED Monitor WAS already executed BEFORE state check monitor in the same cycle). But that is really "fine tuning".
Quote
If i may ask for just a little change - that´s the blink-frequency.
I changed it to 1/2 cycles, because 1 sec was to slow for me, but that is also not optimal, maybe just adding options for 3,4 cycles would be nice.
Download the latest version ;)
In case your head still ready to accept even more "programming". You can do "not regular" blinking as well. Add another state to "Play LED State", call it "Nothing". You should see the effect (no other changes required). In the PlayLED Monitor, change condition "Play LED State:ON" to "Play LED State:Nothing". You get one more blinking "pattern".
Quote from: azslow3 on April 25, 2015, 08:40:04 PM
SONAR call plug-in under 2 conditions only:
...
Thanks for the explanations, the picture gets clearer now!
Quote from: MarKo on April 25, 2015, 07:12:38 PM
If i may ask for just a little change - that´s the blink-frequency.
I changed it to 1/2 cycles, because 1 sec was to slow for me, but that is also not optimal, maybe just adding options for 3,4 cycles would be nice.
Quote from: azslow3 on April 25, 2015, 08:40:04 PM
Download the latest version ;)
In case your head still ready to accept even more "programming". You can do "not regular" blinking as well. Add another state to "Play LED State", call it "Nothing". You should see the effect (no other changes required). In the PlayLED Monitor, change condition "Play LED State:ON" to "Play LED State:Nothing". You get one more blinking "pattern".
Man, you are so fast - terrible!
And ok, it´s time now to admit that i´m a programmer myself (a bit ashamed that i have to ask things which seem so logical to you).
But i´m more into GUI-stuff (mostly classic VB6), and one of the key-points i learned is that´s the hardest part to transport the logic of a program/programmer into a nice intuitive GUI for the average user.
In NO way that should sound critical - i know it´s a fun project and how uncountable hours you must have spent.
And i would not know of a much simpler solution either, without spending similar hours.
But i could imagine to help some day eg. with a nice Display-GUI, if you expose it via COM...
i don´t know if this makes sense, perhaps it get´s even more complicated for you.
Quote from: MarKo on April 25, 2015, 09:28:22 PM
But i could imagine to help some day eg. with a nice Display-GUI, if you expose it via COM...
i don´t know if this makes sense, perhaps it get´s even more complicated for you.
Thank you for willing to help, but....
- You have programmed VB6, but are you ready to write VB6 itself, so that it is "average user" friendly? AZ Controller is an interpreter, the GUI is its IDE.
- While AZ Controller is free to use, it is not open source. And I do not want violate any licenses. So I could not use any GPL GUI for example. And I do not want spend money for commercial staff.
- To make it long living and lightweight, I do not use ANY library at all, except Windows RunTime (unavoidable, but pretty stable).
- I am not fun of nice looking GUI. I still program in Emacs for Linux. AZ Controller is developed in Geany.
- As you can see, I implement new featured pretty fast. If I need new combo, I just add it. Any intermediate layer (like COM) is going to slow down the development (and introduce something which can be buggy). The GUI you see is historical, there was no plans to make the plug-in so powerful as it is now. And I have no idea how far I am going to go with it.
- After the preset is configured, you do not need the interface. So I do not think its old style is so disturbing.
- Most users are waiting for "ready to use" preset. My "build-in" presets are generated from C code, not inside the GUI
In general, every time I think to improve look/fell of this GUI, I remember all that and decide to implement yet another useful controller feature instead 8)
Quote from: azslow3 on April 25, 2015, 11:28:37 PM
Thank you for willing to help, but....
i completely agree with all your arguments and hope you did´nt get me wrong!
as i´ve said - in no way that was meant critically, maybe you misunderstood.
i was just talking about the display (the matrix), because i´ve seen that in other plugin.
this guy also spliltted the real plugin (C++) from just the display (VB6), because it´s much easier to get relativelly nice GUI.
I was not talking about the plugin-gui itself (the logic part) - that seems impossible, since you see that i have even problems in using it with all it´s possibilities.
Sorry, my fault.
Yes, Display (what is now is text matrix) should be reworked at some point.
In todo list I have support font selection, bg and fg colors and may be bg image
But what could be really nice is a (WYSIWYG) editor (think of dialog editor) with the following elements:
- Label (static)
- Text (what you see now)
- Border (panel)
- Image
- "Knob"
- "Fader"
- "Switch" (to display state graphically)
Unfortunately, taking (2) and (3) into account that is not a one week job.
I would not say that a nice display is SO important, but it´s always something people look at.
In fact, i´m not using it that much, so for me personally i would´nt spend too much either.
i like more to look at the surface itself (BCR) and see alle important states, instead of looking up to the monitor (although i have a second one there).
But now, maybe a dumb question - i see no way of copying/pasting between diff. Presets - is this possible? and another related question: to copy a whole list of actions, nothing has to be selected. How to do that? i found no way "de-selecting"
Quote from: MarKo on April 26, 2015, 11:56:55 PM
I would not say that a nice display is SO important, but it´s always something people look at.
In fact, i´m not using it that much, so for me personally i would´nt spend too much either.
i like more to look at the surface itself (BCR) and see alle important states, instead of looking up to the monitor (although i have a second one there).
I use it in ACT mode to see which parameters are mapped.
Quote
But now, maybe a dumb question - i see no way of copying/pasting between diff. Presets - is this possible?
Unfortunately there is no such possibility. In todo list is "copy/paste" to/from text. I have to implement "text form" of internal format for that. My todo list is so long...
Quote
and another related question: to copy a whole list of actions, nothing has to be selected. How to do that? i found no way "de-selecting"
In Logic actions, temporarily select another control. In Monitors it is not possible, but if you copy monitor is the Logic its action list is copied as well.
Quote from: azslow3 on April 27, 2015, 10:59:39 AM
I use it in ACT mode to see which parameters are mapped.
i see, in ACT mode the display is more neccessary.
Quote
Unfortunately there is no such possibility. In todo list is "copy/paste" to/from text. I have to implement "text form" of internal format for that. My todo list is so long...
it´s ok, i was just not sure if i overlook something.
Quote
In Logic actions, temporarily select another control.
hm - i have tried that before and it does not work, but i found now another way:
if i temp. select a different preset, then the action-list gets deselected.
Quote from: MarKo on April 27, 2015, 01:22:42 PM
Quote
In Logic actions, temporarily select another control.
hm - i have tried that before and it does not work, but i found now another way:
if i temp. select a different preset, then the action-list gets deselected.
I use that all the time... Select another control, select the source one (not click any action in it!), press Copy.
Quote from: azslow3 on April 27, 2015, 02:03:13 PM
Quote from: MarKo on April 27, 2015, 01:22:42 PM
Quote
In Logic actions, temporarily select another control.
hm - i have tried that before and it does not work, but i found now another way:
if i temp. select a different preset, then the action-list gets deselected.
I use that all the time... Select another control, select the source one (not click any action in it!), press Copy.
Sorry, too stupid, i was reading "select another control" in terms of windows-control, but did not think of Az-control! Of course it´s working that way, thank you.
Small tip for that: since using some control switch Logic tab to this control, you cat press/turn "from" control, "Copy", press/turn "to" control, "Paste". That is a bit faster then changing controls in the drop box (especially if you have long list). We are configuring the Control Surface for faster operations, we can use it to accelerate the configuration as well :)
ok, the last tip was good!
Unfortunately i had not much time the last week, so i got a bit stuck.
But i´ve already managed to implement many things like i want.
and i think i had a nice idea for my rew/ff buttons:
to get more possible actions with these 2 buttons, i can press them now also together - but in different order!
while this may sound complicated, i think it´s a quite intuitive way (at least for me).
so: rew/ff-buttons pressed alone act like normal (rewinding/forwarding while hold down)
but pressing left button(rew), and then together pressing the right button(ff) does "marker back".
same the other way: first pressing(holding) the right(ff) button, then together the left(rew) does "to next marker".
of course, rewinding starts (shortly) while i press the left button, but that does not matter, because the next marker is always more far away.
this is additionally to the "shift"-functions! so 2 more useful actions directly available, which are "nice to press".
i´m currently trying if it´s better to have 1 measure back/forw on this 2-button-presses, and using Shift for the markers,
but the concept should be clear and is expandable to other/more buttons and actions of course.
so i thought about sharing the idea in form of a preset, because your example for the blinking Led´s was really helpful
(i think better than a complete preset, which is not simple to understand).
but my preset as a whole is far from complete and would cause more confusion then help -
so is there a way to get only some selected logic exported?
copying the preset and deleting the rest is even more work than creating it new.
And because the thread is still about Status-Led´s another question:
i´ve got 2 Led´s, which i want to show the "WAI"-position.
e.g. for WAI 1-8 i want Led1, for WAI 9-16 i want Led2, for 17-24 both,...
(could be expanded with blinking, but 32 tracks is enough for now)
how do i get the WAI-position into a state?
Quote from: MarKo on May 06, 2015, 10:02:56 PM
so i thought about sharing the idea in form of a preset, because your example for the blinking Led´s was really helpful
(i think better than a complete preset, which is not simple to understand).
but my preset as a whole is far from complete and would cause more confusion then help -
so is there a way to get only some selected logic exported?
copying the preset and deleting the rest is even more work than creating it new.
There is no exporting/copy. It is in long term plan (I want be able to "copy" control as text, to put inside post for example and be able "paste" it back from text). But in practice, small ideas can normally be shown as separate preset build from scratch within 1-2 minutes.
Quote
And because the thread is still about Status-Led´s another question:
i´ve got 2 Led´s, which i want to show the "WAI"-position.
e.g. for WAI 1-8 i want Led1, for WAI 9-16 i want Led2, for 17-24 both,...
(could be expanded with blinking, but 32 tracks is enough for now)
how do i get the WAI-position into a state?
You will not believe, the question has puzzled me for a half an hour! :o
But the answer is in attachment ;)
Explanation. Open internal display (Show/Hide in the Options tab) to test.
We need 2 State Sets, both with the same states. One is "the real" one, which we are going to monitor and send LED when changed. another one is "temporarily" one, which we are going to set in monitoring every cycle.
Look at _funcWAI function (in Logic). It first try to set "WAI-16" track, if WAI is really 17+ it will be valid track. So, we set tmpWai to "17" and that is final action (in function!). If that is not valid, we check WAI -8 and set "9" if that was successful. Otherwise we set "1" unconditionally (so it works even the project has no tracks at all).
Now look at WAI Monitor in Logic. First is State Monitor for real "Where is WAI", in which we set LED/Display (note priority 1, we want it executed AFTER timer in the same monitoring cycle). But to make it work, we need periodical timer. So, we call _funcWAI BEFORE timer. In that mode, the function will be executed every time the timer triggers and set tmpWAI to what it should be. We could not just put all actions from _funcWAI there. We rely on "Final" actions, and final actions before Timer will prevent timer execution. In case of "final" in _func, it just exit the function, not the list.
Now look at Feedback WAI Monitor::Timer. We "map" tmpWAI to real one (with "Set engine state" set, so the changes are "permanent"). That is going to happened every time the timer works, but in case there is no change in "Where is WAI" state, "State monitor" is not triggered and so we do not send LED many times per second.
In Feedback WAI Monitor::State Monitor I update display. You are going to update LEDs.
I know, it is hard to understand. But you have asked for somehow not trivial plug-in reaction, and so the answer is also not trivial :)
Quote from: azslow3 on May 07, 2015, 12:04:16 AM
You will not believe, the question has puzzled me for a half an hour! :o
But the answer is in attachment ;)
hehe - i would´nt have asked if i had´nt thought that you (and AzCtrl) always have a solution!
But it´s nice to have questions, which can puzzle even you - at least for a short time ;)
Quote
I know, it is hard to understand. But you have asked for somehow not trivial plug-in reaction, and so the answer is also not trivial
I assumed that this will not be trivial.
So it´s a good example of what complex stuff can be done with your PlugIn. I can´t think of other solutions, which would allow the same.
For me, this means now quite some time & work to understand, but i think i got the main idea. I´m at the office now, i hope to try it in the evening.
And i´m sure i have to come back with more questions.
Many thanks for your continuing help!
"Rethinking" about my solution during the day (it was late evening yesterday when I have created it), I come to the conclusion that one "Where is WAI" Software Set is sufficient. So, you can replaces all "tmpWhere is WAI" with "Where is WAI" and remove that "temporarily" set.
"AZ Controller Expert exam" question: do you understand why? ;)
Note that you still need the mapping in monitor, this time it looks really strange: "Where is WAI: Track 1-8 -> Where is WAI: Track 1-8, set engine state". That "fix" monitored value of this set to permanent one. That operation looks so ugly in case of many states in the set, that I have added such operation to the "Set State" Action (<Set to monitored>). But the version with the change is not released yet (can be found in the "Test versions" section).
i have a lot of "Rethinking" now!
so please, no expert questions today :o
it´s just working as you described (both versions) - thank you!
but i need to play with that example...
Ok, i´ve been "rethinking" now and hope to (partially) understand.
The "_FuncWAI" is completely clear, i think i perfectly understood the state-logic, no problem there.
As you know i could successfully implement some of my other wishes.
But i´ve still problems understanding timers and general sequence of actions.
E.g. i really can´t understand how/from where the action "WAI Monitor" get´s triggered first.
Of course there is timer at the and of the list - but how does it start initially???
If i build a list of actions just as "function" (like _funcWAI), i understood this just like a "sub" in programming logic. And as you have explainend, i can "exit" them (with final), and the "calling" Action-list will proceed. i hope i see this correctly?
But how/from where gets the list "WAI Monitor" called?
And regarding your "expert question": first problem is, i don´t understand why you initially introduced the "tmpSet".
And although you explained - esp. i can´t really get the meaning of "set engine state".
Even if the tmpSet is not necessary in this case - you must have had a reason to try it like that, which i´d like to understand.
This strange feedback event:
Quote
"Where is WAI: Track 1-8 -> Where is WAI: Track 1-8, set engine state".
That "fix" monitored value of this set to permanent one.
this triggers the "WAI Monitor"?
i get the same loop in my brain - how get´s this called first???
I have tried to explain how it works in the documentation, but that is really "advanced" topic. The knowledge of "conventional" programming does not help here, it really prevent you understand there are other approaches.
I think you understand, that Timer Monitor is executed periodically. But what you see in the "Feedback" Tab for it is the SECOND half of the execution process. Before it is executed, the system execute EVERYTHING what exist in the Logic Tab where the monitor is declared up to the monitor declaration. But you do not want it is REALLY executed, so it is executed special way, a kind of "dry run". Lets look at simple example:
Fader (Logic Actions List):
Select current track volume
Set value (from fader)
Set state "Is fader moved" to "Moved" (initially "Not moved").
Monitor parameter name (in Feedback action of which we for example put the track name to internal display).
What will happened in case we just periodically call "Monitor parameter name" feedback action without doing something special? It will always display "some" track name, let say the track which was current during the time we have moved the fader last time. But that is NOT what we want! We want display the name of track which WILL be modified WHEN we move the slider. So, real current track, even in case we have changed it by mouse in sonar.
So, we have to somehow execute the whole action list before calling our monitor actions, to select real current track every time we monitor.
But we can not do that directly... Select current track will modify system wide current parameter, Value will set the volume (to which value?), and "Is fader moved" will be set to "Moved". We have not moved the fader yet, so the result will be wrong.
And so, we create "virtual" environment just to IMITATE what is going to happened if the fader is moved. Select current track set temporarily "current" track, Value does nothing and "Is fader moved" is set to "Moved" temporarily as well. Then the Monitor actions are executed using this "future" environment and all these changes are discarded!
So, the example works as "naturally" expected, showing real current track name without state or volume modification.
But in out case, we want to "save" the fact WAI was changed. So we need some way to say the system that some part of the "virtual"/"temporarily" environment should become "reality". And we do this by "Set engine state" flag, instructing that while we are still in "monitoring" we want set "real" thing.
Since you have programmed before, may be you can understand better by example how it is really written in C.
Each "Action" (for example Set State) has 3(!) different execution methods. And each State Set has 2(!) current states. So,
"Set State"::Logical execution method is "Set Current State to XXX"
"Set State"::Dry run execution method is if "Set engine" is NOT set, "Set Tmp Current State to XXX" (nothing otherwise).
"Set State"::Monitor execution method is "Set Tmp Current State to XXX" and(!) in case "Set engine" is set, also "Set Current State to XXX".
Note that "Logical" and "Dry run" work with actions from "Logic tab" while "Monitor" work for action in the Feedback list.
Without this technology, we have to double all actions (in logic and in monitor). And even then, we will need some kind of explicit "If the track is changed" thing. With this technology, the system check if the parameter WAS NOT changed since the last check ("dry run" is executed every time), and so "Parameter Monitor" WILL NOT call feedback actions if the track is still the same!
May be still sound crazy, but the result looks so compact and logical for me :)
QuoteI have tried to explain how it works in the documentation,
i know, i also re-read it and i really appreciate your explanations, but it leaves me unsure...
QuoteI think you understand, that Timer Monitor is executed periodically.
Of course i understand timers, but something in this area is unclear to me: how is it started?
you won´t call every action-list with every timer-tick?
so why gets a specific action-list called the first time?
it´s clear for logical controls, which are bound to MIDI - but for independent _funcActions?
QuoteMay be still sound crazy, but the result looks so compact and logical for me :)
I´m sure that you invented some serious genius logic, because i see all the possibilities.
i just hate it that it´s not so logical to me >:(
Quote from: MarKo on May 08, 2015, 11:09:03 PM
Of course i understand timers, but something in this area is unclear to me: how is it started?
you won´t call every action-list with every timer-tick?
You will be surprised... Every action list with "Ultra" timer/monitor in it IS executed every CS timer tick (13 times per second)!
If you think that is a lot, imagine Sonar in fact execute all plug-ins (FXes, Synth, PCs, internal routings) much more times per second.
Just imagine, you want have 5ms "round trip time", then EVERYTHING should be executed at lease 1/0.005=200 times per second!.
And that includes complicate DSP algorithms of Guitar Amps and other non trivial CPU consuming tasks. Compare to that, single loop
in C which just checks some conditions is nothing. Even some complicated presets like MCU, with 100s of monitors still not "visible" on CPU monitor.
I wish Sonar had "asynchronous" API, so I could ask "please let me know when the current track is changed". That is not the case, the only way is to "scan" for all changes all the time. I have optimized many routine scans, and there are still many possibilities.
Quote
I´m sure that you invented some serious genius logic, because i see all the possibilities.
i just hate it that it´s not so logical to me >:(
Look at it from conventional point of view. You plan tomorrow morning. You set alarm clock for 8AM, you need 30 minutes to get up and prepare the breakfast.
Imagine you have the breakfast now... What time is it? Around 8:30AM. Is it dark outside? No, I see the sun.
Do you think the answers are "logical", even so it is 23:33 PM and it is dark behind the window at the time of PLANNING?
My system has exactly the same "look in the future" logic. You describe what WILL happened and then can use the information. In the example, you write "If I move the fader, current track is going to be (let say) 3". And so, you can ask the question "What is going to be the track name which volume is changed once I move that fader?".
The same is with WAI monitoring. You define "Logical Control". In case you activate it (which really never happens in out case, but you can assign it to some MIDI), it will detect where current WAI is. We put timer with question "What is WAI in case we activate that control?" and just save the result.
I can imagine (understand the process) how metal string of E-Guitar inducted current in the coil, which is then transfered to ADC which digitize it, digital elements put that information into the buffer, the buffer is composed to packet, the packet is transfered throw USB, chipset trigger interrupt, CPU switch to kernel mode, extract information and put into sound buffer, Sonar take the buffer, call VST, collect VST output, put it into buffer, ask kernel to transfer it throw USB into the DAC, which change the current on speaker and so change the magnet field, which trigger physical movement producing sound waves... But does everyone who want to use Sonar should understand the process in "down to the bit or even electron" details? Definitively not. "It works and sound nice", that is the only thing most musicians know ;)
So, I propose you choose the level of AZ Controller "black magic" and do not dive deeper. I can try to explain you the process on any deepness level. But I think that will just destruct you from the final goal - making great music!
Hi Alexey,
It seems i can not describe my logical problem...
I wasn´t so much worried about performance, i know what´s going on to calc realtime fx and all the like (in videoprocessing even much more).
And i don´t want to bother you with unneccessary questions - if i can´t get it, i´ll take the "black magic" as it is. But i always like fully understanding, so i can build the logic myself, and don´t have to ask for every idea that i want to try.
So if you are not too bored, please give me one more try.
Could you list the real executing order in this WAI-Example?
I mean step by step the different cycles including priorities and feedback (just in short words).
Perhaps i see then the light.
My intention in no way was an attempt to stop your questions! You are welcome and I can write about the staff all the day long. I just do not want you get mad from my long posts in bad English ::)
So, the execution order.
1. I have separate Monitors list with all monitors from all controls. So, every time Sonar call me (~13 times per second) I check either some monitor is "armed". For ultra, the arming is "1", Fast, Normal are "2", "6". "Once" and "State" monitors are not armed till requested explicitly, "State" monitor is armed when persistent state is changed (I have already explained that each State Set has "current" state which is system wide and persisting and "current monitoring" state, reset before any monitor execution to corresponding "current").
2. WAI Monitor::State monitor is executed once initially (armed during preset loading) and then stay unarmed till the state is changed.
3. WAI Monitor::Timer "Normal" is armed all the time, so every 6 cycles its arming counter drop to 0 and it is time to execute it.
4. The monitor execution procedure is the following:
4.a it takes the Logical Control (WAI Monitor) and execute it in "dry run mode", which means
4.b "State Monitor" action does nothing in "dry run mode"
4.c "Call _funcWAI" is called in "dry run mode", so
4.d WAI Track -16 set "current monitoring parameter" to "WAI Track -16 volume". If current WAI track is less then 17, the result is "invalid" and so "Selection" set "current monitoring state" is set to "Invalid". Let say current WAI track is 9, so that is the case.
4.e Set "Where in WAI -> Track 17-24" is NOT executed since "Selection:Valid" Action Condition is not true.
4.f WAI Track -8 set "current monitoring parameter" to 9-8 = 1 (first track volume). That is Valid parameter, and so "Selection" is set to "Valid"
4.g "Where in WAI -> Track 9-16" is executed in "dry run" mode, that means "current monitoring" state for "Where in WAI" is set to "9-16". The action also has "Final" flag set, so the execution of funcWAI is terminated and returned to "WAI Monitor" list (from where it was called)
4.h "Timer" is reached, its Action Conditions is checked (it has no visible, but there is still one implicite Note On). We see that it should be executed. That is "Our" timer monitor, so "dry run" execution is terminated, with result that we should call the monitor.
4.i Feedback Action list of "WAI Monitor::Timer" is executed in "Monitor" mode (not logical, not "dry run", it is third!).
4.j "Where in WAI: 1-8" is not satisfied, so skipped.
4.k "Where in WAI: 9-16" is satisfied. So, thanks to "Set engine state" flag, both "current" and "current monitoring" states for "Where is WAI" are set to "9-16". If "current" state was already 9-16, nothing happens. But if it was 1-8, it checks either there are some "Where is WAI" Set State Monitors. We have one! "WAI Monitor::State Monitor" is State Monitor for "Where is WAI". So, it is armed (with "1"). The action is "Final", so that stop Timer monitor execution. Since that is Timer monitor, it is rearmed with usual delay, "6" cycles in case of "Normal" speed.
5. If you remember, we are still in all monitors/timer check procedure. If our Timer and State Monitor have the same "priority", the order in which we check them is undefined. But since Timer has priority "0" and State Monitor "1" we know State Monitor is not checked yet in this cycle. So, the system check it.
6. We have armed State Monitor in 4.k, so it should be executed.
7. The system start "WAI Monitor" Logical Control "dry run" (yes, again!)
8. There is no actions before "State Monitor" itself, so its conditions are checked (satisfied) and Feedback actions are executed.
9. "Where is WAI" "current monitoring" state (which is the same as "current", as set prior "dry run" execution) is put to Text buffer
10. The Text buffer is displayed.
11. There is no other actions, there in no more monitors, State Monitor is disarmed, all monitors check cycle is ended.
12. The system continue to work from (3).
If you put all that in "C", the procedure is not going to be significantly shorter. We have to get current WAI, check it against our predefined values (9,17), check what we have displayed last time and in case it is different display new value. The preset has 11 lines (actions) for that. Can you write that procedure in "C" or other "normal" programming language in less then 11 lines? 8)
One more note. The location of the "State Monitor" in Logical Actions list is not important. We could put it into separate Logical Control. We could put it between "Call" and "Timer" or after "Timer" as well. But in that case, it its "dry run" the "Call" is executed again. In that particular example, it will not influence the result, but it will "waste" CPU cycles. That is why I always put "State monitors" as the first in the Logical Actions. Since it does "nothing" by itself (in all 3 modes!), it can not significantly slow down other "dry runs" (in this example, the Timer "dry run"). So I do not create separate Controls for that monitors which just "bloat" the number of controls in the list (there can be 100 or event more, one per real hardware message plus functions)
Thank you very much for this detailed description, I really think it helps (after studying it again).
You mention the position of StateMonitor: that was one thing, i was unsure and experimenting, because sometimes i had the impression that the result was faster (a Cycle earlier), if it´s after the call to _funcWAI.
But i´m sure that was just imagination, because it´s always async (can be anytime in the next 6 Ticks - correct?)
Now we´ll see how i can proceed with that infos.
Yes, State monitor has no influence on when system detect the change. Only timer speed. Also in case they have different priorities, the sequence of processing withing one tick is always predictable.