新WAQL(Wwise Authoring Query Language)の紹介

オーディオプログラミング / Wwiseの使い方やツール

「まるでWwiseは表計算ソフト。」これは私たちUEチームがよく聞くコメントです。Wwiseはサウンドデザインをするためのツールですが、実際、エンジン部分を見るとWwiseプロジェクトは依然データです。しかも大量の。最近の現実として、ゲームは巨大であり、問題を事前に回避したければデータをうまくコントロールした方が良いというわけです。

幸い、Wwiseには大量のデータを操作するためのツールとして、 List ViewMulti EditorBatch RenameQuery Editor などが用意されています。

WAQL_List-1

また、大量のデータを処理しやすくするために、Wwiseプロジェクトの中を整理する技やグッドプラクティスも色々とあります。例えばWork Unitの設定、命名規則の導入、タブ区切りファイルのオーディオファイルのインポート、カスタムプロパティの活用、バッチ操作で行う名前変更、色分けなどがあります。

さらに、データを探し出したいときは 検索Query Editor などがあります。ただ、これらのツールには限界があります。例えば、あなたのプロジェクトのランダムコンテナの中で、ループするサウンドが入っているのはどれ?あるEventが参照するオーディオソースはどれ ?

私たちは数年前、Wwiseプロジェクトをプログラマーが自動化、操作、そしてクエリできるプログラミングAPIとして、WAAPIを発表しました。ただ、WAAPIにはプログラミング言語が必要です。この能力はいまだ、主にプログラマーの手中にあって、残りのWwiseユーザーには手の届かない存在です。また、WAAPIスクリプトを実行できるようになるまで設定にも時間がかかります。

WAAPIのこちらの例はPythonで書かれ、あるEventが参照するすべてのコンバージョン後のファイルをプリントするものです。決して読みやすいものではありません。

from waapi import WaapiClient
import pprint

# connectする(デフォルトURL)
client = WaapiClient() 

# 全ターゲットをreturnする
args = {
    "from": {"path": ['\\Events\\Default Work Unit\\Play']},
    "transform": [
        {"select": ['children']}
    ]
}

options = {
    "return": ['@Target']
}
result = client.call("ak.wwise.core.object.get", args, options=options)
pprint.pprint(result)

# ターゲットの全wemファイルをreturnする
args = {
    "from": {"id": list(map(lambda x: x['@Target']['id'], result['return']))},
    "transform": [
        {"select": ['descendants']},
        {"where": ['type:isIn', ['AudioFileSource']]}
    ]
}

options = {
    "return": ['name', 'id','sound:convertedWemFilePath']
}
result = client.call("ak.wwise.core.object.get", args, options=options)
pprint.pprint(result)

# disconnectする
client.disconnect()

WAQLの導入

Wwise 2021.1 で初めてWAQLが取り入れられました。WAQLはWwise Authoring Query Languageの略で、「ワーケル」とよんでください。JIRAのユーザーは、JIRAデータベースをクエリする方法としてJQL(JIRA Query Language)をご存知かもしれません。またプログラマーの方は、C# LINQやSQLをご存知かもしれません。WAQLは、これらランゲージに似ているところがあります。Wwiseプロジェクトに対するクエリを、そのデータモデルを利用して行えるのです。要約すると、Wwiseオブジェクトや、そのプロパティにクエリをかけます。

WAQLは、自分のプロジェクトの中にあるデータを今までよりも自分でコントロールできるようにしたい、という私たちの計画の次の一歩にあたります。新たに学ばなくてはいけないランゲージではありますが、完全なプログラミング言語のPythonやJavascriptやC#を習うよりハードルがぐっと低いはずです。そしてWwise Authoringに入ったその状態のまま使用を開始できることが、さらに重要なポイントです。今回の記事の目標は、WAQLの基本を理解してもらうことです。実際に私たちは、記事を読み進めながらご自分のWwiseプロジェクトで試してみることをお勧めしています。これはWAQLのチュートリアルでもあり、導入のための概要でもあるのです。

ではまずシンプルなものから始めましょう。あなたのプロジェクトの中にある、ボリュームが0未満であるオブジェクトをすべて探し出します。そのためには、まず List View を開き、次を入力してください: $ where volume < 0

WAQL_list_view

