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

波形描画ビューのその後

1sagamat:2023/08/15(火) 21:00:03
うつぼかずら様

こんばんは。お世話になっております。
波形描画ビューのページにコメントを書き込もうとしましたがうまく反映されないようですので、こちらに失礼いたします。
波形描画ビューの記事、大変参考になりました。ありがとうございます。
記事の最後に触れられている「音声処理クラスから音声波形を取得する方法」が気になります。
音声処理クラスからパラメータ操作クラスへの配列の受け渡し、ならびに、その逆ができるようになれば、いろいろとできることが増えるのではと想像しております。
是非とも続きの記事を拝見したく、今か今かと更新を期待しております。
お忙しいところ恐縮ですが、上記方法のご教示をいただければ幸いです。
今後とも何卒よろしくお願い申し上げます。

2管理人★:2023/08/17(木) 00:59:38
sagamatさん

書き込みありがとうございます。
頑張って記事を書いてみたいと思いますが、少しお時間をください。

3管理人★:2023/08/17(木) 01:01:25
とりいそぎデータ(配列)を受け渡しする方法について簡単なサンプルコードを記載します。

パラメーター操作クラスから音声処理クラスへのデータ受け渡しの方法になりますが、
逆のパターンでも同じ処理でできると思います。

// パラメーター操作クラスから音声処理クラスにメッセージを送信する関数
tresult MyVSTController::sendData(void* data, size_t _size)
{
// パラメーター操作クラスから音声処理クラスにメッセージを送るためメッセージクラスを確保する
IMessage* msg = allocateMessage();

// メッセージクラスのメッセージIDを設定する。メッセージID必ず設定する必要がある。
msg->setMessageID(u8"sendData01");

// メッセージ内にデータを設定する。データは「データID(文字列)+データ中身(ポインタ)」という形をとる
msg->getAttributes()->setBinary(u8"size", (void*)(&_size), sizeof(size_t));
msg->getAttributes()->setBinary(u8"data", (void*)data, (uint32)_size);

// メッセージクラスを音声処理クラスに送信する
sendMessage(msg);

// 確保したメッセージクラスは解放する
msg->release();

return kResultTrue;
}

4管理人★:2023/08/17(木) 01:02:34
// 音声処理クラスでメッセージを受け取った時の関数
result MyVSTProcessor::notify(IMessage* message)
{
// メッセージIDがパラメーター操作クラスから送られたものかどうかチェックする。
if (strcmp(message->getMessageID(), u8"sendData") == 0)
{
// メッセージクラスのデータ読込用の一時変数
const void* tmp;
uint32 datasize;

void* _data;
size_t _size;

// メッセージ内のデータを受け取る
// まずはデータID「size」のデータを受け取る
message->getAttributes()->getBinary("size", tmp, datasize);
memcpy(&_size, tmp, sizeof(size_t));

// 同様にデータID「data」のデータを受け取る
message->getAttributes()->getBinary("data", tmp, datasize);
_data = new char[datasize];
memcpy(_data, tmp, datasize);

// -------------------------------
// ここで何かする。
// -------------------------------

return kResultOk;
}

// メッセージIDがパラメーター操作クラスから送られたものでなければ、継承元クラスのnotifyを呼び出して終了。
return AudioEffect::notify(message);
}

5管理人★:2023/08/17(木) 01:07:58
インデントが消えてかなり見辛くなってしまいましたがご確認いただければと思います。

なお、音声処理クラスでデータの受け渡しをする場合は下記に注意してください。
・マルチスレッド処理のためprocess関数やnotify関数などは別スレッドになっている
・リアルタイムスレッド(process関数など)からデータ送信関数を呼び出さない

6sagamat:2023/08/17(木) 11:54:37
うつぼかずら様

お忙しい中での早速のご教示、感謝申し上げます!!
いくつかわからないところがありそうですが、まずは試してみます!
とりいそぎ、御礼のみにて失礼いたします。
今後とも何卒よろしくお願い申し上げます。

7sagamat:2023/09/10(日) 15:03:42
うつぼかずら様

こんにちは。お世話になっております。
パラメータ処理クラスから音声処理クラスへのデータの受け渡しも逆のパターンで可能とのご教示をいただいておきながら、うまく実装できておりません。大変お恥ずかしいのですが、追加で質問させていただきたく存じます。
「図形・波形描画ビューの実装」を行った上で下記のコードを書きました。やりたいことは音声データの波形をリアルタイムでGUIに表示することです。
「process関数からデータ送信関数を呼び出さない」とヒントをいただいておりますが、書きようがわからず今のところ音声処理クラスのprocess関数内でsendadta関数を呼び出してしまっております。
下記にprocessor.cppに記載しているsendadata関数、guieditor.cppに記載しているnotify関数、processor.cppに記載しているprocess関数を投稿させていただきます。
当方、Fortran, C#, MATLAB, Pythonを少し触ったことがある程度です。下記、いろいろトンチンカンなことをしているのだろうと想像いたします。
お時間の許す際にご指南を頂戴できますと大変助かります。何卒よろしくお願い申し上げます。

8sagamat:2023/09/10(日) 15:05:44
【processor.cpp】

tresult MyVSTProcessor::senddata(void* data, size_t _size)
{
// 音声処理クラスからパラメータ操作クラスにメッセージを送るためメッセージクラスを確保する
IMessage* msg = allocateMessage();

// メッセージクラスのメッセージIDを設定する。メッセージID必ず設定する必要がある。
msg->setMessageID("sendData");

// メッセージ内にデータを設定する。データは「データID(文字列)+データ中身(ポインタ)」という形をとる
msg->getAttributes()->setBinary("size", (void*)(&_size), sizeof(size_t));
msg->getAttributes()->setBinary("data", (void*)data, (uint32)_size);

// メッセージクラスを音声処理クラスに送信する
sendMessage(msg);

// 確保したメッセージクラスは解放する
msg->release();

return kResultTrue;
}

