SFZ - DTMプログラミング言語探訪

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

# SFZ

## 概要

SFZはサンプラーソフトのライブラリを定義するためのロイヤリティフリーなオープンスタンダードフォーマットです。テキストファイル(.sfz)とひとつ以上のサンプルファイル(.wav)のセットで構成されます。
SFZはプログラミング言語と呼べるほどのロジック記述能力はありません。基本的にどのサンプルファイルをどこの鍵盤にマッピングするかを指定する設定ファイルです。それでもキースイッチの状態によって音を変える設定や、ループポイントの設定、ベロシティレイヤ、リリーストリガ、ラウンドロビン、そしてVolume、EG、LFOなどのパラメータの設定も記述できる言語になっています。

代表的な対応アプリケーションは[sforzando](https://www.plogue.com/products/sforzando.html)、[Zampler//RX](https://www.zampler.de/)、[Falcon](https://www.uvi.net/instruments/falcon.html)などがあります。

サウンドフォントのsf2と混同されやすいですが別のものです。sf2はサンプルデータも含めたバイナリ形式。SFZはマッピングのみを記述するテキスト形式の言語とサンプルファイルが別になっています。

## 用途

- サンプルとノートナンバーのマッピング
- サンプルとベロシティのマッピング
- キースイッチによるサンプルグループ切り替え
- エフェクトパラメータ設定

## 言語仕様

- 独自言語
- ヘッダとオペコードによるシンタックス
- 変数
- マッピング設定
- パラメータ設定
- キースイッチ設定

SFZは、&lt;&gt;で囲まれたヘッダと、そこに記述するオペコードから構成されます。
全体の設定は&lt;global&gt;、鍵盤などに対応する最小単位の設定は&lt;region&gt;、複数リージョンにまたがる設定がある場合は&lt;group&gt;に記述します。

マッピングのオペコードは次のように記述します。

```html
<region>
key=60
sample=c4.wav
```

パラメータのオペコードは次のように記述します。

```html
<global>
volume=-3
```
volumeパラメータの場合、値は-144から6までdBで指定します。ボリュームのような設定は&lt;global&gt;、&lt;group&gt;、&lt;region&gt;いずれにも書くことが可能で、グローバルよりグループ、グループよりリージョンに書いた設定が優先されます。

ヘッダもオペコードもそれぞれSFZ標準とベンダー拡張があり、SFZ標準もバージョンによって拡張されているため、どの程度拡張に対応しているかはソフトウェア次第となります。
キースイッチ以上のロジックを記述することはできず、チューリング完全を満たすプログラミング言語ではありません。

[SFZ公式サイト](https://sfzformat.com/)

## GUI仕様

GUIは作成できません。
sforzandoのPlogue社ライブラリなどは、SFZとは別にXMLファイルで画像を使用したGUIを定義できるよう独自拡張しているようですが、その仕様はオープンになっておらず、SFZの規格に含まれていません。


## プログラム例

### ノートナンバーとサンプルのマッピング

ひとつのサンプルが鍵盤ひとつに対応している場合はシンプルに書くことができます。

```html:simple.sfz
<region>key=60 sample=c4.wav
<region>key=61 sample=c#4.wav
<region>key=62 sample=d4.wav
<region>key=63 sample=d#4.wav
<region>key=64 sample=e4.wav
```

ノートナンバー60-71の範囲はc4.wavを、ノートナンバー72-83の範囲はc5.wavを鳴らす範囲指定の例。
範囲指定の場合はオリジナルのピッチがどのノートナンバーに対応するかpitch_keycenterで指定する必要があります。

```html:noterange.sfz
<region>
sample=c4.wav
lokey=60
hikey=71
pitch_keycenter=60

<region>
sample=c5.wav
lokey=72
hikey=83
pitch_keycenter=72
```

### ベロシティとサンプルのマッピング

弱く弾いた場合と強く弾いた場合でサンプルを切り替える例。ベロシティ1-63はsoft.wavを、ベロシティ64-127のときはhard.wavを鳴らします。

```html:velocity.sfz
<region>
sample=soft.wav
lokey=60
hikey=83
pitch_keycenter=60
lovel=1
hivel=63

<region>
sample=hard.wav
lokey=60
hikey=83
pitch_keycenter=60
lovel=64
hivel=127
```

### キースイッチによるサンプルグループ切り替え

ノートナンバー48から50までをキースイッチとして使用する。48を押した以降はsustain_xx.wavのサンプルを使用して、50を押した以降はmute_xx.wavのサンプルを使用する。

```html:keyswitch.sfz
<global>
sw_lokey=48
sw_hikey=50
sw_default=48

<group>
  sw_last=48
  <region>key=60 sample=sustain_c4.wav
  <region>key=61 sample=sustain_c#4.wav
  <region>key=62 sample=sustain_d4.wav
  <region>key=63 sample=sustain_d#4.wav

<group>
  sw_last=50
  <region>key=60 sample=mute_c4.wav
  <region>key=61 sample=mute_c#4.wav
  <region>key=62 sample=mute_d4.wav
  <region>key=63 sample=mute_d#4.wav
```
ヘッダやオペコードのインデントは許可されていますが、=の前後に空白を入れることは許可されません。

### 変数の使用

C言語のディレクティブのような書き方で変数とその値を定義することができます。仕様にはvariableと書かれていますが実質的に定数です。変数名は$をつけます。

```html:variable.sfz
<control>
#define $VOL -12

<group>
volume=$VOL
<region>key=60 sample=c4.wav
<region>key=61 sample=c#4.wav
<region>key=62 sample=d4.wav
```


## 実行方法

例としてsforzandoでの実行方法を示します。

あらかじめ.sfzファイルと、そこで使用する.wavファイルを用意しておきます。
左上のINSTRUMENT名をクリックしてimport。
.sfzファイルを選択します。
![sfz1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22455/ce77d966-8dc2-9e80-f36e-d19e37322359.png)

OPEN IN TEXT EDITORボタンをクリックするとエディタで.sfzファイルを編集できます。
![sfz2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22455/1a43b27f-f106-6d25-56d2-9054c3f58a11.png)


## 感想

ロイヤリティフリーでオープンな仕様、ライブラリ作成にも特殊なソフトウェアを必要としないというのはとても好印象です。記述もシンプルで学習コストが低いわりに現代的なサンプラーとして必要な機能を記述できる表現力を備えています。
ただ、ここまでいくとGUIもサポートしてほしかったと思ってしまいます。
また、オペコードがベンダーごとにまちまちで似たようなキーワードが統一される気配がないことや、ソフトウェアごとのサポート状況もあまりよくないようです。今回のプログラム例もsforzandoでは正常に動きますが、それ以外のサンプラーソフトでは機能しないものも多かったです。

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