VST3ホストを作ろう（６） 〜VST3 プラグインのファイル構造について〜

[目次](https://qiita.com/hotwatermorning/items/5ab2a687a4cbc73a0f56)

## はじめに

　今回は、VST3 プラグインのファイル／ディレクトリ構造に関する仕様を解説します。

　ここでは、 Windows／macOS 環境向けの VST3 プラグインに関する内容のみを取り上げますが、 VST3 SDK のドキュメントには Linux 環境向けの VST3 プラグインに関する仕様も記載されています。そちらに興味がある場合はドキュメントの以下のページを参照してください。

* https://steinbergmedia.github.io/vst3_doc/vstinterfaces/vst3loc.html

## VST3 プラグインのプラグインファイルについて

　VST3 プラグインは、他のオーディオプラグイン形式と同様に、動的リンクライブラリとして作成されます。[^plugin_as_a_dylib]ここでは、この動的リンクライブラリのファイルのことをモジュールと呼ぶことにします。

[^plugin_as_a_dylib]: ホストアプリケーションは、実行時にこの動的リンクライブラリにリンクすることで、プラグインを利用できるようになります。

　VST3 規格では、モジュールと、モジュールが利用するリソースファイル（画像やオーディオデータなど）を特定のディレクトリ構造にまとめ、このディレクトリをひとつのファイルのように考えます。ここでは、このディレクトリのことをプラグインファイルと呼ぶことにします。[^directory_as_a_file]

[^directory_as_a_file]: ディレクトリをひとつのファイルと考えて扱う仕組みは、 Windows 環境ではあまり馴染みがないかもしれません。 macOS 環境では、そのようにして扱う Bundle というファイル形式が OS でサポートされていて、一般的に利用されています。

## プラグインファイルのディレクトリ構造

　macOS 環境向けの VST3 プラグインでは、プラグインファイルのディレクトリ構造は以下のようになります。プラグインファイルの名前には、末尾に .vst3 を付ける必要があります。

```text:プラグインファイルのディレクトリ構造（macOS&nbsp;環境向け）
MyPlugin.vst3/..............プラグインファイルのルートディレクトリ
├── Contents/
│   ├── MacOS/
│   │   └── MyPlugin........モジュール。 Universal Binary であってもよい。
│   └── Resources/..........リソースデータ（画像など）を配置するディレクトリ
│       ├── MyImage1.png
│       ├── MyImage2.png
│       ├── Snapshots/......プラグインのスナップショット画像を配置するディレクトリ
│       └── ...
├────── PkgInfo.............Bundle の設定ファイル
└────── Info.plist..........Bundle の設定ファイル
```

　このディレクトリ構造は、macOS が定義する Bundle というファイル形式[^about_bundle_structure]に沿ったものになっていて、実際に macOS 環境では拡張子が `.vst3` の Bundle ファイルとして VST3 プラグインを作成します。

[^about_bundle_structure]: https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFBundles/BundleTypes/BundleTypes.html#//apple_ref/doc/uid/10000123i-CH101-SW1

　macOS 環境向けのプラグインでは、モジュールを Universal Binary[^about_universal_binary] としてビルドすれば、ひとつのプラグインファイルを 32 bit 版と 64 bit 版両方のホストアプリケーションから利用可能にできます。

[^about_universal_binary]: https://ja.wikipedia.org/wiki/Universal_Binary

　Windows 環境向けの VST3 プラグインでは、macOS の Bundle ファイル形式に似た以下のようなディレクトリ構造をプラグインファイルとして定義しています。プラグインファイルの名前には、末尾に .vst3 を付ける必要があります。また、中に含めるモジュールの名前はプラグインファイルと同一にし、拡張子もプラグインファイルと同じく .vst3 を使用します。

```text:プラグインファイルのディレクトリ構造（Windows&nbsp;環境向け）
MyPlugin.vst3...............プラグインファイルのルートディレクトリ
├── Contents
│   ├── x86-win
│   │   └── MyPlugin.vst3...32 bit 版モジュール（i386 アーキテクチャ向け）
│   ├── x86_64-win
│   │   └── MyPlugin.vst3...64 bit 版モジュール（x86_64 アーキテクチャ向け） 
│   └── Resources...........リソースデータを配置するディレクトリ
│       ├── MyImage1.png
│       ├── MyImage2.png
│       ├── Snapshots/......プラグインのスナップショット画像を配置するディレクトリ
│       └── ...
├── desktop.ini.............Explorer 上でフォルダアイコンをカスタマイズする設定
└── Plugin.ico..............フォルダアイコン画像
```

　Windows 環境向けのプラグインでは、 Contents ディレクトリ内に `x86-win` と `x86_64-win` ディレクトリが定義されていて、この中にモジュールを配置します。これらのディレクトリのうち、少なくともどちらか片方は Contents ディレクトリ内に存在している必要があります。

　`x86-win` と `x86_64-win` ディレクトリにはそれぞれ 32 bit 版のモジュールと 64 bit 版のモジュールを配置します。これによってこのプラグインファイルを 32 bit 版／64 bit 版それぞれのホストアプリケーションから利用できるようになります。これらディレクトリを両方とも用意してモジュールを配置しておけば、ひとつのプラグインファイルを 32 bit 版／64 bit 版両方のホストアプリケーションから利用可能にできます。[^proposal_for_arm_plugin]

[^proposal_for_arm_plugin]: Windows 環境向けのプラグインファイルでは、この他に ARM アーキテクチャ向けのモジュールを配置するための `arm-win` と `arm_x64-win` ディレクトリが提案されています。

　Windows 環境で動作する VST3 ホストアプリケーションを開発する際は、プラグインファイルが実際にはディレクトリであり、ホストアプリケーションがロードするべきモジュールは `Contents/x86_64-win` のようなディレクトリ階層の中にあることに注意する必要があります。一方で macOS 環境では Bundle ファイル形式が OS によってサポートされているため、ホストアプリケーションは CFBundleCreate や CFBundleLoadExecutable などの関数を利用して、プラグインファイルを Bundle ファイルとして直接ロードできます。

### Windows 環境向けプラグインのフォルダアイコンについて

　Windows 環境向けのプラグインに含まれる desktop.ini と Plugin.ico ファイルは、 Explorer 上でのプラグインファイルの見た目をカスタマイズするためのファイルです。これによって、あたかも自分がディレクトリではなくファイルであるかのように擬態できます。

![folder_icon.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/944/79b16776-325a-3b5f-990e-283f6a65289c.png)

　このスクリーンショットで拡張子が .vst3 になっているのが VST3 プラグインのプラグインファイルです。実態はディレクトリですが、フォルダアイコンを設定しているためにファイルのように見えます。

　もしプラグイン開発をドキュメントの [How to add/create your own VST 3 Plug-ins](https://steinbergmedia.github.io/vst3_doc/vstinterfaces/addownplugs.html) に書かれた手順に沿っておこなっている場合は、desktop.ini と Plugin.ico ファイルの設定は自動で行われるため、開発者が特別な設定を行う必要はありません。もしプラグイン開発を独自のワークフローで行っている場合は、以下のようにしてフォルダアイコンを設定します。

1. フォルダアイコンとして表示する画像を Plugin.ico ファイルとして用意する。
1. 次の内容が含まれた desktop.ini ファイルを用意する。
   
    ```ini:desktop.ini
    [.ShellClassInfo]
    IconResource=Plugin.ico,0
    ```
   
1. desktop.ini と Plugin.ico ファイルを、プラグインファイルのルートディレクトリに配置する。
1. desktop.ini ファイルと Plugin.ico ファイル、そしてそれらを含んでいるプラグインファイルのルートディレクトリに対して、次のようにしてファイル属性を設定する。

   ```batchfile
   attrib +s +r +h MyPlugin.vst3/desktop.ini
   attrib +s +r +h MyPlugin.vst3/Plugin.ico
   attrib +s MyPlugin.vst3
   ```
　ここで指定している `+s`／`+r`／`+h` はそれぞれ、システムファイル属性／読み取り専用属性／隠しファイル属性を設定するオプションです。[^attrib_option_difference]

[^attrib_option_difference]: ここに書いているオプションは、 VST3 SDK の AddSMTGLibrary.cmake ファイルに実装されている処理を参考にしたもので、 VST3 SDK の `VST 3 Locations / Format` のドキュメントに書かれたものとは少し異なっています。 VST3 SDK のドキュメントに書かれているオプションを使って属性を設定してもエクスプローラ上でアイコンが正しく反映されないため、 AddSMTGLibrary.cmake に実装されているのと同じようにプラグインファイル自体にもシステムファイル属性を設定する必要があります。

### Snapshots ディレクトリについて

　Resources ディレクトリの中の Snapshots ディレクトリには、プラグインのスナップショット画像を配置します。

　これは VST3 SDK バージョン 3.6.10 から導入された仕組みで、プラグインに含まれる Audio Processor というコンポーネントの ID と同じ名前を付けた PNG ファイルをそこに配置しておくと、ホストアプリケーションがその画像を読み込んで、プラグインのサムネイルとしてその画像を表示できるようになります。 HiDPI 環境を考慮してスケールの異なる複数の画像を含めておくこともできます。

　詳しくはドキュメントの [VST 3 Locations / Format](https://steinbergmedia.github.io/vst3_doc/vstinterfaces/vst3loc.html#snapshots) を参照してください。

### Windows 環境向けプラグインファイルの古い仕様について

　VST3 SDK バージョン 3.6.9 までは、 Windows 環境向けのプラグインファイルに対して Bundle ファイル形式のようなディレクトリ構造は定義されていませんでした。つまり、バージョン 3.6.9 までの VST3 SDK を使用して開発された Windows 環境向け VST3 プラグインは、VST2 プラグインのようにモジュールがそのままプラグインファイルになります。

　モジュールがそのままプラグインファイルであるという仕組みは、モジュールからリソースファイルを扱いにくい問題がありました。[^resource_management_for_old_spec]

[^resource_management_for_old_spec]: たとえば、モジュールと同じディレクトリにリソースファイルをインストールすると、プラグインをインストールするディレクトリが汚れてしまったり、モジュールを移動したときにリソースファイルを見つけられずにプラグインが正常に起動できなくなったりする問題があります。あるいは、その問題を避けるためにモジュールの中にリソースファイルをバイナリデータとして埋め込む方法もありますが、その仕組みはセットアップするのに手間がかかります。

　そこで VST3 SDK バージョン 3.6.10 からは、Windows 環境でも macOS 環境と同様に、モジュールとリソースファイルを Bundle ファイル形式に似たディレクトリ構造にまとめ、これをひとつのプラグインファイルとするように仕様が変更されました。この仕様変更によって、Windows／macOS環境どちらも同じ仕組みでリソースファイルを扱えるようになって、クロスプラットフォームなプラグインを開発しやすくなりました。 

　VST3 SDK バージョン 3.6.9 までの、モジュールがそのままプラグインファイルである仕様はすでに非推奨になっているため、新たに VST3 プラグインを開発する場合は、現在の新しい仕様に従う必要があります。

## Merged Bundleについて

　プラグインファイルは、 Windows／macOS それぞれの環境向けのもので似た構造になっています。 VST3 SDK ではこれを統合することを認めていて、これを Merged Bundle と言います。

　Merged Bundle として統合したプラグインファイルのディレクトリ構造は以下のようになります。

```text:Merged&nbsp;Bundleのファイル構造
MyPlugin.vst3................プラグインファイルのルートディレクトリ
├── Contents
│   ├── MacOS/
│   │   └── MyPlugin
│   ├── x86-win
│   │   └── MyPlugin.vst3
│   ├── x86_64-win
│   │   └── MyPlugin.vst3
│   ├── Resources
│   │   ├── MyImage1.png
│   │   ├── MyImage2.png
│   │   ├── Snapshots/
│   │   └── ...
│   ├── PkgInfo
│   └── Info.plist
├── desktop.ini
└── Plugin.ico
```

　プラグインファイルを Merged Bundle にすることで、ひとつのプラグインファイルを Windows／macOS 両方の環境で利用可能にできます。

　この仕組みは便利そうではありますが、プラグインをインストールすることを考えると、この仕組みを利用するのに少し抵抗があるかもしれません。というのも、インストールする環境以外で使用するためのモジュールがプラグインファイルに含まれていても、それは使用されることのない無駄なデータになってしまうためです。そのため通常は Windows 環境／macOS 環境それぞれに向けた別々のプラグインファイルを用意して配布することになるでしょう。

### おわりに

　今回は、 VST3 プラグインのファイル構造について解説しました。[次回](https://qiita.com/hotwatermorning/items/6a50a5f7ba73f49dd624) はプラグインのインストールディレクトリに関する仕様について解説します。