9sagamat:2023/09/10(日) 15:07:59
【guieditor.cpp】

tresult MyVSTGUIEditor::notify(IMessage* message)
{
// メッセージIDがパラメーター操作クラスから送られたものかどうかチェックする。
if (strcmp(message->getMessageID(), "sendData") == 0)
{
// メッセージクラスのデータ読込用の一時変数
const void* tmp;
uint32 datasize;

//void* _data;
float* _data;
size_t _size;

// メッセージ内のデータを受け取る
// まずはデータID「size」のデータを受け取る
message->getAttributes()->getBinary("size", tmp, datasize);
memcpy(&_size, tmp, sizeof(size_t));

// 同様にデータID「data」のデータを受け取る
message->getAttributes()->getBinary("data", tmp, datasize);
_data = new float[datasize];
memcpy(_data, tmp, datasize);

// 波形情報を設定
waveView->setWave(_data, _size);

// フレームに追加する
frame->addView(waveView);

return kResultOk;
}

// メッセージIDがパラメーター操作クラスから送られたものでなければ、継承元クラスのnotifyを呼び出して終了。
return kResultOk;
}

10sagamat:2023/09/10(日) 15:09:05
【processor.cpp】

tresult PLUGIN_API MyVSTProcessor::process(ProcessData& data)
{
// 入力・出力バッファのポインタをわかりやすい変数に格納
// inputs[]、outputs[]はAudioBusの数だけある(addAudioInput()、addAudioOutput()で追加した分だけ)
// 今回はAudioBusは1つだけなので 0 のみとなる
// channelBuffers32は32bit浮動小数点型のバッファで音声信号のチャンネル数分ある
// モノラル(kMono)なら 0 のみで、ステレオ(kStereo)なら 0(Left) と 1(Right) となる
Sample32* inL = data.inputs[0].channelBuffers32[0];
Sample32* inR = data.inputs[0].channelBuffers32[1];
Sample32* outL = data.outputs[0].channelBuffers32[0];
Sample32* outR = data.outputs[0].channelBuffers32[1];

// numSamplesで示されるサンプル分、音声を処理する
for (int32 i = 0; i < data.numSamples; i++)
{
outL[i] = inL[i];
outR[i] = inR[i];
}

senddata((void*)outL, (size_t)data.numSamples);

// 問題なければkResultTrueを返す(おそらく必ずkResultTrueを返す)
return kResultTrue;
}

11管理人★:2023/09/10(日) 23:47:11
パラメーター操作クラスのnotify()で受け取った後、GUIクラスで描画を更新する必要があります。
(残念ながらいきなりGUIクラスのnotify()で受け取ることはできません。)

別スレッドでのsendMessage関数の実行も含めてメモを下記に保存しましたので、
良ければご確認ください。
https://www.utsbox.com/wp-content/uploads/2023/09/memo20230910.zip

なお、上記のメモはミューテックスを使用しロックをかけていますが、本来はlock-free出なければならないようです。
lock-freeなどについては下記に詳しく書かれていますので、参考にしていただければと思います。

https://qiita.com/aike@github/items/0ebfc60faee3ced98f96

12sagamat:2023/09/11(月) 09:19:52
うつぼかずら様

早速のご指南、ありがとうございます!!
実装を試みておりますが、いくつかコンパイルエラーが出ておりまして、追加で質問させていただきたく存じます。

1. wavlenの値はどこに書けばよいでしょうか?
今のところ、processor.hに
public:
int wavlen = 256;
と書いてみておりますが、guieditor.cppのnotify関数内の
int size = wavlen;
で、識別子"wavlen"が定義されていませんというエラーが生じております。

2. minの引数?
controller.cpp内の
datasize = std::min(datasize, (uint32)(sizeof(float) * wavlen));
で、オーバーロードされた関数"std::min"のインスタンスが引数リストと一致しませんというエラーが生じております。

3. MyVSTControllerの参照ができていない?
guieditor.cppのnotify関数内で、
float* tmp = ((MyVSTController*)controller)->wavdata;
がありますが、識別子"MyVSTController"が定義されていませんというエラーが生じております。

4. copiedという値は何に使っているのでしょうか?
processor.cpp内のprocess関数内に記載する
copied += size;
ですが、このcopiedという変数はどこで定義して、何に使えばよろしいでしょうか?

ご面倒をおかけいたしまして大変恐縮です。
お時間の許す時に助けていただけますと幸いです。
何卒よろしくお願い申し上げます。

13管理人★:2023/09/11(月) 21:56:45
sagamatさん

あくまでサンプルですので、「どのような処理をしているか?」の理解をしていただくためのものになります。
いくつかのコードから継ぎ接ぎで持ってきているので、そのままではコンパイルが通らない可能性があるのはご了承ください。

1.
それぞれで定義したり、共通のヘッダファイルなどを用意すればよいと思います。

2.
配列サイズを超えないようにしているだけです。
datasizeとsizeof(float)*wavelenのうち、小さい方の値をdatasizeに入れているだけなので
std::min関数でなくても大丈夫です。

3.
guieditor.cppからパラメーター操作クラスの定義が見えるようにするだけです。
パラメーター操作クラスのヘッダファイルをguieditor.cppでもインクルードするなどして
対応できます。

4.
誤記になります。
サンプルを作るときに消し忘れましたので無視してください。


新着レスの表示


名前: E-mail(省略可)

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

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

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

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