ADX2LEとUnity標準オーディオ比較

目次


ADX2とUnityの標準オーディオの比較

回避策、解決策、限定された条件などにより捉え方は異なるかと思います。
ここでは、優劣を決めるようなものではなく、純粋に比較してどう違うかの理解を深めてもらえたら幸いです。

なお、ADX2とADX2LEの区別はしていませんが、一部ADX2のみの機能の紹介もまざっています。その場合は、ADX2LEと区別して表記しています。

Unityプロジェクトの起動時間の違い

  • Unity
サウンドデータが増えた時に、楽曲など数分の曲があった場合や初回の起動時の更新などに、UnityEditorでは変換に時間がかかります。
データが増えれば増えるほど無視できない時間になります。(一度変換すれば問題ないですが、ターゲットを切り替える時などに発生します。)

  • ADX2
ADX2では先に変換圧縮済みのデータを扱うため、エディター上でも非常に軽く扱えます。
データ量が増えても別ツールで管理しているため、unityEditor側で負担が増えることはありません。

波形のデコード負荷比較

  • Unity
wav (サイズ大きい)なんでもできる。デコードしないので負荷は低い。
ogg,mp3(圧縮したい時に使う)

  • Unity5
ADPCM 負荷低いが増える

  • ADX2
ADX (ADPCM同等)負荷低い。音質はサンプリングレート次第。(相性もある)
HCA(MP3同等)ゲーム用に特化しているので比較的軽い。ループも問題ない。

リッチなエフェクトがiOS/Androidで使える(Unity IOS/AndroidのPro版なしで)

Unityでリバーブなどエフェクトを使いたい場合Unity Pro版が必要ですが、iOS Pro/Android Proそれぞれでも必要だったりします。
Unity Store

ADX2はUnityエディタの都合上Unity Pro版(約15万)が必要ですが、iOS Pro/Android Pro版は必要ありません。
つまり、iOS/Androidでエフェクト付きの音を鳴らしたい場合にUnity iOS Pro/Android Pro版が要らない。(約30万くらいお得)
- ADX2 Unity標準(4.x) Unity標準(5.x)
Unity Pro 必要 必要 不明
iOS Pro 不要 必要 不明
Android Pro 不要 必要 不明

  • Unity4.x
リスナーか、ソース側にエフェクトがつけられる。
  • Unity5ではミキサーが登場する
UnityEditor上でミキサーツリーを作って、エフェクトをつけられるようになる。どのバス(カテゴリ?ストリップ?)に所属するかをソース側で指定することができるようになる。
バスのルーティングもダイナミックに変更が可能な様子。
サウンドデザイナ、または最終ミックス調整者がUnityEditorを触れる環境なら便利な機能。

  • ADX2
バスエフェクトとして作成、スナップショットなども専用ツール側で作成する。どのバスを使うかはキュー側で設定する。
UnityEditor上では、DSPバス設定名の指定、スナップショット名の指定のみ。

つなぎ目のないループ再生

- ADX2 Unity標準(4.x) Unity標準(5.x)
ループ 簡単 面倒 簡単になる?

  • Unity4.x
  • Unity標準では全体ループは可能。
さらに、AudioSample数によるDelay再生など駆使するとイントロ付きループや、ビートに合わせるとかも可能なはず。
sample_double = (int)((sources [clipName].audio [0].clip.samples - audio.timeSamples) % 88200);
this.sources [clipName].audio [0].Play ((ulong)(sample_double));	// サンプル数遅延して再生開始される
オーディオソースを2つを交互に使うなど必要(clipを切り替えると音が途切れる、遅延でオーバーラップしている時一時的に2つになるなど)
波形のループサンプル数など何らかの方法でUnityの再生側に伝達する必要がある。

  • mp3など制限がある
mp3などのコーデック時は、ループにするとサンプルの先頭にループ分の情報が付与されるため、正確に連結再生させるにはそのサンプル数分考慮して再生リクエストをする必要がある。
  • 生wavのメモリ再生ならループも可能
→ちなみにごく短い波形であれば生wavを再生するとかもあり。BGMとか長いデータの場合はメモリを圧迫するので注意。
  • Unity5.x
→Unity5になれば、ADPCMやOgg/Vorbis拡張があるので、そちらは素直にループができるかもしれない。


  • ADX2の場合は、波形のループ再生(サンプル単位)が可能。
単純に波形側にループポイントがあるだけで、イントロ付きループも可能。(圧縮しても情報が保持される)

  • シーケンスループによる1Shot波形のループ(余韻付き)といった事も可能。
ループかそうでないかは、データに設定されているので、プログラムからはただ再生を呼ぶだけで良い。

シーケンスループの例

オーディオソース

- ADX2 Unity
複数再生 可能 単音再生のみ

  • Unityの場合、複数再生をするには、PlayClipAtPoint()などの関数もあるが、AudioSourceが発音数分増えてしまうので、大量再生時は注意が必要。
AudioSource.PlayClipAtPoint(audioClip_breakWall,pos);

例えば、呼び出し時にカウンタなどで制限したり、あらかじめAudioSourceを発音数分用意して空いているものを再利用するなどが考えられる。
public AudioSource[] audio = new AudioSource[2]; //2個用意
int playCount = 0;
void Start(){
	for(int i = 0 ;i<crashSoundList.Length;i++){
		AudioSource crashSound = gameObject.AddComponent<AudioSource>();
		crashSound.clip = breakWall;
		crashSound.rolloffMode = AudioRolloffMode.Linear;
		crashSoundList[i] = crashSound;
	}
}
void Play(){
	crashSoundList[playCount%(crashSoundList.Length-1)].transform.position = pos;
	crashSoundList[playCount%(crashSoundList.Length-1)].pitch = pos.x;
	crashSoundList[playCount%(crashSoundList.Length-1)].Play();		
	playCount++;
}

  • ADX2の場合、発音数制限は、コーデック単位、カテゴリ単位、キュー単位、ウェーブフォーム単位で行う。
音に優先度を持たせる事で、発音数限界時に、優先度の高い音が鳴るように動作する。
ので、データ側でリミットをかけておくだけで、基本的に再生するだけで良い。

オーディオクリップ

- ADX2 ADX2LE Unity
オーディオクリップ なし なし
波形指定再生 なし
  • Unityは、wavやmp3,oggを直接再生可能。
  • ADX2は、ACBという形のパッキングされた独自形式ファイルを持つ。
ファイル指定再生もサポート(Pro版)しており、wav,adx,hcaを直接再生可能。(一部機種ではmp3も対応)

音楽的なピッチ指定方法

ここでいうピッチ変化は、アナログテープやレコードスクラッチのように変化する事。
速度を上げれば音程も高く、ゆっくりまわせば音が低くなります。1.0で等速(元波形の速度)
  • Unityではピッチは、再生速度になる。2.0と入れればオクターブ上、-1.0と入れれば逆再生。
Unityでcent単位にするには以下のような計算をすると良い。
ratio = Mathf.Pow(2,pitch/12.0f); // ピッチから再生速度
pitch = 1200.0f*logf(ratio)/logf(2.0f); //再生速度からピッチ
  • ADX2ではピッチをcent単位で指定する。100centが1半音なので、1200centでオクターブ上。逆再生は不可。
※ちなみに0を指定すると無音を無限に再生し続けます。(時間が進まない・・・)

ACB(複数サウンドの再生定義ファイル+メモリサウンドのパッケージ)

- ADX2 Unity
パック なし
  • Unityでは、波形単位、あるいはUnityPackage単位など波形の持ち方が考えられる。
  • ADX2ではStreamingAseets以下にacbファイルとして圧縮済み波形データのパックとして置かれる。

ACF(エフェクト、カテゴリ、発音数制限などの情報ファイル)

- ADX2 Unity
全体設定 なし
  • Unityでは、エフェクトやカテゴリ(タグなどで)、あるいは発音数制限などはスクリプトでといったようにファイルがバラバラになる傾向。(そもそもUnityはComponentの組み合わせが基本なので)。うまく扱うことで、プレファブ化してもったりといった事も可能かもしれない。
  • ADX2では、StreamingAseets以下にacfというファイル1つに情報が収まった形となる。

エフェクト(リバーブ)

ADX2 Unity
  • Unityの場合、リバーブゾーンを指定する。Editor上で視覚的に分かりやすく配置が可能となっている。
  • ADX2の場合、バスセンドエフェクトとして、音毎にバスセンド量の設定を行う。

リバーブゾーン

ADX2 Unity
なし
  • Unityの場合、リバーブゾーンを指定する。Editor上で視覚的に分かりやすく配置が可能となっている。
  • ADX2の場合、AISACを使ってリバーブゾーンのようなものを構築する必要がある。
float dist = 0.5f;
source.SetAisac("Distance",dist);

発音数制限

- ADX2 Unity
制限処理 なし
  • Unityはメモリがある限り発音可能。(発音数が増えると処理落ち、メモリ不足などが発生)
  • ADX2はCriWareLibraryInitializer上で、あらかじめコーデック単位で最大発音数を設定可能。(初期化段階で固定でメモリ確保)
同時ストリーム数など細かい設定も可能。ただし、初期化時のみ(途中で変更できない、変更するには再初期化が必要)
CriWareLibraryInitializerの例

3Dサウンド

- ADX2 Unity
3Dサウンド
  • Unityの場合、AudioClipで3Dかどうかを決め、AudioSource側で3Dの減衰距離、カーブ、ドップラーなど変更できる。
Unity 3DSetting
  • ADX2の場合、CRI Atom Craft側で3Dの減衰距離などを指定する。後からドップラーを強くといった設定変更はできない。データ側であらかじめ設定しておく形となる。

Pan3Dの例

センター、LFE出力

- ADX2 Unity
センター/LFE出力 なし
  • ADX2ではセンター、LFEの出力を別途指定可能。ただし、5.1ch環境でないと音が出力されなくなる場合もある。ハード側でダウンミックスされて音が聞こえる(センターはL,Rから)といった事もあるので、扱う場合は注意が必要。
Pro版ではADX2側でソフトダウンミックスすることで差異を軽減するといったオプションあり。

Sin生成などからの再生

- ADX2 ADX2LE Unity
生成再生 なし
  • Unityの場合、AudioのCallbackを使う。OnAudioReadなどでメモリを渡す。
  • ADX2の場合、BusのCallbackを使う。(エフェクトを掛けた再生が可能、マイク入力後や、音声合成音などにエフェクトをかける
△なのはUnityの場合Callback系が不自由なため、対応には若干ネイティブコード側の対応が必要。

シーケンス再生

- ADX2 Unity
MOD再生 ×
シーケンス再生 ×
  • Unityの場合 Modファイルなどに対応していたりするらしい...
  • ADX2の場合、キューそのものがシーケンス化可能。CRI Atom Craft上でタイムライン上に波形を並べて作成する。
 シーケンスか波形なのかは意識せず、ただ再生するだけで良い。

エフェクト

  • UnityはAudioSourcemまたはListener側にコンポーネントを追加し設定する。
UnityReverb設定の例
  • ADX2はCRI Atom Craft側で設定する。
DSPバス設定の例
CriAtomEx.AttachDspBusSetting("DspBusSetting_0"); //バス変更
float depth = 1.0f;
int busNo = 1; //reverb
atomSourceSe.SetBusSendLevelOffset(busNo,depth);

エフェクトの種類(サウンド毎)

AudioSourceレベルで個別のサウンドごとに設定可能なエフェクトの種類です。
- ADX2 Unity
エフェクト種類 約10種 約3種

- ADX2 ADX2LE Unity
ボリューム
ピッチ ○(-2~2倍速)
パン2D
パン3D
センター/LFE/バスセンド ×
バイクアッドフィルタ ×

  • Unity:ボリューム、ピッチ、パン(2D,3D)
  • ADX2:ボリューム、ピッチ、パン(2D,3D)、センター、LFE、バスセンド、バンドパス(ハイ、ロー)、バイクアッド(ローパス、ハイパス、ローシェルフ、ハイシェルフ、ピーキング、ノッチ)
UnityもADX2もSourceに対して、ボリュームやピッチ、パンの操作が可能。

エフェクトの種類(Unity:AudioSourceコンポーネント系、ADX2:バス系)

- ADX2 Unity
バスエフェクト種類 約20種 -
AudioSourceコンポーネント - 6種

- ADX2 ADX2LE Unity Unity5
ローパス -
ハイパス -
ローシェルフ × -
ハイシェルフ × -
ピーキング × -
ノッチ × -
エコー -
ディストーション -
リバーブ -
コーラス -
ディレイ × -
コンプレッサ × -
マルチバンドコンプレッサ ×
EQ × -
ピッチシフタ/フォルマント調整(FFT) × -
フランジャー × -
振幅解析器 × -
サラウンダ × -
タイムストレッチ(グラニュラ系) × × -
タイムストレッチ(FFT) × × -
  • Unity5は分からない点は「-」になってます。Unity5ではdll化callbackできる環境であればネイティブのDSPも書けるそうなのであるいみ何でもできる気がする。

  • Unity:ローパス、ハイパス、エコー、ディストーション、リバーブ、コーラス
  • ADX2:バンドパス(ハイ、ロー)、バイクアッド(ローパス、ハイパス、ローシェルフ、ハイシェルフ、ピーキング、ノッチ)、ディレイ、エコー、ディストーション、リバーブ(I3DL2)、コーラス、コンプレッサ、イコライザ(3Band)、ピッチシフタ、フランジャー、振幅解析器、サラウンダ

エフェクトパラメータの操作

- ADX2 ADX2LE Unity
エフェクトパラメータ操作 ×

  • Unityでは、Componentに対して操作が可能。動的(プログラム上で)自由に付けたり外したりが可能。
  • ADX2では、バスのエフェクトに隠蔽されているため直接操作できない。エフェクトアルゴリズムの変更や効果の掛け方などは、DSPバス設定であらかじめ決めておく必要がある。
また、DSPの設定パターン(パラメータ違い)はスナップショットの切り替えで行えるが今のところPro版のみ。
代わりにAISACなど経由してセンド先、センド量などを操作可能となっている。

レベル解析

- ADX2 ADX2LE Unity Unity5
レベル解析
FFT解析 ×
ピッチ解析 × × ×
BPM解析 × × ×
ラウドネス解析 × ×

  • UnityではFFT解析結果を取得できます。
samples = audio.GetSpectrumData(128,1,FFTWindow.Triangle);
SourceまたはListenerのどれか1つのみ取得できます。

  • ADX2ではバス(8個)のレベルをチャンネル(LR)毎に取得できます。
CriAtom.SetBusAnalyzer(true); 					// バス解析器を有効化
CriAtomExAsr.BusAnalyzerInfo lBusInfo = CriAtom.GetBusAnalyzerInfo(0);//	Lch
level = lBusInfo.peakLevels[0];
※ADX2 Pro版ではFFT結果も取得できます。

オーディオのルーティング変更

通常は、5.1ch(L,R,C,LFE,sL,sR,Ex1,Ex2)という出力固定ですが、
プレーヤー毎にチャンネルの出力ルーティングを変更する事ができます。
例えば、2ch*4(L1,R1,L2,R2,L3,R3,L4,R4)といった設定
  /* 音声データの0チャンネルと1チャンネルを他のスピーカーへルーティング */
  criAtomExPlayer_SetSendLevel(player, 0, CRIATOMEX_SPEAKER_FRONT_LEFT, 1.0f);            // 0ch->L
  criAtomExPlayer_SetSendLevel(player, 1, CRIATOMEX_SPEAKER_FRONT_RIGHT, 1.0f);           // 1ch->R
  criAtomExPlayer_SetSendLevel(player, 0, CRIATOMEX_SPEAKER_FRONT_CENTER, 1.0f);          // 0ch->C
  criAtomExPlayer_SetSendLevel(player, 1, CRIATOMEX_SPEAKER_LOW_FREQUENCY, 1.0f);         // 1ch->LFE
  criAtomExPlayer_SetSendLevel(player, 0, CRIATOMEX_SPEAKER_SURROUND_LEFT, 1.0f);         // 0ch->Ls
  criAtomExPlayer_SetSendLevel(player, 1, CRIATOMEX_SPEAKER_SURROUND_RIGHT, 1.0f);        // 1ch->Rs
  criAtomExPlayer_SetSendLevel(player, 0, CRIATOMEX_SPEAKER_SURROUND_BACK_LEFT, 1.0f);    // 0ch->Lb
  criAtomExPlayer_SetSendLevel(player, 1, CRIATOMEX_SPEAKER_SURROUND_BACK_RIGHT, 1.0f);   // 1ch->Rb
- ADX2 ADX2LE Unity
ルーティング変更 × ×
Unityの場合若干修正が必要です。ネイティブは対応済み。マルチチャンネルエフェクト(リバーブなど)バスエフェクトは正しく動作しません。
(最終出力のルーティングが切り替わるだけ)

オーディオリソースの扱い方の違い

そもそもオーディオの管理方法の違いについて

音は途切れると目立ちます。
3Dモデルは「パッ」と消えてもそれほど気になりませんが、音の場合、「プツッ」というノイズになります。
(プツっという音は、波形変化ではなくスピーカの振動が急激に0に戻る時に発生する事が多い)
オーディオリソースは、フェードアウトして消えるのが理想です。(フェードアウト:徐々にレベルを下げて行く)

少し遅延して消える仕組みを構築するのは、Unity上でも難しいです。

例えば、Unityでミサイルの飛翔音(ループの音:AudioSource)をつけたオブジェクト(プレファブ)を用意します。
この問題として、
ミサイルを消す(Destroy)すると、消した瞬間に音が停止する。「プツッ」となる。
これは、Audioのリソースをモデルに紐付けてしまう事により発生します。

さらに、ミサイルが数個なら良いが、100個くらい出た時には、AudioSourceが増えたり、減ったり、Destroy時の負荷も大変な事になります。
(オブジェクトやコンポーネントが100個分複製(インスタンス)化されたり破棄されたりするのです)

ADX2では上記のリソース問題を解決する事ができます

まず、オーディオの管理を別のオブジェクトが行います。
シーン上にあるCriWareオブジェクトが、ACBという単位でオーディオリソースをまとめて読み込みます。

シーンに必要なオーディオアセットをあらかじめキューシートという単位でまとめ、キューという単位で再生を行います。

上の例では、100個のミサイルが鳴るとしても、オーディオリソースは1つで済みます。
また、そもそも、100個の音を判別できるでしょうか?
おそらく5~6個あれば十分です。というかそれほど音が鳴っていたら通常個々に音を判別できません。
ので、あらかじめキューリミットで5個までと決めておきます。
この時、後着優先がデフォルトとして機能するので、時間的に後発に鳴る音が、先に鳴っている音を止めてくれます。

さらに、この音を止める時、ウェーブフォームにエンベロープのリリースをつけておく事で、自動的にフェードアウト効果がかかります。
※このため、リリース時のオーバーラップしている間は実際のリソースは5個以上消費しています。

根本的に最大のリソース数というのがあり、これはCriInitializerが行っています。
ゲーム中に、発音数がどれだけ増減しても、メモリの確保量は一切変化しません。
メモリの解放でおこるガベコレのような事も発生しません。
(もちろん、発音数やInitializer自身を破棄、再構築する場合は発生しますが、頻度は相当低いはず。)

さらに音の演出にこだわるならば、50,100のミサイルが鳴った時用の音を別途用意し、
ミサイルの数に応じて付与音をならすといった事が可能になります。
これも、AISACなど使うことで、少ない手間で鳴らす事が可能になるでしょう。