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

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

11管理人:2011/04/23(土) 12:29:51
書き込みに気づかず書き込んでしまった…

12管理人:2011/04/23(土) 12:41:19
私自身も詳しくはないですが、

> と、書き換える必要があるのでしょうか。
> 最初からdefファイルに記述されている「VSTPluginMain」メソッド を利用することによって、
> VSTプラグインを使用するのでしょうか?
vstplug.defは書き換える必要はないと思います。
ご認識のとおりだと思われます。

> これを見ると、VSTホストアプリケーションは、
> AEffect構造体を利用するのだろうか?
AEffectクラスを継承した自作のVSTクラスを利用することとなります。
C++のクラスの「継承」「オーバーライド」といった機能を調べていただけると
ご理解いただけるかと思います。

なおnewしたAudioEffectインスタンスの解放は
ホストアプリケーション側で行われていると思います。

13管理人:2011/04/23(土) 12:49:20
> C++のクラスの「継承」「オーバーライド」といった機能を調べていただけると
> ご理解いただけるかと思います。
「仮想関数」が抜けていました。

14ちあ.dat:2011/04/23(土) 13:13:40
管理人様、すばやいご回答ありがとうございます!

なるほど!
AEffectクラスを継承した自作クラスを作成することが基本方針なのですね!

このクラスの中身はまだわからないことが多いのですが、色々調べたり試したりして
がんばってみようと思います。

本日、こちらのサイトを発見してから、長い間の疑問が色々解決しました!
今後のサイトの更新を、楽しみにしております。

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

15管理人:2011/04/23(土) 14:08:38
ちあ.datさん

無事解決してよかったです。

ここに書かれている以外のことでも可能な範囲で答えますので
よければまたご質問ください。

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

16nobu:2011/08/15(月) 11:09:11
> AudioEffectインスタンスは、いつ解放されるの?

>なおnewしたAudioEffectインスタンスの解放は
> ホストアプリケーション側で行われていると思います。

本当にそうか気になったのでざっとSDKとサンプルのコードを見てみました。

VST hostが受け取れるのは AudioEffect の持っている AEffect 構造体。

AEffect::object は そのAEffect自身を持っている AudioEffect へのポインタ。

AudioEffect::dispatchEffectClass で effClose がきた時に引数として受け取った AEffect構造体のメンバ AEffect::object (= AudioEffectのインスタンス) に対して delete している。

AudioEffect::dispatchEffectClass は AudioEffect のコンストラクタで、AEffect の dispatcher に設定されている。

minihostのサンプルを見ると、VST hostは終了処理として
> effect->dispatcher (effect, effClose, 0, 0, 0, 0);
のように effClose を投げる

ということで、当初の予想通り、AudioEffectのインスタンスの解放はVST hostの責任で、VST pluginを作る人は気にする必要はありませんでした。
情報共有まで。

17管理人:2011/08/17(水) 01:32:42
nobuさん情報提供ありがとうございました。

有益な情報をいただけて助かりました。
これからもよろしくお願いいたします。

18<削除>:<削除>
<削除>

19<削除>:<削除>
<削除>

20ken:2012/01/27(金) 00:17:33
初めまして、kenと申します。
「C++でVST作り」と拝見させていただいております。

Microsoft Visual C++ (2008 Express Edition)とVST SDK 2.4をインストールし、
VC++ プロジェクトの準備のNo.1〜No.5を読みながら、まずビルドまでを挑戦しています。
手順どおりの操作を行ったつもりなのですが、以下のようなエラーが出てしまいます。

------ ビルド開始: プロジェクト: MyTremoloVST, 構成: Release Win32 ------
リンクしています...
ライブラリ C:\Documents and Settings\ken\デスクトップ\MyTremoloVST\Release\MyTremoloVST.lib とオブジェクト C:\Documents and Settings\ken\デスクトップ\MyTremoloVST\Release\MyTremoloVST.exp を作成中
vstplugmain.obj : error LNK2001: 外部シンボル ""class AudioEffect * __cdecl createEffectInstance(int (__cdecl*)(struct AEffect *,int,int,int,void *,float))" (?createEffectInstance@@YAPAVAudioEffect@@P6AHPAUAEffect@@HHHPAXM@Z@Z)" は未解決です。
C:\Documents and Settings\ken\デスクトップ\MyTremoloVST\Release\MyTremoloVST.dll : fatal error LNK1120: 外部参照 1 が未解決です。
ビルドログは "file://c:\Documents and Settings\ken\デスクトップ\MyTremoloVST\MyTremoloVST\Release\BuildLog.htm" に保存されました。
MyTremoloVST - エラー 2、警告 0
========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ==========


Microsoft Visual C++ (2010 Express Edition)でも試したのですが、同様のエラーが出てしまいます。
------ ビルド開始: プロジェクト: MyTremoloVST, 構成: Release Win32 ------
ライブラリ C:\Documents and Settings\ken\デスクトップ\MyTremoloVST\Release\MyTremoloVST.lib とオブジェクト C:\Documents and Settings\ken\デスクトップ\MyTremoloVST\Release\MyTremoloVST.exp を作成中
vstplugmain.obj : error LNK2001: 外部シンボル ""class AudioEffect * __cdecl createEffectInstance(int (__cdecl*)(struct AEffect *,int,int,int,void *,float))" (?createEffectInstance@@YAPAVAudioEffect@@P6AHPAUAEffect@@HHHPAXM@Z@Z)" は未解決です。
C:\Documents and Settings\ken\デスクトップ\MyTremoloVST\Release\MyTremoloVST.dll : fatal error LNK1120: 外部参照 1 が未解決です。
========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ==========


単純なミスなのかも知れませんが、このエラーから何か設定すべきこと等わかりましたら、教えていただければ幸いです。
よろしくお願いいたします。

21管理人:2012/01/28(土) 04:05:20
kenさんはじめまして

おそらくプロジェクトの準備だけしてすぐにビルドしたのでは無いでしょうか?

残念ながらプロジェクトの準備だけではビルドすることができません。
ビルドするには.cppファイルを作成し、最低限の関数とクラスを
定義する必要があります。

ビルドするための最低限必要な定義については
「最小構成のVST作成方法」に記載しております。

・最小構成のVST作成方法
  http://www39.atwiki.jp/vst_prog/pages/70.html

・最小構成のVST(ソースコード全体)
  http://www39.atwiki.jp/vst_prog/pages/73.html

22ken:2012/01/28(土) 12:28:53
早速のご教示ありがとうございました。
「簡単な音源(VSTi)の作成」ページのMySynthSampleVSTをビルドすることができました。
これからソースコードの内容を勉強させていただきたいと思います。

VST、VSTiに関してはこれから学ぶところですが、
私もまた違ったアプローチでバーチャルアナログ音源を作っています。
よろしければ見てみてください。

・What is Flageoboard?
  http://mbed.org/users/kentasaito/notebook/what-is-flageoboard/

・Me playing Flageoboard (YouTube)
  http://www.youtube.com/watch?v=chereNrys5Q

23管理人:2012/01/29(日) 11:20:45
kenさん

無事解決してよかったです。

すでにマイコンを使って作られたことがあるんですね.
VSTの規格自体はあまり難しく無いと思いますので
すぐに作成できると思います。

ほかに不明点がありましたらいつでもご質問ください。
また、書けていない内容(MIDI処理とかフィルタとか…)も
ありますのでそちらもわかる範囲で答えさせていただきます。

これからもよろしくお願いいたします。

24ken:2012/01/30(月) 00:12:22
お返事ありがとうございます。
「VST GUIの作成」ページのつまみやスライダーも拝見させていただいています。
VSTiは学べば学ぶほどやってみたいことが増えそうな気がします。

今後ともよろしくお願いいたします。

25<削除>:<削除>
<削除>

26<削除>:<削除>
<削除>

28名無しさん:2012/11/20(火) 12:20:46
管理人様、はじめまして。
自作のVstHostアプリを開発中の者です。
ホームページに載っている色々な情報を参考にさせていただいています。
ありがとうございます。

上記の通りVstHostアプリを開発中なのですが、
嵌ってしまっておりましてアドバイスをいただけたらと思い、書き込みさせていただきました。

現在vsti(Synth1)をホストアプリにloadして
processEvents()とprocessReplaceing()を実行するコードを書き、
エラー無しでコンパイルされること、
また、プログラムを実行すると正常終了するところまでは確認できているのですが、
肝心の音が鳴らない状況です。

vstiのdllの中でトレースすることも出来ず困っているのですが、
自分の書いたコードをご覧いただき、おかしなところがあればご指摘いただけたら幸いと思っている次第です。
以下の様な感じになります。
http://codepad.org/m52oPA93

またトレースの仕方についても良い方法がありましたらご教示いただけましたら幸いです。

ご回答いただけますと嬉しいです。
どうぞ宜しくお願いします。

29管理人:2012/11/21(水) 02:13:31
書き込みありがとうございます。

VSTHostについてはあまり詳しくありませんので
見当違いかもしれませんが、AEffect構造体ではなく
AudioEffectXクラスを利用されてはいかがでしょうか?

dispatcher()関数でMIDIメッセージをセットし、
音を鳴らそうとしているようですが、AEffect構造体(AudioEffectクラス)の
dispatcher()関数にはopcodeがeffProcessEventsの場合の処理が
記載されていないようです。
(aeffect.h、audioeffect.cppを見た限りですが…)

AudioEffectXクラスはAudioEffectクラスのdispatcher関数を
オーバーライドしており、opcodeがeffProcessEventsの場合に
processEvents()関数を呼び出すようになっています。
(aeffectx.h、audioeffectx.cppに記載があります。)

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

またトレースの方法ですが、本格的な開発をしたことが無く
こちらはまったくわかりません…

30らい:2012/11/21(水) 16:34:21
初めまして.
卒業研究でVSTを制作しており,毎日そちらのサイトで勉強させていただいてます.

サンプルコードのトレモロは無事実装でき,それに対するGUIを実装したいと思い
まずはウィンドウを表示するだけのサンプルプログラムの実装を試みているのですが
なかなか思うようにいかず苦戦しております.
vstcontrols.cpp,vstgui.cpp,aeffguieditor.cppのソースファイルもプロジェクトに入れ,実行しても以下のようなメッセージが出てきました.

1>------ ビルド開始: プロジェクト: GUI, 構成: Release Win32 ------
1> vstcontrols.cpp
1>C:\vstsdk2.4\pluginterfaces/vst2.x/aeffect.h(296): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1> c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(188) : 'strncpy' の宣言を確認してください。
1>C:\vstsdk2.4\pluginterfaces/vst2.x/aeffect.h(306): warning C4996: 'strncat': This function or variable may be unsafe. Consider using strncat_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1> c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(175) : 'strncat' の宣言を確認してください。
1>..\..\..\..\..\..\..\vstsdk2.4\vstgui.sf\vstgui\vstcontrols.cpp(707): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1> c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : 'sprintf' の宣言を確認してください。
1>..\..\..\..\..\..\..\vstsdk2.4\vstgui.sf\vstgui\vstcontrols.cpp(1408): error C2664: 'CreateWindowExW' : 2 番目の引数を 'const char [5]' から 'LPCWSTR' に変換できません。(新しい機能 ; ヘルプを参照)
1> 指示された型は関連がありません。変換には reinterpret_cast、C スタイル キャストまたは関数スタイルのキャストが必要です。
1>..\..\..\..\..\..\..\vstsdk2.4\vstgui.sf\vstgui\vstcontrols.cpp(1420): error C2664: 'strcpy' : 1 番目の引数を 'WCHAR [32]' から 'char *' に変換できません。(新しい機能 ; ヘルプを参照)
1> 指示された型は関連がありません。変換には reinterpret_cast、C スタイル キャストまたは関数スタイルのキャストが必要です。
1>..\..\..\..\..\..\..\vstsdk2.4\vstgui.sf\vstgui\vstcontrols.cpp(1864): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1> c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(105) : 'strcpy' の宣言を確認してください。
1>..\..\..\..\..\..\..\vstsdk2.4\vstgui.sf\vstgui\vstcontrols.cpp(1868): error C2664: 'GetWindowTextW' : 2 番目の引数を 'char [255]' から 'LPWSTR' に変換できません。(新しい機能 ; ヘルプを参照)
1> 指示された型は関連がありません。変換には reinterpret_cast、C スタイル キャストまたは関数スタイルのキャストが必要です。
1>..\..\..\..\..\..\..\vstsdk2.4\vstgui.sf\vstgui\vstcontrols.cpp(1869): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1> c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(105) : 'strcpy' の宣言を確認してください。
1>..\..\..\..\..\..\..\vstsdk2.4\vstgui.sf\vstgui\vstcontrols.cpp(3098): error C2664: 'AppendMenuW' : 4 番目の引数を 'char *' から 'LPCWSTR' に変換できません。(新しい機能 ; ヘルプを参照)
1> 指示された型は関連がありません。変換には reinterpret_cast、C スタイル キャストまたは関数スタイルのキャストが必要です。
1> MyVstGui2.cpp
========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ==========

C++を勉強してまだ半年ほどのものですが,ご指南頂けたらと思います.
何卒よろしくお願いします.

3128:2012/11/21(水) 19:28:18
管理人様

