したらばTOP ■掲示板に戻る■ 全部 1-100 最新50 | まとめる | |

C++でVST作りの指摘・質問

1 管理人 :2010/12/10(金) 18:06:52
「C++でVST作り」内の誤記やサンプルコードのバグ、指摘・質問等がございましたらこちらへお願いいたします。

C++でVST作り→http://www39.atwiki.jp/vst_prog/

133 管理人★ :2017/10/22(日) 14:17:18
Lowさん

私の試した手順で基本ライブラリらしきものができました。
試してみてください。

1.CMAKEを下記からダウンロードし、インストールする

 https://cmake.org/download/

2.VST SDK 3.6.7を任意のフォルダに解凍する

3.解凍したフォルダの「VST_SDK\VST3_SDK」配下に「build」フォルダを新規作成

4.cmakeを起動し、下記の通り設定

 ・where is the sorce code
    →「VST_SDK\VST3_SDK」を指定
・where to build the binaries
    →「VST_SDK\VST3_SDK/build」を指定

5.cmake下側の「Configure」ボタンを押し、下記を設定し
 「Finish」ボタンを押す

  Specify the generator for this project
    →「Visual Studio 14 2015 Win64」を指定
  (他はそのまま)

6.cmakeの設定が自動始まり、中央部分に情報(赤字)が表示される
 「Configure」ボタンの下側のログにエラーがないことを確認する

7.「Generate」ボタンを押し、Visual Studioのプロジェクトを作成する
 「VST_SDK\VST3_SDK/build」配下に「ALL_BUILD.vcxproj」が
 作成されていることを確認する

8.「ALL_BUILD.vcxproj」を開き、Visual Studioでビルドを行う
 「VST_SDK\VST3_SDK/build/lib」配下にライブラリが作成される
 (おそらく「base.lib」が基本ライブラリだと思います。)

ここから不確定ですが、3.6.7では下記の変更点があるようです。
・64bitのみの対応
・プロジェクトのプロパティでマルチスレッド(/MT、/MTd)ではなく
 マルチスレッドDLL(/MD、/MDd)を使用する必要がある

134 Low :2017/10/23(月) 17:59:20
再三失礼します。この方法で行ったのですが、5の後に、

CMake Error at CMakeLists.txt:24 (project):
Failed to run MSBuild command:

MSBuild.exe

to get the value of VCTargetsPath:

とエラーが出てしまいます。
また、このエラーを調べたのですが、自分のVisualStudioと違うものを指定した場合に出るといったことが書かれていたため、
5の設定を、Visual Studio 14 2017 Win64
で試してみたのですが、今度は、

CMake Error at CMakeLists.txt:24 (project):
Failed to run MSBuild command:

C:\Program Files (x86)\Microsoft Visual Studio\2017\Community/MSBuild/15.0/Bin/MSBuild.exe

to get the value of VCTargetsPath:

.NET Framework 向け Microsoft (R) Build Engine バージョン 15.4.8.50001

Copyright (C) Microsoft Corporation.All rights reserved.



2017/10/23 17:44:59 にビルドを開始しました。

ノード 1 上のプロジェクト "C:\vstsdk367_03_03_2017_build_352\VST_SDK\VST3_SDK\build\CMakeFiles\3.9.4\VCTargetsPath.vcxproj" (既定のターゲット)。

C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\VC\VCTargets\Platforms\x64\PlatformToolsets\v141\Toolset.targets(36,5): error MSB8036: Windows SDK バージョン 10.0.15063.0 が見つかりませんでした。必要なバージョンの Windows SDK をインストールするか、プロジェクト プロパティ ページで SDK バージョンを変更するか、ソリューションを右クリックして [ソリューションの再ターゲット] を選択してください。 [C:\vstsdk367_03_03_2017_build_352\VST_SDK\VST3_SDK\build\CMakeFiles\3.9.4\VCTargetsPath.vcxproj]

プロジェクト "C:\vstsdk367_03_03_2017_build_352\VST_SDK\VST3_SDK\build\CMakeFiles\3.9.4\VCTargetsPath.vcxproj" (既定のターゲット) のビルドが終了しました -- 失敗。



ビルドに失敗しました。



"C:\vstsdk367_03_03_2017_build_352\VST_SDK\VST3_SDK\build\CMakeFiles\3.9.4\VCTargetsPath.vcxproj" (既定のターゲット) (1) ->

(Desktop_PlatformPrepareForBuild ターゲット) ->

C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\Common7\IDE\VC\VCTargets\Platforms\x64\PlatformToolsets\v141\Toolset.targets(36,5): error MSB8036: Windows SDK バージョン 10.0.15063.0 が見つかりませんでした。必要なバージョンの Windows SDK をインストールするか、プロジェクト プロパティ ページで SDK バージョンを変更するか、ソリューションを右クリックして [ソリューションの再ターゲット] を選択してください。 [C:\vstsdk367_03_03_2017_build_352\VST_SDK\VST3_SDK\build\CMakeFiles\3.9.4\VCTargetsPath.vcxproj]



0 個の警告

1 エラー



経過時間 00:00:00.16



Exit code: 1

といったエラーが出てしまいます。
そこで、プロジェクトのプロパティを変更し、ソリューションの再ターゲットを行ったのですが、やはり同様のエラーが出てしまいます。
これらの原因はわかりますでしょうか?

135 管理人★ :2017/10/23(月) 21:32:23
Lowさん

CMAKEについては詳しくないのですが、エラーで
「Windows SDK バージョン 10.0.15063.0 が見つかりませんでした」
とあります。

「Visual Studio 2017 バージョン 15.3 の既知の問題」(下記)には
特定の条件下で「Win32 C++ デスクトップ プロジェクトに必要なヘッダー/ライブラリが
インストールされません。」とあります。

  https://msdn.microsoft.com/ja-jp/vs-knownissues/vs2017-knownissues

  ※「Windows 10 Creators Update SDK (10.0.15063.0) をインストールした後、
   新しく作成した C++ Win32 デスクトップ プロジェクトをビルドできない」の項目です。

