Help us understand the problem. What is going on with this article?

Siv3D で音楽プレイヤーを作る

More than 1 year has passed since last update.

概要

完成形はこれです。Open でダイアログから音楽ファイルを選び、Play で再生、Pause で一時停止、シークバーを動かして再生位置を変更します。
https://lh6.googleusercontent.com/-cqhFHZ5kNx0/VHkWYj5aNsI/AAAAAAAADiI/SSH4EIZYhbo/s800/soundplayer.gif

実装 [1/4]

SoundPlayer クラスを作ります。
GUI をデフォルトの GUIStyle で初期化します。

# include <Siv3D.hpp>

class SoundPlayer
{
private:

    GUI m_gui;

public:

    SoundPlayer()
        : m_gui(GUIStyle::Default)
    {

    }

    void update()
    {

    }
};

void Main()
{
    SoundPlayer soundPlayer;

    while (System::Update())
    {
        soundPlayer.update();
    }
}

実装 [2/4]

GUI に以下のアイテムを追加します。

  • Play ボタン
  • Pause ボタン
  • Open ボタン
  • [0.0, 1.0] を調節する幅 500px のスライダー

そのあと、GUI を画面下の中央に移動させます。

# include <Siv3D.hpp>

class SoundPlayer
{
private:

    GUI m_gui;

public:

    SoundPlayer()
        : m_gui(GUIStyle::Default)
    {
        m_gui.add(L"PlayButton", GUIButton::Create(L"Play"));

        m_gui.add(L"PauseButton", GUIButton::Create(L"Pause"));

        m_gui.addln(L"OpenButton", GUIButton::Create(L"Open"));

        m_gui.add(L"Slider", GUISlider::Create(0.0, 1.0, 0.0, 500));

        m_gui.setPos((Window::Width() - m_gui.getRect().w) / 2, 360);
    }

    void update()
    {

    }
};

void Main()
{
    SoundPlayer soundPlayer;

    while (System::Update())
    {
        soundPlayer.update();
    }
}

実装 [3/4]

GUI::button(name).pushed で、指定したボタンが押されたかを取得できます。
それぞれのボタンを押したときの処理を加えます。

# include <Siv3D.hpp>

class SoundPlayer
{
private:

    GUI m_gui;

    Sound m_sound;

public:

    SoundPlayer()
        : m_gui(GUIStyle::Default)
    {
        m_gui.add(L"PlayButton", GUIButton::Create(L"Play"));

        m_gui.add(L"PauseButton", GUIButton::Create(L"Pause"));

        m_gui.addln(L"OpenButton", GUIButton::Create(L"Open"));

        m_gui.add(L"Slider", GUISlider::Create(0.0, 1.0, 0.0, 500));

        m_gui.setPos((Window::Width() - m_gui.getRect().w) / 2, 360);
    }

    void update()
    {
        if (m_gui.button(L"PlayButton").pushed)
        {
            m_sound.play();
        }
        else if (m_gui.button(L"PauseButton").pushed)
        {
            m_sound.pause();
        }
        else if (m_gui.button(L"OpenButton").pushed)
        {
            m_sound.pause();

            m_sound = Dialog::OpenSound();
        }
    }
};

void Main()
{
    SoundPlayer soundPlayer;

    while (System::Update())
    {
        soundPlayer.update();
    }
}

実装 [4/4]

GUI::button(name).enabled プロパティを変更すると、ボタンのアクティブ / 非アクティブを切り替えられます。
サウンドがロードされていないか再生中である時には Play ボタンを非アクティブに、
サウンドが再生されていないときは Pause ボタンを非アクティブにします。

スライダーがユーザによって操作されたとき GUI::slider(name).hasChanged が true を返します。
スライダーの位置に応じてサウンドの再生位置を変更します。

また、サウンドの再生位置に応じてスライダーを GUI::slider(name).setValue() で動かします。

# include <Siv3D.hpp>

class SoundPlayer
{
private:

    GUI m_gui;

    Sound m_sound;

public:

    SoundPlayer()
        : m_gui(GUIStyle::Default)
    {
        m_gui.add(L"PlayButton", GUIButton::Create(L"Play"));

        m_gui.add(L"PauseButton", GUIButton::Create(L"Pause"));

        m_gui.addln(L"OpenButton", GUIButton::Create(L"Open"));

        m_gui.add(L"Slider", GUISlider::Create(0.0, 1.0, 0.0, 500));

        m_gui.setPos((Window::Width() - m_gui.getRect().w) / 2, 360);
    }

