Wwise 2023.1では、2017年にリリースされたWAAPI(Wwise Authoring API)でこれまでにない大きなアップデートが行われています。What's New in Wwise 2023.1に新機能の一覧が記載されていますので、まだチェックされていない方はぜひご覧ください。WAAPI 関連の変更点が多数記載されています。私たちが具体的にどのような変更を実施したのかを、このブログで詳しく説明したいと思います。
そもそもWAAPIとは?
WAAPIはWwiseオーサリングアプリケーションと外部アプリケーションの間のやりとりを可能にするものであり、PythonスクリプトやC++プログラムのようなものです。詳しく知りたい方はこちらのページでご確認ください:
https://www.audiokinetic.com/ja/library/edge/?source=sdk&id=waapi.html
WAAPIを使って行うことができる一般的なタスク:
- オーディオファイルのインポート
- オブジェクト構造の作成
- サウンドバンクの生成
- プロジェクトのクエリ(WAQL使用)
- これ以外にもたくさんあります。
実は知らないうちにあなたもすでにWAAPIを使っているかもしれません。WAAPIは裏で以下のようなことに使われています:
- REAPERからWwiseへの転送:
- Audiokinetic ReaWwise (https://github.com/audiokinetic/ReaWwise)
- LKC GRIM SYNC (https://www.lkctools.com/grimsync)
- ゲームエンジンとのインテグレーション:
- Wwise Unrealインテグレーション
- Wwise Unityインテグレーション
- オーディオファイルの管理
- BaseheadとWwiseのインテグレーション(https://baseheadinc.com/)
- SoundlyとWwiseのインテグレーション(https://getsoundly.com/)
- SoundminerとWwiseのインテグレーション(https://store.soundminer.com/)
WAAPIをゲーム開発パイプラインに統合することは、一部のタスクを自動化し、日々のデータフロー内のデータの質を改善するためにもよい方法です。
今回のリリースの目的
Wwiseをリリースするたびに、私たちはユーザの皆さまの声と私たちのロードマップのバランスを取るようにしています。今回のリリースにあたり、最もよく聞かれたご意見の1つとしてソースコントロール環境でのWAAPIの使用がありました。2つ目のご意見も私たちのロードマップと一致していて、インタラクティブミュージックオブジェクトを含むWwiseのデータモデルの一部をリファクタリングし、WAAPIが対応する範囲を広げるということでした。ミュージックオブジェクトについては後述することにし、ソースコントロールの話からしたいと思います。
ソースコントロール対応
2017年にWAAPIを開発した当初、MVP(Minimum Viable Product)として送り出すためにいくつかの要素をカットする必要がありました。そのような要素の1つがソースコントロールへの対応でした。数多くのユーザのパイプラインにWAAPIが統合された今こそ、この欠点をどうにかする必要がありました。
今回私たちは以下のことを検討しました:
- オーディオファイルをインポートした時のポップアップのブロック。単純な例としてReaWwiseを使いREAPERからレンダリングを行うと、毎回Wwiseでソースコントロールのポップアップが表示されてREAPERのユーザインターフェースを隠してしまい、結果的にユーザエクスペリエンスが悪化してしまいます。
- ワークユニットの作成、削除、移動、名前変更。ファイルシステム操作に関連することはすべてソースコントロールに登録する必要があります。ワークユニットを作成することのできるWAAPI関数は多くあります。
- コマンドラインにおけるソースコントロール。WwiseConsole.exeを使用した場合、すべてのソースコントロールが利用できる状態ではありませんでした。
- オーディオファイルの管理。Originalオーディオファイルを自動的に整理しなおすことが不可能でした。プロジェクトを破壊せずにオーディオファイルを移動したり名前変更したりするには、File Managerを使うしか方法がありませんでした。大きなプロジェクトではアセット整理を自動化させることが非常に重要です。
これらの目標を達成するために、私たちはソースコントロールプラグインの仕組みを再確認する必要がありました。一番の目的は私たちのすべてのAPIが沈黙を守り、ソースコントロールと完全に互換性をもつことでした。
テスト戦略
作業をはじめる前にテスト戦略について考える必要がありました。ソースコントロールをテストすることは常に手間のかかる仕事であり、見落としてはいけません。今回の変更内容の範囲があまりにも広かったため、自分たちで気が付かないうちに何かを破壊してしまう恐れがありました。嬉しいことに追加した機能のおかげで、今までできなかったテストの自動化が可能となりました。
このため私たちが自動テストフレームワークとしてPerforceに対応したことは当然でした。すべてのWAAPI 関数をすでにテストフレームワークでカバーできているため、新しいソースコントロール機能においても同じアプローチを取り、変更内容の品質について自信を持つことができます。
ユーザインターフェース
まず最初に、ソースコントロールプラグインが作成するユーザインターフェースを私たちがコントロールできることが重要でした。自動化をブロックする主な要因となるためです。2種類のポップアップがありました:
- チェックアウトのダイアログ(下図)のようなカスタムポップアップ。
- ソースコントロールログ
私たちがダイアログを削除するたびに、WAAPI関数で同等のオプションを提供し、ファイルに対して自動的にチェックアウトや追加するためのマークが行われるようにする必要がありました。最終的に自動ソースコントロール操作に対応したWAAPI関数は以下の計10種です:
- ak.wwise.console.project.open
- ak.wwise.ui.project.open
- ak.wwise.core.audio.import
- ak.wwise.core.audio.importTabDelimited
- ak.wwise.core.object.copy
- ak.wwise.core.object.create
- ak.wwise.core.object.delete
- ak.wwise.core.object.move
- ak.wwise.core.object.set
- ak.wwise.core.project.save
たくさんのAPIにソースコントロールへの対応を追加することは簡単ではありませんでした。Wwiseオーサリングのコアには、修正すべきコードパスがあまりにも多くありました。テスト自動化の範囲がすでに広かったことは救いでしたが、ワークユニットを操作する時にこの範囲を広げることはちょうどよい機会となりました。
次にログダイアログの代替となるものを探しました。私たちはすべてのソースコントロールメッセージをLogsビューへ回すことに決め、そのための新しいタブ(下図)もつくりました:
幸い集約化されたログがWAAPIですでに公開されていました。私たちはAPIに新しいチャンネルを追加しただけです。
極限まで自動化を
この時点で間接的なソースコントロール操作をほぼカバーできていました。例えばak.wwise.core.object.setでワークユニットオブジェクトを作成した場合、これに関連するWWUファイルに対してAdd操作がトリガーされます。一方、WAVファイルの名前変更や移動など、WAVファイルに対してソースコントロール操作を直接行う場合はどうでしょう。ソースコントロールのコアを直接テストする方法がなく、これまでは非ソースコントロール操作を通してテストするしかありませんでした。
そこでWAAPIに完全なソースコントロールAPIを追加することにしました。ソースコントロール機能に直接マッピングされる以下の関数を追加しました:
- ak.wwise.core.sourceControl.add
- ak.wwise.core.sourceControl.checkOut
- ak.wwise.core.sourceControl.commit
- ak.wwise.core.sourceControl.delete
- ak.wwise.core.sourceControl.getSourceFiles
- ak.wwise.core.sourceControl.getStatus
- ak.wwise.core.sourceControl.move
- ak.wwise.core.sourceControl.revert
- ak.wwise.core.sourceControl.setProvider
さらに先にすすめるためにwaapi-server, 、generate-soundbank、そしてtab-delimited-importを使用する時のソースコントロール対応をWwiseConsoleに直接追加しました。これらの機能では自動化をさらに先へすすめ、機能を本当に分離させることができました。
WAAPIカバレッジの拡大
ここでWAAPIのカバレッジ拡大という私たちの目標について、もう少し詳しく説明します。ここ数年Wwiseの各種データモデルのリファクタリングを数多くすすめ、より汎用的にして既存WAAPI関数を通してアクセスできるようにしてきました。今回のリリースではInteractive Music Hierarchyに焦点を当てました。例えばこれまでWAAPIで一部のミュージックオブジェクトを設定することができませんでした。以下はミュージックオブジェクトに関連して2023.1において公開したものです:
- ミュージックスイッチコンテナのAssociationsおよびArgument
- ミュージックシーケンスコンテナのPlaylist Root
- ミュージックスティンガーのTriggerおよびSegmentのリファレンス
- ミュージックオブジェクトのTransition Root
上記のミュージック要素に加え、以下も公開しました:
- ダイアログイベントのEntries
- オーディオファイルソースのMarkers
- ランダムコンテナやシーケンスコンテナのPlaylist
インタラクティブミュージックの例
次にコードを少し掘り下げてみます。再生可能なインタラクティブミュージック構造を作成し、ミュージックスイッチコンテナ、ミュージックプレイリストコンテナ、ミュージックセグメント、ミュージックトラック、ミュージックキュー、そしてミュージックトランジションを設定します。コードと共に順を追いたい方は、GitHubでこの例全体をダウンロードすることができます:
https://gist.github.com/ak-brodrigue/b98d12e67167eb0e00291cd9c2c02164
この例はak.wwise.core.object.setを使用してミュージック構造全体を1つの固有のWAAPIコールで作成します。なお構造の作成中にオーディオファイルのインポートも行います。Wwiseのこれまでのバージョンでは不可能なことでした。
オブジェクト定義という概念からはじめます。ak.wwise.core.object.setをコールする時に関数にオブジェクト定義を渡します。最小オブジェクト定義は以下のフィールドです:
- type:オブジェクトのタイプのことで、https://www.audiokinetic.com/ja/library/edge/?source=SDK&id=wobjects_index.htmlにあります。
- name:オブジェクトの名前。(オブジェクトのタイプによっては空です。)
さらに以下の任意のフィールドがオブジェクト定義に含まれることがあります:
- children:その他のオブジェクト定義の配列を定義します。
- import:オブジェクトにどのオーディオファイルをインポートするのかを定義します。(2023.1より)
- VolumeやOutputBusのようなプロパティ、リファレンス、リストなどの値で、プレフィックス@が付きます。
もう少し簡単にするために、私はPythonで汎用ユーティリティ関数を書き、ak.wwise.core.object.setに渡されるオブジェクト定義に対応するJSONコードを生成させました。この関数は実際に理解していなくても使用できます。以下に使い方の例を紹介します。
def Object(タイプ, 名前, *子, **プロパティ):
# 基本定義
definition = {
"type" : type,
"name" : name
}
# 任意のキーワード引数をプロパティに変換します
for key, value in properties.items():
definition['@'+key] = value
# 子はほかの定義、またはファイルインポート命令です。
if len(children) > 0 and isinstance(children[0], str):
# 第1の引数として文字列がある場合、ファイルパスを考慮します
definition["import"] = {}
definition["import"]["files"] = []
for file in children:
definition["import"]["files"].append({
"audioFile" : file,
})
else:
# または子定義のアレイを検討します
definition["children"] = children
return definition
またこれは最初の2つの引数が固定であり、その他の引数は自動的に子またはオーディオファイルインポート定義に変換されるというPythonの引数システムを活用していることに着目してください。最後に、この関数はプロパティを定義するためにキーワード引数も使用します。
上記関数を再利用し、ミュージックセグメントを作成するための専用関数を導入します:
def MusicSegment(name, *children, **properties):
# 音楽セグメントのための定義を作成
return Object("MusicSegment", name, *children, **properties)
この関数を使い、以下のようにミュージックセグメントの定義を作成することができます:
MusicSegment("Segment1",
R"C:\MyAudio.wav",
Volume = -3)
あるいは複数のミュージックトラックも欲しい場合は以下を使用できます:
MusicSegment("Segment1",
MusicTrack("TrackA",
R"C:\TrackA.wav",
Volume = -2
),
MusicTrack("TrackB",
R"C:\TrackB.wav",
Volume = -2
)
)
ミュージックプレイリストコンテナの作成もさほど異なりません。ただしこの場合はプレイリスト自体を指定する必要があります。以下の例ではコンテナに対してPlaylistRootを設定していますが、これはプレイリストアイテムのツリーです。またLoopCountとSegmentを異なるミュージックプレイリストアイテムに設定します:
MusicPlaylistContainer(
R"MPL1",
MusicSegment("Segment1", R"C:\Segment1.wav"),
MusicSegment("Segment2", R"C:\Segment2.wav"),
PlaylistRoot =
MusicPlaylistItem(
MusicPlaylistItem( Segment = root + "\MSC\MPL1\Segment1"),
MusicPlaylistItem( Segment = root + "\MSC\MPL1\Segment2"),
LoopCount = 0
)
)
最後にミュージックスイッチコンテナを作成するために、スイッチと子を関連付ける必要があります。MusicSwitchContainer関数の最初の2つの引数でこれを行います。スイッチと子を関連付ける細かい対応ができているこの実装に、目を通してみることをおすすめします。
MusicSwitchContainer(root + R"\MSC",
# ミュージックコンテナが登録されているスイッチグループ
[
R"\Switches\Default Work Unit\SWG_1",
R"\Switches\Default Work Unit\SWG_2"
],
# 関連付けのエントリー
{
R"SW_1_1.SW_2_1": R"MPL1",
R"SW_1_2.SW_2_1": R"MPL1",
R"*.SW_2_2": R"MPL2",
},
# 子たち
MusicPlaylistContainer("MPL1", ...),
MusicPlaylistContainer("MPL2", ...),
最後にこれらの定義はWAAPIのak.wwise.core.object.setに渡されます。定義のツリー全体がミュージック構造のつくり方を決めています。
次は?
Wwise 2023.1の新しいWAAPi機能を自由にさわってみることができます。ご感想を聞きたいと思いますし、あなたのお役に立てることを願っています。これを使って何を構築したいと思いますか?みなさんが私たちの製品をどのように使うのか、常に興味を持っています。
将来WAAPIに取り入れて欲しいものは、ほかにありますか?Q&AのBeta Feedbackカテゴリでぜひ教えてください。
WAAPIに興味があってもどこからはじめてよいのか分からない場合は、以下のリンクをご参照ください:
- WAAPIを使いはじめる(https://www.audiokinetic.com/ja/library/edge/?source=SDK&id=waapi_gettingstarted.html)―サポートされる様々なプログラミング言語の概要と例。
- WAAPIリファレンス(https://www.audiokinetic.com/library/edge/?source=SDK&id=waapi_functions_index.html)―WAAPIの各関数の詳細について。
- ak.wwise.core.object.set(https://www.audiokinetic.com/library/edge/?source=SDK&id=ak_wwise_core_object_set.html)―ak.wwise.core.object.setの詳細について。
- オーディオファイルのインポートと構造の作成(https://www.audiokinetic.com/library/edge/?source=SDK&id=waapi_import.html)―Wwise構造の作成方法について。
- Wwiseオブジェクトリファレンス(https://www.audiokinetic.com/library/edge/?source=SDK&id=wobjects_index.html)―Wwiseオブジェクトとそのプロパティについて。
コメント