大福未来研究所

大福フューチャーラボのなんか色々なアレ。プログラミング(C++/DirectX/Unity/UE4あたりやりたい)とか音楽とかの。

【UE4】BGMの現在の小節数・拍数をチェックできるようにする

先月、「UE4Meetup名古屋」「どテックNAGOYA」と2つのイベントに立て続けに登壇させて頂き、
技術ブログを更新せねばと思い立った大福です、お久しぶりです。

ちょっとした宣伝でございますが、このようなゲームを冬コミに向けて開発中です。
dfkfuturelab.wixsite.com
今回のブログ記事は、このゲームでも使った技術について書いています。

注意:この記事に書かれているやり方は、テンポが途中で変わらない&最初に無音などが入っていないBGM用ですのでご了承ください。

BGMに合わせた演出をするために

音楽ゲームなどでよくある「BGMのテンポに合わせた演出」や、
Rezなどに代表される「一定の拍数のタイミングで音が鳴るように補正する」などの技術は、
ゲーム内でテンポの管理が出来ないと難しいです。

ですから、まずはゲーム内でBGMにテンポの情報を付随させておく必要があります。
例として、このような構造体を作ります。
f:id:dfk_ohnuma:20161202110312p:plain
Audio:BGMファイル
BPM:BGMのテンポ
↑この2つがあればだいたい大丈夫です
Measure:BGMが何小節あるか(今回は使わないので忘れてください)
IsUseSmoothFade:フェード処理を使うか(今回は使わないので忘れてください)


で、サウンドを鳴らすアクタにはこのように
f:id:dfk_ohnuma:20161202111630p:plain
AudioComponentをつけておきます。(画像では5つ用意してありますが、普通は1つでいいです)
これがないとサウンドを鳴らした後に停止やらなんやらがめんどくさいことになります……
あと、float型の変数「BPM」と「BGMStartTime」を用意しておきます。

AudioComponentからサウンドを鳴らす

サウンドを鳴らすには、まずAudioComponentにSetSoundノードで構造体から持ってきたサウンドを突っ込んでやって
f:id:dfk_ohnuma:20161202111530p:plain
そのタイミングで、構造体からBPMも引っ張ってきましょう。

そしてこのサウンドをPlayノードで再生すると同時に、
GetAudioTimeSecondsノードで時間を取ってきて、BGMStartTimeに突っ込みます。
f:id:dfk_ohnuma:20161202111928p:plain

これで、
・BGMのテンポ
・BGMが再生された時間
が、アクタ内で確認できるようになりました。
これを使って、小節数や拍数をゲットできる関数「GetMeasure」を作ってみます。

GetMeasure関数を作る

ここでBGMのテンポ、BPMとはなんぞやという話になるのですが、

BPM(Beat Per Minute)……1分間に4分音符が何回鳴らされるか

というものなのです。つまり、

60.0秒÷BPM=4分音符の長さ ここから、

60.0秒÷{BPM×(n/4)}=n分音符の長さ となります。

これを利用して、GetMeasure関数では、

(現在の時間 - BGMStartTime)÷n分音符の長さ

の結果を返します。このnが1のとき、GetMeasure関数は小節数を返すのです。

f:id:dfk_ohnuma:20161202113654p:plain
私の場合はこのようなBPを組みました。

これでTickイベントにGetMeasureの引数に1,4,8,16をそれぞれ入れたものを繋ぎ、出力されたものと現在のBPMをPrintしてチェックしてみます。
f:id:dfk_ohnuma:20161202114322p:plain
毎フレームごとにプリントされているので見づらいですが、現在の小節数と拍数を計算できています。
これを使って、特定の拍数・小節数でイベントを起こしたりすることができるようになるはずです。