    void update()
    {
        m_gui.button(L"PlayButton").enabled = (m_sound && !m_sound.isPlaying());

        m_gui.button(L"PauseButton").enabled = m_sound.isPlaying();

        if (m_gui.button(L"PlayButton").pushed)
        {
            m_sound.play();
        }
        else if (m_gui.button(L"PauseButton").pushed)
        {
            m_sound.pause();
        }
        else if (m_gui.button(L"OpenButton").pushed)
        {
            m_sound.pause();

            m_sound = Dialog::OpenSound();
        }

        if (m_gui.slider(L"Slider").hasChanged)
        {
            m_sound.setPosSec(m_sound.lengthSec() * m_gui.slider(L"Slider").value);
        }

        m_gui.slider(L"Slider").setValue(m_sound.streamPosSec() / m_sound.lengthSec());
    }
};

void Main()
{
    SoundPlayer soundPlayer;

    while (System::Update())
    {
        soundPlayer.update();
    }
}

完成

リファレンスの サンプル | オーディオスペクトラム を参考に簡単なオーディオビジュアライザを加えました。これで完成です!

このソースコードはパブリックドメインです。

// Siv3D March 2016
# include <Siv3D.hpp>

class SoundPlayer
{
private:

    GUI m_gui;

    Sound m_sound;

public:

    SoundPlayer()
        : m_gui(GUIStyle::Default)
    {
        m_gui.add(L"PlayButton", GUIButton::Create(L"Play"));

        m_gui.add(L"PauseButton", GUIButton::Create(L"Pause"));

        m_gui.addln(L"OpenButton", GUIButton::Create(L"Open"));

        m_gui.add(L"Slider", GUISlider::Create(0.0, 1.0, 0.0, 500));

        m_gui.setPos((Window::Width() - m_gui.getRect().w) / 2, 360);
    }

    void update()
    {
        m_gui.button(L"PlayButton").enabled = (m_sound && !m_sound.isPlaying());

        m_gui.button(L"PauseButton").enabled = m_sound.isPlaying();

        if (m_gui.button(L"PlayButton").pushed)
        {
            m_sound.play();
        }
        else if (m_gui.button(L"PauseButton").pushed)
        {
            m_sound.pause();
        }
        else if (m_gui.button(L"OpenButton").pushed)
        {
            m_sound.pause();

            m_sound = Dialog::OpenSound();
        }

        if (m_gui.slider(L"Slider").hasChanged)
        {
            m_sound.setPosSec(m_sound.lengthSec() * m_gui.slider(L"Slider").value);
        }

        m_gui.slider(L"Slider").setValue(m_sound.streamPosSec() / m_sound.lengthSec());
    }

    void drawVisualizer() const
    {
        if (!m_sound.isPlaying())
        {
            return;
        }

        const auto fft = FFT::Analyze(m_sound);

        for (int i = 0; i < 640; ++i)
        {
            const double size = Pow(fft.buffer[i], 0.6f) * 500;

            RectF(i, 200 + size, 1, -size * 2).draw(HSV(240 - i));
        }
    }
};

void Main()
{
    Graphics::SetBackground(Color(70, 80, 170));

    SoundPlayer soundPlayer;

    while (System::Update())
    {
        soundPlayer.update();

        soundPlayer.drawVisualizer();
    }
}

拡張

このプログラムを拡張するヒントです。

オーディオビジュアライザー

オリジナルのエフェクトのオーディオビジュアライザーを作ってみましょう

ループ再生

GUIToggleSwitch と Sound::setLoop(loop) を使ってループの有無を切り替えます

サウンドの情報

Dialog::GetOpenSound() でファイルパスを取得したあとに Audio::GetProperty(path) で音楽ファイルのメタデータ(タイトル、ビットレート等)を取得できます

再生時間の表示

公式リファレンスの「サウンドの再生」チュートリアルが参考になります

Siv3D について

Siv3D は C++ で楽しく簡単にゲームやメディアアートを作れるライブラリです。Kinect や Leap Motion, カメラやマイクといった多くのデバイスに対応し、複雑なインタラクションを短いコードで書くことができます。2008 年から開発を始め、2012 年に α 版を公開、2013 年 9 月には IPA 未踏事業に採択 、2014 年 9 月に CEDEC に出展、2016 年 8 月に最新版 Siv3D August 2016 をリリースしました。

Siv3D 公式ページ http://play-siv3d.hateblo.jp/

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした