Edited at

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/