# Sending information backwards through the script chain



## kotori (Apr 18, 2006)

An observation I did today: it's possible to send information from scripts later in the script chain to earlier scripts. It's based on a little timing trick.

For simplicity let's call the script loaded in the first script slot A, and the one in the second slot B. We already know that A may send B information by encoding it as controller data or notes in some unmapped range. For example, this is what Bob uses in his scripts to transfer presets. Now what I found out was that A may poll B for information by sending a note (in some unmapped range). To communicate backwards through the chain B now runs note_off on the incoming note which will invoke the release callback in A. By invoking note_off directly using slightly different timings B may send information back to A. Eg. running note_off instantly means 0 and running it after a 5ms delay means 1. Now any bit stream can be sent.

Not exactly the prettiest solution, but it should work! :mrgreen:


----------



## Thonex (Apr 18, 2006)

kotori @ Tue Apr 18 said:


> An observation I did today: it's possible to send information from scripts later in the script chain to earlier scripts. It's based on a little timing trick.
> 
> For simplicity let's call the script loaded in the first script slot A, and the one in the second slot B. We already know that A may send B information by encoding it as controller data or notes in some unmapped range. Now what I found out was that A may poll B for information by sending a note (in some unmapped range). To communicate backwards through the chain B now runs note_off on the incoming note which will invoke the release callback in A. By invoking note_off directly using slightly different timings B may send information back to A. Eg. running note_off instantly means 0 and running it after a 5ms delay means 1. Now any bit stream can be sent.
> 
> Not exactly the prettiest solution, but it should work! :mrgreen:



Nils.... you have broken down the barriers of Time and Space!!!!! It's like Sci-Fi.... very cool.

I'm still having problems having B read A's values without initializing them on a callback  But Bob said I should read paragraph 4 and page 4 of the SIPS pdf.

Cheers,

T


----------



## kotori (Apr 18, 2006)

Thonex @ Tue Apr 18 said:


> Nils.... you have broken down the barriers of Time and Space!!!!! It's like Sci-Fi.... very cool.
> 
> I'm still having problems having B read A's values without initializing them on a callback  But Bob said I should read paragraph 4 and page 4 of the SIPS pdf.
> 
> ...


Yeah, kinda strange isn't it.  

Regarding Bob's scripts, have you tried this:
* load the script containing the settings you wish to export in the first slot with all changes saved to presets (don't know if this is necessary, but it can't hurt)
* load a fresh copy of the script in the second slot
* select "import" on the second script
* select "export all" on the first script

This seems to work for me.

Cheers,
Nils


----------



## Thonex (Apr 18, 2006)

kotori @ Tue Apr 18 said:


> Thonex @ Tue Apr 18 said:
> 
> 
> > Nils.... you have broken down the barriers of Time and Space!!!!! It's like Sci-Fi.... very cool.
> ...



Actually,

I have a bypass script that works to bypass the SIPS Legato... or VIbrato script for that matter. It works if I write the code into the scripts themselves, but what I wanted to do was write a bypass module the would be in the first slot. This module would allow the user to select either a Key Switch as a bypass or a CC toggle as a bypass, but when I put it first the (for example) $LegBypas variable loses it's value in the SIPS script. I had to declare it in the SIPS script, but I thought if you change it's value after the init call all should be fine... I guess not.... anyway... that's what I'm trying to do... because there is no GUI space on the SIPS script to add it within the SIPS script itself.

Cheers,

T


----------



## kotori (Apr 18, 2006)

Thonex @ Tue Apr 18 said:


> Actually,
> 
> I have a bypass script that works to bypass the SIPS Legato... or VIbrato script for that matter. It works if I write the code into the scripts themselves, but what I wanted to do was write a bypass module the would be in the first slot. This module would allow the user to select either a Key Switch as a bypass or a CC toggle as a bypass, but when I put it first the (for example) $LegBypas variable loses it's value in the SIPS script. I had to declare it in the SIPS script, but I thought if you change it's value after the init call all should be fine... I guess not.... anyway... that's what I'm trying to do... because there is no GUI space on the SIPS script to add it within the SIPS script itself.



Oh, I see. Sorry, I thought you were talking about preset export.
How do you send the value of $LegBypas from A to B? Using a MIDI controller?
Please provide more details. Even if you declare $LegBypas in both scripts it will be two different variables each with their own value, but that you knew right?
Another way of solving the space issue than writing another script could be to change SLS slightly so that negative values for LegCC or VibCC would indicate keyswitches. Eg. setting LegCC to -24 would let you toggle legato on and off using key 24.

Cheers,
Nils


----------



## Thonex (Apr 18, 2006)

kotori @ Tue Apr 18 said:


> Thonex @ Tue Apr 18 said:
> 
> 
> > Actually,
> ...



Oh, I see. Sorry, I thought you were talking about preset export.
How do you send the value of $LegBypas from A to B? Using a MIDI controller?
Please provide more details. Even if you declare $LegBypas in both scripts it will be two different variables each with their own value, but that you knew right?
Another way of solving the space issue than writing another script could be to change SLS slightly so that negative values for LegCC or VibCòIÀ   7cIÀ   7cIÀ   7cIÀ   7cIÀ   7cIÀ   7cIÀ   7cIÀ   7cIÀ   7cIÀ   7cIÀ   7cIÀ   7cIÀ   7cIÀ   7c IÀ   7c!IÀ   7c"IÀ   7c#IÀ   7c$IÀ   7c%IÁ   7c&IÁ   7c'IÁ   7c(IÁ   7c)IÁ   7c*IÁ   7c+IÁ   7c,IÁ   7c-IÁ   7c.IÁ   7c/IÁ   7c0IÁ   7c1IÁ   7c2IÁ   7c3IÁ   7c4IÁ   7c5IÁ   7c6IÁ   7c7IÁ   7c8IÁ   7c9IÁ   7c:IÁ   7c;IÁ   7c<IÁ   7c=IÁ   7c>IÁ   7c?IÁ   [email protected]IÁ   7cAIÁ   7cBIÁ   7cCIÁ   7cDIÁ   7cEIÁ   7cFIÁ   7cGIÁ   7cHIÁ   7cIIÁ   7cJIÁ   7cKIÁ   7cLIÁ   7cMIÁ   7cNIÁ   7cOIÁ   7cPIÁ   7cQIÁ   7cRIÁ   7cSIÁ   7cTIÁ   7cUIÁ   7cVIÁ   7cWIÁ   7cXIÁ   7cYIÂ   7cZIÂ   7c[IÂ   7c\IÂ   7c]IÂ   7c^IÂ   7c_IÂ   7c`IÂ   7caIÂ   7cbI


----------



## sbkp (Apr 18, 2006)

Thonex @ Tue Apr 18 said:


> I'm still impressed with the use of a mod command to make a toggle.



If you're toggling or rotating through something that's a power of 2 (2, 4, 8, etc), you can do it even faster. It's only a concern if you want to avoid division (which are generally "slow" -- and mod is a division). This was a bigger deal in the old days. It's a trick I learned doing graphics programming for games.

For toggling:
value = (value + 1) and 1

For rotating through 4:
value = (value + 1) and 3

etc....

