macでビルドしてLogicで動作させるとうまくいかない現象がでました
どこがどうだめなのか、確認してみよう~
前回のタイマー処理でパラメータを更新するという記事を作成したのですが、動作環境の違いでうまく動作しない場合がありましたので、問題の状態を(個人的な迷走を^^;)備忘録したいと思います。
また、この問題は、解決しなかったので、macで開発したバージョンのみ、以前のprocessBlock内でパラメータを更新する方法に戻しました。
問題の状態
windows環境、visual studio2019でビルド、reaperで動作させると、正常に動作するのですが、macのXcodeでビルド、Logicで動作確認をしたところ、次のような問題が発生しました。
開発環境、mac OS X 10.14.6、Projucer、JUCEはv6.1.2ビルド後、Logic ProX v10.4.6の環境で実行しました。
テンポを変更しても、それに応じてディレイの長さが変更されないという現象が確認できました。これは、タイマーを利用したパラメータ更新の仕組みの際に発生しました。パラメータの更新処理をprocessBlock内で行うと、動作しました。
その後、タイマー処理でパラメータの更新がなぜできないのかを検証していました。
問題の検証
確認として、タイマーが処理するメッセージスレッドから、音声処理のディレイのインスタンスを確認できていない、という点を検証してみました。JUCEの仕組みである音声処理スレッドとメッセージスレッド、確かに違うスレッドで動作しているなら、メッセージスレッドから音声処理スレッドのインスタンスは参照できないのかな、と思いました。(OSによってこのあたりの違いがあるのでしょうか・・・)
現状で、processorChainでsetDelayTimeをしても値が反映されていないようなので(エラーも出ないので)、もしかしたら、スレッドが違うので、それぞれのスレッドに同じ名前のインスタンスが生成されているのかな、とも考えました。
ということで、タイマー処理で計算したパラメータをメンバ変数に渡し、processBlock関数でsetDelayTimeを呼び出すというような処理をやってみました。
まずは、パラメータの受け渡し用メンバ変数を準備しました。
class TheDelayAudioProcessor : public juce::AudioProcessor
{
//...略...
private:
float delayTimeL_param = 0.0f;
float delayTimeL_param = 0.0f;
timerCallback関数内は、これらの変数を更新するように変更しました。
void timerCallback() override
{
playHead = this->getPlayHead();
playHead->getCurrentPosition(currentPositionInfo);
current_bpm = currentPositionInfo.bpm;
if (previous_bpm != current_bpm) {
delayTimeL_param = (float)60.0 / current_bpm;
if (delayTimeL_param >= 2.0f) {
delayTimeL_param = 1.99f;
}
delayTimeL_param = delayTimeL_param;
}
DBG("timer:" << delayTimeL_param);
}
DBG関数で、とりあえずパラメータの値が見られるようにしておきました。
processBlock内で呼び出すsetDelay関数には、このパラメータを渡すのみとしています。
void TheDelayAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages)
{
//...略...
//[1]setDelayTime関数をprocessBlockで呼び出すように変更しました。
processorChain.get<DelayIndex>().setDelayTime(0, delayTimeL_param);
processorChain.get<DelayIndex>().setDelayTime(1, delayTimeL_param);
DBG("processBlock:" << delayTimeL_param);
//processorChain.get<DelayIndex>().setMaxDelayTime(val1);
processorChain.get<DelayIndex>().setWetLevel(val4);
processorChain.get<DelayIndex>().setFeedback(val5);
//...略...
}
processBlock側からも、delayTimeL_paramの値がタイマーで更新されたものになっているか確認してみました。
結果は変わりませんでした。タイマーでdelayTimeL_paramが変化して、processBlockで見ている値も変化しているのですが、どうも音にノイズが入ってきたり、BPMを変化させても全くディレイ時間が変化しないなどの不具合が見られました。
ということで、一度パラメータの計算もprocessBlock内で処理している以前のバージョンに戻すことにしました。(以前のバージョンは、こちらの記事の実装です。)
その他の迷走
タイマーコールバックを削除して、元の状態に戻そうとしたら、shared codeの方でエラーが出るようになってしまいました。このプログラムは、もともとJUCEに準備されていたもので、何も触っていないはずなのですが、謎にエラーが出現し始めました。
以前、ビルドが成功していた他のプロジェクトをビルドしても、同様のエラーが出ることから、共通のライブラリ部分で何か無意識のうちに変更を加えてしまった??ようです^^;
色々と修正しようと頑張りましたが、時間が勿体無いと思いましたので、JUCE自体を再インストールすることで、正常に戻りました。JUCEは、フォルダごと削除して、ダウンロードしたものに差し替えれば良いので、この点は楽ですね 笑