ご返信ありがとうございます!
なるほど、AEffect構造体のdipsatcherを呼んでもだめだったのですね。
重ね重ねになり申し訳ないのですが、またお伺いさせていただけますでしょうか。

ご教示いただいたようにAudioEffectXクラスのdispatcherを呼ぶ形で試してみようとしたのですが、
そもそもsynth1のdllをhostアプリ側で読み込んだ際に、どうやってAudioEffectXクラスのインスタンスのポインタを得ればいいのか
よくわからないのです。

現在、VstEventsTransporter::execute()
の中で使われている
vsti変数の中身 (synth1.dllをloadした際に得られたAEffect*)
は下記のような形で取得しています。
http://codepad.org/cYO1Je5z

mainEntryPoint()では AEffect*が返ってきてしまいますが、
ここでAEffect* ではなくAudioEffectX*を得る方法があるのでしょうか?

その方法を調べてみたのですが分からなかったため、
下記のように
http://codepad.org/SHkfCs6v
無理矢理キャストしてみたのですが、
コンパイルエラー等はでないものの、やはり音が鳴りません。

どこかで間違っているのだと思うのですが、
アドバイスをいただけますと幸いです。

よろしくお願い致します。

32管理人:2012/11/21(水) 23:26:31
>>30
らいさん書き込みありがとうございます。

プロジェクトの文字コードの設定がおそらくUnicodeになっていると思われます。
マルチバイト文字セットにすれば解決すると思います。

変更方法は下記のとおりです。
1.メニューから「プロジェクト」→「【プロジェクト名】のプロパティ」を選び、
 プロパティダイアログを開く
2.開いたダイアログ左側「構成プロパティ」→「全般」を選択
3.ダイアログ右側の「文字セット」を「マルチバイト文字セットを使用する」に変更
4.ダイアログ下側の「OK」を押す

上記内容をWebページのほうに更新いたしましたのでご参考までに。
http://www39.atwiki.jp/vst_prog/pages/61.html

33管理人:2012/11/22(木) 00:28:13
>>28さん

AudioEffectXクラスのポインタを得るには
 > AudioEffect* aex = (AudioEffectX*)vsti->object;
で問題ないと思います。

ただし、aexはAudioEffectクラス型ですので、
 > aex->dispatcher(
の部分ではAudioEffectクラスのdispatcher()関数が
呼ばれていると思います。

AudioEffectXクラスのdispatcher()関数を呼ぶには
  ((AudioEffectX*)aex)->dispatcher(
のようにキャストするか、
そもそもaexをAudioEffectXクラスで定義すればよいと思います。
  AudioEffectX* aex = (AudioEffectX*)vsti->object;

あまり自信がありませんがよろしくお願いします。

34らい:2012/11/22(木) 15:12:55
管理人様

迅速な対応ありがとうございます.
おかげ様で無事にウィンドウとつまみ表示のGUIを構築出来ました.
これをもとに勉強し,まずはトレモロエフェクトに対してGUIを構築することを目標としてやっていきたいと思います.

またこちらで質問させていただくことがあると思いますが
何卒よろしくお願い致します.

35管理人:2012/11/23(金) 01:46:27
らいさん

無事解決してよかったです。

WebページのほうにGUIの情報はあまり乗せていませんが
多少のことであれば知っています。
何かあればまたよろしくお願いします。

3628:2012/11/23(金) 12:55:01
管理人様

レスありがとうございます。
ご指摘ありがとうございます。
>AudioEffect* aex = (AudioEffectX*)vsti->object;
ここの部分なのですが、確かに
>AudioEffectX* aex = (AudioEffectX*)vsti->object;
の間違いでした。

しかし
>AudioEffectX* aex = (AudioEffectX*)vsti->object;
のようにしてもやはり音が鳴らないのです・・

proessReplacing()関数は、
それを実行した瞬間実際に音が鳴るものだと思っていたのですが、
もしかしますと、違うのでしょうか??
(波形を生成してどこかに格納しておくだけだったりしますでしょうか)
もしそうだとすると波形データを読み込んで実際に発音させる仕組みを
host側で持っておく必要があるのでしょうか・・?

2chの方でも色々と質問してみようと思うのですが、
ご教示いただけますと幸いです。

37管理人:2012/11/23(金) 13:34:28
>>28さん

processReplacing()関数はprocessEvents()関数で渡されたVstEventと引数inputsから
outputsに波形を出力するの関数です。

ですので音を出す仕組みはWinAPIのマルチメディア関数(waveOutOpen、waveOutWrite等)や
DirectSound等を利用し作成する必要があります。

processReplacing()関数の前にoutputsを0で初期化しているようですので、
呼び出した後にoutputsに0以外の値が入っているかどうか確認し、
波形が生成されているかまずは確認してみてはいかがでしょうか?

3828:2012/11/26(月) 01:01:32
管理人様

レス有難うございます。
お礼が遅れましてすみません。

>processReplacing()関数はprocessEvents()関数で渡されたVstEventと引数inputsから
>outputsに波形を出力するの関数です。

なるほど、そういうことだったのですね・・色々と勘違いしておりました。
vstiから返って来たデータをもとにwindows上でwaveデータを扱う
構造体を生成する必要があるようですね。
とても勉強になりました。
ひとまずその辺りの仕組みについて色々調べてみることにします。

ご丁寧に対応頂きましてありがとうございました。
また疑問点等が出たときは質問させていただくかもしれませんが、
よろしくお願いいたします。

39管理人:2012/11/27(火) 00:53:32
>>28さん

また何かありましたらわかる範囲で答えさせていただきます
よろしくお願いします。

4028:2012/12/09(日) 22:37:27
お世話になっております。
28です。

先のレスでいただいたアドバイスに従って色々と試行錯誤しているのですが
またよく分からない点が出てきましたので質問させていただけますでしょうか。


//vsti変数 には Synth1のdllをloadした際に得たAEffect*が格納されている

AudioEffect* aex = (AudioEffectX*)vsti->object;
aex->dispatcher(
effProcessEvents,
0,
0,
&vst_events,
0.0f
);
vsti->processReplacing(
vsti,
this->inputs,
this->outputs,
kBlockSize //512
);


このようなコードを書き、this->outputsの中に結果(波形データ?)が入って返ってくることは
確認したのですが、その内容が、processEventsでどんなmidiメッセージを送っても全く
同じになってしまうのです。

例えば 曲を再生して一番最初にドを発音するMidiイベントをvstiに送ると

this->outputs[0][0]; //3.94429e-09
this->outputs[0][1]; //2.08869e-08
this->outputs[0][2]; //3.11984e-08
this->outputs[0][3]; //4.43643e-08
this->outputs[0][508]; //8.25091e-07
this->outputs[0][509]; //8.25096e-07
this->outputs[0][510]; //8.251e-07
this->outputs[0][511]; //8.25104e-07

というデータが返って来ました。

しかし、開発中のVstHostを再起動し、今度はドではなく数オクターブ離れた別の音の
イベントを送信しても、
上と全く同じデータが返ってくるのです。

また、生成し始めて2つ目のイベント、3つ目のイベントなども
再起動してもそれぞれ全く同じになってしまいます。
また、processEvents & processReplacingを数回繰り返すと今度は浮動小数点が全く返ってこなくなり、
全て nan という文字列で埋まった float** this->outputs しか返さなくなってしまうようです。

processEventsでvstiに送っているイベントは大体以下のような感じです

vst_events.numEvents; // 1
vst_events.reserved; // 0
vst_events.events[0]->type; // 1
vst_events.events[0]->byteSize; // 24
vst_events.events[0]->deltaFrames; // 0
vst_events.events[0]->data[0]; // 0xffffff90 (ノートオン)
vst_events.events[0]->data[1]; // 0x3c (真ん中のドの音)
vst_events.events[0]->data[2]; // 0x64 (ベロシティ100)


どこかがおかしいのだと思うのですが、原因としては何が考えられますでしょうか・・
ご教示頂けると嬉しいです。

4128:2012/12/11(火) 01:15:49
度々書き込み失礼致します。

色々と調べておりまして、以下のURLで
http://www.kvraudio.com/forum/viewtopic.php?t=360826#
こう書かれているのを見つけました。

-------------------------------------------------
- all the MIDI events for the next audio buffer will be sent in one processEvents() call, rather than multiple calls.
-------------------------------------------------

VstEventsに複数の必要な分のVstEventを持たせ、processEventsは一回しか呼ばないようにしましょう、
つまり、曲の頭から終わりまでのすべてのVstEventを持ったVstEventsを一気に1回だけvstiに送って、
その後に一回だけprocessReplacingを呼びましょう、という風に読めたのですが、
この解釈で合っていますでしょうか。

管理人様のHPのこちらのページ
http://www39.atwiki.jp/vst_prog/pages/77.html
で、

【ホストアプリケーションの動作】
①processEvents()関数呼び出し
     ↓
②processReplacing()関数呼び出し
     ↓
③いろいろ処理
     ↓
④processEvents()関数呼び出し
     ↓
⑤processReplacing()関数呼び出し
     ↓
・・・・以降繰り返し     
     
のような記述がありましたので、
VstEvent一個につきprocessEventsを毎回発行するということかと思っていたのですが
自分の勘違いでしたでしょうか。
(よくよく考えればprocessEvent's' ですし、deltaframeという領域もあるので
イベントを一個一個送るのはおかしかった気がします)

しかし、この考え方ですと、曲の頭から終わりまでのすべてのwavデータをホスト上でバッファとして持っておく必要があるように思われ、
メモリの容量的に大丈夫なのだろうかなどという懸念が出てきます。

色々と自分が分かっていないのだと思うのですが、
ご指南いただけますと幸いです。

42管理人:2012/12/11(火) 02:19:20
>>28さん

まず気になったのは下記の部分です。
> vst_events.events[0]->data[0]; // 0xffffff90 (ノートオン)
> vst_events.events[0]->data[1]; // 0x3c (真ん中のドの音)
> vst_events.events[0]->data[2]; // 0x64 (ベロシティ100)

VstEvent構造体のdata[0]〜[3]はVstMidiEvent構造体のnoteLengthとなるかと思います。
それぞれの構造体の定義をご確認されてみてはいかがでしょうか?


また、processEvents()関数の呼び出しですが、マニュアルには下記のように記載されておりますので
http://www39.atwiki.jp/vst_prog/pages/77.htmlの解釈で間違いないと考えております。
> Events are always related to the current audio block. For each process cycle,
> processEvents() is called once before a processReplacing() call (if new events are available).


最後に、VST SDK中のminihostサンプルをもとにVSTiを呼び出すサンプルを作成してみましたが
波形は正常に生成されているようです。
http://www39.atwiki.jp/vst_prog/?cmd=upload&act=open&page=sample&file=host.zip

VSTiはこちらのページのものを利用しております。(ファイル名は変更しております。)
http://www39.atwiki.jp/vst_prog/pages/84.html

ご参考にされてみてはいかがでしょうか?

4328:2012/12/15(土) 01:14:06
管理人様

レスいただきありがとうございます。
お礼が遅くなりまして申し訳ございません。

>VstEvent構造体のdata[0]〜[3]はVstMidiEvent構造体のnoteLengthとなるかと思います。
なるほど・・ご指摘ありがとうございます。
(VstEvent*)&vst_midi_event;
このやり方で試してみることにします。

まだ解決していない状況でございまして、諸々調べている途中です。

進捗がありましたらご報告させていただければと思います。

4428:2012/12/15(土) 01:21:44
お礼が抜けておりました。
懇切丁寧にサンプルまで付記していただきましてありがとうございました。
こちらも現在参考にさせていただいております。

45管理人:2012/12/15(土) 14:40:38
>>28さん

確認不足で申し訳ありません。
>>42で作成したサンプルでSynth1を実行するとエラーとなりました。

確認したところいちいちAudioEffectXクラスのポインターを取得する必要は
なさそうです。

ですので当初のコード(http://codepad.org/m52oPA93)のように
> vsti->dispatcher(vsti, effProcessEvents, 0, 0, &vst_events, 0.0f);
という形で呼び出して問題なさそうです。

>>42のサンプルも修正いたしましたのでご参考までに。

4628:2012/12/16(日) 02:47:34
管理人様

ご丁寧にありがとうございます。
確かに手元で試していたところ、synth1だと処理落ちしてしまっておりました。
再度いただいたサンプルと同様の方法で試したところ正常に波形デーがが返って来るようになった感じがします。
ありがとうございます!

重ね重ねで申し訳ないのですがもう一点お伺いさせていただけますでしょうか。

サンプルの中で
for (VstInt32 processCount = 0; processCount < kNumProcessCycles; processCount++)
{
printf ("HOST> Process Replacing...\n");
effect->processReplacing (effect, inputs, outputs, kBlockSize);
}
という処理があるのですが、この意図するところがよく分からないのです。

kNumProcessCycles は5に設定されていますが、1回のprocessEventsの実行に対して
なぜ5回のprocessReplacingが必要になるのでしょうか。
この5という数字はどこから来ているものなのでしょうか。
(もしかするとVstEventsのMidiデータを実際音として鳴らした時の長さと関連があるのか?
などど考えております)

ご存知でしたら教えていただけますと幸いです。

47管理人:2012/12/17(月) 00:28:01
>>28さん

本来は1回のprocessReplacing()関数に対して1回のprocessEvents()関数を呼び出すべきかもしれませんが
今回のサンプルではイベント(ノートオンMIDIメッセージ)を最初にVST(Synth1)に渡した後は、とくにイベントが
ありませんでしたので省略いたしました。

本来であれば下記のようにすべきかと思います。
(このあたりもサンプルに反映させましたのでご参考までに。)

 if( ホストアプリからVSTに渡すイベントがあるか? )
 {
  // ホストアプリからVSTに対して渡すイベントを作成する。
  〜〜何らかの処理を行い、VstEvent構造体(仮にeventとする)を設定する〜〜

  // numEventsを1とし、eventsにイベントのポインタを格納する。
  evs.numEvents=1;
  evs.events[0] = (VstEvent*)&event;
 }
 else
 {
  // ホストアプリからVSTに対して渡すイベントはないので、
  // numEventsは0にする
  evs.numEvents=0;
 }

 // ProcessEvents()関数を呼び出し、VSTにイベントを渡す。
 effect->dispatcher (effect, effProcessEvents, 0, 0, &evs, 0.0f);

 // 波形をkBlockSize分生成し、outputsへ格納する。
 effect->processReplacing (effect, inputs, outputs, kBlockSize);

また、kNumProcessCyclesですが、おそらく生成される波形が短すぎるため、
何度かループで呼び出しているだけだと思います。
(サンプルはSteinbergのVST SDK付属のものをベースにしていますので
真意は分かりません)

processReplacing()関数は1回呼び出されるとkBlockSize分の波形を生成します。
サンプリング周波数44100Hzの場合、512サンプル分ですので約11ミリ秒の
波形を生成しますが、これでは生成された波形を確認しづらいため、
5回(つまり約58ミリ秒分)としているのだと思われます。

4828:2012/12/22(土) 23:24:09
>>管理人様

レスありがとうございます。
またしてもお礼が遅くなりましてすみません。

>また、kNumProcessCyclesですが、おそらく生成される波形が短すぎるため、
>何度かループで呼び出しているだけだと思います。
>(サンプルはSteinbergのVST SDK付属のものをベースにしていますので>
真意は分かりません)
>processReplacing()関数は1回呼び出されるとkBlockSize分の波形を生成します。
>サンプリング周波数44100Hzの場合、512サンプル分ですので約11ミリ秒の
>波形を生成しますが、これでは生成された波形を確認しづらいため、
>5回(つまり約58ミリ秒分)としているのだと思われます。

なるほど・・ご丁寧にありがとうございます。
管理人様のおかけで諸々の疑問点が解消されました。
正しい波形データが返ってくることも確認でき、ちょっとずつ前に進めています。

また書込さみせていただくことがあるかもしれませんがどうぞよろしくお願いします。
ありがとうございましたm(_ _)m

4928:2012/12/23(日) 12:36:10
>>管理人様

1点お聞きし忘れたのですが、
管理人様の開発成果物のvstiはどこかのページで公開されているのでしょうか。
http://www39.atwiki.jp/vst_prog/pages/43.html
こういったサンプルのページは見つけたのですが、
オフィシャルなダウンロードサイトのようなものは見当たりませんでした。
もしお在りでしたらぜひ拝見させていただきたいです。

よろしくお願いいたします。

50管理人:2012/12/23(日) 14:58:25
>>28さん

疑問が解消されてよかったです。

サンプルVSTですが、楽器として使えるほどのものではないので
DLLファイルは特にアップロードしていません。
VSTとして動かしたい場合はビルドしていただければよいかと思います。

VC++ プロジェクトの準備(下記URL参照)にしたがってプロジェクトを作成した後、
サンプルコード一覧(下記参照)でダウンロードしたサンプルをプロジェクトに追加すれば、
コンパイル・ビルドができるはずです。
コンパイル・ビルドができなければご指摘いただければと思います。

VC++ プロジェクトの準備
 No1. http://www39.atwiki.jp/vst_prog/pages/55.html
 No2. http://www39.atwiki.jp/vst_prog/pages/59.html
 No3. http://www39.atwiki.jp/vst_prog/pages/60.html
 No4. http://www39.atwiki.jp/vst_prog/pages/61.html
 No5. http://www39.atwiki.jp/vst_prog/pages/62.html

サンプルコード一覧
 http://www39.atwiki.jp/vst_prog/pages/43.html

5128:2013/01/02(水) 23:57:06
管理人様

あけましておめでとうございます。
レス頂きありがとうございます。
またもお礼が遅くなりましてすみませんでした。

上記了解致しました。
サンプルの方も拝見させて頂きます。

ありがとうございましたm(_ _)m
また書き込みさせていただくやもしませんが
よろしくお願いいたします。

52管理人:2013/01/03(木) 11:01:51
>>28さん

あけましておめでとうございます。
サンプルのほうも不明点等があれば
ご質問いただければと思います。

今後ともよろしくお願いいたします。

5328:2013/04/16(火) 14:17:44
管理人様

お世話になっております。
数ヶ月ほど前、色々と質問させていただきました28です。

簡易daw的なものを作っており、いただいたアドバイスのおかげもありまして
それになりに音を再生できるようになってきていますが、
また分からないことが生じたため質問させていただきに来ました。

vstiが返す波形データについてなのですが、
synth1が返す波形データをざっと眺めたところ -1.0〜1.0 の範囲で収まっているように見えました。
また
http://www13.plala.or.jp/kymats/study/MULTIMEDIA/waveOut_create.html


「16ビットの場合は、-32768〜32767 の範囲で振幅値を表現します。0 が中心(振幅なし)です。」

とあったので、
synth1から帰ってきたサンプルの値それぞれに 32768を掛け、-1を引くというやり方で
波形データを生成してみたのですが、
その波形データをwaveOutWriteで書きだして発音させる際、
音が大きかったり何音も重なっていたりすると音が割れることがあるのに気付きました。
調べてみると、最初はsynth1から返ってくるサンプル値は全部 -1.0〜-1.0に収まっていると思っていたのですが
実際にはたまに -1.0〜1.0に収まらない値 (1.01など)がsynth1から返ってきていることが分かり、
そのサンプルを発音させようとした際に音が割れてしまっているようでした。

そこで2点お伺いしたいのですが、
vstiは基本的に -1.0から1.0までの範囲での値しか返さないようになっているなどの決まりはないのでしょうか?
またvstiから帰ってきたデータを16ビット用のwaveデータに変換する際、
32768を掛けて-1するというやり方は何か間違っている気がするのですが、
他によい方法はありますでしょうか。

ご教示いただけると嬉しいです。
宜しくお願いします。

54管理人:2013/04/16(火) 21:20:15
お久しぶりです。

確認したところ、
「入出力の範囲が-1.0〜+1.0でなければならない」
という決まりはないようです。

私のサイトもSynth1作者のDaichi様のサイトを
非常によく参考にさせていただいており、
その中の一部の記載を勘違いしたものと思います。

また、16ビット用waveデータに変換する方法ですが、
波形データが-1.0〜+1.0であれば、32767を掛けるだけで
よいと思います。

(「32768を掛けて-1する」方法は単純に計算ミスがあり、
最低値の-1.0に対して上記計算を行うと、-32769になり、
16bit整数の場合は負のオーバーフローが発生します。)

VSTについての理解は私もまだまだのところがあり、
DAWとなるとほとんどわかりませんが、VSTやDAWなどにかかわらず
基本的に他者の作ったプログラムやモジュールなどを組み込む際は
「予期せぬ値が合った場合にどのように処理するか?」
が重要になってくると思います。

今回のように-1.0〜+1.0の範囲を超える可能性がある場合は、
掛ける値を30000程度にして余裕を持たせたり、
浮動小数点の値を適正範囲になるよう
「-1.0以下の場合は-1.0に、+1.0以上の場合は+1.0」
と条件処理を付け加えるとよいと思います。

5528:2013/04/21(日) 22:18:11
管理人様

こんばんは。

またしてもお礼が遅れましてすみません。
わかりやすくご丁寧な解説ありがとうございます。

上のレスを拝見させていただき色々と勘違いしていたのが分かりました。
>(「32768を掛けて-1する」方法は単純に計算ミスがあり、
これについてはお恥ずかしい限りです・・・汗

自分はそもそも、windows上では返って来た波形に必ず32768
をかけなければいけないのではないかと思っていました。
色々試してたところ 32768をかけても30000をかけても、1000しかかけなくても、
変わるのは音量だけで音の質は全く変わらないのですね。
かける数を変えると全然違う音色になってしまうのではないかと思っていました。
波形と音の関係性について理解が足りておりませんでした。

また少し音声のデジタル生成について理解が深まりました。
ありがとうございました。

また質問させていただくこともあるかと思いますが、よろしくお願い致します。

56管理人:2013/04/21(日) 22:59:21
>>28さん

無事解決してよかったです。
今後ともよろしくお願いします。

57<削除>:<削除>
<削除>

58<削除>:<削除>
<削除>

59<削除>:<削除>
<削除>

60名無しさん:2013/07/01(月) 03:17:08
初めまして。
趣味でVST作成を始めたのですが、
管理人様のサイトのおかげでなんとかプラグインを作成できるようになってきました。
ありがとうございます。

まだ、ここをご覧になっていらっしゃるかわかりませんが質問させてください。
現在、ステレオトラック2つを入力可能なVSTを作成しようとしています。、
最終的にはトラック1にかける処理をトラック2の信号の情報を使って決める
サイドチェイン搭載エフェクターのようなものを目指しています。

しかし、VSTがHost側から信号を受けとる仕組みがいまいち分からず、困っています。
現在は、Host側のセンドリターン機能を使って、トラック1にトラック2の信号を送っているのですが、
センドで送られてきたトラック2の信号をVST側ではどのように受け取ればいいのでしょうか。
また、上記の方法以外に何か良い実装法があればご教授いただけると助かります。

文章で説明するのが下手で支離滅裂になってしまって申し訳ありません。
もしご覧になっていたらご返信よろしくお願いいたします。

61管理人:2013/07/02(火) 01:05:54
>>60さん始めまして。
書き込みありがとうございます。
今のところほぼ毎日確認しておりますのでご安心ください。

サイドチェインはやったことが無いのでなんともいえませんが、
AudioEffectXを継承した自作クラスのコンストラクタでsetNumInputs()関数を呼び出すときの引数を
「4」にしてみてはいかがでしょうか?

setNumInputs()関数の引数を「4」にしてSonar 8.5 LEで試したところ、参考URLの
設定とほぼ同様のことができそうでした。
(何らかの信号処理をしたわけでは無いのであくまで可能性です。)

 参考:http://tandess.blog121.fc2.com/blog-entry-818.html

 実施内容:
  トラック1のエフェクターとして自作VSTを設定。
  トラック2のセンドに自作VSTの別入力を設定。

また、processReplacing()関数での音声処理は、インプットを4つにすればいいかと思われます。

void MySampleVST::processReplacing (float** inputs, float** outputs, VstInt32 sampleFrames)
{
  float* inL1 = inputs[0]; //入力 左用1(トラック1用。エフェクターに設定したときの入力?)
  float* inR1 = inputs[1]; //入力 右用1(トラック1用。エフェクターに設定したときの入力?)
  float* inL2 = inputs[2]; //入力 左用2(トラック2用。センドに設定したときの入力?)
  float* inR2 = inputs[3]; //入力 右用2(トラック2用。センドに設定したときの入力?)
  float* outL = outputs[0]; //出力 左用
  float* outR = outputs[1]; //出力 右用

  for (int i = 0; i < sampleFrames; i++)
  {
    //ここで何らかの音声処理を行う。
  }
}

私自身やったことがありませんのであくまで推測になります。
調べてみますが、もし結果がわかりましたら、教えていただけると助かります。

62管理人:2013/07/08(月) 00:30:02
>>60さん

遅くなりましたが、>>61の方法で簡単なサイドチェイン付きコンプレッサーの
サンプルを作成してみました。ご参考にしていただければ幸いです。

・サンプルコード ダウンロードページ
 http://www39.atwiki.jp/vst_prog/pages/43.html

不明点等がございましたら書き込みをお願いいたします。

6360:2013/07/10(水) 14:16:33
>>62
管理人様
先週は多忙でこちらを覗いておらず、お返事が遅くなってしまい大変申し訳ありません。
管理人様の方法で、私の環境でも4入力で動作させることができました。
サンプルコードまで添付していただき非常にわかりやすかったです。
この部分の実装で困り果てていたので、本当に助かりました!ありがとうございます!
しかし、入力数をいじるだけで内部で受け取ってもらえるのは意外でした。少し難しく考えすぎていたようです。

教えて頂くばかりで恐縮ですが、また何か疑問が生じたら質問させてください。
ありがとうございました!

64管理人:2013/07/10(水) 22:00:17
>>60さん
無事解決してよかったです。

各トラックからの入力方法については
ホストアプリケーション(Cuabase、Sonar等)ごとに
異なる可能性がありますのでご注意ください。

今回はSonar 8.5 LEで試しましたが他のソフトでは
どうなるかわかりません。
(もしSonar以外で試されて、成功していましたら、
成功したソフトをご教示いただけるとありがたいです。)

なお、サンプルコードのコンプレッサー(CComp::Run()関数)ですが、
計算式はおそらく間違っていますのでこちらもご注意ください。

ほぼ毎日確認しておりますので何かほかに疑問がありましたら
わかる範囲・できる範囲で答えさせていただきます。
書き込みありがとうございました。

65<削除>:<削除>
<削除>

6660:2013/08/19(月) 14:28:03
お久しぶりです。
昨月サイドチェインについて質問させていただいた者です。
別環境で動作させた結果、Reaper、CubaseLEでの動作を確認いたしました。
ご報告が遅くなってしまい申し訳ありません。
お陰様でVSTの制作捗っております。
最近は練習を兼ねていろいろなVSTを作成しています。

現在、FFTを用いた処理を実装しようと試みています。
手始めに単純に入力→FFT→IFFT→出力といったVSTを作成しているのですが、
単体で動作確認済みのFFTプログラムをVSTの処理として組み込むと
DAW側の動作が停止してしまうという問題に悩んでいます。

止まり方としては、音源が読み込まれ再生される前に動作が停止してしまいます。
何となくメモリの確保の仕方がまずいような気がするのですが、いまいち原因がわかりません。
VST開発で、メモリの確保などで気を付けなければならない点などがあるのでしょうか?
また、FFTを用いたVSTの作成経験がおありでしたら、似たような問題が起こった事がありましたでしょうか?

コードを直接張れればいいのですが量が多くなってしまうため張れず、
必然的に前回よりもさらに漠然とした答え辛い質問になってしまっていて大変申し訳ありません。
上記の問題に関して何か思い当たる点がありましたらご教授いただけると幸いです。

67管理人:2013/08/20(火) 00:15:47
>>60さん

情報ありがとうございます。

残念ながらFFTを用いたVSTは作ったことがありません。

コードを見ていないのでなんともいえませんが、
音源(自作VST)が読み込まれてから再生されるまでの間なので
コンストラクタでの処理に問題があるような気がします。

また、一般的な注意事項ですが、
DAWはマルチスレッドのプログラムですので、自作VSTを作成する場合も
頭に入れておく必要があります。

同じメモリ領域へのアクセスを禁止したり、
一定時間処理を返さない処理(たとえば、モーダルダイアログの表示など)には
気をつける必要があります。

最後に、直接関係無いとは思いますが、
processReplacing()関数では下記のような制限があるようです。
・引数のfloat** inputsおよびfloat** outputsはDAWによっては同じポインタが
 渡される可能性がある。
・processReplacing()関数は数ミリ秒程度で応答する必要がある。

もう少し情報があると何かいい答えがあるかもしれません。
よろしくお願いいたします。

68名無しさん:2013/08/20(火) 23:54:28
>>60さん

FFTを用いたVSTのサンプルを作成いたしました。
ご参考になれば幸いです。

・サンプルコード ダウンロードページ
 http://www39.atwiki.jp/vst_prog/pages/43.html
 (「その他」の一番下にあります。)

サンプルではFFTを1から実装する知識・時間がありませんでしたので、
Webで公開されている大浦氏のFFTパッケージを利用しています。
(再配布可能で、比較的簡単に実装できそうなためです。)

・大浦氏 FFTパッケージ
 http://www.kurims.kyoto-u.ac.jp/~ooura/fft-j.html

私がサンプルを作成した際に注意した点としては、
FFT処理を実行するためのバッファと出力用のバッファは
分けた点にあります。

processReplacing()関数内での処理は下記の通りです。

①入力信号(ここではsin波を生成しています。)をFFT用のバッファに保存。
 出力は出力用バッファの内容をコピー。
②FFT用バッファに一定量たまるとFFT/IFFTを実施。
 FFT用バッファと出力バッファをスワップし、FFT/IFFT処理をした結果を
 出力できるようにする。

 ※注意
  入力信号をバッファに保存しているため、遅延が生じます。
  遅延はバッファサイズに影響します。
  サンプル実行時は音量にご注意ください。

なお、大浦氏のFFTパッケージの利用方法は下記URLを参考にいたしました。

・みる きく 考える 進む - 大浦氏のFFTの使い方
 http://geisterchor.blogspot.jp/2011/04/fft_16.html

6960:2013/09/09(月) 17:19:46
管理人様

お返事が大変遅くなってしまい本当に申し訳ありません。
私生活が多忙になり、PCに触れる機会を作ることができず、
お返事できずにおりました。

フリーのFFTでここまで使い勝手がいいものがあることに驚きました。
版権もゆるく、さまざまな用途に使えそうで助かります。

管理人様のFFTサンプルを拝見して、自前のFFTが動作しなかった原因がわかりました。
入力をバッファーに入れずにポインタを直接渡して処理した結果、予期せぬ動作をしていたようです。
また、その他にもメモリの確保がうまくいっておらず、配列のサイズ外の領域を参照したり等、
いろいろなミスが発見できました。
本当に助かりました、ありがとうございます。

お礼が遅くなってしまったことを重ねてお詫びいたします。

70管理人:2013/09/09(月) 22:20:52
>>60さん

無事解決してよかったです。
FFTは窓関数やオーバーラップ処理など私自身、まだまだ勉強すべき点がありますが、
ご参考になれば幸いです。

これからもよろしくお願いいたします。

71<削除>:<削除>
<削除>

72<削除>:<削除>
<削除>

73<削除>:<削除>
<削除>

74<削除>:<削除>
<削除>

75<削除>:<削除>
<削除>

84lyood:2013/12/10(火) 18:04:16
管理人様、はじめまして。
VSTシンセを遊び半分で作り始めてせっかくならGUIをつけよう、ということで情報を探していたところこのサイトにたどり着きました。
GUIの解説、とても参考になっております。ありがとうございます。

ところで、GUI作りで行き詰ってしまったのでひとつ質問をさせてください。
Daichi様のサイトにある「MySynth」を改造しながらシンセを作っているのですが、

ホスト(DAW)を起動、シンセのGUIからパラメタの値をいじる
             ↓
ホストでプロジェクトファイルを保存
             ↓
ホストで上で保存したプロジェクトファイルを読み込む

とすると、音は保存したときの音が出るがGUIはデフォルトの値(初期値)にもどる
という現象が起こります。パラメタの値は保存/復元できているけれどGUIが更新されていない(または下手に更新されている)感じです。
これは、何か処理が足りないために起こるのでしょうか?逆に何か変な処理をしているためでしょうか?

表現力・情報不足ですね…ごめんなさい。。
本当はソースコードを書き込めばいいのでしょうがこれ以上長くなるのもアレなので...
ご教授いただけたらうれしいです。

85管理人:2013/12/11(水) 01:45:50
lyoodさん

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

私のGUIサンプル(下記)においてもGUIのノブやスライダーの値が0に戻ることを
確認しました。
(私のGUIサンプルの場合、パラメーターの値も保存されておりませんでした。)

 http://www39.atwiki.jp/vst_prog/pages/82.html
 http://www39.atwiki.jp/vst_prog/pages/83.html

同じ事象ではないので原因が異なるかもしれませんが、
おそらく、原因はVSTクラス(AudioEffectXを継承したクラス)で
getParametar()関数をオーバーライドしていないためだと思います。

私のサンプルではGUIクラス(AEffGUIEditor, CControlListenerを継承したクラス)の
open()関数でボタンなどを作成する際、VSTクラスからgetParameter()関数を使って
現在の値を取得します。

 150行目前後の下記コード
 【ノブの場合】
  knobVolumeL->setValue(effect->getParameter(MYVST_VOLUME_L));
 【スライダーの場合】
  sliderVolumeL->setValue(effect->getParameter(MYVST_VOLUME_L));

しかし、VSTクラスでgetParametar()関数がオーバーライドされていないため、
呼び出されても0を返すだけとなります。

そのため、GUIクラスのopen()が呼び出されるたびにノブやスライダーの値が
0に戻ります。

getParameter関数については下記を参考にしていただければと思います。

 http://www39.atwiki.jp/vst_prog/pages/44.html

86lyood:2013/12/11(水) 20:53:37
管理人様
詳しく丁寧、迅速な返答、ありがとうございます。

getParameter()関数はオーバーライドしておりました。(MySynthに最初から書いてあったのでそれを使っていた)
その後、デバックしてみたところ、

ホスト側のGUI呼び出し(GUIクラスopen()関数が実行される)
         ↓
open関数の中でGUIのつまみなどに値をセット(GUIクラスの各パーツクラス->setValue())
         ↓
ホスト側からプログラムのセット要求(VSTクラスのsetProgram())
ここでsetParameter的なことをしている

という流れだということがわかりました。
これでは当然GUIのほうは更新されないので、新しくGUIを更新するだけの関数を作って
VSTクラスsetParameter()関数から呼び出すようにしたところうまくいきました。
(具体的にはsetValue()やらsetText()をしているだけ)

なにせつまみの数が50を超えているので
もうちょっとコンパクトにしたかったのですが、私の知識ではこれが限界…

もっと参考になる書き方をできればいいのですがどう書いていいのかわからずです...

また何かあったらお世話になるかもしれません。重ねてありがとうございました。

87管理人:2013/12/13(金) 00:22:53
lyoodさん

あまり力になれず申し訳ありません。
また何かありましたらよろしくおねがいいたします。

88管理人★:2014/06/21(土) 07:02:05
「C++でVST作り」(http://www39.atwiki.jp/vst_prog/)の更新停止について

本掲示板のもととなっている@wikiのサイト「C++でVST作り」の管理パスワードを
紛失したため、管理・更新を行うことができなくなりました。
よって「C++でVST作り」の更新につきましては停止とさせていただきます。

なお、@wikiの規約上、長期のログインが無い場合、上記サイトは削除される可能性あるとのことです。
移転先サイトも検討しておりますので、詳細は決まり次第記載させていただきます。

91管理人★:2014/06/22(日) 16:18:48
http://vstcpp.wpblog.jp/に移転予定です。
コンテンツについては整理しながら1から作り直しています。

92一条あかり:2014/07/23(水) 13:10:50
はじめまして、最近vst開発に挑戦し始めた一条あかりと申します。
FFTやoffline処理に興味を持って四苦八苦しておりますが、いいプラグインができればと思っています。

サイトのほうを再構築されるとのことで、応援しております!

93管理人★:2014/07/23(水) 23:06:55
一条あかりさん

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

平日の更新がなかなか難しく、再構築は進んでおりませんが、
応援いただきまして、非常にありがたく思います。

最低週1回は更新しようと考えておりますので、少し時間がかかるかと
思いますが、よろしくお願いいたします。

FFTやoffline処理についてはほとんど知識がありませんが、
技術的なお話は大好きですので、不明点がございましたら、
ご協力できることがあるかもしれません。

今後ともよろしくお願いいたします。

94でぇあ:2014/08/22(金) 12:11:31
こんにちは。でぇあと言います。
このようによく纏まったサイトを参考にさせて頂けるのは本当に助かります。ありがとうございます。
新サイト構築の方も期待しています。

さて本題ですが、毎秒GUIをを更新するサンプルをビルドしようとすると、以下のようなエラーが出ます。

1>MyVSTGUI.cpp(143): error C2259: 'VstGui' : 抽象クラスをインスタンス化できません。
1> 次のメンバーが原因です:
1> 'void CControlListener::valueChanged(VSTGUI::CControl *)' : は抽象型です
1> C:\VST3 SDK\vstgui.sf\vstgui\vstcontrols.h(105) : 'CControlListener::valueChanged' の宣言を確認してください。

もし何が問題なのかわかるようであれば教えて頂けないでしょうか。
よろしくお願い致します。

95管理人★:2014/08/22(金) 23:19:49
でぇあさん

書き込みありがとうございます。
VSTのGUIクラスを定義していると思いますが、メンバー関数の中に
valueChanged()関数がないのではないでしょうか?

VSTのGUIクラスを定義する際はvalueChanged()関数を
必ず継承しなければなりません。

下記サンプルコードの51〜54行目のように、空の関数でもいいので
定義しておく必要があります。

http://www39.atwiki.jp/vst_prog/pages/93.html

96でぇあ:2014/08/23(土) 13:47:18
管理人様

サイトを拝見しながらプロジェクトを最初から構築し直した所、ビルドがうまくいきました。
どうやら、vst2.4でなくvst3のSDKのプログラムを使ってしまっていたのが原因だったようです。
些細な事で質問してしまって申し訳ありません。
回答して頂いてありがとうございました。

97管理人★:2014/08/24(日) 12:04:47
でぇあさん

無事解決してよかったです。
今後ともよろしくお願いいたします。

98猫十:2015/06/19(金) 11:57:00
はじめまして
いつも拝見させていただいています。
とても貴重な情報をありがとうございます。

旧サイトの「毎秒GUIをを更新するGUIのサンプル」をビルドして
DAWにロードしてみたところ0からカウントアップが始まりました。
ここでふともう1つ同じものをロードしたところ先にロードしたものと同じ値からカウントアップが始まりました。
(後からロードしたものは先のとは別に0からカウントアップするものだと思っていました。)

ソースコードに同梱されていたビルド済みのMyGuiVST5.dllでも同じ現象が起きました。
ここで質問なのですが、ロードしたプラグインごとにカウンタが独立して動作するようにしたい場合はどうすればよいのでしょうか?

99管理人★:2015/06/20(土) 14:18:42
猫十さん

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

VstGui5::idle()内にある変数iがstaticで宣言されているため、
全DLLで共通の変数iを参照することになります。

解決するには変数iをクラスのメンバー変数として定義すればいいと思います。
修正版を下記作成いたしましたのでご参考にしていただければと思います。

 http://vstcpp.wpblog.jp/?page_id=776

 変更点
  ・VstGui5クラスのメンバ変数として「int i;」を定義
  ・VstGui5クラスのコンストラクタで「i = 0;」でiを初期化
  ・VstGui5::idle()関数内の「static int i = 0;」をコメントアウト

サンプルについてはマルチスレッドプログラミングをほとんど意識せず作成していますので、
他にもこのようなことが発生するかもしれません。

100猫十:2015/06/21(日) 03:40:09
管理人様

早速のご回答ありがとうございました。
ご指示頂きました点を変更したところ
複数起動時に独立してカウントアップしましたのでご報告させて頂きます。
マルチスレッドプログラミングに慣れた方なら
尋ねるまでもなかったような件を質問してしまいましてお恥ずかしい限りです・・・


さて大変恐縮なのですが
別件について再び質問させていただきたく存じます。

VSTにおけるパラメータの取り扱いなのですが、
例えば整数で-24〜+24を動くようなパラメータや
7段階切り替えスイッチなどのパラメータの場合はVST開発上はどのように扱うべきでしょうか?

元値→計算してfloatに変換→getParameterで取得→計算して復元、の流れでやってみたものの
端数が出たりして復元後のGUI表示の際の条件分岐や
さらにその後のGUI操作を経てsetParameterでAudioEffectX側に再度渡す際に不都合が生じてしまっています。
これを現状の変換&復元のやり方のまま力技で解決すべきなのか
それとももっと違うやり方があるのかでつまづいております。

もしよろしければどのようなやり方が望ましいのかご教示いただければ幸いです。

101管理人★:2015/06/21(日) 11:16:45
猫十さん無事解決してよかったです。

望ましいやり方…というのはプログラムの書き方はいろいろあるので
正直わからないです。

私は下記のような方法で実装しています。
(7段階切り替えスイッチの例)

■AudioEffectXを継承したクラス(以下VSTクラス)側の処理
1)まずパラメーター用のメンバー変数を定義する
 【例】
  int switch7;

2)VSTクラス setParameter()関数で渡される値を
 パラメータ用に変換
 【例】
 case 0:
  switch7 = (int)(value * 7.0f);
  break;

3)同様にVSTクラス getParameter()関数で返す値を
 0.0〜1.0に変換
 【例】
 case 0:
  return ((float)switch7) / 7.0f;
 
■AEffGUIEditor, CControlListenerを継承したクラス(以下GUIクラス)側の処理
1)GUIクラス setParameter()関数で渡される値を
 7段階にする
 【例】
 case 0:
  // 0.0f 〜 1.0fの7段階に調整
  value = floor(7.0f * value) / 7.0f;

  // 値をノブに設定
  knob->setValue (value);

  // VSTクラス側に値を引き渡し。
  effect->setParameterAutomated(index, value);


-24〜+24の整数パラメータも-24から始まる48段階のスイッチと
考えれば同じ処理で実装できると思います。

102猫十:2015/06/23(火) 03:50:42
管理人様

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

早速管理人様の手法を試してみたところバッチリ動きました。
私のへんなやり方より全然いいのでまとめて修正しようと思います。

私自身「これでいいんだろうか?」の繰り返しでVSTプラグインを書いてまして
何かやるたびに壁にぶつかってる次第です。

また書き込みさせていただくかと思います。
その際は何卒よろしくお願いいたします。

103管理人★:2015/06/24(水) 00:17:52
猫十さん
こちらも無事解決してよかったです。

ご質問や指摘は大歓迎ですので
これからもよろしくお願いいたします。

104専門学生:2015/08/10(月) 15:57:22
初めまして
こちらに記載されてたソースコードをお借りしてサンプラーのVSTを作成しようとしています。
WindowsApiで音源を取得することはできるのですが、音源を格納する方法がわかりません
どうすればいいですか。

105管理人★:2015/08/12(水) 01:21:30
専門学生さん

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

いただいたご質問について不明な点がございますので、下記について確認させてください。

 ・WindowsAPIはどのような関数を利用しているのでしょうか?

 ・"音源"とは何でしょうか?
  (.wavや.mp3等から取得した音声信号(波形)のことでしょうか?)

 ・"格納する"というのはどうしたいのでしょうか?
  ("音声信号をバッファに格納したい"という意味でしょうか?)

106専門学生:2015/08/12(水) 11:06:19
返信ありがとうございます。
情報が不足していてごめんなさい。

ifstreamを使ってます。

音源はwavのことです。

音声信号をバッファに格納したいということです。

お手数をお掛けします。

107管理人★:2015/08/12(水) 21:58:11
専門学生さん

単純に「wavファイルを読み込みたい」ということのようですね。

説明できなくはないのですが、すでに多くのサイト様で記載されている情報ですので、
「wav 読み込み C++」といったキーワードで検索していただければと思います。

なお、他のサイト様ではwavファイルのフォーマットを理解していることを前提としていることが
多いようですので、合わせて「wav ファイルフォーマット」で検索し、wavファイルフォーマットを
理解しておくとよいと思います。

wavファイルを読み込んだ後、VST上で動作させる上で不明な点がございましたら、
再度 ご質問いただければと思います。

ちなみにifstreamはWindows APIではなくC++標準ライブラリですのでお間違いなく。

108猫十:2015/08/14(金) 13:55:06
先日はお世話になりました。
ちょっと便乗なのですが、
管理人様のVSTiのサンプルの発音部分をwav波形直読みにするにはどうすればよいでしょうか?

・wavは5秒程度のピアノ波形
・MIDIノート0から127ので10個くらいのマルチサンプル
・wavは差し替え無しで組み込んだまま(リソースとして組み込む?)
・それ以外は変更なし(サンプルのフィルタ部、アンプ部、同時発音数などはそのまま効果が出るように残したい)

こんな感じで管理人様のサンプルを改造してみようと思っています。
質問ばかりですみませんがよろしくお願いいたします。

109管理人★:2015/08/14(金) 20:12:15
猫十さん

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

私のVSTiサンプルは「http://www39.atwiki.jp/vst_prog/pages/84.html」だと
思いますので、これをを前提として簡単に説明させていただきます。

■MySynthSampleVSTのコンストラクタ
 まず、wavファイルから波形をすべて読み込む。
 読み込みを行うのはファイルでもリソースからでもどちらでもよい。

 次にMIDIノートと再生すべき波形の対応テーブルを作成する。
 対応テーブルは下記のような情報を持つ。
  MIDIノートNo69(A5)の時 … 波形1(440Hz)をそのまま再生
  MIDIノートNo70(A#5)の時 … 波形1(440Hz)を466.2Hzになるように早送りで再生
  MIDIノートNo71(B5)の時 … 波形1(440Hz)を493.2Hzになるように早送りで再生
    :
  MIDIノートNo81(A6)の時 … 波形2(880Hz)をそのまま再生
    :

 ※読み込むwavファイルが固定のためコンストラクタで読み込んでいる。
  サンプラーのように途中で読み込みが必要な場合は読み込みスレッド等を作成する必要あり。

■MySynthSampleVST::onMidiKeyOn()
 OFF状態のオシレータをONにする際に、波形の対応テーブルの情報(使用する波形と再生速度)を
 オシレータに渡すようにする。
 (オシレータに波形の対応テーブル情報引き渡し関数等を追加する必要あり。)

■CVoice::amplitude()
 まず、経過時間から波形の読み込み位置を計算する。
 読み込み位置は、
  経過時間 × (再生したい周波数 ÷ 波形自体の周波数)
 で求められる。
 例えば、波形1(440Hz)で466.2Hzとなるように再生するには、
  経過時間 × (466.2 ÷ 440)
 となる。

 読み込んだ波形は配列に保存されていると思うので計算した読み込み位置が整数でない場合、
 切り捨てたり前後の値から補完する。
 なお、経過時間が波形のサイズより長い場合は0を返す。


Waveテーブルシンセサイザにするには上記のような手順となります。

なお、wavファイルをリソースにするにはrcファイルとヘッダファイルを作れば
リソースに出来ますが、読み込みの部分で一工夫必要となります。
まずはwavファイルで試してみることをお勧めいたします。
(FindResource()やLockResource()等を使う必要が出てくると思います。)

お盆のため、すぐに確認できず記憶で書いている部分があります…
間違いがある可能性がありますが、ご了承ください…

不明点がございましたら再度 ご質問いただければと思います。

110専門学生:2015/08/15(土) 14:56:23
管理人さん。


先日は返信をありがとうございました。書き込みをさせていただいた際、説明不足があり、お手数をかけてしまってすみませんでした。
詳しい内容を再度記述いたします。

現在、此方のサイト様のmythynthSamleVSTのソースコードをお借りしてサンプラーのVSTを作成使用と考えております。
wavの音源ファイルを読み込もうとしていて、ifstreamのライブラリを使用してwavファイルを入れ込む方法を見つけました。
その際に入れ込んだwavのサンプリングレート等の表示、変更することができるようになりました

ですが、mytynthsampleVSTのprocessreplacingのInputs[]の中にPCMを入れ込むとうまく回ると考え、for文でまわしたところ、エラーはないもののDAWが応答なしで止まってしまいました。
現在そこで頓挫してしまい、質問をさせていただきました。

その際に利用したソースコードがprocessreplacingの最初に
WAVE wav1;
WAVE_FORMAT fmt1;
vector<short> ch1;

//ファイルから読み込み
wav1.load_from_file("C:/Users/k012c1117/desktop/ositeru.wav");

//フォーマット情報とデータを取り出す
fmt1 = wav1.get_format();
wav1.get_channel(ch1, 0);
for (long i = 0; i<wav1.data_size; i++){
inputs[0, i] = (float*)ch1[i];
inputs[1, i] = (float*)ch1[i];
outputs[0, i] = (float*)ch1[i];
outputs[1, i] = (float*)ch1[i];
}
を追加したものです。

何度も質問ばかりして申し訳ございませんが 回答をお願いいたします・・・。

111管理人★:2015/08/15(土) 20:17:01
専門学生さん

load_from_file()関数はおそらくwavファイルを読み込む関数だと思います。

processReplacing()関数は数十ミリ秒ごとに何度も呼び出される関数のため、
load_from_file()関数をprocessReplacing()関数の中で呼び出すと、
数十ミリ秒間隔で何度もwavファイルへアクセスすることになります。

これにより作成したVSTiから応答が返らなくなり、結果としてDAW側で応答が
なくなるものと考えられます。

対応としては
 1.事前にコンストラクタ等でwavファイル読み込む
 2.wavファイルの読み込みを別スレッドで行う
が考えられます。

不明点がございましたら再度 ご質問いただければと思います。

なお、コードの中で気になった点がありましたので記載させていただきます。
 ・inputs[]は入力信号が入ったバッファなので、値を代入するのはまずい
 ・short型のch1[]をそのままinput[]、output[]に代入しているが
  -1.0〜1.0の範囲に変更するのが望ましい。
 ・for分の中で、iを波形データのサイズ(wav1.data_size)までとしているが、
  output[]やinput[]の配列サイズよりwav1.data_sizeが大きい場合、
  メモリ破壊につながるので、小さいほうに合わせるほうがよい。

112管理人★:2015/08/19(水) 01:15:22
専門学生さん

あれから少し確認しましたが別スレッドを使用しなくても、「ファイルの非同期読み込み」でも
wavファイルを読み込むことは対応できそうです。

Windows APIのReadFile()関数とGetOverlappedResult()関数を使い、
読み込み状態の管理を行うようプログラムすれば読み込めます。

サンプルについては作成してみようと思いますが、
去年の末からずっと忙しく、なかなか時間が取れないため
いつになるかはわかりません。

以上よろしくお願いいたします。

113管理人★:2015/08/30(日) 02:43:05
専門学生さん
猫十さん

遅くなりましたが、「wavファイルを非同期読み込みする方法」と「WAVEテーブルシンセサイザー」の
簡単なサンプルを作成いたしました。ご参考になれば幸いです。

・サンプルコード ダウンロードページ
 http://vstcpp.wpblog.jp/?page_id=776

 ■wavファイル非同期読み込み 
   20150829_MyWavTableSynthVST.zip

 ■WAVEテーブルシンセサイザー
   20150829_MyAsyncFileLoadVST.zip

114専門学生:2015/09/17(木) 12:32:51
管理人さん、
大切お時間いただいて、お返事とソースコード作成ありがとう存じます。
ソースコードをお借りして、読み解きと実装を試みてみます。

丁寧にご説明いただいてありがとうございました。
またわからなくなったらお邪魔するかもしれませんがその際にはよろしくお願いいたします。

115管理人★:2015/09/17(木) 23:44:14
専門学生さん

参考になればと思います。
またよろしくお願いします。

116<削除>:<削除>
<削除>

117管理人★:2015/10/01(木) 19:20:55
ヒーローゲーマーさん

創作小説は当サイトの掲示板とは無関係です。
他の掲示板等にもスパム的に投稿されているようなので削除いたしました。

続けるようであればブロック等の必要な処置をいたします。

118sym:2016/05/23(月) 14:59:29
「C++でVST作り」を拝見させていただいております。
日本語で解説されたサイトが少ないので重宝しております。ありがとうございます。

一点質問させていただきたいのですが、
以前作ったVSTプラグインを改良するため、新たにパラメータの数を増やそうとしているのですが、
増やした新しいパラメータの標準値が、コンストラクタでの初期化の値にかかわらず0.000000になってしまう現象に見舞われてしまいました。
前に作ったVSTとの互換性を保ちたい場合、新たに増やすパラメータは値が0.000000のときに前のバージョンと同じ挙動をするようにすること以外に方法はないのでしょうか。

動作確認に使っているVSTホストはACID Music Studio 10.0で、調べてみるとどうやら前のVSTに存在しなかったパラメータについても
プロジェクトファイルを開いたタイミングでsetParameter関数が設定値0.000000で呼ばれているようです(コンストラクタ内では値は1.000000で初期化しています)。

何か方法があれば教えていただけるとありがたいです。よろしくお願いします。

119管理人★:2016/05/25(水) 07:28:37
symさん
書き込みありがとうございます

詳しくはわからないのですが、
setChunk()、getChunk()関数あたりを使えばうまくできるかもしれません。
(VST SDK 2.4の場合です。)

setChunk()、getChunk()関数はVSTプラグイン独自のパラメータ形式で
保存したい場合に使用する関数です。

setChunk()、getChunk()関数をオーバーライドし、
「自作VSTのパラメーター + バージョン情報」を保存しておけば、
自作VSTのバージョンに合わせて前バージョンから値を引き継ぐパラメータと
初期化するパラメーターで分けれるのではないかと思います。

詳しい使い方は正直わからないので私もこれから試してみます。
何かわかればお伝えいたしますが、少しお時間をください。

120管理人★:2016/05/28(土) 10:18:44
symさん

setChunk()、getChunk関数の使用方法がわかりましたので
サンプルソースコードを下記にアップロードしました。

・サンプルコード ダウンロードページ
 http://vstcpp.wpblog.jp/?page_id=776

 ■ファイル名
   20160528_MyChunkTestVST.zip

setChunk()、getChunk関数をオーバーライドするとともに
コンストラクタでprogramsAreChunks()を呼び出す必要があります。

>>119で書いたように「自作VSTのパラメーター + バージョン情報」を
保存しておけば、実装できると思いますので一度試していただけますでしょうか?

121sym:2016/05/30(月) 22:19:21
>>120
管理人さん

まさかサンプルまで作っていただけるとは、非常に助かります!
今から試してみて、また書き込ませていただきます。ありがとうございます。

122sym:2016/05/31(火) 11:15:38
管理人さん

作っていただいたサンプルをもとに試したところ、
希望通りの挙動をしてくれるようになりました。
丁寧にコメントを付けてくださっていたので助かりました。

programsAreChunks関数を呼んでいない状態のVSTで作られたfxpファイルやDAWのプロジェクトファイルを
programsAreChunksでtrueとした状態のVSTで読み込む際は、どうやらsetChunk関数が呼び出されないようだったので、
今回のバージョンに限ってこれをもとにChunkを使っていない旧バージョンであるかどうかを判定することにしました。
ご教示いただいたとおり見えないパラメータとしてバージョン情報を書き込むようにしたので、次回バージョンからそちらでバージョン判定をしようと思います。

サンプラーでのファイル名であったり、Glitchなど可変長のデータを扱うようなVSTをいくつか見てきてこれまで疑問に思っていたので、そういった点でも非常に参考になりました。
今回はありがとうございました。

123管理人★:2016/05/31(火) 20:34:54
symさん

無事解決してよかったです。
また何かありましたら可能な範囲で調べてみます。

124名無しさん:2017/03/17(金) 23:39:29
https://www39.atwiki.jp/vst_prog/pages/79.html

こちらの CMidiMsgの addMidiMsg と getMidiMsg の処理中での キュー処理 問題があるのでは?
add add get get add get の順に呼び出すと、未格納なバッファにアクセスすることになるかと思います。

125管理人★:2017/03/20(月) 02:13:38
>>124さん
ご指摘ありがとうございます。

たしかにaddMidiMsg()の途中でgetMidiMsg()を呼び出すと
何が格納されているか分からない領域にアクセスしますね…
(buf[]領域内なのでVSTが落ちるようなことはないと思いますが…)

VST2.4だと「processEvents()→processReplacing()」の順に呼び出され、
基本的には「clearMidiMsg()→addMidiMsg()×n回→getMidiMsg()×n回」
の順になるのであまり問題はないと考えています。

本来なら修正すべきですが、少し手間なのでそのままにしたいと思います。
他のアプリでCMidiMsgクラスを流用する場合は修正する必要があります。

126らいか:2017/09/21(木) 14:35:57
初めまして。
ここ数日このサイトにお世話になっているVST初心者です。

質問なのですが、管理人さんが作成した手順「VST3.6勉強中 2 – VST3作成の準備」から「VST3.6勉強中 6 – VST3プラグインのパラメーター実装方法2」までを実装し、
processor.cppのtypeに自分で新たに作成したものを追加しながらVSTを学んでいたのですが、先日ソースを弄り、ビルドを行いVST3PluginTestHostで動作を確認しようとしたところ、
急にVST3PluginTestHostでファイルを認識しなくなってしまいました・・・

手順通りプロジェクトを作成しなおしてみたのですが、結果は同じでした。辛うじてVST3PluginTestHostが読み込んでくれるVSTファイル(VST3.6勉強中 6 – VST3プラグインのパラメーター実装方法2まで実装したもの)が見つかったので、
それと作成しなおしたVSTファイルと比較ツールにかけたところ、ある程度書かれている内容は同じなのですが書かれているアドレスが異なっていることファイルになっていました・・・

コンパイル自体は通っているのですが正しいVST3ファイルとしてホストに認識されていない状態です。また自分で追加していた内容もVST3ファイルがきちんとホスト側で認識されていた時は問題なく動いたので、
プロジェクトの環境を無意識に弄ったのかもしれませんがお手上げ状態です

とりとめのない質問で申し訳ないのですが、よろしければ管理人さんのお力を貸してください

使用している環境は
win10
Visual Studio2015
VST3.6.7(最新版)
です

127管理人★:2017/09/21(木) 21:59:29
らいかさん

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

考えられるのは
 何かの拍子にビルドがDebugからReleaseになってしまった
ぐらいです…

他に何か思いつけば再度返信させていただきますが、
いただいた状況になったことがないので、原因については正直わからないです…

あまりご協力出来ず申し訳ありません。

128らいか:2017/09/22(金) 09:41:22
>>127 管理人さん

おはようございます。

SDK等使用したソースをDLしなおして解決できました!
原因はVST3_SDKのdllmain.cpp内の
extern bool InitModdule();
extern bool DeinitModule();
をコメントアウトしてました・・・

SDKからコピーしてソースファイルを使用していたつもりでしたが、どうやらコピー元のSDKを取り込んで作業を行っていたみたいです・・・(そりゃ作り直してもおかしいわけだ)

その後色々見なおしていたところ、factory.ccp(20141209_vst3版)のDLLファイルの初期化、終了関数のコメントを歪曲して理解していたらしく、
基本的に何もする必要がない→何もしていない→必要ない っと理解してコメントアウトしたみたいです(だんだん思い出してきた)

最近鎮痛剤を服用しているのでそのせいで半分寝ぼけてコード弄ってたんでしょうね・・・

ともあれお騒がせしました<(_ _)>

VST関係の日本語の情報が少ないためまたお世話になると思いますがその時はよろしくお願いします!

129管理人★:2017/09/22(金) 20:44:00
らいかさん

無事解決してよかったです。

http://vstcpp.wpblog.jp/?p=694 に記載している内容が
おそらく最小構成なので2つの関数を消してしまうと
確かに動かなくなりますね…

いろいろ試すのはいいことだと思います。

私は最近別のことに興味を持っており更新が滞っていて申し訳ありません。
内容的に不十分な点(パラメーターの保存方法やGUIがない 等)がありますので、
引き続きご質問いただければわかる範囲で答えさせていただきます。
(場合によってはサイト更新もいたします。)

130Low:2017/10/20(金) 03:44:24
初めまして。ここ最近サイトの方を拝見させていただいています。

VST3.6.7を使っているのですが、VST3の基本ライブラリの作成、というところで、
base_vc10.vcxprojや、それに近い名前のファイルが見当たりません。
VisualStudio2017を使用しているのですが、
この場合、どのようにして、基本ライブラリを作成すればよろしいでしょうか?

ご協力いただけると助かります。よろしくお願いします。

131管理人★:2017/10/20(金) 22:36:00
Lowさん

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

下記に記載している基本ライブラリ作成の手順は
3.6.0での手順となっています。

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

3.6.7ではまず「CMakeLists.txt」をもとに
プロジェクトファイルを作成するところから始まるようです。

私も今から試すのですが、
おそらく手順としては下記になります。

 http://www.wakayama-u.ac.jp/~chen/cmake/cmakecxx.html

上記のツールはここからダウンロードできるようです。

 https://cmake.org/download/

私も試したことのないやり方です。
上記のサイトからダウンロード等する際は十分ご注意ください。

何かわかりましたら改めてご連絡いたします。

132Low:2017/10/21(土) 00:50:42
ご返信ありがとうございます。
今、試してみています。

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)を使用する必要がある

134Low: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日の時点では生きているようです。)

137Low: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
霧林さん

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

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

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

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

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

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

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

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

155SNRER: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);
}

159SNRER: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を使うのはあまりいい方法ではないと思います。

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

161SNRER: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で更新する方法でも問題なさそうです。

163SNRER: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を作れる方法のようです
バインディングというのは、
 「マウスでコントロール(ノブなど)を作っても自動で割り当てしてくれる」
という意味だと私は理解しています。

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

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

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

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

166SNRER: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

168SNRER: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をセットし、
  パラメータの更新を通知している可能性があります。
  (たぶんこの可能性はないと思いますが…)

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

170SNRER: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クラス)の更新方法のようです。
ご参考までに。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

177SNRER: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だとたしか動きません…。
機能追加した結果等を教えていただけると幸いです。

183猫十:2018/06/29(金) 03:46:30
WavetableSynthとAsyncFileLoadのサンプルありがとうございます。
すっかりご無沙汰してしまい、大変恐縮しております。

3.6.10への移行はちょっと保留にしまして(汗)、遅ればせながらGUI有りの拙作にWavetableSynthとAsyncFileLoadを混ぜる形で組み込んでみています。
WavetableSynthとAsyncFileLoadの信号処理部が相互に干渉しない形でなら混ぜ合わせはできたのですが、
wavbufをsetWaveして打鍵に沿わせようとすると途端にうまく行きません。

現状は添付のtest.wavをwavbufに読み込ませた後にfloatに変換したものと取得したサイズ(51528)をsetWaveに渡しています。
もしよろしければこのあたりの手順についてご教示いただければ幸いです。
何卒宜しくお願いいたします。

184管理人★:2018/06/29(金) 21:15:13
猫十さん

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

昔のコードなので読み返しながらになりますが、作られたプログラムの処理の流れや
setWave()等に渡している引数等を教えていただけると助かります。

また、「うまく行かない」というのはどういう状況なのかも教えてください。

185猫十:2018/06/30(土) 00:22:25
管理人様

お世話になります。猫十です。
ご返信ありがとうございます。

現在の手順なのですが、

コンストラクタで管理人様のtest.wavを読み込んだ後、

>wavbuf = new short[wavsize];
のあとに
f_wavbuf = new float[wavsize];
としまして、

>memcpy_s(wavbuf, wavsize * sizeof(short), buf + sizeof(MyWAVEHEADER), wh.datasize);
のあとに


for (int i = 0; i < wavsize; i++)
{
f_wavbuf[i] = (float)(wavbuf[i]) / 32768.0f;
}
こんな感じでfloatに変換し(汗)
これでkeytableに紐づけできる状況が整ったと(私が勝手に)判断しまして、

for (int i = 0; i < 128; i++)
{
keytable[i] = f_wavbuf;
}
としてます。

setWaveは

onMidiKeyOnで

cvoice[i].setWave(keytable[noteNo], wavsize, 44100.0f / wavsize);

のようにしてます。

この状況で鍵盤を弾くと打鍵に合わせて音階付きでノイズが鳴ります。

以上が現在の流れです。

お手数をおかけいたしますが何卒よろしくお願いいたします。

186管理人★:2018/06/30(土) 10:38:51
猫十さん

2.4の環境がもうないので試せていませんが
onMidiKeyOn()でsetWave()の第3引数を、440.0fぐらいで
試していただけますでしょうか?

 cvoice[i].setWave(keytable[noteNo], wavsize, 440.0f);

187猫十:2018/06/30(土) 13:21:52
管理人様

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

さっそく試してみました。

...ドラム鳴ってます(驚)
打鍵(NoteNo=60)で再生速度こそオリジナルと違いますがドラムが聴こえてきます。
NoteNoに追従して再生速度も変わっています。

ありがとうございます!

ちなみにこれはどういうことなんでしょうか?
もしよろしければぜひご教示いただきたく存じます。

188管理人★:2018/06/30(土) 13:51:02
猫十さん

無事解決してよかったです。