待った!何が起きているのか、考えます。まず、List Viewのサーチバーに入力したときに、普通はプロジェクト全体を対象にテキストサーチが実行されますが、今、最初に $ を入力したので、Wwiseは単純なサーチではなくWAQLクエリが開始されることを知ります。

次に where キーワードが、これから条件文が入力されることを示します。クエリを where で開始するとデフォルトで、条件がプロジェクト内の全オブジェクトに実行されます。最後に条件文を入力します。今回はWwiseオブジェクトのプロパティであるボリュームを、数字のゼロと比較するように指示します。この条件で、ボリュームがゼロ未満でないオブジェクトは外されます。

Wwiseのオブジェクトとプロパティ

ここで気になるのが、Wwiseのオブジェクトとプロパティについてです。Wwiseのオブジェクトとは、要はProject Explorerにあるすべての項目のことで、これに、様々なシステムの中で、隠れていたり見えたりするその他のオブジェクトも加わります。プロパティはオブジェクトの中で定義され、そこに値が格納されます。

Wwiseには多数のプロパティがあります。例えばこちらは、あるSoundオブジェクトで、Property EditorのGeneral Settingsタブにあるプロパティです:

WAQL_Markers

プロパティには以下のようなものを1つ保存できます:

  • 数値(整数値、実数値、ブール値、文字列)。例: Volume
  • プロジェクト内のほかのオブジェクトへのリファレンス。例: OutputBusEffect0
  • ローカルオブジェクトで、‘Custom’と言われるもの。例: Effect0

すべてのWwiseオブジェクトのすべてのプロパティを完全に記載したリストが ここ にあります。

また、ほとんどのオブジェクトにみられる、コアプロパティというものがいくつかあります。例えば‘name’、‘notes’、‘path’、‘id’などは、全Wwiseオブジェクトでアクセスできるコアプロパティで、‘volume’や‘outputbus’は特定の種類のオブジェクトに見られるプロパティです。コアプロパティは算出されることもあれば、オブジェクトと一緒に保存されることもあります。どの場合でも、WAQLではプロパティ名の大文字小文字を区別しません。 

コアプロパティの詳細については こちら を参照にしてください。 

条件を使い始める

すでに見た通り where 文は条件を定義します。この条件は、 where 文に提供された全オブジェクトに対して、判断されます。条件を定義するのはブール式、つまりtrueまたはfalseのどちらかになる文です。

以下は、いくつかの例です:

  • $ where pitch = 1200
  • $ where volume > -10 and volume < 0
  • $ where IsLoopingEnabled or IsStreamingEnabled 
  • $ where (volume >= 0 and (lowpass > 0 or highpass > 0))

それでは where 条件を使って、ほかのシナリオも試してみてください。

以下の3つの文字列比較の演算子を使い、WAQLでテキストを検索し比較することもできます:

  • $ where name = "Hello"
    等号は、ある文字列全体を別の文字列と、大文字小文字を区別せず比較するときに使い、両者が全く同じ場合にtrueを返します。
  • $ where notes : "hell"
    コロン記号は、文字列の中の、ある単語の先頭を見つけるために使います。大文字小文字を区別しません。単語が見つかればtrueを返します。
  • $ where outputbus = /^Music\d+$/
    等号演算子は、正規表現にも使えます (ECMAScript style)。

オブジェクトとプロパティをつなげる

Wwiseオブジェクト上には、プロパティが2種類あります:

値を返すプロパティ:

  • volume、pitch、lowpassなど: Wwiseでスライダーが設定されていることが多く、数値を保存します。オブジェクトの種類によって、これらは変わります。例えばSoundとRandom Containerではプロパティセットが同じではありません。
  • name、notes、id、path: Wwiseオブジェクトシステムの中核をなす要素で、文字列の値を保存する場合が多いです。どのWwiseオブジェクトにもあります。

別のWwiseオブジェクトを返すプロパティ(リファレンスとも呼ばれます):

  • outputbus、target、userauxsend0、effect0: これらは別のオブジェクトを指し、それはオブジェクトの種類によって変わります。例えばEventとSoundは、プロパティが同じではありません。
  • parent: 親オブジェクトを指します。

オブジェクトと値を、 ドット 記号で組み合わせることができます。例えば:

  • $ where parent.name = "Music"
    親の名前が“Music”。
  • $ where parent.parent.name = "Music"
    祖父母の名前が“Music”。
  • $ where parent.volume < 0
    親のボリュームが0未満。
  • $ where outputbus.parent.name = "Master Audio Bus"
    アウトプットバスの親の名前が“Master Audio Bus”。
  • $ where effect0.pluginname = "Wwise Compressor"
    スロット0のエフェクトのプラグイン名が“Wwise Compressor”。

違うソースから始める

ここまで、プロジェクト全体のオブジェクトを対象にフィルターを適用してきました。さて、もっと狭いオブジェクト群の中から探したいような場合もあります。WAQLでは、クエリのソースを、このように設定することができます:

  • 指定した種類のオブジェクトすべて
  • プロジェクト内の1つまたは複数の、特定のオブジェクト
  • レガシーのクエリオブジェクト(Query Editor)の結果
  • 文字列検索クエリの結果

以下を試してみてください:

  • $ from type sound
  • $ from type audiofilesource
  • $ from type randomsequencecontainer, switchcontainer, blendcontainer

種類を、直接 from 文で指定するのは、検索範囲を狭めるための非常に効率的な方法です。WAQLがイテレーションを指定したソースに限定します。最後のクエリは where キーワードを使ったフィルター検索で書くこともできます。ただしこのフィルターはEventやバスやサウンドなど、全プロジェクトオブジェクトを探さなければなりません。実行時間が遅くなります。

  • $ where type = "randomsequencecontainer" or type = "switchcontainer" or type = "blendcontainer"

ほかの種類のオブジェクトでも試してみてください。 こちらを ご参照ください。

以下のように1つのオブジェクトから始めることが、非常に便利な場合もあります:

  • $ from object "\Actor-Mixer Hierarchy\Default Work Unit"
  • $ from object "{1514A4D8-1DA6-412A-A17E-75CA0C2149F3}"
  • $ from object "Event:Play_Footstep_01"7

上記クエリは、 from object を排除することで、さらに短い形式で書くこともできます:

  • $ "\Actor-Mixer Hierarchy\Default Work Unit"
  • $ "{1514A4D8-1DA6-412A-A17E-75CA0C2149F3}"
  • $ "Event:Play_Footstep_01"

また、複数のオブジェクトを指定することもできます。

  • $ "\Actor-Mixer Hierarchy",  "\Interactive Music Hierarchy"
  • $ "{DE2B0843-131F-4E52-BC71-23C43A5324AB}", "{1514A4D8-1DA6-412A-A17E-75CA0C2149F3}"
  • $ "Event:Play_Footstep_01", "Event:Play_Footstep_02", "Event:Play_Footstep_03"

以下も、スタート地点のソースが異なるクエリ例です:

  • $ from search "foot walk"
  • $ from search "hello" where type = "sound"
  • $ from query "\Queries\Factory Queries\Audio Source\Audio Source - Format = Vorbis"

オブジェクトを選択する

ここまで、WAQLクエリのソースを from キーワードで指定する方法を習い、WAQLクエリを where キーワードで絞り込む方法を習いました。次にその結果を select キーワードでさらに展開させる方法を見ていきます。

オブジェクトを選択することで、最初の一連のオブジェクトからほかのオブジェクトを取得できます。WAQLクエリのある部分が、次の部分の元となり、つながっていくことを、常に頭に入れておいてください。

List Viewで、以下のクエリを入力してください:

  • $ from object "\Actor-Mixer Hierarchy\Default Work Unit" select children

これはDefault Work Unitを見て、その直接の子をすべて返します。このクエリには2つの部分があり、それは from 文と、 select 文です。 from 文が、クエリの始まり、つまりソースを定義します。 select 文は、このソースから出てくる各オブジェクトに対して実行されます。

次のクエリは、オブジェクトの階層からそれぞれ異なる要素を選び出します:

  • $ "\Actor-Mixer Hierarchy\Default Work Unit" select descendants
    すべての子を、再帰的に返します。
  • $ "\Actor-Mixer Hierarchy\Default Work Unit" select parent
    直接の親を返します。
    $ "\Actor-Mixer Hierarchy\Default Work Unit" select parent.parent
    直接の祖父母を返します。
  • $ "\Actor-Mixer Hierarchy\Default Work Unit" select ancestors
    すべての親を再帰的に返します。
  • $ "\Actor-Mixer Hierarchy\Default Work Unit" select parent, children
    親と、その子の組み合わせを返します。
  • $ "\Actor-Mixer Hierarchy\Default Work Unit" select this, parent, children
    Default Work Unit自体と、その親と、子を組み合わせて返します。
  • $ from type sound select parent
    すべてのサウンドの、すべての親を返します。

select キーワードを使えば階層の子や親の間を移動することができるだけでなく、プロパティからオブジェクトを選択することもできます。

  • $ from type sound select effect0
    すべてのサウンドオブジェクトの、index 0にあるすべてのエフェクトを返します。
  • $ from type sound select effect0, effect1, effect2, effect3
    すべてのサウンドオブジェクト用に見つかった、すべてのエフェクトを返します。
  • $ from type sound select outputbus
    すべてのサウンドオブジェクトの、Output Busで見つかったすべてのバスを返します。
  • $ from type sound select outputbus.parent
    すべてのサウンドオブジェクトの、Output Busで見つかったバスの親を返します。

追加の演習問題:

  • where 文を select 文のあとに追加してみます
  • where 文を select 文の前に入れてみます
  • select referencesto を使ってみます

複雑なクエリを解明する

次のクエリは、あるEventが参照するすべてのSoundオブジェクトを列挙するものです。このクエリでは、5つの文がつながっています。

  • $ from type event select children select target select this, descendants where type = "sound"

クエリの各部分は、以下の通りです:

  • $ from type event
    まず、プロジェクトのすべてのEventを列挙します。
  • $ from type event select children
    次にEventオブジェクトからEventアクション(直接の子)を取得します。
  • $ from type event select children select target
    次に各アクションのターゲット(targetという名のリファレンス)を取得します。
  • $ from type event select children select target select this, descendants
    次に、ターゲット自体(キーワードthisを使用)と、その子孫を取得します。
  • $ from type event select children select target select this, descendants where type = "sound"
    最後に、サウンドオブジェクトだけを残します。

さて、次は?

これは氷山のほんの一角です。今はWAQLのバージョン1で、今後、さらに進化するのでご期待ください。既にアクセスしてクエリを行えるプロパティ数は450を超え、対象オブジェクトは60種類以上あります。クエリで組み合わせることのできる文の数に制限はなく、順序も自由なので、今でも可能性が無限大です。また、今回は触れていないキーワードもあります。

List View はWAQLの使い方を練習するのにもってこいの場所です。Query Editor を使ってWAQLクエリをプロジェクトに保存することもできます。

WAQL_Query

WAQLや、サポートされる機能について詳しく知りたい場合は、WAQLの リファレンス を参考にしてください。

もしWAAPIを使っていれば、WAQLを関数 ak.wwise.core.object.get の中で直接使うこともできます。あなたの仕事が 楽に なるはずです。

あなたがWAQLを使って何を達成したか、教えてください!

ベルナール・ロドリグ(Bernard Rodrigue)

ベルナール・ロドリグ(Bernard Rodrigue)

AudiokineticDirector of DevelopmentBernard Rodrigueは、AudiokineticのDirector of Development(開発ディレクター)。2005年にAudiokinetic入社。Wwiseの基礎の開発に積極的に関わる。Wwiseの拡張と革新を進める複数のプロジェクトのリーダー。

 @decasteljau

コメント

Replyを残す

メールアドレスが公開されることはありません。

ほかの記事

WwiseのState機能から多数のパラメータにアクセスして、ミキシングできるように!

Wwise...

22.3.2018 - 作者 ブラッドリー・メイヤー(BRADLEY MEYER)

コマンドアドオンで実現できる、ワークフローの改善

継続的なワークフロー改善の努力を...

20.8.2019 - 作者 ベルナール・ロドリグ(Bernard Rodrigue)

A Wwise Unity Cheat Sheet

今日のトピックは、Wwise Unity...

2.2.2021 - 作者 マス・マレティ・スナロプ(MADS MARETTY SØNDERUP)

誰でも使えるWAAPI パート2: wwise.core

16.3.2021 - 作者 トーマス・ワン(汪洋)

Max 8におけるWwise Authoring API(WAAPI)活用の導入

はじめに...

11.4.2023 - 作者 ミカエル・アルトゥング

Wwise 2023.1 最新情報

Wwise 2023.1がリリースされ、Audiokinetic Launcherからインストールできるようになりました。本ブログでは最新機能の概要をご紹介いたします。 ...

9.7.2023 - 作者 Audiokinetic