LoFiBeats・84分の作業用BGMを作成しました!

JUCEプログラミング、Draw audio waveform 6、クリックで再生位置の変更

1_プログラミング

波形の位置をクリックして再生位置を変更できるようになります。

マウスの操作で変更できると本格感があるよね

JUCEチュートリアル、Draw audio waveformsの項目を進めています。ZIPでダウンロードできる「AudioThumbnailTutorial_04.h」のプログラムでは、波形画像の位置をクリックすることでその場所から再生する、という機能が追加されていました。今回は、この機能を前回のプログラムに追加していきたいと思います。

チュートリアルのページはこちらになります。

こんな人の役に立つかも

・JUCEチュートリアル「Draw audio waveforms」の「AudioThumbnailTutorial_04.h」の実装を知りたい人

・JUCEでマウスイベントを取得したい人

スポンサーリンク

DrawComponent.h

SimplePositionOverlayクラスの定義で、AudioTransportSourceクラスのtransportSourceのconst指定をはずしました。以前は、変更できないようにconst指定していましたが、今回、MainComponentクラスの初期化時に渡されるtransportSourceのポインタを受け取り、SimplePositionOverlayクラスの中でtransportSourceの再生位置を変更します。そのため、const指定を取り除く必要がありました。

class SimplePositionOverlay : public juce::Component,
    private juce::Timer
{
public:
    //[1]コンストラクタの引数からconstを取り除きました。
    SimplePositionOverlay(/*const*/ juce::AudioTransportSource& transportSourceToUse);

    void paint(juce::Graphics& g) override;
    //[3]mouseDown関数をoverrideしておきます。
    void mouseDown(const juce::MouseEvent& event) override;

private:
    void timerCallback() override;

    //[2]privateなメンバのtransportSourceもconstを取り除きます。
    //const juce::AudioTransportSource& transportSource;
    juce::AudioTransportSource& transportSource;

    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(SimplePositionOverlay)
};

ヘッダファイル内でconst指定してる部分は[1]と[2]なのでこの部分を変更しました。

[3]では、マウスのイベントを取得するための関数、mouseDown関数をComponentクラスからoverrideしました。

DrawComponent.cpp

コンストラクタ

ヘッダファイルのコンストラクタの引数から、const指定を取り除いたので、cppのコンストラクタ引数も同様にconst指定を取り除く変更を行いました。

SimplePositionOverlay::SimplePositionOverlay(/*const*/ juce::AudioTransportSource& transportSourceToUse)
    : transportSource(transportSourceToUse)
{
    startTimer(40);
}

mouseDown関数の追加

Componentクラスには「mouseDown」というマウスクリックイベントを取得できるイベントハンドラが備わっています。そのため、mouseDownをoverrideして利用することができます。

void SimplePositionOverlay::mouseDown(const juce::MouseEvent& event)
{
    auto duration = transportSource.getLengthInSeconds();

    if (duration > 0.0)
    {
        //[1]X方向のクリック位置を取得して波形の何秒かを計算します。
        auto clickPosition = event.position.x;
        auto audioPosition = (clickPosition / (float)getWidth()) * duration;

        //[2]再生位置を移動させます。
        transportSource.setPosition(audioPosition);
    }
}

音声ファイルを操作できるAudioTransportSourceクラスのtransportSourceオブジェクトは、mainComponentクラスから渡されたポインタです。そのため、SimplePositionOverlayクラスとMainComponentクラスで共有しているようなイメージでしょうか。transportSourceはconst指定を取り除いたので、MainComponentで作成されたAudioTransportSourceクラスのオブジェクトであるtransportSourceオブジェクトにアクセスすることで、SimplePositionOverlayクラスからの音声の操作を可能にしています。

処理内容としては、音声が0秒でない場合、のみ音声の位置取得処理に進むような条件となっています。

[1]では、描画領域の幅のX方向の位置を取得します。MouseEventクラスを引数としてもらいますので、eventのpublicなメンバ「position」の「x」という変数を確認することで取得ができるようです。

Xの位置をgetWidthで得られるコンポーネントの幅で割ると、波形全体のどの位置をクリックしたかの相対位置が得られますので、これに波形全体の秒数を掛け合わせて、波形の何秒がクリックされたかを得ることができます。(波形の幅がコンポーネントの幅と一致しているので、この計算ができます。)

[2]で、ここで得られた秒すうをtransportSourceオブジェクトの「setPosition」関数に指定することで再生位置の移動が行われます。

ポインタでtransportSourceをクラス間で参照できる、という良い参考例にもなりそうです。

タイトルとURLをコピーしました