ADX2をプレビュー再生するだけのツールをC++で作る

# 何をしたのか？
ADX2のデータをちょっとプレビューしたい時に便利なツールをつくってみた。

[C++でADX2LE](https://w.atwiki.jp/soundtasukeai/pages/33.html)　を参考に

# ソースコード

``` SoundManager.h
#pragma once

#include <cri_xpt.h>
#include <cri_atom_wasapi.h>
#include <iostream>
#include <string>
#include <iterator>
#include <vector>
#include <cctype>

using namespace std;

class SoundManager
{
public:
	SoundManager(char* acf_file, char* acb_file, char* awb_file);
	~SoundManager();

	//void Play(string &mml);
	void Play(const char* cueName);

private:

	/* エラーコールバック関数 */
	static void user_error_callback_func(const CriChar8 *errid, CriUint32 p1, CriUint32 p2, CriUint32 *parray)
	{
		const CriChar8 *errmsg;

		/* エラー文字列の表示 */
		errmsg = criErr_ConvertIdToMessage(errid, p1, p2);
		cout << ("%s\n", errmsg);

		return;
	}

	static void *user_alloc_func(void *obj, CriUint32 size)
	{
		void *ptr;
		ptr = malloc(size);
		return ptr;
	}

	static void user_free_func(void *obj, void *ptr)
	{
		free(ptr);
	}

private:
	CriAtomExPlayerHn		player;		/* 再生プレーヤ */
	CriAtomExVoicePoolHn	voice_pool;	/* ボイスプール */
	CriAtomExAcbHn			acb_hn;		/* ACBハンドル(音声データ) */
	CriAtomDbasId			dbas_id;	/* D-BASの作成*/

	CriAtomExPlaybackId		playback_id;	/* VoiceキューのプレイバックID(再生開始時に保持する) */

};



```

``` SoundManager.cpp

#include "SoundManager.h"

/* 最大ボイス数を増やすための関連パラメータ */
#define MAX_VOICE			(24)
#define MAX_VIRTUAL_VOICE	(MAX_VOICE + 8)		/* バーチャルボイスは多め */
#define MAX_CRIFS_LOADER	(MAX_VOICE + 8)		/* 読み込み数も多めに */

/* 最大サンプリングレート（ピッチ変更含む） */
#define MAX_SAMPLING_RATE	(48000*4)

SoundManager::SoundManager(char* acf_file, char* acb_file, char* awb_file)
{
	/* エラーコールバック関数の登録 */
	criErr_SetCallback(user_error_callback_func);

	/* メモリアロケータの登録 */
	criAtomEx_SetUserAllocator(user_alloc_func, user_free_func, NULL);

	/* ライブラリの初期化（最大ボイス数変更） */
	CriAtomExConfig_WASAPI lib_config;
	CriFsConfig fs_config;
	criAtomEx_SetDefaultConfig_WASAPI(&lib_config);
	criFs_SetDefaultConfig(&fs_config);
	lib_config.atom_ex.max_virtual_voices = MAX_VIRTUAL_VOICE;
	fs_config.num_loaders = MAX_CRIFS_LOADER;
	lib_config.atom_ex.fs_config = &fs_config;
	criAtomEx_Initialize_WASAPI(&lib_config, NULL, 0);

	/* D-Basの作成（最大ストリーム数はここで決まります） */
	dbas_id = criAtomDbas_Create(NULL, NULL, 0);

	/* ACFファイルの読み込みと登録 */
	criAtomEx_RegisterAcfFile(NULL, acf_file, NULL, 0);

	/* DSP設定のアタッチ */
	criAtomEx_AttachDspBusSetting("DspBusSetting_0", NULL, 0);

	/* ボイスプールの作成（最大ボイス数変更／最大ピッチ変更／ストリーム再生対応） */
	CriAtomExStandardVoicePoolConfig vpool_config;
	criAtomExVoicePool_SetDefaultConfigForStandardVoicePool(&vpool_config);
	vpool_config.num_voices = MAX_VOICE;
	vpool_config.player_config.max_sampling_rate = MAX_SAMPLING_RATE;
	vpool_config.player_config.streaming_flag = CRI_TRUE;
	voice_pool = criAtomExVoicePool_AllocateStandardVoicePool(&vpool_config, NULL, 0);

	/* ACBファイルを読み込み、ACBハンドルを作成 */
	acb_hn = criAtomExAcb_LoadAcbFile(NULL, acb_file, NULL, awb_file, NULL, 0);

	/* プレーヤの作成 */
	player = criAtomExPlayer_Create(NULL, NULL, 0);

	criAtomExPlayer_SetCueId(player, acb_hn, 1);

}


SoundManager::~SoundManager()
{
	/* DSPのデタッチ */
	criAtomEx_DetachDspBusSetting();

	/* プレーヤハンドルの破棄 */
	criAtomExPlayer_Destroy(player);

	/* ボイスプールの破棄 */
	criAtomExVoicePool_Free(voice_pool);

	/* ACBハンドルの破棄 */
	criAtomExAcb_Release(acb_hn);

	/* ACFの登録解除 */
	criAtomEx_UnregisterAcf();

	/* D-BASの破棄 */
	criAtomDbas_Destroy(dbas_id);

	/* ライブラリの終了 */
	criAtomEx_Finalize_WASAPI();
}



void SoundManager::Play(const char* cueName)
{

	criAtomExPlayer_SetCueName(player, NULL, cueName);
	playback_id = criAtomExPlayer_Start(player);

	{
		while (true)
		{
			if (criAtomExPlayer_GetStatus(player) == CriAtomExPlayerStatus::CRIATOMEXPLAYER_STATUS_STOP)break;
			if (criAtomExPlayer_GetStatus(player) == CriAtomExPlayerStatus::CRIATOMEXPLAYER_STATUS_ERROR)break;
			if (criAtomExPlayer_GetStatus(player) == CriAtomExPlayerStatus::CRIATOMEXPLAYER_STATUS_PLAYEND)break;

			Sleep(0);
		}

		cout << "end" << endl;
		criAtomExPlayer_Stop(player);
	}




}
```

``` adx2preview.cpp

#include <iostream>
#include "SoundManager.h"
using namespace std;

int main(int argc, char* argv[])
{
	std::cout << argv[0] << std::endl;
	std::cout << argv[1] << std::endl;　//ACFパス
	std::cout << argv[2] << std::endl;　//ACBパス
	std::cout << argv[3] << std::endl;　//AWBパス
	std::cout << argv[4] << std::endl;　//キュー名

	SoundManager sm(argv[1], argv[2], argv[3]);

	sm.Play(argv[4]);
}

```

これをADX2のサンプルの設定とかを参考にコンソールツールとしてビルドする。

# UnityEditor拡張から呼ぶ

``` EditorPreviewADX2.cpp
				if (GUILayout.Button ("Editor時再生テストボタン")){

					// 別アプリ(プロセス)起動
					System.Diagnostics.Process proc = new System.Diagnostics.Process ();
					proc.StartInfo.FileName = @"C:\Chronos\adx2preview\adx2preview\Release\adx2preview.exe";   
					proc.StartInfo.Arguments = "\"C:\\Chronos\\Assets\\StreamingAssets\\Megalith.acf\" \"C:\\Chronos\\Assets\\StreamingAssets\\BGM.acb\" \"C:\\Chronos\\Assets\\StreamingAssets\\BGM.awb\" \"Chronos\"";
					proc.Start ();
				}
```