[VRChat]自作ShaderからAudioLinkを使う方法メモ
あくまで個人用メモなので、間違いがあるかもしれないです。
想定読者
頂点シェーダーとフラグメントシェーダーの書き方をある程度理解しており、AudioLinkを使ってみたい方
基本的な使い方
-
VCCから最新のAudioLinkパッケージを導入する。
-
シェーダーファイル内で、
#include "Packages/com.llealloo.audiolink/Runtime/Shaders/AudioLink.cginc"と書いてAudioLinkの機能をインクルードする。 -
上記でインクルードされた関数のうちの一つ、
AudioLinkData()を使うと、AudioLinkが提供する音声解析データが載っているテクスチャから指定したピクセルの色データを取り出すことができる(tex2D()みたいな感じ)。引数はuint2で、テクスチャのuv座標を指定する。

AudioLink Textureの一例
(AudioLink公式ドキュメント(https://github.com/llealloo/audiolink/tree/master/Docs)より)
- 取得した色データを用いて処理を行う。
取得したい情報のピクセル座標の算出方法
AudioLink.cgincはファイルの最初に以下のように定数を宣言している。
// Map of where features in AudioLink are.
#define ALPASS_DFT uint2(0,4) //Size: 128, 2
#define ALPASS_WAVEFORM uint2(0,6) //Size: 128, 16
#define ALPASS_AUDIOLINK uint2(0,0) //Size: 128, 4
#define ALPASS_AUDIOBASS uint2(0,0) //Size: 128, 1
#define ALPASS_AUDIOLOWMIDS uint2(0,1) //Size: 128, 1
#define ALPASS_AUDIOHIGHMIDS uint2(0,2) //Size: 128, 1
#define ALPASS_AUDIOTREBLE uint2(0,3) //Size: 128, 1
#define ALPASS_AUDIOLINKHISTORY uint2(1,0) //Size: 127, 4
#define ALPASS_GENERALVU uint2(0,22) //Size: 12, 1
#define ALPASS_GENERALVU_INSTANCE_TIME uint2(2,22)
#define ALPASS_GENERALVU_LOCAL_TIME uint2(3,22)
#define ALPASS_GENERALVU_NETWORK_TIME uint2(4,22)
#define ALPASS_GENERALVU_PLAYERINFO uint2(6,22)
#define ALPASS_THEME_COLOR0 uint2(0,23)
#define ALPASS_THEME_COLOR1 uint2(1,23)
#define ALPASS_THEME_COLOR2 uint2(2,23)
#define ALPASS_THEME_COLOR3 uint2(3,23)
#define ALPASS_GENERALVU_UNIX_DAYS uint2(5,23)
#define ALPASS_GENERALVU_UNIX_SECONDS uint2(6,23)
#define ALPASS_GENERALVU_SOURCE_POS uint2(7,23)
#define ALPASS_MEDIASTATE uint2(5,22)
#define ALPASS_CCINTERNAL uint2(12,22) //Size: 12, 2
#define ALPASS_CCCOLORS uint2(25,22) //Size: 12, 1 (Note Color #0 is always black, Colors start at 1)
#define ALPASS_CCSTRIP uint2(0,24) //Size: 128, 1
#define ALPASS_CCLIGHTS uint2(0,25) //Size: 128, 2
#define ALPASS_AUTOCORRELATOR uint2(0,27) //Size: 128, 1
#define ALPASS_FILTEREDAUDIOLINK uint2(0,28) //Size: 16, 4
#define ALPASS_CHRONOTENSITY uint2(16,28) //Size: 8, 4
#define ALPASS_FILTEREDVU uint2(24,28) //Size: 4, 4
#define ALPASS_FILTEREDVU_INTENSITY uint2(24,28) //Size: 4, 1
#define ALPASS_FILTEREDVU_MARKER uint2(24,29) //Size: 4, 1
#define ALPASS_GLOBAL_STRINGS uint2(40,28) //Size: 8, 4
これらはその定数名[1]の機能に対応付けられたテクスチャの範囲の最初の部分を示している。それぞれの定数名の意味は、公式ドキュメント(https://github.com/llealloo/audiolink/tree/master/Docs)を参照。
例えば、公式ドキュメントによれば、ALPASS_AUDIOLINKは(0,0)から横1px,縦4pxで音声の各周波数に対する音量のデータを提供している。(0,0)がBass帯, (0,1)がLowMid帯, (0,2)がHighMid帯, (0,3)がTreble帯として割り当てられている。

これらは例えば以下のようにして用いる。
fixed4 frag (v2f i) : SV_Target
{
float impulse = AudioLinkData( ALPASS_AUDIOLINK + uint2( 0, i.uv.y * 4. ) );
return fixed4(impulse, impulse, impulse, 1.0);
}

結果
AudioLink Textureからデータを取得する関数
上記ではデータを取得する関数としてAudioLinkData()を使ったが、AudioLinkにはこれを含めて4つのデータ取得用関数がAudioLink.cginc内に定義されている。それぞれの機能について解説する。なお、分かりやすさのために若干本来の実装と異なる書き方をしているものもあるが、使用する側としては不都合はないはず。
-
float4 AudioLinkData(uint2 xycoord)
単純に、指定されたピクセル座標での色を取ってくる。 -
float4 AudioLinkDataMultiline(uint2 xycoord)
AudioLinkData() に改行機能が付いたもの。AudioLinkが提供する機能の一部は複数行にまたがってデータが提供されていることもあるので、それらを使用する際はこちらを使うと便利だと思う。 -
float4 AudioLinkLerp(float2 xy)
指定したピクセルと、その右隣のピクセルのデータを線形補完してくれる。内部実装はとなっている。return lerp( AudioLinkData(xy), AudioLinkData(xy+int2(1,0)), frac( xy.x ) );
波形表示をするとき、こちらを使うと波が滑らかになる。 -
float4 AudioLinkLerpMultiline(float2 xy)
AudioLinkLerp() の複数行対応版。
ワールド側でのAudioLinkのセットアップ
アバターのシェーダーとして使用する場合はこの章は読み飛ばしても問題ない。
-
Tools/AudioLink/Add AudioLink Prefab to SceneでPrefabをシーンに追加 - 僕の場合は音声ファイルを直に流したかったので、中にあるAudioLinkInputは消して、Audio Sourceコンポーネントを持つオブジェクトを新たに作成してAudioLinkのスクリプトに参照を設定したが、この辺りはやや理解が怪しい。
- Audio Sourceで
ゲーム開始時に再生にチェックを入れるなり、Udonから再生するなりして音を流し始めると、AudioLinkが自動で音声を解析してテクスチャを毎フレーム作成してくれる。
この記事がお役に立ちましたら、いいねを押していただけると大変励みになります。
(余談: ここまで辿り着くのに5時間くらいかかりました... 自分がシェーダー初心者なのもあるかもしれませんが、AudioLink難しい...)
-
ALPASSはたぶんAudioLinkPassの略 ↩︎
Discussion