setWave()の第3引数は単純な「サンプルレート÷サイズ」ではなく「波形データ自体の音程(周波数)」になります。

今回のように「44,100÷51,528」とすると波形データの周波数は「約0.85Hz」となるので
例えばA4の音(440Hz)で鳴らそうとすると、517倍(440Hz÷0.85Hz)のスピードで波形データを
再生することになります。

MyWavTableSynthサンプルプログラムは「波形データサイズ=1周期分」なので
単純に「44,100÷8」で周波数(=5,512Hz)を計算していますが、wavファイル等から波形データを読み込んだ場合、
「波形データサイズ=1周期分」とならないので、別途指定してあげる必要があります。

 // 第三引数の周波数を設定するにはwavファイルが何Hzかあらかじめ調べておく必要がある。
 (onMidiKeyOn()のこの部分のコメントです。改めてみると分かりにくいコメントで恐縮です。)

今回はリズム音だったのでピッチ自体が不明なため、とりあえずA4キーを押したときに
そのまま再生されるよう440Hzとしました。
ピアノ等の音程のあるwavサンプルの場合はその音程に合わせた周波数を設定すれば大丈夫だと思います。

189猫十:2018/06/30(土) 22:28:26
管理人様

お世話になっております。

こちらこそサンプリング周波数とデータサイズの関係に考えがいたらず、お手数をおかけいたしました。

まだまだ課題は山積みですが引き続き頑張ります。
またお尋ねさせていただくこともあるかと思いますが何卒よろしくお願いいたします。

190猫十:2018/07/15(日) 22:14:17
管理人様

こんばんは。
またまた書き込み失礼します。

2.4でWAVファイルを読み込むサンプラーもどきを作っています。
VSTクラス(AudioEffectX)で読み込んだWAVファイルの情報を文字列としてGUIクラス(AEffGUIEditor)に送りたいのですが方法がわかりません。

VSTクラス(AudioEffectX)とGUIクラス(AEffGUIEditor)間で相互に文字列を受け渡すにはどうすればよいのでしょうか?

いつも質問ばかりですいません。
何卒よろしくお願いいたします。

猫十

191管理人★:2018/07/16(月) 13:53:10
猫十さん

2.4ではやったことがなく、すでに開発環境もないので試せませんが、
下記の方法で出来るのではないでしょうか?
(コードのイメージは全角スペースになっているのでご注意ください。)

①音声処理クラス側(AudioEffectXを継承したクラス側)で文字列を受け取る関数を定義する

class MyVST : public AudioEffectX
{
public:
  // 引数の文字列 fileをメンバー変数のfilepathに設定する関数
  void setFilePath(char* file) { strcpy(file, filepath); };

  〜〜以下略〜〜
protected:
  char filepath[256]; // ファイルパス用の文字列
};

②GUIクラス(AEffGUIEditorを継承したクラス側。MyGUIとする)で
 CTextEditコントロールなどから文字列をうけとった際に通知する処理を追加する

void MyGUI::valueChanged (CDrawContext *pContext, CControl *pControl)
{
  // どのパラメーターが操作されたかを取得する。
  VstInt32 index = pControl->getTag();

  // 操作されたパラメーターを確認。
  // ファイル名入力用のパラメーターなら音声処理クラスに文字列を渡す
  if ( index == MYVST_FILENAME )
  {
    char filepath[256];

    // テキストエディットから文字列を取得
    // (SDK 2.4のテキストエディットの文字列の長さは256固定なので注意)
    ((CTextEdit*)pControl)->getText(filepath);

    // 音声処理クラスに文字列を渡す
    ((MyVST*)effect)->setFilePath(filepath);
  }
  〜〜以下略〜〜
}

以上です。CTextEditの作成方法は下記とほぼ同じだったと思います。
http://vstcpp.wpblog.jp/?p=1722

なお、音声処理クラスのfilepathに書き込む際は排他処理等がいるかもしれません。

192管理人★:2018/07/16(月) 15:45:38
猫十さん

すいません。今質問を読み返して逆方向だということに気付きました

やりかたは>>191と同様で出来ると思います。
(コードのイメージは全角スペースになっているのでご注意ください。)

①GUIクラス側(AEffGUIEditorを継承したクラス側)で文字列を受け取る関数を定義する

class MyGUI : public AEffGUIEditor, CControlListener
{
public:
  // 引数の文字列 fileをメンバー変数のfilepathに設定する関数
  void setFilePath(char* file) { strcpy(file, filepath); };

  〜〜以下略〜〜
protected:
  char filepath[256]; // ファイルパス用の文字列
};

②音声処理クラス側(AudioEffectXを継承したクラス側 MyVSTとする)で
 CTextEditコントロールなどから文字列をうけとった際に通知する処理を追加する

void MyVST::processReplacing(float** inputs, float** outputs, VstInt32 sampleFrames)
{
  〜〜以下略〜〜

  // wavファイルのパスが変更された場合だけ、MyGUI側に新しいファイルパスを渡す
  // (条件式は省略。プログラムに合わせてください。)
  if(〜〜〜〜)
  {
    // たぶん排他処理が必要
    ((MyGUI*)editor)->setFilePath(newfilepath);
  }
}

