1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

On Listener and starting off the bar.

Discussion in 'KONTAKT: Sampling, Programming & Scripting' started by Discotron, Aug 12, 2017.

  1. Discotron

    Discotron Member

    11
    0
    Jun 23, 2017
    Hi guys and girls,
    I'm trying to make some kind of note sequencer and it is kind of working and looping around playing notes(if I press stop on my DAW and reset to start of bar) but there is a problem with starting off bar - When starting off beat it will only wait for the next bar if the DAW is two beats into the bar.

    If I start the DAW for example before the second beat, the sequencer starts up right away and is out of time, if I start it after the 2nd beat the sequencer waits until it reaches the next bar and the starts which is great.

    Weirdly if I change the $NI_SIGNAL_TIMER_BEAT,4 to $NI_SIGNAL_TIMER_BEAT,1 it works, but then the loop is slow. I thought $NI_SIGNAL_TIMER_BEAT,4 is the same as wait $DURATION_SIXTEENTH.

    The script below is updating two variables ($daw_is_playing and $bar_start)before the sequencer is allowed to start.

    Play is pressed on the DAW and $daw_is_playing is set to 1 and then if ($bar_position mod $SIGNATURE_NUM = 0) sets $bar_start to 1 which then satisfies the if statement below and the loop starts
    if ($daw_is_playing = 1 and $bar_start = 1)

    loop around
    play notes etc
    increase $step etc
    end if

    Am I way off the mark here?

    on init
    set_listener($NI_SIGNAL_TRANSP_STOP,1)
    set_listener($NI_SIGNAL_TRANSP_START,1)
    set_listener($NI_SIGNAL_TIMER_BEAT,4)
    end on

    on listener
    if ($NI_SIGNAL_TYPE .and. $NI_SIGNAL_TRANSP_STOP # 0)
    $bar_start :=0
    $daw_is_playing :=0
    end if{this stops the sequencer}

    if ($NI_SIGNAL_TYPE .and. $NI_SIGNAL_TRANSP_START # 0 )
    $daw_is_playing :=1
    $step := 0
    end if{this sets up one of the needed variables to start the loop }


    if ($NI_SIGNAL_TYPE .and. $NI_SIGNAL_TIMER_BEAT # 0)
    $bar_position := $NI_SONG_POSITION/960

    if ($bar_position mod $SIGNATURE_NUM = 0)
    $bar_start :=1
    end if{this sets the final variable needed to start the loop below}


    if ($daw_is_playing = 1 and $bar_start = 1)

    loop around
    play notes etc
    increase $step etc
    end if

    Any help or guidance about the above or the on listener call back would be very appreciated.
    Thanks guys.
     
    Last edited: Aug 13, 2017 at 12:49 AM
  2. EvilDragon

    EvilDragon KSP Wizard

    3,002
    1,284
    May 25, 2010
    Croatia
    Why not run the listener at the highest rate (24 ticks per beat)? Then the delay will be at most 1/64T.


    You don't need $daw_is_playing variable at all. Just use $NI_TRANSPORT_RUNNING instead, it's the same thing, and built into KSP.
     
  3. OP
    OP
    Discotron

    Discotron Member

    11
    0
    Jun 23, 2017
    Thanks.
    Just tried it and still not working and the speed of the sequencer has become really fast.
    All I want it to do is not start my scripted sequencer until the pointer in the DAW reaches the start of the next bar. So, if I press stop on my DAW and it has stopped somewhere in-between a bar and then I press start again I just want my sequencer to wait until the DAW reaches the start of the next bar and then start my sequencer so it is is time. Is it not possible to do this in Kontakt? I thought the script below would make it wait until the start of a bar was reached.

    if ($bar_position mod $SIGNATURE_NUM = 0)
    $bar_start :=1
    end if

    If I'm using $NI_TRANSPORT_RUNNING can I now totally remove the start signal type check from the script - if ($NI_SIGNAL_TYPE .and. $NI_SIGNAL_TRANSP_START # 0 )
    $step := 0
    end if
    Thanks
     
    Last edited: Aug 13, 2017 at 2:58 AM
  4. EvilDragon

    EvilDragon KSP Wizard

    3,002
    1,284
    May 25, 2010
    Croatia
    Ah, I get ya. I don't think you want Kontakt to wait for next bar. What would be better is to start from the current position in the bar, would it not? For this, I recommend checking out the arpeggiator part of Retro Machines II script, it contains some useful code for this exact purpose. Check it out (it's in tick_received() function at the beginning):



    If you want to restart $step, you need to keep that check in. However I'm not sure why you're not simply doing if ($NI_SIGNAL_TYPE = $NI_SIGNAL_TRANSP_START), works to the same effect and it's shorter to write. :)


    By the way, please use CODE tags when posting code.
     
  5. OP
    OP
    Discotron

    Discotron Member

    11
    0
    Jun 23, 2017
    Thanks very much for your help. Yes, starting at current position would be amazing if I could get that to work. I will go through the arp code and see what absolute disaster I can make of it :)
     
  6. Lindon

    Lindon KSP Developer

    462
    75
    Jul 27, 2010
    Republic of Yorkshire
    I've put this up here before but one more time, if you want your sequencer to start at bar start(assuming a 4/4 signature), and a way to see which bar you are in:
    Code:
    $bar_position := $NI_SONG_POSITION/960
    
    if ($NI_SONG_POSITION-(3840*($NI_SONG_POSITION/3840))<4)
         {do your stuff here...}
    end if
    
     
  7. EvilDragon

    EvilDragon KSP Wizard

    3,002
    1,284
    May 25, 2010
    Croatia
    That of course assumes everybody lives and breathes in 4/4 all the time (and Retro Machines II script is much the same) :P
     
  8. OP
    OP
    Discotron

    Discotron Member

    11
    0
    Jun 23, 2017
    Code:
    Code:
    $bar_position := $NI_SONG_POSITION/960
    
    if ($NI_SONG_POSITION-(3840*($NI_SONG_POSITION/3840))<4)
         {do your stuff here...}
    end if
    Thanks for this.
    I'm still getting a delay which seems to vary in time when using this. If I stop my DAW and ensure it returns to the start of bar and press play, all is fine but if I start somewhere other than the beginning of a bar my sequencer waits until it reaches the start of the next bar(using above code snippet), but seems to be a bit early in timing.
     
    Last edited: Aug 14, 2017 at 8:37 AM
  9. Lindon

    Lindon KSP Developer

    462
    75
    Jul 27, 2010
    Republic of Yorkshire
    its using the song position pointer sent to it by your DAW so its not late....and yes its SUPPOSED to wait for a bar start. That's the point.
     
  10. OP
    OP
    Discotron

    Discotron Member

    11
    0
    Jun 23, 2017
    yes, it is waiting as it is supposed to, but when it lands on the beginning of a bar and starts my sequencer it is starting out of time, but is not out of time if I stop my daw and reset to the beginning of the bar that way. It must be my sequencer code causing the issue. Thanks
     
  11. OP
    OP
    Discotron

    Discotron Member

    11
    0
    Jun 23, 2017
    Code:
    on init
        set_ui_height_px(200)
        make_perfview
        set_listener($NI_SIGNAL_TRANSP_STOP,1)
        set_listener($NI_SIGNAL_TRANSP_START,1)
        set_listener($NI_SIGNAL_TIMER_BEAT,4)
    
        declare $bar_start :=1
        declare $tick_counter :=0
        declare $ticks_per_step :=1
        declare $bar_position
        declare $play_the_notes
        declare $step_counter :=0
        declare ui_knob $start_knob(0,31,1)
        declare ui_knob $end_knob(0,31,1)
        declare ui_table %note_table[32] (20,20,127)
     
    
        set_control_par(get_ui_id(%note_table),$CONTROL_PAR_WIDTH,500)
        set_control_par(get_ui_id(%note_table),$CONTROL_PAR_HEIGHT,100)
    
        move_control_px($end_knob, 125,140)
        move_control_px($start_knob, 25,140)
        move_control_px(%note_table, 1,26)
    
        make_persistent($start_knob)
        make_persistent($end_knob)
        make_persistent(%note_table)
    end on
    
    on note
        allow_group($ALL_GROUPS)
    end on
    
    on listener
    
      select ($NI_SIGNAL_TYPE)
    
        case $NI_SIGNAL_TRANSP_STOP
        $step_counter := $start_knob
        $tick_counter := 0
        $bar_start :=0
     
    
    
        case $NI_SIGNAL_TRANSP_START
        $step_counter := $start_knob
        $tick_counter := 0
        $bar_start :=0
     
    
        case $NI_SIGNAL_TIMER_BEAT
        $bar_position := $NI_SONG_POSITION/960
    
        if ($NI_SONG_POSITION-(3840*($NI_SONG_POSITION/3840))<4)
             $bar_start :=1
        end if
    
        if ($NI_TRANSPORT_RUNNING = 1  and $bar_start = 1 )
    
                
            if (%note_table[$step_counter] > 0) {only play a note if table value is above 0}               
                $play_the_notes := play_note(%note_table[$step_counter]+36,127,0,$DURATION_SIXTEENTH)
            end if
    
            inc($tick_counter)
             if ($tick_counter >= $ticks_per_step)
                inc($step_counter)
                if ($step_counter >= $end_knob)
                    $step_counter := 0
                end if
                $tick_counter := 0
             end if
    
        end if {the end if for if ($NI_TRANSPORT_RUNNING = 1  and $bar_start = 1 )}
      end select
    
        end on
    
    This is the code I'm using. It works if I press stop on my DAW and then press play, but if I start off beat somewhere it waits for the next bar as expected and then starts but sometimes the playing sequencer above feels a tad out of time, like it has been started a fraction too early or maybe late.

    It is probably my code that is causing the problems. Am I on the correct lines with the code above?

    Thank you.
     
    Last edited: Aug 16, 2017 at 1:48 AM
  12. EvilDragon

    EvilDragon KSP Wizard

    3,002
    1,284
    May 25, 2010
    Croatia
    Can't you do something with the Retro Machines code I posted above?

    You basically just need to modify what happens when a step is reached in tick_received() function. Everything else is practically set up for you.

    (Also, make sure that you reset $tick_counter to -1, not 0, for reasons.)
     
  13. OP
    OP
    Discotron

    Discotron Member

    11
    0
    Jun 23, 2017
    Thanks.
    I'm curious as to what is wrong with the code above as I'm trying to further my understanding of on listener. I can't understand why the above code does not work as it waits for bar as it should, but the sequencer starts a bit out of time.

    Also, if I set_listener($NI_SIGNAL_TIMER_BEAT,24) the thing goes haywire and sounds like it is repeating notes really quickly. Should it always be set to set_listener($NI_SIGNAL_TIMER_BEAT,4) ?
     
    Last edited: Aug 16, 2017 at 1:01 PM
  14. EvilDragon

    EvilDragon KSP Wizard

    3,002
    1,284
    May 25, 2010
    Croatia
    You set the listener rate however you want, that's why you can decide which number of ticks to respond to per beat. That means your code needs to be adjusted in order to match the rate you want the notes to be played at. In other words, when you have listener running at 4 ticks per beat, that equals 1/16 notes, because you respond on every tick.

    If you run it at 24 ticks per beat, in order to get 1/16th notes, you need to respond to every 6th tick, and you do that by counting ticks and then only playing notes on each n-th tick. Modulo operation is a godsend for stuff like this. Again, this has all already been handled in the Retro Machines script, so study it a bit. :)
     
  15. OP
    OP
    Discotron

    Discotron Member

    11
    0
    Jun 23, 2017
    Thanks for the explanation, it is starting to make sense why and how things are set in the on listener callback.
     

Share This Page