How to sync LCB beat ticks to transport start? [REPHRASED]

merlinhimself

Active Member
What is the best way to achieve listener beat accuracy when it comes to pressing play on your transport and ticks sync up perfectly to the beat as well as when the transport is stopped playing a note and listener starting on that?

Basically, I have an issue now that my sequencer is occasionally starting late 1/64th note because the listener may or may not be in the middle of a tick when a note is called, so it waits till the next time it gets its signal and then goes through it all causing a delay. Right now the listener is running every 64th as soon as kontakt starts not in relation to the transport activating or a note being played.


(I rephrased this whole thread as it started out as me having no clue what or why, and slowly i figured it out lol. Just making it easier for anyone willing to help! At this point I know whats happening but stuck on how to fix it)

Heres a general sum of my code (please pardon my mess, I was trying to figure it out)
Code:
function playseq1
if ($seqmute1 = 0)
        if ($tick_counter mod %rate_ticks[$notevalue1] = 0)
            $velocity1 := %steps1[$counter1]

            if ($velocity1 > 80)
                select ($RR_F1)
                        case 0
                                $Magic_Note_ID := play_note($key_seq1, 83, 0, -1)
                            call groupswitch1
                        case 1
                                $Magic_Note_ID := play_note($key_seq1, 88, 0, -1)
                                call groupswitch1
                        case 2
                                $Magic_Note_ID := play_note($key_seq1, 93, 0, -1)
                                call groupswitch1
                        ETC
                        ETC
                        ETC
                    end select

                change_vol($Magic_Note_ID, (($velocity1 - 128) * $velnum), 1)

                inc($RR_F1)
                if($RR_F1 = 8)
                    $RR_F1 := 0
                end if
              
                                        DOES OTHER VELOCITIES ETC ETC
            end if
end function

on listener
    if ($note_count = 0)
        $tick_counter := 0
    end if
  
    if ($seq1_note_count > 0)
                call playseq1
        end if

on note
    ignore_event($EVENT_ID)

if ($EVENT_NOTE = 48 )
        $note := $EVENT_NOTE
        $note1 := $EVENT_NOTE
        $count := 0
        while ($count < 8)
                if ($EVENT_NOTE = %seq1_notes[$count])
                %seq1_note_held[$count] := $EVENT_NOTE
                $seq1_note_held := $EVENT_NOTE
                inc($seq1_note_count)
                end if
                inc($count)
        end while
        inc($note_count)
    end if
    message($note_count)
end if

end on





on release
    ignore_event($EVENT_ID)
    message($note_count)

if ($EVENT_NOTE = 48)
    dec($note_count)
    $note_released := $EVENT_NOTE
    $count := 0
    while ($count < 8)
        if ($note_released = %note_held[$count])
            %note_held[$count] := 0
        end if
        inc($count)
    end while

    $count := 0
    while ($count < 8)
            if ($note_released = %seq1_notes[$count])
            %seq1_note_held[$count] := 0
            dec($seq1_note_count)
            end if
            inc($count)
    end while

    if ($NOTE_HELD = 0)
        $counter1 := 0
        $counter2 := 0
        $counter3 := 0
        $counter4 := 0

        if ($seq1_note_count = 0)
            $note1 := 0
        end if
    end if

    $count := 0
    if ($note_count = 0)
        while ($count < 8)
            %note_held[$count] := 0
            inc($count)
        end while
        wait(1)
        $note := 0
        $note1 := 0
        $note2:= 0
        $note3 := 0
        $note4 := 0
        $tick_counter := 0
        $note_count := 0

    end if
end if

end on
 
Last edited:
OP
merlinhimself

merlinhimself

Active Member
I could be totally wrong about that too, but seems like the best bet. I scoured a bunch of forums looking for an answer but came back with nothing, anyways, just a hobbyist trying to learn so I would greatly appreciate anyone's help!
 

Suganthan

Member
I barely have any experience with on listener. Does the sequencer lags throughout, or does it just skips the first note but other notes on time?

So, did you try to recreate the same problem in any other DAW?
 
OP
merlinhimself

merlinhimself

Active Member
I barely have any experience with on listener. Does the sequencer lags throughout, or does it just skips the first note but other notes on time?

So, did you try to recreate the same problem in any other DAW?
Thanks for responding! Yeah it's the whole sequence but the sequence is in sync with itself. For example if my pattern is 4/4 all notes on, if it delays every sound will be 1/64th late not just the first. I haven't tried recreating it in another daw, I'm pretty sure my main issue is how I've set up my listener, because it's basically counting 64th notes as soon as kontakt starts in the saw, it won't perfectly time up with anything played in the daw.
 

Suganthan

Member
1. Running on listener faster should help the accuracy right? but then some additional code has to be there in on listener - with tempo ticks calculations maybe?

2. Or how about the track can be given a negative delay, so that every notes play advance 1/64 which is compensated by this on listener lag?
 
OP
merlinhimself

merlinhimself

Active Member
Yeah I agree, I think a buffer of some sort is what I need, just not entirely sure how to set it up. I would have to read each tick of the listener with Ms somehow, do some math, and then add that variable into everything, like if ($tick_counter mod etcetc and $tick_buffer mod etcetc). I think that would work? I got so frustrated with it I was taking a little break from this side project haha
 

szcz

Member
About notes missing a tick: delay listener function a little, like use wait (500) in front of calling your tick function, this way you make sure that incoming notes are processed ahead of the listener. This solves possible late notes if events are aligned in DAW.
Also listener is not perfect, it can drop ticks sometimes, use $NI_SONG_POSITION to adjust your tick counter whenever transport is available.
 
OP
merlinhimself

merlinhimself

Active Member
About notes missing a tick: delay listener function a little, like use wait (500) in front of calling your tick function, this way you make sure that incoming notes are processed ahead of the listener. This solves possible late notes if events are aligned in DAW.
Also listener is not perfect, it can drop ticks sometimes, use $NI_SONG_POSITION to adjust your tick counter whenever transport is available.
Hm never thought of that, I will give it a try! Although I think your $NI_SONG_POSITION tick adjustment sounds like a good idea. I found another post referencing it sort of

tick_counter := (NI_SONG_POSITION / 40) mod ticks_per_step

is this the kind of thing? Seems like the right idea, then when the transport is not running it could just inc($tick_counter) on its own for playability. I understand NI_SONG_POSITION is 960/quarter note. 960/40 = 24 (tick amount). and then they used $tick_per_step as grid selection. My onyl question is where and how to implement that.

I assume it should be in the LCB
But not sure whether the listener should still be on BEAT,24 or if it should be on MS now
 

szcz

Member
tick_counter := (NI_SONG_POSITION / 40) mod ticks_per_step
is this the kind of thing?
Yes. And not my idea.

I understand NI_SONG_POSITION is 960/quarter note.
Correct.

But not sure whether the listener should still be on BEAT,24 or if it should be on MS now
Beat, it will be more efficient. Just use song position as counter when transport is running, so even if it skips a tick you will be in sync with DAW.
 
OP
merlinhimself

merlinhimself

Active Member
@szcz you are my savior! it seems like the wait() command was the main solution, but the NI_SONG_POSITION is also just a better way of counting it all
 

thesteelydane

Senior Member
You can actually have the listener run BEAT and MS at the same time. Gives you more ticks to do something with, and stays in sync. Not at the computer right now and typing on a phone, but something along the lines of this (note: pseudo code, can’t be bothered, nor remember all the correct variable names, and like I said typing on a phone)


Code:
on init

    set_listener(ni_signal_timer_beat, 24)
    set_listener(ni_signal_timer_ms, 1000)

end on

on listener

   if(signal=beat)
       change listener par(signal_timer_ms, duration_quarter/24/6)
       {set your length of sequence here and reset tick counter if end of sequence reached}
    else
       {here you have 6 ticks pr 24 slices of a quarter note, to do something with}
     end if
end on
hope that makes sense - it’s a nifty way of using MS and still have it sync to tempo changes.
 

polypx

Hoser
Nicolaj, when you do the "change listener par(signal_timer_ms, duration_quarter/24/6)"... does that reset the ms counter, so that it starts exactly on that beat-slice?
 

thesteelydane

Senior Member
Nicolaj, when you do the "change listener par(signal_timer_ms, duration_quarter/24/6)"... does that reset the ms counter, so that it starts exactly on that beat-slice?
It seems to, yes, but I don’t know how to measure that. All I can see is it stays very well in sync, even with extreme tempo changes, and it gives me a lot more ticks to do something with.

When I message out to a debugger to see what’s going on, I get 6 ticks between every call to the beat timer. I don’t think it will catch it if there’s a tempo change between the beat ticks, but it will catch It on the next beat tick, so it stays in sync, and I get very fine resolution.
 
Last edited: