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

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

# Native Instruments KONTAKT KSP

## 概要

Native Instrumentsのサンプラーソフト[KONTAKT](https://www.native-instruments.com/jp/products/komplete/samplers/kontakt-6/)にはKSPという拡張用の独自言語が用意されています。KSPでGUIやアーティキュレーションを実装したKONTAKTライブラリは、Native Instrumentsやサードパーティーから商用、フリー関わらず数多くリリースされており、多くの音楽制作者がその恩恵を受けています。

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

## 用途

NoteOnイベントに対応してサウンドエンジンのパラメータをカスタマイズしたり、タイマーイベントで音を鳴らしたりするのが主な使い方です。

- キースイッチなどによるアーティキュレーション切り替え
- 乱数やラウンドロビンによるヒューマナイズ
- スウィング
- アルペジエーター
- ストラミング
- GUI


## 言語仕様

- 独自言語
- イベントコールバック
- サウンドエンジンAPI
- GUI API
- MIDIファイルAPI

制御文、変数、配列、関数、APIなどを持つ本格的なプログラミング言語です。
シンタックスは独自のものですが、C言語などに似ているシンプルな文法です。
変数につける$、!などの記号で型を表します。
ローカル変数や関数引数がなく、関数呼び出しにも制限が多い原始的な言語です。
たとえば三和音を鳴らしたときには３つのスレッドがKSPプログラムを並行処理します。変数は各スレッドで共通のものを参照しますが、変数宣言時にpolyphonicキーワードをつけておくとスレッド固有の変数となります。

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


## GUI仕様

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

UIの横幅は以前は633px固定でしたが、最近の公式ライブラリは970pxにすることが多いようです。set_ui_width_px(970)のようにして変更します。

## プログラム例

### ノートナンバー表示 

押された鍵盤のノートナンバーを表示します。

```sh:ShowNoteNumber.nkp
on note
  message("note = " & $EVENT_NOTE)
end on
```

メッセージ出力は最下段に1行分だけ表示されます。CREATOR TOOLSを使用すると過去の出力もログとして確認することができます。


### デチューン

デチューンされた二つの音を鳴らす例です。デチューンの幅はノブで指定します。

```sh:Detune.nkp
on init
  declare ui_knob $Detune(0, 100, 1)
  declare $note1
  declare $note2
end on

on note
  if ($Detune > 0)
    ignore_event($EVENT_ID)
    $note1 := play_note($EVENT_NOTE, $EVENT_VELOCITY, 0, -1)
    $note2 := play_note($EVENT_NOTE, $EVENT_VELOCITY, 0, -1)
    change_tune($note1,  $Detune * 1000, 0)
    change_tune($note2, -$Detune * 1000, 0)
  end if
end on
```


## 実行方法

FDボタン→New Instrument選択
スパナボタンをクリック
![ksp1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22455/37740baa-d869-d682-aa54-df94ef820c11.png)

Script Editorボタンをクリック
5個のスロットのタブがあるのでいずれかを選択してEditタブをクリック
![ksp2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22455/6b1495e0-84f7-1d6b-a85e-d2ca433db615.png)



### (1) 内蔵エディタから入力する方法
Editタブをクリックすると内蔵エディタが開くので入力する（内蔵エディタは使いにくいので他のエディタで書いてペーストすることも多い）
Applyボタンを押すと適用される
![ksp3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22455/c2ac38d9-fd26-026e-c109-6213d43e214a.png)


### (2) リソースフォルダから読み込む方法
あらかじめ　Instrument OptionsボタンからResource ContainerのCreateボタンを押してリソースフォルダを生成しておく
![ksp4_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22455/1173a3aa-2842-9c1a-9cf0-1a3516648236.png)


生成されたResources/scriptsフォルダにスクリプトファイルを置く。拡張子は.txtとする。
内蔵エディタのApply from...メニューを開いてResources folderからスクリプトファイルを指定する。
![ksp5_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22455/2179f109-4381-f5a5-8983-a63238a6799a.png)
※リソースから読み込むと内蔵エディタはリードオンリーとなる
※リソースフォルダのスクリプトファイルを更新した場合は、その都度Applyボタンを押す必要がある
※内蔵エディタから保存するときのデフォルト拡張子は.nkpであるが、リソースから読み込む場合は.txtとする必要がある

リソースから読み込む方はリソースコンテナの知識が必要で若干煩雑ですが、ソースコード管理がしやすいというメリットがあります。

### ユーザープリセット

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


## 感想

ローカル変数がない、関数を呼べる条件がきつい、モジュール化の仕組みがない、など現代的な言語にくらべるとはるかに原始的です。
ただ、ノートオンイベントに対して、ひとつずつ別スレッドでスクリプトが実行されるという仕組みは、VST SDKなどでは自作する必要があり煩雑になりがちな部分なので、そういったところを気にせずポリフォニックのバーチャルインストゥルメンツを作成できるのは開発者に優しい設計になっていることも感じます。
音楽制作の現場ではKONTAKTの使用率が非常に高く、高品質のKONTAKTライブラリも多数リリースされていることから、今のところ大きな影響力を持っている言語です。

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