③GUIクラス側(AEffGUIEditorを継承したクラス側)でテキストラベル等に文字列を反映させる
 (ここではidle関数を利用。参考→https://www39.atwiki.jp/vst_prog/pages/93.html)

void VstGui5::idle ()
{
  // まずは継承元の関数を呼び出す(必須)
  AEffGUIEditor::idle ();

  // このVSTGUI固有の処理を記載する

  // テキストラベルの文字を設定する
  // setText()処理中にfilepathが更新ないように排他処理がいるかもしれません。
  textLabel->setText (filepath);

  // テキストラベルの描画を更新する
  textLabel->setDirty();
}

193管理人★:2018/07/16(月) 15:49:25
>>192
誤記がありました…。

【誤】
②音声処理クラス側(AudioEffectXを継承したクラス側 MyVSTとする)で
 CTextEditコントロールなどから文字列をうけとった際に通知する処理を追加する

【正】
②音声処理クラス側(AudioEffectXを継承したクラス側 MyVSTとする)で
 ファイルパスを渡す処理を追加する。

194猫十:2018/07/18(水) 01:46:05
管理人様

頂きました回答をもとにさっそく試してみたところ、
AudioEffectX側からAEffGUIEditor側へ文字列を送ることができました。(その逆もできました。)

具体的には
AEffGUIEditor側でFileSelector経由で読み込んだファイルのフルパスをAudioEffectX側に送り、
AudioEffectX側でWAVを読み込んで発音部にセット、
読み込んだWAVのサンプリング周波数やビットレートその他の情報(デバッグ用にチャンク位置とか)をAEffGUIEditor側に送って表示
です。(VSTiなサンプラーとしてこのやり方が合っているのかどうかわかりませんが・・・。)

排他処理は入れていないのですが基本的な動作はOKっぽくなってきましたので
実際の曲で市販のプラグインと混ぜて使ってみようと思ってます。

いつも本当にありがとうございます。

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


猫十

195管理人★:2018/07/19(木) 22:37:42
猫十さん

動いてよかったです。

VSTのサンプラーとしてやり方があってるかどうかはわかりませんが、
私はプログラムに正解はないと思っています。
想定通り動いたのであればそのやり方でいいと思います。

196pylab:2018/10/03(水) 22:06:37
こんばんわ
最近VSTに興味をもち始めたものです。

VST3.6開発01 – VST3開発環境の準備にて

「VST SDK 3.6.10の場合、下記のエラー LNK1104でビルドが失敗しますが、サンプルプラグインなので上記のライブラリファイルが生成されていれば、
次に進んで頂いても大丈夫です。(サンプルプラグインの動作を見ることはできませんが…)」

とありますが、
https://github.com/steinbergmedia/vst3sdk/issues/17
にて
SMTG_CREATE_BUNDLE_FOR_WINDOWSをオンにすればよいという
情報がありました。

CMAKEの画面の中ほど(赤いところ)で「SMTG_CREATE_BUNDLE_FOR_WINDOWS」のチェックボックスが
ありましたのでオンにしてビルドしましたら
リンカのLNK1104エラーが出なくなりました。

ですが警告でNo snapshot in Bundle は出ています。

確認お願いします。

197管理人★:2018/10/03(水) 23:20:17
pylabさん

情報ありがとうございます。
内容確認して再度ご連絡いたします。

198管理人★:2018/10/04(木) 22:47:39
pylabさん

確認いたしました。

「SMTG_CREATE_BUNDLE_FOR_WINDOWS」をオンにすると
VST 3.6.9以前のフォルダ構成でサンプルを配置するので
確かにエラーはなくなるようです。

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

199らく:2020/02/03(月) 10:47:03
はじめまして。
VSTに関して全くの初心者であり、調べていたら、あらゆるところからここへ導かれました。非常に参考にさせて頂いております。

早速ですが、質問させて頂きます。
「はじめてのVST3.6プラグインの作り」の手順通りに「パラメータの保存方法」まで進みました。
ここに至るまでにもVST3プラグインができ、REAPER上で動作しています。
ところが、別のPC(開発環境的なものは一切入っておりません)にプラグインを持って行くと、同じREAPERですが、VSTプラグイン(.vst3ファイル)が見えません。
原因はどこにあると推測されますか?
ちなみに、VSTプラグインを作成した環境は
 VDT_SDK:Version 3.6.14
 Visual Studio:2019 Version 16.4.2
です。

宜しくお願い致します。

200管理人★:2020/02/04(火) 00:12:56
らくさん

書き込みありがとうございます。
マシュマロと同じ質問だと思いますので、Twitterにて回答させていただきました。
https://twitter.com/vstcpp/status/1224347122364862466

201hiro:2020/05/08(金) 08:19:05
初めましてです。
VSTを作ってみたいと思いまして今日vst_sdkをダウンロードしてhttps://vstcpp.wpblog.jp/?page_id=21の進めたのですが
audioeffectx.hを開くとソースファイルを開けません"pluginterfaces/vst2.x/aeffectx.h"とエラーが出ます。
ダウンロードしたフォルダを見てもaeffectx.hは見つからず、入手できる他のサイトも見つかりません。
解決策を教えてください。VS 2019です。

202管理人★:2020/05/12(火) 13:57:00
hiroさん

書き込みありがとうございます。
お返事が遅くなり申し訳ありません

そちらの方法は、古いバージョンのSDKを使ったものになり、もう実施することができません。
新しいバージョンのSDKを使った方法はこちらになりますのでこちらの方法でご確認いただけますでしょうか。
https://vstcpp.wpblog.jp/?p=1287

203hiro:2020/05/13(水) 10:35:59
解決しました!ありがとうございます。
原因はCMAKEが(ブラウザのバグなのか?)何故かダウンロードできなくて手こずってました...
今日はダウンロードができ、送って頂いたURLの手順通りに進めることができています。
ご丁寧な説明をありがとうございました。

204管理人★:2020/05/13(水) 20:25:13
hiroさん
無事解決できてよかったです。

205ank:2020/07/05(日) 00:35:13
はじめまして。
本、VSTプラグインを読み進めているのですが、GUIのところでつまづいています。
myEditor.uidescのパスを修正した後にテストホストで読み込むとノブ等が表示されるはずですが、黒い画面のままです。
管理人様のサイトを見ると本に記述されていないresource.rcに関する記述があるのですが、このファイルの作成が必要なのでしょうか。

206管理人★:2020/07/09(木) 23:31:30
ankさん

書き込みありがとうございます。
ご連絡が遅れて申し訳ありません。もう少し内容確認にお時間をください。

207管理人★:2020/07/10(金) 00:02:18
ankさん

書籍のResourcesフォルダの配置位置に誤記がありました。申し訳ありません。
MyVstProject.vst3フォルダの配下ではなく、Contentsフォルダの配下にResourcesフォルダを移動させていただけますでしょうか?

208ank:2020/07/14(火) 21:31:39
返事が遅れまして申し訳ございません。
無事にリリース版までVSTの作成が進めることができました。
とても丁寧に書かれた本でC++に慣れていない人間にとって大変ありがたい存在です。続編の予定はあるのでしょうか。
VST作成の第一歩が踏み出せてとても感謝しております。

209管理人★:2020/07/15(水) 22:55:40
ankさん

無事進めることができてよかったです。

続編の予定ですが、今のところありません。
より高度なVSTを作成する際は、SDKのマニュアルか私のサイトなどを
ご確認いただければと思います。

210てつ:2021/02/18(木) 21:07:40
管理人さん、はじめまして。
著書VSTプラグインならびにホームページからこちらの掲示板にたどり着いた初心者です。

プロジェクトの設定を行い、その後、ビルドの実行を行ったのですが、下記のエラーが出ます。
リビルドを開始しました...
1>------ すべてのリビルド開始: プロジェクト:MyVstProject, 構成: Debug x64 ------
1>dllmain.cpp
1>myvst3.cpp
1>コードを生成中...
1> ライブラリ C:\Users\***\source\repos\MyVstProject\x64\Debug\MyVstProject.lib とオブジェクト C:\Users\***\source\repos\MyVstProject\x64\Debug\MyVstProject.exp を作成中
1>MSVCRTD.lib(exe_main.obj) : error LNK2019: 未解決の外部シンボル main が関数 "int __cdecl invoke_main(void)" (?invoke_main@@YAHXZ) で参照されました
1>C:\Users\***\source\repos\MyVstProject\x64\Debug\MyVstProject.vst3 : fatal error LNK1120: 1 件の未解決の外部参照
1>プロジェクト "MyVstProject.vcxproj" のビルドが終了しました -- 失敗。
========== すべてリビルド: 0 正常終了、1 失敗、0 スキップ ==========

ネットで自分なりに探したところ、プロパティのリンカー - システム ー サブシステムを
コンソールからWINDOWSに変えると解決したというサイトがあったので
試してみましたが、上記エラーの「未解決の外部シンボル main」が「未解決の外部シンボル WinMain」に変わるだけで同じエラーが出ます。

dllmain.cppは記載通りに追加したつもりです。

環境はWIN10, VisualStudio2019, VST-SDK3.6.14です。

解決方法をご教授いただけると幸いです。

長文で失礼いたしました。

211管理人★:2021/02/18(木) 21:26:06
てつさん

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

WinMainがないというエラーですので、おそらくVisual Studioのプロジェクト作成時に
「ダイナミックリンクライブラリ(.dll)」を選んでいない気がします。

「VST3のプロジェクトの作成」(https://vstcpp.wpblog.jp/?p=1319)にある
下記の画像の部分になります。
https://vstcpp.wpblog.jp/wp-content/uploads/2020/12/20201230_04.png

お手数だと思いますが、ご確認いただけますでしょうか。

212てつ:2021/02/19(金) 00:33:16
管理人様
迅速なご回答をありがとうございました。

ご指摘の部分からやり直してみたところ、ビルドが成功し、VST HOSTでの音の確認まで
無事に出来ました。
自分ではちゃんとやっているつもりではありましたが、このような些細なミスで
お手を煩わせてしまい、申し訳ありません。

今後ともよろしくお願いします。

213管理人★:2021/02/19(金) 00:40:18
てつさん

無事解決してよかったです。
開発環境やプロジェクトの準備はつまずきやすい難所なので仕方がないです。

214rerohm:2021/05/11(火) 15:48:56
こんにちは
最近VSTの開発を始めようとしているプログラム初心者です。
サイトに掲載されている手順で基本ライブラリのビルドを行ったのですが、

ninja: build stopped: subcommand failed.

すべてビルド が失敗しました。

と表示されて途中で終わってしまいます。Debug版Release版いずれもです。
一応https://vstcpp.wpblog.jp/?p=1287 に記載されている.libファイルは生成
されてはいたのでそのままプラグインの作成を進めてみたのですが、こちらでは

ビルドを開始しました...
1>------ ビルド開始: プロジェクト: MyVSTProject, 構成: Debug x64 ------
1>factory.cpp
1>C:\Users\shoyasaito\source\repos\MyVSTProject\MyVSTProject\factory.cpp(2,10): fatal error C1083: include ファイルを開けません。'public.sdk/source/main/pluginfactoryvst3.h':No such file or directory
1>プロジェクト "MyVSTProject.vcxproj" のビルドが終了しました -- 失敗。
========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ==========

と表示されてビルドが失敗します。
VSTSDKのバージョンは3.7.2、Visual StudioはCommunity 2019 Version 16.9.4です。
よろしくお願いします。

215管理人★:2021/05/12(水) 10:08:15
rerohmさん

書き込みありがとうございます。
おそらくポリフォニックシンセサイザー(https://vstcpp.wpblog.jp/?p=1361)のサンプルだと思いますが、
factory.cppの2行目にある「pluginfactoryvst3.h」を「pluginfactory.h」に修正して試してみてください。

216tk:2021/08/06(金) 00:27:18
管理人様 はじめまして.

現在,VST基本プラグインのビルド(https://vstcpp.wpblog.jp/?p=1287)
をしているのですが,debug,release共に以下のようなエラーがでました.

>------ すべてビルド 開始済み: プロジェクト: VST3_SDK、構成: x64-Debug ------
.
.
.

[299/452] Linking CXX shared module VST3\Debug\helloworld.vst3\Contents\x86_64-win\helloworld.vst3
FAILED: VST3/Debug/helloworld.vst3/Contents/x86_64-win/helloworld.vst3
cmd.exe /C "cd . && "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -E vs_link_dll --intdir=C:\VST_SDK\my_plugins\build\helloworld\CMakeFiles\helloworld.dir --rc=C:\PROGRA~2\WI3CF2~1\10\bin\100190~1.0\x86\rc.exe --mt=C:\PROGRA~2\WI3CF2~1\10\bin\100190~1.0\x86\mt.exe --manifests -- C:\PROGRA~2\MICROS~4\2019\COMMUN~1\VC\Tools\MSVC\1429~1.300\bin\Hostx86\x64\link.exe /nologo C:\VST_SDK\my_plugins\build\helloworld\CMakeFiles\helloworld.dir\source\plugfactory.cpp.obj C:\VST_SDK\my_plugins\build\helloworld\CMakeFiles\helloworld.dir\source\plugcontroller.cpp.obj C:\VST_SDK\my_plugins\build\helloworld\CMakeFiles\helloworld.dir\source\plugprocessor.cpp.obj C:\VST_SDK\my_plugins\build\helloworld\CMakeFiles\helloworld.dir\C_\VST_SDK\VST3_SDK\public.sdk\source\main\dllmain.cpp.obj C:\VST_SDK\my_plugins\build\helloworld\CMakeFiles\helloworld.dir\resource\plug.rc.res /out:VST3\Debug\helloworld.vst3\Contents\x86_64-win\helloworld.vst3 /implib:lib\helloworld.lib /pdb:WIN_PDB64\helloworld.pdb /dll /version:0.0 /machine:x64 /debug /INCREMENTAL /SAFESEH:NO lib\sdk.lib lib\sdk_common.lib lib\base.lib lib\pluginterfaces.lib kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cmd.exe /C "cd /D C:\VST_SDK\my_plugins\build\helloworld && "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -E copy C:/VST_SDK/VST3_SDK/vst3_doc/artwork/VST_Logo_Steinberg.ico C:/VST_SDK/VST3_SDK/out/build/x64-Debug/VST3/Debug/helloworld.vst3/PlugIn.ico && "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe" -E copy C:/VST_SDK/VST3_SDK/cmake/modules/../templates/desktop.ini.in C:/VST_SDK/VST3_SDK/out/build/x64-Debug/VST3/Debug/helloworld.vst3/desktop.ini && attrib +s C:/VST_SDK/VST3_SDK/out/build/x64-Debug/VST3/Debug/helloworld.vst3/desktop.ini && attrib +s C:/VST_SDK/VST3_SDK/out/build/x64-Debug/VST3/Debug/helloworld.vst3/PlugIn.ico && attrib +s C:/VST_SDK/VST3_SDK/out/build/x64-Debug/VST3/Debug/helloworld.vst3 && cd /D C:\VST_SDK\VST3_SDK\out\build\x64-Debug\bin && echo [SMTG] Validator started... && C:\VST_SDK\VST3_SDK\out\build\x64-Debug\bin\validator.exe C:/VST_SDK/VST3_SDK/out/build/x64-Debug/VST3/Debug/helloworld.vst3/Contents/x86_64-win/helloworld.vst3 && echo [SMTG] Validator finished. && cd /D C:\VST_SDK\my_plugins\build\helloworld && echo [SMTG] Delete previous link... && rmdir "C:\Program Files\Common Files\VST3\helloworld.vst3" & del "C:\Program Files\Common Files\VST3\helloworld.vst3" && echo [SMTG] Creation of the new link... && mklink /D "C:\Program Files\Common Files\VST3\helloworld.vst3" C:\VST_SDK\VST3_SDK\out\build\x64-Debug\VST3\Debug\helloworld.vst3 && echo [SMTG] Finished.""
[SMTG] Validator started...
.
.
.

ninja: build stopped: subcommand failed.

すべてビルド が失敗しました。

対策法等ご存じでしたらお教えいただきたいです.
vst_sdk 3.7.2,visual studio 16.10です.

217管理人★:2021/08/07(土) 11:54:17
tkさん
確認しますので少々お時間ください。

218管理人★:2021/08/08(日) 12:16:20
確かにビルドの出力では「すべてビルド が失敗しました。」と出ますね…。
(あまり見てなかったです…。)

「エラー一覧」のウィンドウにエラーは出ていますでしょうか?
(警告はたくさん出ていると思いますがこれは問題ありません。)
エラーが出ていなければ、失敗しているのはサンプルのようなのでおそらく問題はありません。

「VST_SDK\VST3_SDK/out/build/x64-Debug/lib」配下にVST基本ライブラリ(下記)が作成されていれば
VST開発はできますのでそのまま続けていただければと思います。

【作成される主なライブラリファイル】
base.lib
sdk.lib
sdk_common.lib
pluginterface.lib
vstgui.lib
vstgui_support.lib
vstgui_uidescription.lib

219<削除>:<削除>
<削除>

220minty:2024/03/05(火) 08:40:26
うつぼかずら様

以前はdllmainの件でお世話になりました、ありがとうございました。
新たに問題が発生しましたので質問させていただきます。パラメーター実装方法1にて紹介されているボリュームパラメーターですが、こちらで実装したところシンセ等が音声処理中にこのボリュームパラメータを弄るとノイズが乗ってしまいます。これは当方の環境の問題なのか、それとも仕様なのかご教授いただければ幸いです。

221管理人★:2024/03/06(水) 09:48:57
mintyさん

「パラメーター実装方法1」のサンプルでノイズが乗るようなことはないと思います。

222minty:2024/03/08(金) 12:38:09
うつぼかずら様

返信ありがとうございます。生成された波形を詳しく見たところ、どうやら音量(=振幅)変化で波形が不連続になることによってクリッピングノイズが発生しているようでした。こういった場合、フェードイン/フェードアウト処理を行って解決するのがやはり一般的でしょうか。
また、今回の件に関係あるか分かりませんが、DAW(ableton live 11)でparam1のオートメーションを書いた際、何故かオートメーション記述よりも3-8ms程度先に処理が行われてしまうようです。例えば、1:00:000の時点でparam1 = 0となるようなオートメーションを書くと、0:59:995時点でparam1=0となる、といった具合です。他のボリュームコントロールプラグインにて同様の処理を行うと正しい時刻で処理が行われる為、DAWの設定の問題ではなさそうです。
DAW側の設定も含めかなりいろいろ調べましたが正直なぜこのような事になっているのかさっぱり分からなかったので、もし何か知見がございましたらご教授いただければと思います。

223管理人★:2024/03/08(金) 19:27:36
mintyさん

急激な音量変化であれば確かにノイズが発生する可能性はありますね。
フェードイン/フェードアウトのような処理にすれば解決すると思います。

タイミングのずれはVST3プラグインのパラメーター実装方法1(https://www.utsbox.com/?p=737)に記載がある下記の通りです。
サンプルプログラムのタイミングについては、厳密なものとなっておりません。

厳密なタイミングにするには、getPoint()関数の引数sampleOffsetを参照する必要があるかと思います。

>パラメーターの操作(変更)は処理するサンプル(numSamples)内で複数回 操作されていることがあるため
>キュー(queue)という形式をとっています。
>例えば、「タグ(ID) 100のパラメーター」が処理するサンプル(numSamples)内で「10サンプル目に値が0.1」
>「20サンプル目に1.0」「30サンプル目に0.5」と操作された場合、下記のような形でIParamValueQueueクラスに変更情報が格納されます。


>前述の通り、パラメーターの操作(変更)は処理するサンプル内で複数回 操作されていることがあるのですが、
>今回のサンプルプログラムでは、最後に変更された値のみを反映しています。
>これは、一般的に処理するサンプルの長さが2〜5ミリ秒程度(※)のため、キュー(queue)の内容に合わせて1つ1つを処理(反映)しても、
>最後に変更された値のみを処理(反映)しても、聴覚的な差がほとんどないためです。
>(※一般的にnumSamplesは100〜200程度の値になる。サンプリングレートを44100Hzで換算すると2〜5ミリ秒程度)

224名無しさん:2024/03/15(金) 11:15:32
こんにちは、初めまして
コンプレッサーの記事のほうにコメントをいれてみたのですが、うまく書き込めないようで、こちらにも書いてみます。
重複していましたら、申し訳ありません。

ゲインの計算ですが、間違っていないでしょうか。

gainL = threshold + (tmpL - threshold) / ratio;
ここは、
gainL = (threshold + (tmpL - threshold) / ratio)/ tmpL;
ではないかと思いますが、私の理解が間違っていますでしょうか?

225管理人★:2024/03/15(金) 12:20:21
ご指摘ありがとうございます。
確かに計算式がおかしいですね。
この計算式だとthresholdを超えると一気に音量が下がって、そのあとまた上がってしまいますね…。

ご指摘の通り、いただいた計算式
 gainL = (threshold + (tmpL - threshold) / ratio)/ tmpL;
もしくは、
 gainL = 1.0f - (tmpL - threshold) / ratio;
のような計算式にすべきですね。

(どのような計算式が良いのかはわかりませんのでご了承ください。)


新着レスの表示


名前: E-mail(省略可)

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

※画像アップローダーはこちら

(画像を表示できるのは「画像リンクのサムネイル表示」がオンの掲示板に限ります)

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