自制模拟“连奏”KSP脚本(实为淡出过渡)

x7890

侦察机
KONTAKT VIP
初级 VIP
正式用户
🧱星陨矿
40,184
🧊星能体
62
🍀星灵素
0
🏵️星元核
0
入门了一点KSP知识,自制了一个脚本,可利用淡出效果模拟“连奏”效果,现分享给大家,希望能起些抛砖引玉的作用。
原理:将每个音符延迟一段时间释放,在释放之前,若有新的音符按下,则将旧音符淡出,从而实现单音的平滑过渡。将多个音认作一个同时发出的音,可实现复音淡出过渡。
使用方法:展开乐器左上角的扳手,将脚本加载并到已有脚本右边任意一个空格子即可,需要完整版Kontakt(对于Kontakt 6 原厂音色,还需要禁用最后的Dynamic Key Switches)。
共提供3个单位为ms的旋钮:第一个旋钮Release设置的是每个音符延迟释放的时间,用于识别新的音符;第二个旋钮Fade设置的是旧音符淡出的时间;第三个旋钮Tol设置的是复音识别的阈值时间。

代码:
{ Faded Mono (模拟连奏) By x7890 }
{ 加载方法:点开乐器左上角的“扳手”,展开“Script Editor”,将脚本加载到已有脚本的右边 }
{ 用于Kontakt6原厂音色时,需要Bypass掉最后的Dynamic Key Switches }
{ 功能:若在当一个键松开后的Release旋钮设置的时间内有新的键按下,或者在未松开时就有新的键按下,则对旧音符应用淡出过渡,过渡时间为Fade旋钮设置的时间 }
{ 副作用:若没有新的键按下,旧音符会被额外延长Release旋钮设置的时间 }
{ 通常只需要调整Fade旋钮,获得平滑的过渡效果即可 }
{ Tol旋钮用于设置将多个音认作一个同时发出的音的时间上限,可实现复音淡出过渡 }
on init
    make_perfview
    set_script_title("Faded Mono - x7890")

    declare $i := 0
    declare const $cnt := 64 { 按下导致同时发声的最大音符数 }
    declare %ids[$cnt] := (0)
    declare %times[$cnt] := (0) { 按下时间 }
    declare $time_last_release := 0
    reset_ksp_timer

    declare ui_knob $Release(0, 1000, 1)
    $Release := 100
    set_knob_defval($Release, 100)
    set_knob_unit($Release, $KNOB_UNIT_MS)
    make_persistent($Release)

    declare ui_knob $Fade(0, 1000, 1)
    $Fade := 400
    set_knob_defval($Fade, 400)
    set_knob_unit($Fade, $KNOB_UNIT_MS)
    make_persistent($Fade)

    declare ui_knob $Tol(0, 1000, 1)
    $Tol := 50
    set_knob_defval($Tol, 50)
    set_knob_unit($Tol, $KNOB_UNIT_MS)
    make_persistent($Tol)
end on

on note
    if ($KSP_TIMER - $time_last_release > 2000) { 本音符是按下导致的音符 }
        $i := 0
        while ($i < $cnt) { 淡出所有以前按下导致的音符 }
            if (%ids[$i] # 0 and %times[$i] # 0 and ($KSP_TIMER-%times[$i])/1000 > $Tol) { 相差时间超过复音允许间隔 }
                fade_out(%ids[$i], $Fade*1000, 1)
                %times[$i] := 0 { 由于on release使用ids判断按下导致的音符,故用times表示音符已淡出 }
            end if
            inc($i)
        end while

        $i := search(%ids, 0) { 记录本次按下导致的音符,不会记录松开导致的音符 }
        %ids[$i] := $EVENT_ID
        %times[$i] := $KSP_TIMER
    else
        fade_out($EVENT_ID, $Fade*1000, 1) { 本音符是松开导致的音符,直接淡出 }
    end if
end on

on release
    if (search(%ids, $EVENT_ID) # -1) { 是按下导致的音符 }
        $time_last_release := $KSP_TIMER { 记录松开时间,以便排除松开导致的音符 }
        ignore_event($EVENT_ID) { 暂不松开 }
        wait($Release*1000) { 保持一段时间 }
        %ids[search(%ids, $EVENT_ID)] := 0 { 重新搜索,并删除记录 }
        note_off($EVENT_ID) { 立刻关闭音符 }
    end if
end on