# Script Generated Notes



## Hans Adamson (Mar 3, 2014)

Hello guys,

Can script generated notes trigger note on callbacks?

If so, would it be possible to use a modified version of the arpeggiator to trigger note on callbacks at certain intervals as long as a certain key is held down?

If it isn't possible, does anyone have a suggestion how to trigger automated callbacks at certain intervals as long as a key is held down.

I thought I'd getting some expert advice before spending too much time on this.

Thanks in advance for any advice.

/Hans


----------



## kb123 (Mar 4, 2014)

This thread should be useful

http://www.vi-control.net/forum/viewtopic.php?t=36801


----------



## Hans Adamson (Mar 4, 2014)

Thanks KB,

Great that blip notes can trigger callbacks. I am trying to write a script that will issue an note off for a held note after a certain time, and then re-start the note with play_note at an exact time. 

Any suggestions would be greatly appreciated.

/Hans


----------



## Big Bob (Mar 4, 2014)

Hi Hans,

Could you be more specific?

For example, how does the held note (you want to end after some time) originate? Is it played and held on a keyboard? If so, when will the key that was played be released? etc, etc.

Where/how will you obtain your 'exact time' that is supposed to retrigger the original note? When retriggered, is it to be the same note and velocity and when should it stop, etc etc.

As Sherlock Holmes used to say, I cannot operate without data :lol: 

Rejoice,

Bob


----------



## Hans Adamson (Mar 4, 2014)

Big Bob @ Tue Mar 04 said:


> Hi Hans,
> 
> Could you be more specific?
> 
> ...



Bob,

Thank you for responding! 

Depressing a key triggers a loop. As long as the key is depressed, the loop will play - unless legato mode is used and one or more notes follows, played legato. In that case, the total playback length of legato loops will only be as long as the first loop's wav (if several keys are played in succession.)

So in this case the loop needs to be re-triggered. The person player should not have to count bars to re-trigger before the loop abruptly ends. So if a script could quickly fade out, issue a note off, before the loop ends (determined by the tempo set in Kontakt, and the loop's length in bars), and then re-trigger the loop exactly on the next bar-line, the player need not worry about how many bars until shut-off to re-trigger the loop.

Maybe there is another workaround for this problem, but I have not found it.

Any advice would be greatly appreciated,
/Hans


----------



## Reegs (Mar 4, 2014)

A possible solution, which I have not tested nor optimized:

Assuming K4.2:

Use the on_listener callback with the $NI_SIGNAL_BEAT or $NI_SIGNAL_TIMER_MS and a parameter will give you deterministic callback scheduling. See set_listener()

For the releases that need retriggering, perhaps keep an active array of your loop switches and set them in a "must_retrigger" state when released. Intercept their re-activation from the on_note callback, set a bit in a "retrigger_on_beat" array, and in the listener cb retrigger the necessary loops. 

Perhaps use a running sum of active retriggers to limit the array walking you'll need to do on most listener cbs (if sum =0, ignore the walk). You might also be able to get crafty with the by_marks() functions to handle this quickly.


----------



## Big Bob (Mar 5, 2014)

Hans,

Looks like Reegs has jumped in with some nice suggestions to get you started. So, I'll just keep an eye on this thread from time to time to see if any issues arise that I might be able to help with.

Rejoice,

Bob


----------



## Hans Adamson (Mar 5, 2014)

Thanks Reegs, Bob,

I appreciate the detailed advice! I still have some studying to do to grasp it, though. For now I have one question: 

What is "walking"?

Thanks again,
Hans


----------



## Big Bob (Mar 5, 2014)

I presume Reegs means something like 'advancing through' or 'searching through' the arrays looking for what must be done. I usually refer to this as crawling through the arrays but then I haven't learned to walk yet. :lol:

But I'm sure Reegs will chime in with a more precise answer, especially if I'm way off the right answer :lol: 

Rejoice,

Bob


----------



## Hans Adamson (Mar 5, 2014)

Thanks Bob,

In this case it is bass loops, and there will only be one key depressed at the time, so maybe the array work will be minimal, from what I understand of reegs's description.

I realize there are a whole lot of commands relating to loops in Kontakt scripting, but I have never used them, so I need to look into that, starting with those Reegs pointed out.

My initial thought (always looking for the 'easiest' way) was to study the factory arpeggiator script, to generate blip notes that would trigger note on callbacks that would fade out user-played notes and re-trigger them at the intervals needed.

/Hans


----------



## Big Bob (Mar 5, 2014)

Hi Hans,

*My initial thought (always looking for the 'easiest' way) was to study the factory arpeggiator script, to generate blip notes that would trigger note on callbacks that would fade out user-played notes and re-trigger them at the intervals needed. *]

Just to add a bit of clarification, a blip note cannot trigger the NCB in the same script slot. It can of course trigger the RCB which in turn can generate new notes (but these new notes will not trigger the NCB either). However, a blip note in one script slot can trigger the NCB for all the following script slots. You haven't said anything about multiple script slots so I have so far presumed that you are talking about a single slot?

Rejoice,

Bob


----------



## Hans Adamson (Mar 5, 2014)

Thanks Bob,

So far I have only used the first script slot. So I guess I can move the main script down to the second slot and put the NCB triggering blip script in the first slot. It could blip at the end of every loop, and if conditions are met, a note off and a play_note could be issued in the callback triggered by the blip in the main script in the second slot. Is this correct?

/Hans


----------



## Big Bob (Mar 5, 2014)

Yes, but you could also do the note_off and new note creation from the RCB of the first script just as well. 6 of 1, half-dozen of the other I guess :lol:


----------



## Hans Adamson (Mar 5, 2014)

OK, thanks Bob!


----------



## Reegs (Mar 5, 2014)

Hans Adamson @ Wed Mar 05 said:


> Thanks Reegs, Bob,
> 
> I appreciate the detailed advice! I still have some studying to do to grasp it, though. For now I have one question:
> 
> ...



Hi Hans,

Bob had it right-- by walking I mean inspecting each element of the array systematically, starting at position 1 and ending at the last. The non-slang term is array traversal. In pseudocode, something like

```
//inside of listener callback
while $i < $array_size
    if notes_to_retrigger[$i] == 1
        code to retrigger/reset arpeggiator for this note, e.g. play_note()
        notes_to_retrigger[$i] = 0
   end
   $i = $i + 1
end
```

Since the listener callback would be constantly running, it would be important to keep this code fast and light-- the less time you spend traversing, the smaller number of resources it would use. But, since you mention you're using only one active loop at a time, you wouldn't have to traverse an array of queue states for notes. Possibly something like the following would work:


```
on_note_on
    if $EVENT_NOTE == special_loop_note
        schedule_loop_start = 1
        //Placeholder for code to prevent note/loop from playing immediately
    end
end

on_note_off
     if $EVENT_NOTE == special_loop_note
         schedule_loop_start = 0 //Prevent retriggering if user changes mind mid wait-cycle
         loop_fade_out_code()
      end
end

on_listener
     if $NI_SIGNAL_BEAT
          //Placeholder for code to figure out what beat you're on
          if beat == start_of_bar
               if schedule_loop_start == 1
                    schedule_loop_start = 0
                    play_note()  //Restarts loop at start of bar or musically-correct equivalent
               end
          end
       end
end
```
 
[/code]Reegs


----------



## Hans Adamson (Mar 6, 2014)

Thanks Reegs,

I will test this today.

/Hans


----------



## Hans Adamson (Mar 6, 2014)

After working with this today, I am more and more convinced that the problem cannot be solved unless the legato function in Tone Machine control is re-written in KSP. The problem is simply that a second note (legato) is not being read for time position information.

The legato function in Tone Machine reads the position in the first sample in a phrase, and when it is followed by a (monophonic) legato note, the legato note starts from the position in the sample where the previous note stopped. Now the problem is that if a third legato note is played, the position is not read from the previous legato note.

Could the same functionality be written in KSP, but with the ability to always read the time position in the sample from the previous note - also when the previous note is a legato note? 

/Hans


----------



## Mike Greene (Mar 7, 2014)

I think this could be done. I would make a variable $Start_Time which marks the time (in milliseconds) of when the first note in a legato phrase starts. Like this:


```
if (first note of phrase)
	ignore_event($EVENT_ID)
	$Start_Time := $ENGINE_UPTIME
	$new_note_id := play_note ($EVENT_NOTE, $EVENT_VELOCITY, 0, -1)
	$old_note_id := $new_note_id
end if
```

Then for each successive note in the legato string (2nd, 3rd, 4th, whatever,) figure out how long it's been since the start of the legato phrase. (Current Time minus Start Time.) Then use that in the sample offset parameter of a play_note command for the new note. Like this:


```
if (new note is part of legato phrase)
	ignore_event($EVENT_ID)
	$SampleOffset := ($ENGINE_UPTIME - $Start_Time) * 1000  {Need to multiply by 1000 because sample offset is in microseconds, instead of milliseconds}
	$new_note_id := play_note ($EVENT_NOTE, $EVENT_VELOCITY, $SampleOffset, -1)
	fade_out($old_note_id, 10000, 1)
	$old_note_id := $new_note_id
end if
```


----------



## Hans Adamson (Mar 7, 2014)

Thanks Mike,

What do you think about using $ENGINE_UPTIME instead of $KSP_TIMER for better precision (mostly to get the best timing when syncing to host). Also, could mod 'sample length' be used to time the position in a looped sample?

/Hans


----------



## Big Bob (Mar 7, 2014)

I think you guys got these backwards :roll: 

ENGINE_UPTIME is in milliseconds

KSP_TIMER is in micro seconds.

Or am I standing on my head today :lol:


----------



## Hans Adamson (Mar 7, 2014)

You are absolutely right Bob. Funny, I just read the definitions yesterday, but I read them wrong.... like when you hear "turn right", and then you turn left... (o) Thanks for pointing it out.
/Hans


----------



## Mike Greene (Mar 7, 2014)

Yes, Bob is right. Which is kinda embarrassing, because I _never _use $KSP_TIMER and I always use $ENGINE_UPTIME.

I've corrected the post, in case anyone sees it later.


----------



## Mike Greene (Mar 7, 2014)

Hans Adamson @ Fri Mar 07 said:


> Thanks Mike,
> 
> What do you think about using $ENGINE_UPTIME instead of $KSP_TIMER for better precision (mostly to get the best timing when syncing to host). Also, could mod 'sample length' be used to time the position in a looped sample?
> 
> /Hans


I never do anything where I need accuracy greater than 1 millisecond, so I always use $ENGINE_UPTIME. My samples are not phase-aligned, and I do crossfades anyway, so it would be overkill for me. But that's just me, and maybe there could be reasons for greater accuracy.

I don't know whether or not the sample offset can be inside a loop. But . . . if a sample was looped, then it seems to me that it wouldn't matter anymore whether your offset point was exact, since the loop means the sample is no longer evolving. In that case, I would think you could just always have the sample offset to somewhere just after the attack, since the sample would presumably be consistent after that. Unless I'm misunderstanding something.


----------



## Hans Adamson (Mar 7, 2014)

Mike,

These are bass loops with precise timing, grooving subtly, playing ahead, or relaxed behind the perfect timing, and when switching in the middle of a bar, or, at the end of a bar you would want to keep precise timing in relation to the metronome. When playing a large number of loop segments as legato notes in a row, laying down a track for a song, the inaccuracies will build up. Every time there is a note that is not a legato note, the timing can be reset, but a complete song could theoretically be played without this happening, so I am trying to get the timing as tight as possible to prevent an accumulation of timing inaccuracies that would spoil the groove.

BTW, I am using your code to see if I can create the script I need. o-[][]-o 
/Hans


----------



## Big Bob (Mar 7, 2014)

Hey Guys, besides resolution, there is another important difference between KSP_TIMER and ENGINE_UPTIME that may or may not affect what you are trying to do. But, perhaps you should be aware of this 'little known' problem.

ENGINE_UPTIME is apparently *not updated at all* during compute-bound processes (with no wait statements) whereas KSP_TIMER *continues to coun*t. This makes UPTIME almost useless for things like trying to measure execution time of user functions that may do a lot of number crunching.

Most often, blocks of code between wait statements do not take too long to complete. Moreover those that do take some time to run usually contain nested while loops and Kontakt automatically aborts those after about 45000 total loop-body passes.

Under the right conditions though, it is possible (for example) for KSP_TIMER to report a differential interval of say 8000 microseconds while ENGINE_UPTIME reports 0 millisecs. *So, watch out for this mechanism, it could bite you someday.* :lol: 

Rejoice,

Bob


----------



## acabreira (Apr 8, 2014)

Hi, Bob, so you suggest that for higher precision we should always use KSP_TIMER? Any quirks with that?

Thanks!

Adriano


----------



## Big Bob (Apr 8, 2014)

Hi Adriano,

I guess it's kind of a mixed bag. While mathematically, KT has several advantages over UT (better resolution and more reliable updating), I understand that there may be some problems with host syncing and some of the related issues. Apparently, KT more or less is a measure of 'real time' while UT may track the tempo mechanisms better (at least when they deviate from 'real time').

Since I have never done anything in the 'beat area' :lol: , I'm not in a position to provide reliable input on the subject. But, as far as measuring real time accurately (even when you only need a one-millisecond resolution), you will be better off just using:

time = (KT+500)/1000 instead of UT 
(where KT = KSP_TIMER change and UT = ENGINE_UPTIME change).

Rejoice,

Bob


----------



## acabreira (Apr 8, 2014)

Since my adventures with scripting are focused in time rather than tempo related operations, I'll stick to KT for awhile 

Thanks, Bob.

By the way, how things are going?


----------



## Big Bob (Apr 9, 2014)

> Thanks, Bob.
> 
> By the way, how things are going?



Hi Adriano, lots of health issues but I'm still 'Praising the Lord' whenever I can. Thanks for asking and I hope all is well with you.

God Bless,

Bob


----------

