Welcome to %s forums

BrainModular Users Forum

Login Register

"one-shot" script output parameters

Tell us what you'd like Usine to do
Post Reply
sm_jamieson
Member
Posts: 555
Contact:

Unread post by sm_jamieson » 10 Feb 2015, 18:14

It is a common problem in scripting that you wish to send a "message" from an output rather than just set its value. The way to accomplish this is to set the output to the value, wait a processing cycle and then set the output length to zero. This requires flags and use of the Process routine, etc. In fact, doing this is vital for MIDI messages, as they are always "one-shot".
You can rig up various modules to the script to just about achieve the same thing, but it is very clumsy.
NOTE: the "Pass If Changed" module lacks in one vital aspect - often you want to send the same value you sent last time !

I suggest new functionality in Usine to make this easier.

The script Parameters should have a new "one-shot" property. When this is set, the output will be set to length zero (parameter OFF) on creation. Then any SetValue() on this output will causes the output to appear on the wire for 1 processing cycle before the output length is set back to zero (OFF). When the output is switched ON by Usine, it should set the output length to 1 if the user has not set it to some other value (this would be needed to output a set of midi messages).

The new "one-shot" property should also be settable independently at various points in a script. e.g. SetParamOneShot(paramnumber, true).

Thanks,
Simon.

sephult
Member
Posts: 1144
Contact:

Unread post by sephult » 10 Feb 2015, 20:41

Hello sm_jamieson!

I agree with the difficulty in setting values concurrently within a script. Writing an event-driven control such as setting a value from 3 to 4 to 5 to 0 concurrently does not seem very straight-forward, and during the process you find the output only to remain at 0 and have never seen any of the other values.

As far as the types such as setting an output type to a PtButton, I would like to assume that the output would act like a button. Set the value and the output One-Shots like a button similar to how you describe.

Possibly modifying so an output type of PtButton can One-Shot, where the Min/Max values could be assigned. I don't know the difficulty, but possibly a time setting as well for the transition?

Like the following for a one-shot?
Type PtButton
Procedure ButtonRange(min,max)
Procedure ButtonDelay(ms)

-S
"Every act of creation is first an act of destruction." -Picasso

sm_jamieson
Member
Posts: 555
Contact:

Unread post by sm_jamieson » 13 Feb 2015, 10:50

I don't quite follow your suggestion, but I think all parameter types (not just buttons) should be able to be in one-shot mode, including midi array output, which would remove the requirement to reset the midi array size to zero on the next processing bloc to avoid repeated midi messages.

User avatar
senso
Site Admin
Posts: 4424
Location: France
Contact:

Unread post by senso » 14 Feb 2015, 13:07

I understand your pb.
But it's normally very easy to avoid?

for example

Code: Select all

Procedure Process;
begin
  if MyCondition
  then  setValue(param,1)
  else SetLength(param,-1);
end;
Your solution is not so easy to implement and will make heavy the overall script engine for very specific needs.
So I don't know?
senso+++

sm_jamieson
Member
Posts: 555
Contact:

Unread post by sm_jamieson » 03 Mar 2015, 14:32

If it would impose an overhead on the script engine then best not to include it I agree. They way I do it is to set the parameter length to zero which works fine. I would think setting it to "-1" as in your example does the same thing.
Simon.

sephult
Member
Posts: 1144
Contact:

Unread post by sephult » 04 Mar 2015, 02:17

I beat myself up tonight over a MIDI output message that I cannot get to one-shot....uggg
I do find myself getting stuck trying to only send the message once, and every time I try to set the length to 0 it wont even send.

I am going to have to second..... some better solution.
I know I've done it before, just seems so cumbersome to do something simple like send a common midi message.

-S
"Every act of creation is first an act of destruction." -Picasso

bsork
Site Admin
Posts: 1334
Location: Asker, Norway
Contact:

Unread post by bsork » 04 Mar 2015, 08:18

You have to first set the length to the number of MIDI messages, and then in the next block set the length to 0.
Bjørn S

sephult
Member
Posts: 1144
Contact:

Unread post by sephult » 04 Mar 2015, 13:44

Thanks bsork,

It's probably just me at the moment, I am setting the message and then after set to length 0, it seems in the context though I am not setting my loop up right.
So in most cases the midi is read in and sets the length. I am just wanting to generate, so I always seem to fumble around with trying to get the message to stop.

I am taking another shot (no pun intended) at it this morning, if anyone has any examples I would appreciate. I cant seem to find my examples I made before.

-S
"Every act of creation is first an act of destruction." -Picasso

sephult
Member
Posts: 1144
Contact:

Unread post by sephult » 04 Mar 2015, 13:52

So this is the problem I run into, although the message is sent within the loop, after exiting and setting to 0 it just prevents sending at all.
Logically this should work, these kind of one-shot messages or parameters are what gives me the most problems.

Code: Select all

if lngthMidi > 0   
   then begin                      
     
      SetLength(MidiOut,lngthMidi);
     
     for i := 0 to lngthMidi-1
     do begin       
     
      ReceivedMidi.msg := 176;
      ReceivedMidi.data1 := x;
      ReceivedMidi.data2 := pad_Array_B[i];
      ReceivedMidi.channel := 3;
                     
      SetMidiArrayValue(MidiOut,i,ReceivedMidi);              
      x:=x+1;          
     end;                 
   end                
   else SetLength(MidiOut,0); 
   SetLength(MidiOut,0);
"Every act of creation is first an act of destruction." -Picasso

bsork
Site Admin
Posts: 1334
Location: Asker, Norway
Contact:

Unread post by bsork » 04 Mar 2015, 14:01

Why do you have the last SetLength? To me it looks like the culprit...

BTW, you don't have to set the length before you fill the array. In this case I suppose you are sending as many messages as you get in, so you have the number anyway, but in other cases the script can create X messages in a block, and you can wait until the array is filled before using SetLength. Very handy :)
Bjørn S

sephult
Member
Posts: 1144
Contact:

Unread post by sephult » 04 Mar 2015, 14:07

Hi bsork,

So the last SetLength(MidiOut,0), was my intention to get the message flow to stop. (This prevents message from even sending).

Without this the messages do send, but continuously and not one-shot.

-S
"Every act of creation is first an act of destruction." -Picasso

sephult
Member
Posts: 1144
Contact:

Unread post by sephult » 04 Mar 2015, 14:23

Essentially I am trying to do a Create MIDI from a script, pressing the send button to send the one message or array of messages.
The confusion almost makes me want to rewrite and just trigger using Create MIDI, because I can get a one-shot message at least.

-S
"Every act of creation is first an act of destruction." -Picasso

bsork
Site Admin
Posts: 1334
Location: Asker, Norway
Contact:

Unread post by bsork » 04 Mar 2015, 15:07

I guess you are running this code from within Callback, or a procedure called from Callback? In other words, only when the script have received some value. That is not sufficent. If you omit the last SetLength, the above code will do within the execution block that creates and the message. However, in the next block, you have to reset the length back to 0 (unless, of course, you are sending another batch of messages). This should be done in the Process procedure, since you have no guarantee that there any callbacks within that block.

Within a block, Process is executed after any callbacks, so you cannot just check the length and set it to 0. The problem can be solved in several ways - one example is to use a global integer value as a counter: When updating the array from Callback, set the counter to 1, and then in Process check the counter. If it is 1, increment to 2, if it is 2, set both array length and the counter to 0.
Bjørn S

sephult
Member
Posts: 1144
Contact:

Unread post by sephult » 04 Mar 2015, 15:17

Thank bsork,

Yes I am triggering from a switch, recording the value in callback, then setting the length as a fixed value (not from midi input) based on updating an external controller.
The midi procedure is within a user-defined procedure.
I will have to revisit and rework, I was thinking the same thing but trying to avoid rewrite.

Regardless I guess my point in regards isn't just a scripting help, but the complexity of sending a one-shot message.
Although I know I will figure it out (with your great help of course, bsork), it just seems overly complicated to perform a simple and basic function that Usine presents.

The scripting engine could use some efficiency and easier methods to do basic functions. I love using it, I just think that it could be simplified.

-S
"Every act of creation is first an act of destruction." -Picasso

sephult
Member
Posts: 1144
Contact:

Unread post by sephult » 04 Mar 2015, 15:33

Thanks bsork, I finally got working based on your counter:

For reference to others:
1. Switch triggers callback and records the value of the switch,
2. PAD_CHANGE increments the length of messages and updates my second array,
3. Process provides counter to shut off Midi after sending the messages based on my second array.


I just wish I could send a message as a one-shot without having to execute another block, then you could place anywhere easily without the counter.

Code: Select all

procedure callback (n:integer);
Begin
       
 Case n of         

//Go to Pad_Change
          pad:begin  
             j:=1;
             pad_array_values[0] := round(getvalue(pad)); 
             PAD_CHANGE; 
          end;                      
                                                                  
 end;                    

End;

Code: Select all

procedure PAD_CHANGE;
Begin
  
 for i:=0 to 15 do begin   
  if pad_Array_Values[i] = 127 then begin
   pad_Array_B[i]:=127;
   lngthMidi:=lngthMidi+1;  
  end
  else begin   
   pad_Array_B[i]:=0;
   lngthMidi:=lngthMidi+1;
  end;  
end;                           
 
 
End;

Code: Select all

procedure process;
Begin                                                                                
       
      if j=2 then begin
       j:=0;
       lngthMidi:=0;
      end  
      else begin
        if j=1 then inc(j); 
      end;
                                   
                 
   x:=20;     
      
   if lngthMidi > 0   
   then begin                             
     for i := 0 to lngthMidi-1
     do begin       
      ReceivedMidi.msg := 176;
      ReceivedMidi.data1 := x;
      ReceivedMidi.data2 := pad_Array_B[i];
      ReceivedMidi.channel := 3;              
      SetMidiArrayValue(MidiOut,i,ReceivedMidi);              
      x:=x+1;          
     end;                    
     SetLength(MidiOut,lngthMidi); 
   end 
   else SetLength(MidiOut,0);            

End;
"Every act of creation is first an act of destruction." -Picasso

Post Reply

Who is online

Users browsing this forum: No registered users and 18 guests