processBlockでどのくらい時間がかかるのか知りたいな
C++の処理時間計測クラスを使ってみたらわかるかも
ディレイのプラグイン内では、音声処理部分で条件を利用してしまっているので、処理時間が気になっていました。そのため、C++で処理時間を計測するようなプログラムを検証してみました。ディレイプラグインのprocessBlockがどのくらい時間かかっているかを計測してみました。
今までのディレイプラグインの制作過程の記事については、こちらをご参照ください。
C++の処理時間計測について、幾つかの方法があるようです。こちらの記事を参考にさせて頂きました。
今回は、C++11以降で利用できる、Chronoクラスを選択してみました。いろいろと調べた結果、次のような特徴がありました。
①クロスプラットフォーム
②記載が直感的でわかりやすい
③およそミリ秒単位で時間取得可能
こんな人の約に立つかも
・C++のChronoクラスで処理時間を計測したい人
・JUCEプログラミングで処理時間を計測したい人
・JUCE開発のデバッグ手法を模索している人
処理時間計測の実装
処理の概要
C++のChronoクラスで時間を計測するには、次のシンプルな3ステップで計測ができます。
①最初にchronoをincludeします。
#include <chrono>
②chronoクラスを使った処理で計測対象処理を挟み込みます。
std::chrono::system_clock::time_point start, end;
start = std::chrono::system_clock::now();
//ここに時間を計測したい処理を挟みます。
end = std::chrono::system_clock::now();
③次のようにして、計測時間をミリ秒で出力します。最後はJUCEのDBGでコンソールに出力します。
//ミリ秒で処理時間を取得します。
double time = static_cast<double>(std::chrono::duration_cast<std::chrono::microseconds>(end - start).count() / 1000.0);
DBG("time:" << time);
プラグイン内の処理時間計測
先ほどの計測プログラムを、プラグインの音声処理の時間計測に埋め込んでみました。
プリプロセッサの追加を行いました。
#pragma once
#include <JuceHeader.h>
#include <chrono>//追加しました
#define MAXDELAYNUM 10.0f
processBlockの処理時間を計測したかったので、次のようにChronoクラスのプログラムで処理を挟み込みました。
void TheDelayAudioProcessor::processBlock (juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages)
{
//[1]chronoクラスの準備です。
std::chrono::system_clock::time_point start, end;
start = std::chrono::system_clock::now();//[1-1]スタート時間を記録します。
juce::ScopedNoDenormals noDenormals;
auto totalNumInputChannels = getTotalNumInputChannels();
auto totalNumOutputChannels = getTotalNumOutputChannels();
//...略...
auto block = juce::dsp::AudioBlock<float>(buffer).getSubBlock((size_t)0, (size_t)buffer.getNumSamples());
auto context = juce::dsp::ProcessContextReplacing<float>(block);
processorChain.process(context);
//[2]処理終了時間を記録します。
end = std::chrono::system_clock::now();
//[3]計測時間をミリ秒で出力します。
double time = static_cast<double>(std::chrono::duration_cast<std::chrono::microseconds>(end - start).count() / 1000.0);
DBG("time:" << time << "ms");
}
③のようにして、最後にDBGでコンソール出力を行いました。
結構処理時間にもばらつきがありますので、今の状態では、処理が速すぎて追うのも大変なので、100階の処理を平均化して出力しようと思いました。
publicなメンバとして、テスト用のカウンターと累積用の変数を作成しました。
int test_cnt = 1;
double test_time = 0.0;
processBlock関数の最後で、次のように平均化処理を行いました。
//...略...
double time = static_cast<double>(std::chrono::duration_cast<std::chrono::microseconds>(end - start).count() / 1000.0);
//以下の処理で100回の平均を作成して出力するように変更しました。
test_time += time;
if (test_cnt >= 100) {
DBG("time:" << test_time/100);
test_cnt = 1;
test_time = 0.0;
}
else {
test_cnt++;
}
}
大体、0.06msec~0.2msecくらいの処理時間ということが分かりました。