CRIADX2のビート同期を使ってリズムに合わせた演出をつける

音ゲーを作っていると、リズムに合わせてタイミングの良い演出をつけたくなることがあるでしょう。
今回は、CRIADX2のビート同期を使ってさくっと実装してみます。
実行環境はUnityを使用しています。

# CRIADX2とは
株式会社CRI・ミドルウェアから提供されている、オーディオミドルウェアです。
商用ですが、無料版の[ADX2 LE](https://www.adx2le.com/index.html)もありますので、お試ししたい方はそちらからどうぞ。

# ビート同期の機能とデータの作成
ADX2にはビート同期機能が存在し、データ内にビート同期情報を埋め込み、コールバックで呼び出すことでビートに同期した演出を作成することが可能です。
また、途中でビート情報の変更も可能です。

##  素材データの準備
再生する音声データを準備します。
今回は、途中でBPMが切り替わる素材を試したいのですが、ちょうど良い素材がないので、２つの曲を１つに繋げた素材を作成し、wavファイルにしました。
（AtomCraftには１つのキューに複数の素材を入れて再生することもできますが、ビート同期が未対応の様子なので、1ファイルのwavとして準備しました） 

## オーディオデータの作成
オーディオデータにビート同期データを挿入します。
オーディオデータの作成には専用ツールAtomCraftを使用します。

新規プロジェクトを作り、準備した音声データを「マテリアルツリー」に入れます。
プロジェクトにCueを作成し、トラックに音声データを追加します。
![スクリーンショット](https://qiita-image-store.s3.amazonaws.com/0/314163/e893a378-f529-0e6d-0fe6-b8de49e566e0.png)

## ビート同期の設定
「タイムライン」で「ビート同期情報の作成」で同期情報を追加します。
![スクリーンショット](https://qiita-image-store.s3.amazonaws.com/0/314163/86efc03d-0d7f-0edb-bc8e-c0eba2d69a5a.png)

「BeatSync」を曲の頭に設定しましょう。１つ目は0秒目から再生なので、0:00:00に。
BeatSyncを複製して、もう一つをBPMが変わった２曲目の頭に設定します。

「BeatSync」をダブルクリックすると、「BPM」「分子」が設定可能です。
（分母は変更不可。半拍などを表現したい場合は、BPMを倍速にして分子を8にすればいけるかもしれません）
![スクリーンショット](https://qiita-image-store.s3.amazonaws.com/0/314163/009d48ef-147d-e313-753a-a20903d06fad.png)

また、ビートパターンの設定も可能です。今回は最初は１拍ずつ、BPM変更後は２拍・４拍のみのオフビートに設定してみました。
画面右側の「ビートパターン」で、１つ目は４拍全て、２つ目はオフ・オン・オフ・オンと設定されていることが分かると思います。

ここまで作ったら、キューシートをビルドします。
「ビルド」→「Atomキューシートのバイナリビルド」を選択。
ターゲットは「PC」、一番下の「Unity Assets出力」のチェックをお忘れなく。
正しく設定できたら「ビルド」を選択。
指定したビルドフォルダにPC/Assets/StreamingAssets/フォルダが生成され、その中にacb,awb,acfファイルができていると思います。

# Unityでビート同期演出を実装
ここからはUnityを使用してBGMの再生とリズムに合わせてスケーリングする表示演出の作成を行います。

## Unityプロジェクトでの再生準備
Unityの新規プロジェクトを作成してCRIミドルウェアをプラグインを導入します・・・というのが一般的な手順ですが、面倒なのでここは提供されているsampleを利用し、サンプルシーンをコピーします。
criatom/basicのいずれかのシーンをコピーし、
CRIWARE,CriWareErrorHandler,CriWareLibraryInitializer以外不要なものを削除します。

先程生成された、acb,awb,acfファイルをプロジェクトのStreamingAssetsフォルダに追加しましょう。

シーン上のCRIWAREオブジェクトに「Cri Atom(Script)」が存在していますので、ここのCueSheet情報を、先程のキューシート名に書き換えます。

また、シーンにオブジェクトを配置し、「Cri Atom Source」コンポーネントを追加します。正しいCueSheet名、CueName名を入れて実行、正しく再生されるか確認します。

## ビート同期コールバックの設定

今回は、ビートのたびにテクスチャが大きくなる演出を作ります。
SpriteをスケーリングさせるMonoBehaviorをSpriteにアタッチします。
BeatOn()がビート同期が来るたびに呼び出したい関数となります。

```cs:SpriteScaler.cs
	/// <summary>
	/// ビートイベントが来た時に実行する関数
	/// </summary>
	public void BeatOn()
	{
		// サイズを最大に
		SetScale(MaxScale);
	}
	
	void SetScale(float scale)
	{
		// Spriteにスケールを設定
		nowScale = scale;
		this.transform.localScale = new Vector3(nowScale, nowScale, 1.0f);
	}
	
	void Update()
	{
		// サイズが大きければ元のサイズまで徐々に戻す
		SetScale(Mathf.Max(NormalScale, nowScale - (ScaleSpeed * Time.deltaTime)));
	}
```

ビート同期時に呼び出したい関数をコールバックに登録します。
BeatOn()をコールバック関数で呼び出します。

```cs:BeatSyncTest.cs
	[SerializeField] private SpriteScaler spriteScaler;

	void callback(ref CriAtomExBeatSync.Info info)
	{
		spriteScaler.BeatOn();
	}
	
	/* Initialization process */
	void Start()
	{
		CriAtomExBeatSync.SetCallback(this.callback);
	}
```

これでビート同期コールバック登録ができました。
実行したものがこちらになります。

# ビート同期の準備
<blockquote class="twitter-tweet" data-lang="ja"><p lang="en" dir="ltr">BeatSyncTest <a href="https://t.co/thxkyN6oQf">pic.twitter.com/thxkyN6oQf</a></p>&mdash; maki_n (@makin13652923) <a href="https://twitter.com/makin13652923/status/1075750067624001538?ref_src=twsrc%5Etfw">2018年12月20日</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 

BPMの拍に同期して音符が動くこと、曲が変わったタイミングでBPMと拍のとり方が変わったことが確認できました。

今回のサンプル作成にあたり、以下の素材を使わせていただきました。ありがとうございました。
楽曲素材：[Music-Note.jp](http://www.music-note.jp/index.html)
絵素材：[いらすとや](https://www.irasutoya.com)