NI KONTAKT KSP Multi Script - DTMプログラミング言語探訪

[DTMプログラミング言語探訪](https://qiita.com/aike@github/items/77b3eccc6861de09513a)

# Native Instruments KONTAKT KSP Multi Script

## 概要

Native Instrumentsのサンプラーソフト[KONTAKT](https://www.native-instruments.com/jp/products/komplete/samplers/kontakt-6/)用言語KSPにはマルチスクリプトという特殊なスクリプトがあります。通常のスクリプトがKONTAKTライブラリに組み込んで使うのに対して、マルチスクリプトはKONTAKTライブラリの前段に配置してMIDIメッセージを加工して出力するのが主な用途です。
マルチスクリプトを使用した商用製品としては[NoteMatrix](https://www.hagaid.com/en/shop)のような例があります。

KSPはKONTAKT Script Processorの略と言われていますが、KONTAKT6の最新ドキュメントを見る限り何の略かは明記されていないようです。
本記事ではマルチスクリプトの説明のみおこない、通常のKSPスクリプトは[別記事](https://qiita.com/aike@github/items/35f7d85d4c0e61cfabf7)で説明します。

## 用途

KONTAKTライブラリに対するMIDIメッセージを加工したり生成したりするのが主な用途です。

- MIDIエフェクト
- MIDIチャンネルマッパー
- 簡易シーケンサー

## 言語仕様

- 独自言語
- イベントコールバック
- MIDIメッセージ出力
- GUI API
- MIDIファイルAPI

制御文、変数、配列、関数、APIなどを持つ本格的なプログラミング言語です。
シンタックスは独自のものですが、C言語などに似ているシンプルな文法です。
変数につける$、!などの記号で型を表します。
ローカル変数や関数引数がなく、関数呼び出しにも制限が多い原始的な言語です。

公式リファレンス　[KSP REFERENCE MANUAL](https://www.native-instruments.com/jp/products/komplete/samplers/kontakt-6/downloads/)


## GUI仕様

ノブ、ボタン、スライダー、メニュー、XYパッド、ファイルセレクターなど。
パーツを自作画像に置き換えられるため、独自デザインのGUIを作ることができます。
UI全体の背景やロゴなどの画像を読み込んで表示することも可能。

マルチスクリプトの場合、リソースをコンテナにまとめることはできません。そのため画像リソースを使う場合 C:\Users\ユーザ名\Documents\Native Instruments\Kontakt\pictures のような所定のフォルダに置く必要があります。つまり画像リソースを使用するマルチスクリプトを配布する場合はインストーラが必要になります。
また通常のスクリプトでは背景は$INST_WALLPAPER_IDで指定できますが、マルチスクリプトはそのようなシステム変数を持たないため大きなラベルを使用して疑似的に背景を設定するしかないようです。

## プログラム例

### MIDIチャンネルマッパー

MIDIの1ch宛のメッセージを5ch宛に変更、2ch宛のメッセージを3ch宛に変更する。
MIDIチャンネル(1-16)を表すシステム変数$MIDI_CHANNELは0-15の値をとるので少し工夫が必要です。

```sh:MidiMapper.nkp
on init
  declare %map[17] := (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16)

  %map[1] := 5  { map 1ch -> 5ch }
  %map[2] := 3  { map 2ch -> 3ch }
end on

on midi_in
  set_midi(%map[$MIDI_CHANNEL + 1] - 1, $MIDI_COMMAND, $MIDI_BYTE_1, $MIDI_BYTE_2)
end on
```

### MIDIエフェクト

MIDI NoteOnを受信したらベロシティを減少しながらリピートすることでフィードバックディレイを実現するエフェクトの例です。

```sh:MidiDelay.nkp
on init
  declare ui_knob $DelayTime(10, 400, 1)
  declare ui_knob $Feedback(0, 8, 1)
  $DelayTime := 400
  $Feedback := 4
  declare %cnt[128]
end on
 
on midi_in
  if ($MIDI_COMMAND = $MIDI_COMMAND_NOTE_ON)
    set_midi($MIDI_CHANNEL, $MIDI_COMMAND_NOTE_ON, $MIDI_BYTE_1, $MIDI_BYTE_2)
    wait($DelayTime * 1000)
    set_midi($MIDI_CHANNEL, $MIDI_COMMAND_NOTE_OFF, $MIDI_BYTE_1, 0)
    %cnt[$MIDI_BYTE_1] := $Feedback
    while (%cnt[$MIDI_BYTE_1] > 0)
      set_midi($MIDI_CHANNEL, $MIDI_COMMAND_NOTE_ON, $MIDI_BYTE_1, $MIDI_BYTE_2 / 2)
      wait($DelayTime * 1000)
      set_midi($MIDI_CHANNEL, $MIDI_COMMAND_NOTE_OFF, $MIDI_BYTE_1, 0)
      dec(%cnt[$MIDI_BYTE_1])
    end while    
  end if
end on
```


## 実行方法

KSPボタンクリック
![kspm1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22455/5b9130c2-6fc5-86b0-f91c-c93c44608f6d.png)

5個のスロットのタブがあるのでいずれかを選択してEditタブをクリック
![kspm2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22455/01a3ec94-1431-86e5-c90d-76dd11f546a3.png)

Editタブをクリックすると内蔵エディタが開くので入力する（内蔵エディタは使いにくいので他のエディタで書いてペーストすることも多い）
Applyボタンを押すと適用される
![kspm3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22455/4a78d9cc-d90c-ddbd-5179-f22b2ffa5f07.png)

汎用的によく使うスクリプトはPreset→Save Presetでセーブしておくと、次回以降Presetから選択して内蔵エディタに読み込むことができるようになります。
![kspm4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22455/669c8b2e-6e4f-3210-76df-ed8e51370335.png)


## 感想

用途がKONTAKTに限るものの、簡単にMIDIのマッピングを変えられるのは便利なので、もっと活用されて良い機能だと思います。
特にKONTAKTライブラリ制作者はマルチスクリプトを活用すると動作検証が楽になる場面も多いように思います。
デフォルトのUIが地味なので、画像リソースを使用してわかりやすいUIのツールを作りたいところですが、通常のKONTAKTライブラリと違ってスクリプトとリソースをまとめて配布する仕組みがないのが残念です。

[DTMプログラミング言語探訪](https://qiita.com/aike@github/items/77b3eccc6861de09513a)