(I don't know the KSP syntax for that, but there you go...)


----------



## kotori (Apr 18, 2006)

Hi Stefan,
that would be '.and.' in KSP syntax for bit-wise and. But I doubt the performance gains would be noticable since the overhead of executing KSP code is probably greater anyway. Nice trick anyway and good to see that there are more people with programming background here.  

Just for the record, the general way of cycling through eg. 0 to 9 using KSP would be:
$value := ($value + 1) mod 10


----------



## kotori (Apr 18, 2006)

Regarding assigning to builtin-variables I might just add that it can lead to somewhat unexpected results.

For example:

```
on note
  %CC[90] := 100
  message("this text will never appear")
end on
```

It seems that if you assign a value to a builtin variable the script processor will abort at the line where you do this without any error message. In the example above this means that the line showing the message will never be executed.


----------



## Big Bob (Apr 18, 2006)

Hey Nils,



> Just for the record, the general way of cycling through eg. 0 to 9 using KSP would be:
> $value := ($value + 1) % 10


Don't you mean:
$value := ($value + 1) mod 10

or is this another change to the KSP that I didn't know about?

Regarding your 'reverse' inter-script communication idea, that's very clever. But I wonder if maybe we can't send data back via CCs also. While it probably won't produce a 'on controller' callback, we could use your scheme. After A creates a note, before B turns it off it also sets a pair of CC values (one as a sentinel the other to contain 7-bit data). Then when the RCB occurs in A, it can check the sentinel and read the data.

Incidentally, for the rest of you that might be interested in SIPS forward communication scheme, it also uses a pair of CCs. The sentinel CC indicates when 'transmission started' occurs and it ultimately delivers an index for the data which itself is sent 7-bits at a time in the data CC. SIPS is setup to send full, signed, 32-bit integers to one of 127 slots in a Global data array using a serial protocol.

Have a beautiful day.

Bob

PS I see you got it fixed before I could finish typing, you sly dog!


----------



## kotori (Apr 18, 2006)

Big Bob @ Tue Apr 18 said:


> Regarding your 'reverse' inter-script communication idea, that's very clever. But I wonder if maybe we can't send data back via CCs also. While it probably won't produce a 'on controller' callback, we could use your scheme. After A creates a note, before B turns it off it also sets a pair of CC values (one as a sentinel the other to contain 7-bit data). Then when the RCB occurs in A, it can check the sentinel and read the data.



Yeah, good idea. And even better it works! :smile: That variant is a bit nicer - less bit twiddling when a 32-bit number can be transferred using five 7-bit data packets. 
I wish you a beautiful day too, Bob.

Cheers,
Nils


----------



## Thonex (Apr 18, 2006)

sbkp @ Tue Apr 18 said:


> Thonex @ Tue Apr 18 said:
> 
> 
> > I'm still impressed with the use of a mod command to make a toggle.
> ...



Wow... very interesting. 

I looked up the '.and.' command in he KSP manual... and all it says is: "Bit Operator.... Bitwise and" .... that's all. :???: 

I'm a composer... this tells me nothing :smile: 

I'd love to know what is going on with the '.and.' statement. I do understand the mod statement.... and like Nils showed... it can be used very creatively. But I'm at a loss on what the '.and.' statement does.

If it's not to complex, could you post a 1 or 2 sentence summary of the '.and.' statement?

Thanks,

T


----------



## Tod (Apr 18, 2006)

Thonex said:


> I'd love to know what is going on with the '.and.' statement. I do understand the mod statement.... and like Nils showed... it can be used very creatively. But I'm at a loss on what the '.and.' statement does.



Hehe, well back in my old DOS programing days it basically went with a conditional routine.

if
.....condition
and
.....condition
then 

But for script writeing I'm not sure. :???:


----------



## Thonex (Apr 18, 2006)

Tod @ Tue Apr 18 said:


> Thonex said:
> 
> 
> > I'd love to know what is going on with the '.and.' statement. I do understand the mod statement.... and like Nils showed... it can be used very creatively. But I'm at a loss on what the '.and.' statement does.
> ...



:lol: :lol: :lol: Yeah.... that's what it looks like... but this command has a period before and after the "and"... like '.and.'

It has something to do with Bits.... I'm guessing....


----------



## Big Bob (Apr 18, 2006)

re: bit twiddling

Since I'm an old bit twiddler from way back, maybe I can clarify.

If you .and. two 32-bit integers the result is a bitwise logical and. For example suppose you .and. two 4-bit values: 0101 .and. 0110 the result will be 0100. An old assembly language trick for doing power of two modulo operations quickly was to use a bit-mask of all ones for the least bits. For example if you wanted to do modulo 8 you would make a bit mask 0000.......0111 where the lowest three bits are on. In the decimal system this is the number 7.

Now if you want to make a circular index (or something similar) that runs from 0..7 and then falls back to zero, you could use:

```
$x := ($x + 1) .and. 7
```

Suppose $x is 6, if you increment it, it will become 7. Now when you .and. $x with 7 and the value of $x is less than 8 it will remain unchanged. But, when you increment $x the next time ist becomes 8 which in binary is 1000. Then this is anded with 7 (0111) in binary, you end up with 0. Clear as mud?

God Bless,

Bob


----------



## kotori (Apr 18, 2006)

Thonex @ Tue Apr 18 said:


> I looked up the '.and.' command in he KSP manual... and all it says is: "Bit Operator.... Bitwise and" .... that's all. :???:



Well, the .and. operator is not really used very often. I think you could live happily without it, but if you really want to know here's an explanation:
The binary-and is an operation that takes two bits (one or zero) and gives you back 1 if both bits are 1, and 0 otherwise. This is logical if you think of 1's as 'true' and 0's as 'false'. Every integer can be represented as a binary number - a series of bits. What the bitwise-and operator ('.and.') does is that takes two numbers, pair up their bits and then performs the binary-and operation for each pair.

For example let's say you calculate '3 .and. 5'.
The binary representation of 3 is 011 and the binary representation of 5 is 101.
Now we will pair up the bits. I do this by writing the two numbers on top of each other:
011
101

We have three pairs: 0 and 1, 1 and 0, 1 and 1 for which we will perform the binary-and. This yields 0 for the first pair (not both 1), 0 for the second pair (not both 1), 1 for the last pair (both 1). So we get: 001. In decimal representation this is the number 1. So '3 .and. 5' results in the number 1.

Ok, so how is this useful you might ask. Well, the primary use in KSP as I see it is to be able to pick out a certain part of a bit-pattern. Eg.
101101010010100
000001111110000
---------------------------- .and.
000001010010000

As you see the second number is used as a mask to extract the middle part of the number on the first line. There's a function that let's you move bits to the left or right - sh_left and sh_right. By shifting the above number to the right four steps we would get 101001. This number is small enough (between 0 and 127) to enable us to send it as a MIDI controller value. This is the technique Bob uses to send large numbers (many bits) in the preset export. A 32-bit integer is simply chopped into five parts using bitwise-and and then shifted to the right and then sent using the set_controller function. On the other end they are shifted back and bitwise-or:ed together.

These bitwise operations can also be used to trick the sort function into sorting values by keys. Those are the primary uses I think.
Please ask if there's anything you wonder about. These things can be kind of tricky to get a grip of the first time.

Cheers,
Nils

_Edit: I see Bob already answered._


----------



## Thonex (Apr 18, 2006)

Thanks Bob and Nils!!!!!!!

THis is great for round robins and maybe sawtooth lfos drived from 'while' statements.

Man... I love this place... thanks for the lesson... awesome!!!!!

BTW Bob.. I sent you a working Bypass Module for SIPS :smile: 

I got it to work with your and Nils help.

T


----------



## Big Bob (Apr 18, 2006)

Hey Nils,



> Yeah, good idea. And even better it works! That variant is a bit nicer - less bit twiddling when a 32-bit number can be transferred using five 7-bit data packets.
> I wish you a beautiful day too, Bob.


I was off doing something else when this idea popped into my head. We create another 128-word Global array and dedicate another pair of CCs to function as 'reverse' data carriers. Let's call them RGCC_1 and RGCC_2. Then we implement something like this: Any earlier script that wants data from a later script, first sends an ID# in RGCC_1 and waits for a response. This of course produces 'on controller callbacks', CCBs, in all the later scripts. Now, only the script whose ID# was sent, responds on RGCC_1 by setting it to zero and it also sets itself up to receive on RGCC_2. The other scripts continue to not respond to RGCC_2. The first script now senses the handshake and then sends the index of the required data on RGCC_2. When the 'addressed' script receives the index, it sets RGCC_1 to its ID#. This causes the requesting script to set itself up to receive a 5-byte data stream on RGCC_2 from the addressed script.

This sort of scheme would allow us to do reverse communication without using anything but a pair of CCs (no unused notes, no RCB, etc). Between this and the forward scheme we already have (such as that used by SIPS), I think we can handle most interscript communication that we'd need except for the situation where a later script wants to send unsolicited data backwards. We probably can get by without that I think.

Anyway, this isn't fully baked yet it was just a thought. When I get some time later I'll flesh it out in a little more and see if there are any holes in it.

God Bless,

Bob


----------



## ComposerDude (Apr 19, 2006)

In case Kontakt also supports the .xor. bitwise operator you can do bit toggles.

XOR (Exclusive-OR) returns a 1 if the inputs are (1,0) or (0,1) and returns a 0 if the inputs are (0,0) or (1,1). So setting one of the inputs to 1 means that the output is the inverse of the other input.

In theory (and it will be a little while before I acquire K2 here) you could do:

$x = $x .xor. 1

if you were flipping only the lowest bit.

To flip all the bits, XOR against a number with all 1s. In C that would be (for 32-bits) 0xFFFFFFFF hexadecimal; I do not yet know the K2 equivalent.

There is also a bitwise NOT that will flip all the bits to their opposite state. But for a simple toggle, that means in 2-complement arithmetic that you are toggling between 0 and -1 instead of between 0 and 1. So we will skip that one for now.

Anyway, fascinating thread, and it looks like this forum has taken off like the proverbial rocket. Nils and Big Bob, so glad you joined!


----------



## kotori (Apr 19, 2006)

Kontakt doesn't support xor but it's possible to implement it as your own (pseudo-) function using my http://nilsliberg.se/ksp/using_functions.py (extended scripting syntax):


```
function xor(a, b, result)
  result := (a .and. .not. b) .or. (b .and. .not. a)   { either but not both of a and b taken bitwise }
end function
```
I don't know if xor is particularily useful in KSP though. The code above was mostly for fun. :wink:


----------



## Thonex (Apr 19, 2006)

kotori @ Wed Apr 19 said:


> I don't know if xor is particularily useful in KSP though. The code above was mostly for fun. :wink:



Wow Kotori.... you really know how to party :lol: :wink: 

T


----------



## sbkp (Apr 19, 2006)

LOL....

(desperately trying to think of some programming trick to show that I can geek-out with the best of them.... failing.... can't..... remember.... brain.... fading....)

Well, as I tell people, I'm a "recovering software engineer." I have relapses, though...

- Stefan


----------



## José Herring (Apr 19, 2006)

Now that we have this forum topic I'm going to have to learn to script so that I can figure out WHAT THE HECK YOU GUYS ARE ALL TALKING ABOUT!!!!!
:shock:


----------



## Big Bob (Apr 19, 2006)

It's all just gibberish Jose but, it makes us feel important :wink: 

Bob


----------



## Big Bob (Apr 20, 2006)

ComposerDude @ Wed Apr 19 said:


> And keeps people in Kontakt.


Oh that's precious ... and Very Clever!


----------



## Thonex (Apr 20, 2006)

Big Bob @ Thu Apr 20 said:


> ComposerDude @ Wed Apr 19 said:
> 
> 
> > And keeps people in Kontakt.
> ...



Actually, Composer Dude is a very clever man.... a real coder... I'm just waiting for him to buy Kontakt so we can all peck his brain too   

C'mon Peter (composer dude)... what are you waiting for!! :smile: 

T


----------



## ComposerDude (Apr 21, 2006)

Thonex @ Thu Apr 20 said:


> Big Bob @ Thu Apr 20 said:
> 
> 
> > ComposerDude @ Wed Apr 19 said:
> ...



Andrew and Bob, thanks for the kind words!
Studio is halfway relocated; when it's up then I can build a Kontakt PC.

-Peter


----------