回避策としてはインストーラーで [C++ によるデスクトップ開発] ワークロードの
[デスクトップ C++ x86 および x64 用 Windows 10 SDK (10.0.15063.0)] 機能を
選択する必要があるようです。

試されてみてはいかがでしょうか?

136 管理人★ :2017/10/23(月) 21:53:28
Lowさん

どうしてもCMAKEがうまくいかない場合、
古いバージョンのものを利用してみてはいかがでしょうか?

■VST SDK 3.6.6
http://www.steinberg.net/sdk_downloads/vstsdk366_27_06_2016_build_61.zip

■VST SDK 3.6.5
http://www.steinberg.net/sdk_downloads/vstsdk365_12_11_2015_build_67.zip

なお、上記リンクのファイルについては安全かどうかわかりませんので十分ご注意ください。
(ドメインがwww.steinberg.netなので大丈夫だと思いますが…)

また、リンクがいつ切れるかわかりませんのでご了承ください。
(2017年10月23日の時点では生きているようです。)

137 Low :2017/10/24(火) 11:16:50
ありがとうございます。
[デスクトップ C++ x86 および x64 用 Windows 10 SDK (10.0.15063.0)] 機能を選択して、何度か追加しようとしたのですが、なぜかチェックを入れて変更をしても追加されなかったため、
(他のバージョンのものは選択したらちゃんと追加されたのですが、なぜかこれだけ。)
VSTSDK3.6.6を試してみたところ、ライブラリファイルが作成でき、また、
サンプルに入っていたものをビルドしてみたところ、それらしき者ができたため、動作が確認できたものと思われます。

138 管理人★ :2017/10/24(火) 22:15:03
Lowさん

CMAKEが解決できなかったのは残念ですが、
3.6.6でVSTを作れそうなのは良かったです。

また何か有りましたらよろしくお願いします。

139 らいか :2017/10/31(火) 14:35:42
お久しぶりです、早速ですが質問したいことがあります。

会社にあるVSTプラグインのソースをたどっているのですが、処理等を行っている関数の呼び出しがないものが多く、
実際に動いている関数なのか、動いていない関数なのかよくわかりません。何か判断する方法はありますでしょうか?

http://vstcpp.wpblog.jp/?page_id=437
例えば上記のコード(管理人さん作)の23〜35行目で関数の宣言をしていて、40行目〜167行目まで関数の定義がされていると思います。
この中で関数createEffectInstanceはVSTのSDKの内容から呼び出されていているのはわかるのですが、
それ以外の関数はどのように呼び出されているかわかりますでしょうか?

140 らいか :2017/11/01(水) 16:55:06
>>139

お騒がせしました。解決しました。

継承元のAudioEffectXクラスに記載されているメンバー関数をオーバーライドって書いてありましたね(-_-;)

141 管理人★ :2017/11/01(水) 20:56:37
らいかさん

お久しぶり(?)です。書き込みありがとうございます。

無事解決してよかったです。
また何かありましたらよろしくお願いします。

142 らいか :2017/11/14(火) 11:07:52
更新お疲れ様です。いっぱい更新が来ててびっくりしました。
とりあえず更新分を試したのですが躓いたので質問です。

まず http://vstcpp.wpblog.jp/?p=1095 を参考にVST_SDK3.6.7の基本ライブラリの作成を行いました。

次に http://vstcpp.wpblog.jp/?p=683 を参考にプロジェクトの作成を行いました。
プロジェクトのプロパティの設定
C/C++ コード生成 ランライムライブラリ マルチスレッドデバッグ(/MTd)
リンカー 入力 追加の依存ファイル base_vc10.lib (デバッグ版)
上記の記載内容は基本ライブラリに合わせて
マルチスレッドDLL(/MD、/MDd)
base.lib
に変更して設定しました。

次に http://vstcpp.wpblog.jp/?p=1016 のソースファイル一式を作成したプロジェクトに追加してビルドしたのですが、
未解決の外部シンボル系のエラー(LNK2001,LNK2019)が16個ほど出てしまい、うまく実行できません。

少しググって入力しているライブラリとプロジェクトの文字コードの設定が違うとこのエラーが出るとあったので、
試したのですが解決はしませんでした。

何か他に設定し忘れている内容ってありますでしょうか?

143 管理人★ :2017/11/14(火) 18:32:25
らいかさん

書き込みありがとうございます。

VST SDK 3.6.7はまだ試していないので詳細まではわからないです。
(そろそろ触ってみようと思うのですが、Windows10の環境がないので
ちょっと時間かかりそうです…)

そのエラーだと何らかのcppファイルがプロジェクトに必要な感じですね…
エラー詳細があれば何かわかるかもしれません。

あまり役に立てなくて申し訳ないです。

144 管理人★ :2017/11/14(火) 22:19:55
らいかさん

軽く確認してみました。
 C:\VST3_SDK\pluginterfaces\base\funknown.cpp
をプロジェクトに追加して確認してもらえるでしょうか?

145 らいか :2017/11/15(水) 08:21:37
管理人さん

おはようございます。早速試してみました。

ドンピシャですね。無事ビルド&動作できました。

昨日書き込んだ後、入力するlibを増やしたりしてビルドはできたけどホストから
音が出ないなど色々沼にはまっていたので助かりました。ありがとうございます。

146 管理人★ :2017/11/15(水) 22:25:03
らいかさん
無事解決してよかったです。

147 霧林 :2017/12/05(火) 02:51:52
初めまして。VST プラグインの制作を試みている学生です。
VST 開発について詳細に解説しているサイトは少ないので、
「C++でVST作り」は大変参考になっています。貴重なサイトをありがとうございます。
プログラミング及び VST 初心者なのでわけのわからないことを書いてしまうかもしれませんが、質問をしてもよろしいでしょうか。

簡単なエフェクターを作成してみる - http://vstcpp.wpblog.jp/?page_id=314
こちらの記事を始まりとした、VST2.4 で実装しているトレモロエフェクトについての質問です。
このトレモロエフェクトに、「入力信号にトレモロ効果がかかるまでの時間(ディレイ)」
というパラメータを実装したい場合、どのようにすればよろしいでしょうか?

管理人様が実装イメージとして書かれているプログラムでは、
for(int i = 0; i < wavelength; i++)
この for 文内で入力信号の長さ分、信号処理を行っていることがわかります。
なので、例えばサンプリング周波数 44100Hz の入力信号に対して、
トレモロ効果がかかるまで1秒間あけたい場合は、単純に考えると

for(int i = 0; i < wavelength; i++)
{
 if(i <= 44099) {
  output[i] = input[i];
 }
 else if(i >= 44100) {
  //トレモロの計算…省略
  output[i] = b * input[i];
 }
}

このように実装すればよいと考えました(数値がダイレクトなのはご容赦ください)。
i が 0〜44099 の間(1秒間)は入力信号をそのまま出力信号に代入して、
i が 44100 以降は入力信号にトレモロ処理を施した値を出力信号に代入するといった具合です。

しかし、実際に prosessReplacing 関数内で上記イメージのように書き直してもうまく動いてくれません。
ビルドはできますが、実際に使用してみるとトレモロ処理に移らない感じです。
これを望みの挙動にするためには、どのようにすればよろしいでしょうか。

また、prosessReplacing 関数では、実装イメージの wavelength が sampleFrames という変数になっていますが、
この sampleFrames という変数がよく理解できていません。そのためにうまくプログラムが書けないのだと思いますが…
これは、入力信号の長さという単純なものとは違うのでしょうか?

現在 VST3 について意欲的に更新されている最中、旧バージョンの話題で申し訳ありません。
お時間のある時にでもご回答いただければ幸いです。

148 管理人★ :2017/12/05(火) 20:30:31
霧林さん

書き込みありがとうございます。ST2.4でも全然問題ありません。

簡単に言うとsampleFramesは「入力信号の一部の長さ」になります。

ホストアプリ(DAWなど)は入力信号を数ミリ秒ずつ順番にVSTに渡していきます。
音声処理をリアルタイムに行うためにこのような方法がとられます。

1回に渡す入力信号は数ミリ秒ですので、sampleFramesはだいたい50〜200ぐらいになります。
1秒分の長さを処理するためにホストアプリ(DAWなど)はprosessReplacing関数を200〜1000回ぐらい呼び出します。
(sampleFramesや何回呼び出されるかは環境によって異なります。)

いただいた例の「VSTを読み込んでから1秒後にトレモロがかかるようにする」で、
ずっとトレモロがかからなかったのは、「 if(i <= 44099) 」の条件に合致していたからだと思います。
(for文のint iは毎回 0 になりますし、sampleFramesは大きくても200ぐらいですので)

ですので、実際に例の通りに動かそうとすると、VSTが読み込まれてからの時間(サンプル数)を
保持しておく必要があります。実装例としては下記となるとおもいます。

①メンバー変数としてVSTが読み込まれてからのサンプル数を保持する変数を追加。
【例】
VstInt32 totalSample;

②上記変数をコンストラクタ等で 0 に初期化しておく。
【例】
totalSample = 0;

③prosessReplacing関数のfor文内で処理を行う。
 経過したsampleFrames分はtotalSampleに加えていく。
【例】
for(int i = 0; i < sampleFrames; i++)
{
 if(totalSample < 44100) {
  output[i] = input[i];
totalSample++;
 }
 else {
  //トレモロの計算…省略
  output[i] = b * input[i];
 }
}

149 霧林 :2017/12/06(水) 03:41:54
管理人様

迅速なご回答ありがとうございます。わかりやすい解説で助かります!
無事トレモロ効果がかかるまでの時間を設定することができました。
いくつか気になる点があるので、また質問させていただきます。
(ちなみにホストアプリは VSTHost (http://www.hermannseib.com/vsthost.htm) を使用しています。
その他の環境は Windows 7 (64bit), Visual Studio 2015 Community です)


ご教示いただいた実装例でそのまま実装してみたところ、
「信号が入力されてから1秒後」ではなく、「VST を読み込んでから1秒後」になるようですね。
VSTHost でビルドした VST を読み込んだところ、
読み込み1秒後からは入力信号に常時トレモロがかかる状態になりました(普通のトレモロエフェクトと同じ状態)。
信号の入出力を全くしなくても、設定した時間が経過次第この状態になるので、
processReplacing 関数は信号の入力がない状態でも呼び出され続けているのでしょうか?

今回私が目指しているものは
「VST 読み込みから n 秒後」ではなく、
「毎回、エフェクトに信号が入力されてから n 秒後」なので(わかりにくくて申し訳ありません)、
管理人様のコードを下記のようにしてみました。

if (inputs[L][0] == 0 && inputs[R][0] == 0){ //入力信号の先頭が 0 の時
 totalSample = 0; //totalSample を 0 に固定しておく
}
else{
 for (int i = 0; i < sampleFrames; i++){
  if (totalSample < 44100){
   outputs[L][i] = inputs[L][i];
   outputs[R][i] = inputs[R][i];
   totalSample++;
  }
  else{
   //トレモロの計算…省略
   outputs[L][i] = b * inputs[L][i];
   outputs[R][i] = b * inputs[R][i];
  }
 }
}

時間は例として 44100=1秒 としています。

VST を読み込んでから1秒経つと、それ以降の入力信号にトレモロがかかりっぱなしの状態になるのは、
processReplacing 関数が呼び出され続け、totalSample がリセットされないことが原因だと推察し、
for 文に移る前に上記のような if 文を書いてみました。

このように実装すると、毎音入力から1秒後にはトレモロがかかるようになりました。
しかし、最初 if 文の条件を「入力信号のバッファ(?)の先頭が 0 」としているため、
入力信号のリリースがわずかでも残っていると、その次に入力した信号にもトレモロがかかってしまいます。
文章だと少しわかりにくいので、今回のトレモロを録音してみました。

http://up.cool-sound.net/src/cool53865.mp3

ド〜、ミ〜、ソ〜 | ド〜ミ〜ソ〜
と鳴らしています。

前半のように各音きちんと区切って鳴らす分には問題ありませんが、
後半のレガートのような演奏をすると、入力信号が 0 にならないため、
totalSample がリセットされず継続してトレモロがかかってしまいます。

これを信号が入力(ノートオン)される度に、
1秒経ってからトレモロがかかるようにするには、どのようにすればよろしいでしょうか。
ノートオンという言葉の通り、MIDI 信号の処理も必要になりますかね?

面倒くさい質問になってしまい申し訳ありません(汗

150 管理人★ :2017/12/06(水) 22:19:18
霧林さん

いつ入力信号があるか分からないので、processReplacing関数は
信号の入力がない状態でも呼び出され続けます。


「毎回、エフェクトに信号が入力されてからn秒後」とするにはなかなか難しいです。

信号が入力されたという状態をどう考えるか?や
エフェクターをかける対象をどんなものにするか?で変わってくると思います。

記載いただいているサンプルだとおそらくノイズが少しでも乗ると
「信号が入力された」という状態になってしまいます。

信号が入力されたかどうかを判断する方法の一つに音圧をもとにするものがあります。
コンプレッサーでアタックやリリースを出すときに使われる方法です。
RMS(2乗平均平方根)を使えば音圧を取得できるので、RMS値が一定値を超えたら
入力があったとみなす方法です。
ただし、小さい音やオルガンなどの減衰のない音に対してはあまり効果がないと思います。

他にも音程が変わったら入力があったとみなす方法もあると思います。
音圧と組み合わせてみるのもいいかもしれません。

エフェクトをかける対象がシンセで必ずMIDIメッセージを取得できるなら
MIDIノートオンメッセージを条件にすると簡単で正確だと思います。

回答になっていないですが、ご参考になればと思います。

151 霧林 :2017/12/12(火) 01:46:15
管理人様

返信が遅くなってしまい申し訳ございません。ご回答ありがとうございます。
processReplacing 関数、信号の入力がない状態でも呼び出されているのですね。

なるほど、信号が入力される度に…となると難しいのですね。
私がエフェクトをかける対象として考えているのは、今のところソフト音源(VSTi)のみなので、
MIDI ノートオンメッセージを条件にしてみる方法で挑戦してみます。

今回、エフェクト効果がかかるまでの時間の実装方法について質問をした理由を一応説明しておくと、
時間機能を付けたビブラートの VST エフェクトを作りたいなと思っているからです。
イメージとしては、MIDI のビブラート系の CC にある
Vibrato Rate, Depth, Delay のうちの”Delay”の実装ですね。

また何かわからないことがあれば質問するかもしれませんが、
その時はよろしくお願いいたします。

152 管理人★ :2017/12/12(火) 20:45:12
霧林さん

とりあえずは解決してよかったです。
また何かあればよろしくお願いします。

153 SNRER :2018/02/09(金) 16:56:10
管理人さま

はじめまして
VST作成に役立つ資料いつも参考にさせていただいております。
オーディオFxのVSTを作成中なのですが、
ホスト側で違うチャンネルに2つ以上自作VSTを起動した際に、コントローラの値が
同期してしまい、一つのVSTの値を変更すると起動しているVST全ての同コントローラの値が変わってしまっております。

複数起動の場合には何か特別な処置を施す必要がありますでしょうか。
初歩的な質問で申し訳ないです。。

154 管理人★ :2018/02/10(土) 21:56:11
SNRERさん

書き込みありがとうございます。
複数のVSTプラグインを起動する際に特別な処理は必要なかったと思います。

考えられるとすれば…
コントローラの値を保存する変数をグローバル変数にしたり、staticで定義したりすると
複数のスレッドで値が共有されてしまったと思います。

状況がわかればもう少し詳細に回答できるかもしれません…。

155 SNRER :2018/02/13(火) 16:54:37
管理人さま

GUI、コントローラ、プロセッサで値を共有するため、グローバル変数を使用しております。
GUIがオートメーションに対応して自動で動けなかったのをなんとかしようと、
グローバル変数に頼っておりました。
ここが問題ですね。力技になってしまっているので、複数スレッドの事まで考慮できていませんでした。

SDKのサンプルコードをみていると、バインディングする記述があったので、
もう少し試してみようと思います。

もし簡単な解決法があればご教示いただけますと幸いですが、
 特別は処理は必要ないこと
 全ての値が変わってしまう原因が分かった
ことで、大変助かりました。

ありがとうございました。

156 管理人★ :2018/02/13(火) 21:47:28
SNRERさん

とりあえず解決(?)してよかったです。

> SDKのサンプルコードをみていると、バインディングする記述があった
というのがすごく気になります…
どのサンプルなのか教えていただけると助かります。

またオートメーションの際にGUIに値を更新する方法ですが、
実は私もよくわかっていません。

VST GUIには標準でタイマーがあるので、タイマーを使うと比較的簡単にできるのでは?
と考えていますが、正しい実装ではないような気がしています。

157 管理人★ :2018/02/13(火) 21:57:22
ちなみに…
タイマーの使い方はVSTGUIEditorクラスのnotify関数をオーバライドして使います。

下記のような方法で実装すればオートメーションに伴ってGUIが更新されるはずです。
(動作確認したわけではないので、動かなかったら教えてください。)
なお、インデントは全角スペースになっているのでご注意ください。

①VST GUIクラス(VSTGUIEditorを継承したクラス)でコントロール用の変数を定義
 (ここではつまみ(ノブ)コントロールとしています。)
【例】
CKnob* knob1;

②notify関数をオーバーライド
【例】
public:
 CMessageResult notify(CBaseObject *sender, const char *message);

③open関数でコントロールを作成した際にポインタを保存しておく
【例】
bool PLUGIN_API MyVSTGUIEditor::open(void* parent, const PlatformType& platformType)
{
// GUIウィンドウが開かれたときに、UIを作成する
  〜〜 中略 〜〜

  // つまみ(ノブ)コントロールを作成( createKnob関数は http://vstcpp.wpblog.jp/?p=1550 参照)
  knob1 = (CKnob*)createKnob(1, 20, 20);

  〜〜 中略 〜〜
}

④notify関数でタイマーイベントを受け取り、コントロールを更新
 (コントロールの更新はsetDirty関数を使います。)
【例】
CMessageResult MyVSTGUIEditor::notify(CBaseObject *sender, const char *message)
{
  if (message == CVSTGUITimer::kMsgTimer)
  {
    if (knob1 != nullptr)
    {
      knob1 ->setDirty(); // 表示を更新
    }
  }

  return VSTGUIEditor::notify(sender, message);
}

158 管理人★ :2018/02/13(火) 22:15:27
すいません…。
「④notify関数でタイマーイベントを受け取り、コントロールを更新」で
パラメーターの値を取得する必要がありそうです。

CMessageResult MyVSTGUIEditor::notify(CBaseObject *sender, const char *message)
{
  if (message == CVSTGUITimer::kMsgTimer)
  {
    if (knob1 != nullptr)
    {
       // 現在の値をパラメーター操作クラスから取得し反映する
      ParamID tag = 1;
      ParamValue value = controller->getParamNormalized(tag);
      knob1->setValueNormalized(value);

      knob1->setDirty(); // 表示を更新
    }
  }

  return VSTGUIEditor::notify(sender, message);
}

159 SNRER :2018/02/14(水) 18:38:32
管理人さま

詳しいご説明誠にありがとうございました。
私はまだプログラミング初心者ですが、サイトも今回の解説もとても分かり易く感謝しております。

GUIクラスで常に呼ばれる系の関数が見つけられずにいましたが、notifyがまさにそれなのですね。
解説いただいた通りでオートメーションが追従しました。さすが管理人さまです!

バインディングについてですが、「note_expression_synth_ui」を見ておりました。
実際に使用してみるとGUIを使ったVSTで、オートメーションに追従していたので、
この中にヒントがあると思い探っておりましたが、「setValueNormalized」は見つかっておりません。
やはり何か実装が違うのでしょうか。。

また、
「#include "vstgui/plugin-bindings/vst3editor.h"」の中の

//-----------------------------------------------------------------------------
//! @brief VST3 Editor with automatic parameter binding
//! @ingroup new_in_4_0
//-----------------------------------------------------------------------------

からの部分が怪しい気がしましたが、勉強不足で理解できておりません。。。。

加えて、大変不躾ではございますが、
今回ご教示いただいた「kMsgTimer」ですと、再生バーを動かしただけでは反応しませんが、
「note_expression_synth_ui」では再生開始しなくても、
バーを違う地点に動かすだけで、その地点のオートメーションの値がGUIに反映されておりました。
(私が作っているのはエフェクトで、このVSTはインストゥルメントという違いはありますが・・・)

できれば「note_expression_synth_ui」同様に再生開始前に追従したいのですが、
kMsgTimer以外のメッセージ種別は何かありますでしょうか?
(探してはみたのですが、みつからず・・)

大変お手間をとらせて申し訳ありません。

160 管理人★ :2018/02/14(水) 22:57:52
SNRERさん

バインディングの情報ありがとうございます。

私もオートメーションと再生バーの追従はまだ試していないのでもう少し確認してみます。

kMsgTimer以外のメッセージもたしかあったのですが、再生やバー移動などの関連の
メッセージはなかったと思います。

「note_expression_synth」で再生バーの追従が出来ているということは
おそらく、notify関数でkMsgTimerを使うのはあまりいい方法ではないと思います。

あいまいな回答で申し訳ありません。

161 SNRER :2018/02/15(木) 10:01:08
管理人さま

ご返答ありがとうございます。
こんな素人の質問に付き合っていただき本当に感謝しております。
私も引き続き調べてみようと思います!

162 管理人★ :2018/02/15(木) 23:04:52
SNRERさん

私も>>157-158の方法を試してみました。

つまみ(ノブ)等の実装方法(下記)をベースにnotify関数
で更新する方法をとりましたが、再生バーを移動させた際も
コントロールの状態は更新されました。

http://vstcpp.wpblog.jp/?p=1230

SDKは3.6.8を動かせるDAWがないので使用したSDKは3.6.0になります。
DAWはSteinberg Sequel 3です。

可能であれば使用しているSDKやDAWなどを教えていただけますでしょうか?

また、動かないのであれば、setDirty関数をinvalid関数に変えて
試していただけますでしょうか?
(インデントは全角スペースになっているのでご注意ください。)

④notify関数でタイマーイベントを受け取り、コントロールを更新
CMessageResult MyVSTGUIEditor::notify(CBaseObject *sender, const char *message)
{
  if (message == CVSTGUITimer::kMsgTimer)
  {
    if (knob1 != nullptr)
    {
       // 現在の値をパラメーター操作クラスから取得し反映する
      ParamID tag = 1;
      ParamValue value = controller->getParamNormalized(tag);
      knob1->setValueNormalized(value);

      knob1->invalid(); // 表示を更新
    }
  }

  return VSTGUIEditor::notify(sender, message);
}

なお、「note_expression_synth」の中身を確認しましたが、
オートメーションと再生バーの追従方法は自前でクラスを用意していました。

サンプルの実装方法を見る限りでは、
notify関数のkMsgTimerで更新する方法でも問題なさそうです。

163 SNRER :2018/02/16(金) 15:27:56
管理人さま

ご返信ありがとうございます!
本当に丁寧に考えていただき、とても嬉しいです。

まず、私の環境についてですが、
DAW SONAR Platinum(つい先日開発中止になってしまいましたが・・・・)
SDK 3.6.8

となります。

ご教示いただいた「invalid」についてですが、
「setValueNormalized」の行までだけで表示は更新されている様で、
「invalid」「setDirty」
どちらをコメントアウトしても動作しております。
また、「invalid」を試してみましたが、こちらの環境では再生バーに追従できませんでした。

その後に、VisualStadio からSONARにアタッチしてデバッグをしていて
 再生バーを動かしただけでもnotify内のif分の中まで入ってきているが
 getPramで取得してくる値が再生バーを動かす前の値がそのまま残っている。
という事がわかりました。

しかし、再生バーを動かしてプロセッサ関数に来た時に
「getPoint」で取得するvalueは再生バーを動かした後の最新の値がホストから提供されていました。

この最新の値をコントローラ側でも把握できればいけそうですが、
EditController* controller
のパラメータがどのタイミングにどの様に更新されているのかを理解できておりません。

ちなみに先日のバインディングの件ですが、
怪しいと思っていたところはVST上でエディターを起動する事ができて、
それ上でのバインドの事を指している様な感じでしょうか。
実際VST上で起動してエディターの中身も見てみましたが、用意されたテンプレート以外の自分で作った絵を使う事が出来ない感じに見えましたので、
今回の自分がやりたい事にはマッチしない感じでした。
お騒がせしてすみません。。

引き続きいろいろと試してみます!

164 管理人★ :2018/02/16(金) 22:09:16
SNRERさん

ご確認ありがとうございます。少し整理のために、私の理解している動作を記載させていただきます。

まず、オートメーションや再生バーを動かした時、DAWからは状態とGUIを反映するため下記が行われる

 A)音声処理クラス(AudioEffectを継承したクラス)へは
  process関数の引数ProcessData& dataに値を設定し反映する。
  音声処理クラスは渡された値で内部状態を更新する。

 B)パラメータ操作クラス(EditControllerを継承したクラス)へは
  setParamNormalized関数を呼び出して変更を通知・反映する。(値を更新する)
  パラメータ操作クラスはsetParamNormalized関数のtagで指定された
  パラメータの値を更新する。

上記とは別にVST GUIクラス(VSTGUIEditoを継承したクラス)はタイマーを使って
0.1秒ごと(デフォルト時)にnotifyを呼び出している。

 C)notifyでは、パラメータ操作クラスから現在の値をgetParamNormalized関数で取得し、
  コントロール(ノブなど)の値を更新している。
  値更新後はsetDirty関数で画面UIの更新をDAWに通知し、DAWに再描画させる。(0.1秒ごと)

VST GUIクラスのEditController* controllerはパラメータ操作クラスへのポインタなので
B)のタイミングで値は更新されている。

C)は0.1秒ごとに呼び出されるので、どこかのタイミングでコントロールは更新される
再生バーを動かした時でも0.1秒以内には更新される。

以上が私の理解している動作になります。

いま、A)とC)は呼び出されていることが確認できており、B)が確認できていない状況で
間違いないでしょうか?

B)が呼び出されない可能性はDAWの実装に原因があるように思えます。
(ただ、サンプルVSTで動いているのが気になります…)

再生バーを動かしたときにB)が確認できるか?(DAWからsetParamNormalized関数が呼ばれているか?)
を確認してもらえますでしょうか?

また、呼び出されていても反映されていない状況もあるかと思います。
たとえばParameterクラスを継承して自作Parameterクラスを作っていて、そのクラスの実装が
間違っている場合などです。
自作Parameterクラス等は作っていないでしょうか?

最後にバインディングの件ですが、VST SDK 3.6.8からサンプルのVST GUIが
Inline UI Editor(VST3Editorクラス)を使うようになったようです。
このInline UI Editorはコード書かなくても、マウスでUIを作れる方法のようです
バインディングというのは、
 「マウスでコントロール(ノブなど)を作っても自動で割り当てしてくれる」
という意味だと私は理解しています。

長文失礼しました。以上よろしくお願いします。

165 SNRER :2018/02/20(火) 10:03:14
管理人さま

ご返信ありがとうございます!
作業できる環境から少し離れておりました。

 再生バーを動かしたときにB)が確認できるか
など確認して追ってご報告いたします。

166 SNRER :2018/02/20(火) 15:22:56
管理人さま

改めまして、パラメータ共有の流れについてご説明誠にありがとうございました!
いつも本当に丁寧なご回答助かっております。

まず、

いま、A)とC)は呼び出されていることが確認できており、B)が確認できていない状況で
間違いないでしょうか?

についてはその通りでございます。

vsteditcontroller.cpp
内の

tresult PLUGIN_API EditController::setParamNormalized (ParamID tag, ParamValue value)
{
Parameter* parameter = getParameterObject (tag);
if (parameter)
{
parameter->setNormalized (value);
return kResultTrue;
}
return kResultFalse;
}

のあたりでブレイクしてみましたが、
再生開始時には通っている様で、再生バーを動かしただけの場合には通りませんでした。

やはり再生していない場合では最新の値がセットされない事で、GUIの値が更新されないと思われます。

また、自作Parameterクラスなどは作っておりません。
バインディングについてもご説明いただきありがとうございました。

サンプルで動くという事は何かしらホストから発信はあるはずなので、
もう少しサンプルのソースを見てみようと思います。

167 管理人★ :2018/02/20(火) 21:43:34
SNRERさん

ご確認ありがとうございます。

EditController::setParamNormalized関数の「parameter->setNormalized (value);」
が呼び出されていないのですね…。

「note_expression_synth」サンプルソースもParameterクラスのsetNormalized関数から
更新するタイミングを受け取っているようなので、本来なら動かない気がします…。

「note_expression_synth」と同じ方法でGUIを更新する方法は今私も試しているところです。
なにか分かりましたら、また共有させていただきます。

あと、「つまみ(ノブ)等の実装方法」( http://vstcpp.wpblog.jp/?p=1230 )を元に
私がnotify試したサンプルを下記に保存しておりますので、よければご参考にしていただければと思います。

http://vstcpp.wpblog.jp/wp-content/uploads/2018/02/20180220_vst3.zip

168 SNRER :2018/02/21(水) 16:06:14
管理人さま

ご返信ありがとうございます!

ご指摘の通り、setParamNormalizedが呼ばれない事で、
「parameter->setNormalized (value);」
が実行されていないという感じでした。

「note_expression_synth」の
「note_expression_synth_controller.cpp」
でオーバーライドされている setParamNormalized でブレイクしてみましたが、
再生バーを動かすだけ、というか、SONARをアクティブにした時点でブレイクしました。

こちらは正常にsetParamNormalizedが呼ばれている様です。
何が違うのか・・・現状まだ分かりませんが、ホストは正しく動作している様です。

また、頂いたソースで試してみたのですが、
VST起動の際、 Sample32* inL = data.inputs[0].channelBuffers32[0]; がnullでエラーになったので、
変数への格納を
  for (int32 i = 0; i < data.numSamples; i++)
の中で行う事で動作しました。

ただし、簡易デバッグとして使っております 
 「Vst3HostDemo_x64.exe」
というソフトではそのままで問題無く起動しておりますので、
未再生状態でプロセッサを呼んでしまう様なSONAR独自の動きのせいでエラーになるのかもしれません。

続いて動作内容ですが、
再生開始からは同期しますが、バーを動かすだけでは追従しませんでした。

なぜ「note_expression_synth」では
 setParamNormalized
が再生バー移動でもコールされているのかが肝だと思いますので、
自分も引き続き調べてみます。
何か気付きがあればまたご報告いたします。

169 管理人★ :2018/02/21(水) 21:17:59
SNRERさん

何度もご確認ありがとうございます。

やはり私のサンプルでも動かなかったのですね…。
となると後は下記ぐらいの内容しか思いつきません…。

1.再生バーの動作ではsetState関数やsetComponentState関数が呼ばれている
 →setState関数やsetComponentState関数からsetParamNormalized関数が
  呼び出されている可能性があります。

2.パラメータ操作クラスで初期化時に何らかのフラグを立てている
 →パラメータ変更時にホストからsetParamNormalized関数を呼び出すような
  設定をしている可能性があります。
  (サンプルを見た感じではありませんでしたが…)

3.音声処理クラスから、パラメータ更新を受け取っている
 →音声処理クラスのprocessでdata.outputParameterChangesをセットし、
  パラメータの更新を通知している可能性があります。
  (たぶんこの可能性はないと思いますが…)

可能性としては以上になります。
上記の可能性でない場合、正直分からないというのが現状です。

170 SNRER :2018/02/26(月) 10:01:55
管理人さま

可能性についてピックアップありがとうございます!
1.2.3.について自分なりに見てみましたが、
現状答えにはたどり着けておりません。

方向性は変わりますが、
VST上でのエディターについてもう少し調べておりました。
どうもエディターで作った内容はリソースファイルとして出力される様で、
その中に各コントローラとタグを結びつける記述がありました。

自分で作ったPNGもエディターから使用する方法が分かりましたので、
ひとまずこちらで試してみようと思います。
(エディター上で、何故か他ドライブからPNGをインポートすると落ちるのですが、
 Cドライブからインポートなら落ちないという事が分かるまでに時間がかかりました)

また発見がありましたら共有させていただきます。

171 管理人★ :2018/02/26(月) 23:40:49
SNRERさん

ご確認ありがとうございます。原因が分からず残念です。

Inline UI Editor(VST3Editorクラス)の情報ありがとうございます。
どうもSDK 3.6.8からこのエディターが推奨されているようですが、
私はまだ試せていないので情報頂けると非常にたすかります。
(全部のサンプルがこのエディターになっていたのでそう考えています。)

また、試したわけではありませんが、私が分かっている範囲で
Inline UI Editor(VST3Editorクラス)でのUI更新方法について
分かる内容を記載させていただこうと思います。
本日はまだ整理できていないので近日中に記載させていただきます。

172 管理人★ :2018/03/02(金) 20:11:36
SNRERさん

遅くなりすいません。
Inline UI Editor(VST3Editorクラス)でのUI更新方法について
分かる内容を記載させていただきます。

Inline UI Editor(VST3Editorクラス)ではParameterクラスと依存関係を作成して、
Parameterクラスが変更されたとき(setNormalized関数が呼ばれたとき)に
コントローラを更新できるようにしているようです。

具体的にはvst3editor.cppのParameterChangeListenerクラスで実装されています。

①ParameterクラスのaddDependent関数を呼び出して依存関係にあるクラスを登録する。
 (VST3EditorクラスではコンストラクタでParameterChangeListener自身を登録)

②ParameterクラスのsetNormalized関数が呼び出されると変更されたことを
 依存関係にあるクラスに通知するためchanged関数が呼び出される。

③changed関数が呼び出されるとVST内部でいったんキューイングされた後、
 ParameterChangeListenerクラスのupdate関数が呼び出される。

④ParameterChangeListenerクラスのupdate関数内で関連付けられた
 コントロール(CControlクラス)の値を更新(setValueNormalized関数の呼び出し)し、
 再描画(invalid関数の呼び出し)する。

以上がInline UI Editor(VST3Editorクラス)の更新方法のようです。
ご参考までに。

173 SNRER :2018/03/12(月) 17:35:03
管理人さま

大変お返事遅くなりました。
申し訳ないです。

Inline UI Editorで進めていきたいのですが、
うまくバインドされずにまた困っておりました。

ご教示いただいた内容を紐解きつつ確認してみます!
また進捗あればご報告させていただきます。

174 管理人★ :2018/03/12(月) 22:18:33
SNRERさん

ご確認ありがとうございます。

私も最近Inline UI Editorを試しました。
慣れるまでちょっと大変なツールですね…。

バインドされないとのことですが、「Control-tag」の項目に
パラメーターのタグを設定してもバインドされないでしょうか…?

175 SNRER :2018/04/02(月) 17:19:30
管理人さま

ご無沙汰しております。
多忙により少しコードを触れずにおりました。

Control-tagにはタグ名称、その下のエリアで、ラベルとタグの記載をしているのですが、
それによって作られたコントローラが何の反応もなく(動かす事はできるのですが)
つまんで動かしてもvalueChangedにも来ていない状況です。

今、UI Editorの記事を拝見しました。まず、この記事に沿って構築し直してみようと思います。
貴重な記事大変感謝致します。

176 管理人★ :2018/04/02(月) 20:21:39
SNRERさん

こちらこそいろいろ情報を頂きありがとうございます。
valueChanged()が呼び出されていないとなるとちょっと分からないですね…

Inline UI Editorの記事がご参考になればと思います。

177 SNRER :2018/04/04(水) 10:41:47
管理人さま

parameters.addParameter(STR16("●●"), STR16("●●"), 0, 0, ParameterInfo::kCanAutomate, TAG, kRootUnitId);

の様に設定しておりましたが、ここをノートエクスプレッションに合わせて

Parameter* param;
param = new RangeParameter(STR16("●●"), TAG, STR16("●●"), 0, 100, 100);
param->setPrecision(1);
parameters.addParameter(param);

の様に変更する事で、オートメーション追従まではできました。

引き続き改めてコードとにらめっこしていますが、
UIエディターを使って作った場合は、そもそも「guieditor.cpp」などに相当する部分は必要なく、
「guieditor.cpp」に作った valueChanged なども必要無いという事になるでしょうか?(通っていなくて動いているので)


但し、再生バーの地点を動かしただけの場合にはやはり、
setPramNomalized が呼ばれておらず、表示も更新されません。

引き続き自分なりに調べてみますが、ひとまず動いたという事でご報告させていただきました。

178 管理人★ :2018/04/04(水) 21:30:12
SNRERさん

一つ問題が解決してよかったです。

Inline UI Editorで「guieditor.cpp」に相当するものは
VST SDK内にある「vst3editor.cpp」になります。
valueChanged関数もこの「vst3editor.cpp」で定義されています。

また、Sonarの再生バーを動かした場合、
パラメータ操作クラス(EditController)のsetComponentState関数が
呼び出されているのではないかと思っています。

ノートエクスプレッションのサンプルでは、setComponentState関数から
setParamNormalized関数が呼び出されていますのでこれによって
UIの状態が更新されていると考えています。

179 あると :2018/04/17(火) 18:59:40
管理人様

お世話になります.私,貴サイトを参考にVST3プラグインを作成しようとしているものです.
現在,貴サイトの「最小構成のVST3」の手順を行い,ビルドを行ったところなのですが,
問題が生じたので,もし何か解決の糸口が見つからないかと考え書き込ませていただきます.

現在,
Windows10(64bit)
Visual Studio 2017 community
VST SDK3.6.8
という貴サイトでの環境を構築し,
手順通り進めることでビルドが成功しました.
ソースコードは全て貴サイトのものを使用させていただきました.
生成された.vst3ファイルを動作確認するため,.vst3を
C:ProgramFiles\Common Files\VST3に入れました.

しかし,現在使用しているDAW「StudioOne3.5 professional」
でインサートプラグインとして使用したところ,
VSTプラグイン一覧上で自作VST3は見えるのですが,
インサートしてもインサート欄に追加されず,何も起きません.
ちなみに,他のVST2,3プラグインは正常にインサート欄に追加されて使用できます.

このような現象に心当たりはありますでしょうか?
DAWとの相性などもあるのでしょうか?.

辿々しい説明でわかりづらいとは思いますが,はじめの一歩でつまずいてしまい
大変困窮しておりますので,何卒ご返信いただければ幸いです.

180 管理人★ :2018/04/17(火) 20:06:42
あるとさん

書き込みありがとうございます。

頂いた事象についての心当たりはないのですが、
「最小構成のVST3」では何か足りないのかもしれませんね…
(説明しやすいようにかなり無理して削っている部分があるので…)

もし可能であれば、他のDAWで動作確認していただけないでしょうか?

VST SDKにもテスト用ホストが「VST3_SDK\bin\Windows 64 bit」にあります。
「VST3PluginTestHost_x64_Installer_2.6.0.zip」を解凍すればインストーラーがあります。
(私はこちらで動作確認しております。)

テスト用ホストで動くのであれば、パラメーター実装方法等で少し機能を追加してから、
再度Studio Oneで動作確認いただけますでしょうか?
(「最小構成のVST3」にはパラメーター操作クラスがないので、おそらくこのあたりで
はじかれているのではないかと推測しています。)

181 あると :2018/04/20(金) 10:19:16
管理人様

ご返信ありがとうございます!
返信が遅くなってしまい申し訳ございません.

テスト用ホストの存在を知らなかったので,
その情報だけでも有難いです!

テスト用ホストをDLしてみたところ,
サンプルコードのvst3プラグインは認識されました.
しかし,本当に信号処理が出来ているかわからなかったので,
出力を1/4にするようにコードを書き換えて実行したのですが,
バイパス機能が実装されていないため,オンオフで確認することが出来ませんでした.
ということで,バイパス機能を実装してみたいと思います.
パラメータ実装の方も試してみます.

また,他のDAWでも試してみたほうがいいというアドバイスを受け,
知り合いのCubase使いのDTMerにプラグインを渡して試してもらったのですが,
そもそも認識されなかったそうです.おそらくCubase pro9.5です.
REAPERもDLしてみましたが,vst3を読み込んだら落ちました.

とりあえず解決できそうな糸口は色々と見つかったので試してみます.
ご回答ありがとうございました.何か進展があった際はご報告いたします.

182 管理人★ :2018/04/21(土) 19:33:24
あるとさん

ご連絡ありがとうございます。

他のDAWでも駄目でしたか…
ちなみに私のサイトに記載されている環境構築方法の場合
Windows 7だとたしか動きません…。
機能追加した結果等を教えていただけると幸いです。


新着レスの表示


名前: E-mail(省略可)

※書き込む際の注意事項はこちら



掲示板管理者へ連絡 無料レンタル掲示板 powered by Seesaa