音声のループも簡単にできるみたいです。
JUCEのクラスは強力だね~
前回、演習ファイル「PlayingSoundFilesTutorial_03.h」を参考にして、音声ファイルの再生時間を表示する機能を追加しました。「PlayingSoundFilesTutorial_03.h」を見ていると、どうやら、音声のループ機能も含まれているようで、前回はこの部分を切り離して実装しました。今回は、せっかく例にあるので、音声のループ部分も実装していきたいと思います。
公式チュートリアルのzipファイル、「PlayingSoundFilesTutorial_03.h」を参考にしています。
こんな人の役に立つかも
・JUCEフレームワークに入門したい人
・JUCEで音声プログラミングを学びたい人
・JUCEのAudioチュートリアルを進めている人
ループ機能
実装すると、次のスクリーンショットのように、ループのトグルボタンができ、チェックが入っていると音声ファイルのループ再生ができるようになります。
MainComponent.hの変更
MainComponent.hに次のプログラムを追加しました。
public:
//...略...
void updateLoopState(bool shouldLoop);//[1]
音声ファイルがループするかどうか制御する関数です。
//==============================================================================
void paint (juce::Graphics& g) override;
void resized() override;
private:
//...略...
void stopButtonClicked();
void loopButtonChanged();//[2]ループのチェックを入れるトグルボタンのコールバック関数として登録する関数です。
//...略...
juce::Label currentPositionLabel;
//[3]
ループのオンオフのためのトグルボタンオブジェクトです。
juce::ToggleButton loopingToggle;
[1]では、音声ファイルをループするかどうかを制御するための関数のプロトタイプ宣言をしています。この関数の中身は後程実装しますので、詳細は後程記載します。
[2]は、ループのオンオフのためのトグルボタンに紐づけるコールバック関数のプロトタイプ宣言です。これも、後程、コンストラクタで紐づけ、内容はcppに記載していきます。
[3]で、ループのオンオフをするためのトグルボタンオブジェクトを定義しました。
MainConponent.cppの変更
コンストラクタ
コンストラクタで、トグルボタンのloopingToggleをGUI上で可視化して、ボタンのテキストを変更、最後にコールバック関数「loopButtonChanged」関数をラムダ式で紐づけます。
//...略...
//↓以下の3行を追加しました。
addAndMakeVisible(&loopingToggle);
loopingToggle.setButtonText("Loop");
loopingToggle.onClick = [this] { loopButtonChanged(); };
formatManager.registerBasicFormats();
transportSource.addChangeListener(this);
//...略...
updateLoopState関数
次に、cppファイルの一番最後に、先ほどプロトタイプ宣言をした「updateLoopState関数」を実装します。
void MainComponent::updateLoopState(bool shouldLoop)
{
if (readerSource.get() != nullptr)
readerSource->setLooping(shouldLoop);
}
updateLoopState関数の中では、readerSourceの「setLooping」関数を利用してループするかどうかのフラグをオンオフしています。readerSourceは、「AudioFormatReaderSource」クラスのオブジェクトです。
あとは、このupdateLoopSourceを任意のタイミングで呼び出すと音声ファイルのオンオフ状態の変化ができます。
playButtonClicked
先ほど作成したupdateLoopState関数を呼び出すタイミングとして、playButtonClicked関数の最初が良いです。音声の開始時点で見に行くことで、これから再生する音声がループするのか、確実に反映させることができます。
void MainComponent::playButtonClicked()
{
updateLoopState(loopingToggle.getToggleState());//←ここで呼び出すように追記しました。
if ((state == Stopped) || (state == Paused))
changeState(Starting);
else if (state == Playing)
changeState(Pausing);
}
loopButtonChanged関数
cppの一番下、(updateLoopState関数の↓)にトグルボタンのコールバック関数「loopButtonChanged」を実装しました。この関数も、updateLoopStateを呼び出すタイミングの一つとするのが良いです。音声ファイルへのループの設定が、トグルボタンを押されたときに設定されるからです。そのため、音声の再生中でもループのオンオフを切り替えることができます。
void MainComponent::loopButtonChanged()
{
updateLoopState(loopingToggle.getToggleState());
}
resized関数への追記
GUIに反映させるために、resized関数にトグルボタンの配置に関するプログラムを追加します。
void MainComponent::resized()
{
openButton.setBounds(10, 10, getWidth() - 20, 20);
playButton.setBounds(10, 40, getWidth() - 20, 20);
stopButton.setBounds(10, 70, getWidth() - 20, 20);
currentPositionLabel.setBounds(10, 130, getWidth() - 20, 20);
//↓このように追加しました。
loopingToggle.setBounds(10, 100, getWidth() - 20, 20);
}
AudioFormatReaderSourceクラスのループフラグを制御する、という点がポイントでしたね。