WAQL 2.0

Programmation audio / Outils et conseils pour Wwise

Cela fait déjà quelques années que la première version du Wwise Authoring Query Language (WAQL) a été publiée. Il n'a pratiquement pas changé depuis la première version. Le changement le plus notable depuis son introduction a été l'intégration de WAQL dans la fonction de recherche (Project Explorer Search) dans Wwise 2022.1. Désormais, avec la sortie à venir de la version 2023.1, nous allons voir ici comment nous avons amené WAQL à la vitesse supérieure.

Si vous ne savez pas ce qu'est WAQL, je vous invite à lire cet article : https://blog.audiokinetic.com/en/introducing-waql/

Avant d'entrer dans les détails, résumons certaines des réalisations que nous avons faites de manière discrète pour Wwise Authoring 2023.1. Au cours des dernières années, nous avons converti certains des plus anciens modèles de données de Wwise Authoring en ce que nous appelons des modèles d'objets génériques. Fondamentalement, cela nous permet de traiter tous les objets de Wwise de la même façon. Par exemple, chaque objet a des propriétés comme le Volume, ou des références à d'autres objets, comme l'Output Bus. Cela nous permet d'exposer tout ce qui est générique à WAQL ou WAAPI sans avoir besoin de créer des fonctions spécialisées. Par exemple, WAAPI n'a pas de fonction setVolume. Pour définir le volume, vous pouvez appeler ak.wwise.core.object.setProperty ou ak.wwise.core.object.set et passer « volume » comme nom de propriété.

Une chose relativement nouvelle que nous avons ajoutée à notre modèle d'objet est le concept de listes d'objets. Les listes d'objets nous permettent de stocker un nombre variable d'objets, ou de références à des objets, à l'intérieur de n'importe quel objet. Par exemple, chaque objet de l'Actor-Mixer Hierarchy possède désormais une liste d'objets RTPC, ainsi qu'une liste d'Effect Slots. De la même manière que pour le volume, il est possible de définir des objets RTPC ou des effets avec ak.wwise.core.object.set.

Parlons un peu plus des effets et de WAQL. Dans la version 2022.1 et versions antérieures, si vous vouliez faire une requête pour tous les objets avec un EQ sur le slot 0, vous pouviez faire :

$ where effect0.pluginname : "EQ"

Cette requête retournait tous les objets du projet dont le nom du plugiciel du premier effet contenait « EQ ». Cependant, la requête devenait plus chargée si vous faisiez la recherche dans n'importe quel emplacement d'effet :

$ where effect0.pluginname : "EQ" or effect1.pluginname : "EQ" or effect2.pluginname : "EQ" or effect3.pluginname : "EQ"

En outre, dans la version 2023.1, nous supprimons ces quatre emplacements d'effets fixes et les remplaçons par une liste d'objets. Comment pouvons-nous alors interroger les effets de la liste d'objets avec WAQL ? Pour rendre cela possible, nous avons dû ajouter un support approprié pour les listes d'objets dans WAQL.

Présentation des fonctions de liste

Dans WAQL, les différents types d'accesseurs que vous pouvez utiliser à l'intérieur d'une instruction where, select, ou à l'intérieur d'une expression de retour, peuvent être de différents types. Voici une liste de ces types :

Type d'accesseur

Expression de retour

Exemples

Propriété

Variante (entier, flottant, booléen, chaîne).

Volume, Pitch, IsLoopingEnabled

Référence

Objet Wwise

Output Bus, User Aux Send 0, Attenuation

Liste d'objets (NOUVEAU !)

Un tableau d'objets Wwise

RTPC, Effects, enfants, descendants

Objet JSON

Un objet JSON avec des valeurs associées aux clés.

duration.max, duration.min, loudness.integrated

Puisque les listes d'objets sont maintenant supportées nativement dans WAQL, il y a plusieurs choses que nous pouvons faire avec elles. Une chose qui a été ajoutée en relation avec les listes est le concept de fonctions opérant sur tous les éléments d'une liste en même temps. 

Commençons par la fonction count(). La fonction count() renvoie le nombre d'éléments de la liste. Ce nombre peut être comparé à un autre nombre. Par exemple :

$ where effects.count() > 0

Super ! La fonction count() peut par ailleurs également prendre une condition facultative comme argument. Vous pouvez donc compter le nombre d'éléments correspondant à une certaine condition. Essayons de rechercher tout objet ayant un EQ dans sa liste d'effets :

$ where effects.count(effect.pluginname : "eq") > 0

Il est également possible d'écrire cette requête avec la fonction any(), qui renvoie true dès qu'un élément remplit la condition, ce qui est plus efficace :

$ where effects.any(effect.pluginname : "eq")

Voici les fonctions pouvant être utilisées sur les listes :

Fonction

Description

Exemples

count

Retourne le nombre d'éléments de la liste correspondant à la condition spécifiée, sinon renvoie false. L'énoncé de la condition est facultatif.

$ where children.count() > 3
$ where effects.count(effect.pluginname:"eq") > 0

any

Retourne true si un élément correspondant à la condition est trouvé, sinon retourne false. Retourne false si la liste est vide. L'énoncé de la condition est facultatif.

$ where rtpc.any()
$ where children.any(type = "Sound")

all

Retourne true si tous les éléments de la liste correspondent à la condition spécifiée, sinon retourne false. Retourne false si la liste est vide. L'énoncé de la condition est obligatoire.

$ where children.all(type = "Sound")

first

Retourne le premier élément correspondant à la condition spécifiée. L'énoncé de la condition est facultatif.

$ where effects.first(effect.pluginname :"EQ") != null
$ where children.first().type = "Sound"

last

Retourne le dernier élément correspondant à la condition spécifiée. L'énoncé de la condition est facultatif.

$ where effects.last(effect.pluginname :"EQ") != null
$ where children.last().type = "Sound"

take

Prend le nombre d'éléments spécifié et les retourne dans une nouvelle liste. 

$ select children.take(2)

skip

Saute le nombre d'éléments spécifié et retourne le reste dans une nouvelle liste. 

$ select effects.skip(1)

at

Retourne l'élément situé à l'index spécifié dans la liste.

$ select effects.at(0)

where

Retourne les éléments correspondant à la condition spécifiée dans une nouvelle liste.

$ select effects.where(effect.pluginname :"EQ")

Encore plus pour les Effects

Parlons un peu plus des Effects. Dans la version 2023.1, nous augmentons le nombre maximum d'effets de 4 à 255 du côté du moteur sonore. Du côté de Wwise Authoring, cependant, il n'y a pas de limite (à part les ressources du système, comme la mémoire, à un moment donné). Nous stockons donc les effets dans une liste. Voici un diagramme UML du modèle de données concernant les effets d'un objet Sound :

img1

Nous introduisons également un nouveau type d'objet appelé EffectSlot. L'EffectSlot est un petit objet qui stocke les propriétés Bypass et Render et qui stocke également la référence Effect à un ShareSet ou à un effet personnalisé. 

L'objet Sound est celui qui stocke la liste des objets EffectSlot et stocke également la propriété BypassEffects, laquelle contourne tous les effets à la fois sur l'objet Sound.

En fait, vous pouvez interroger tous les objets EffectSlot du projet avec :

$ from type effectslot

Plus de possibilités pour les expressions de retour

Lorsque vous utilisez WAQL avec WAAPI, il est possible d'interroger des données spécifiques pour les objets retournés à l'aide d'expressions de retour. Par exemple, vous pouvez utiliser la requête WAQL suivante, permettant de retourner tous les objets Sound du projet :

$ from type sound

avec un tableau JSON d'expressions de retour :

["name", "volume"]

Elle renverrait le tableau suivant, au format JSON :

name

volume

Silence

0

Ambient_Day_Element_01_01

0

Ambient_Day_Element_01_02

0

waterdrop_05

-4

Ambient_Water_River

-20

Supposons maintenant que vous vouliez obtenir les RTPC de ces sons. Vous pourriez utiliser l'expression suivante, qui était déjà possible dans Wwise 2022.1 :

["name", "volume", "rtpc"]

Cependant, pour la colonne rtpc, pour chaque ligne, nous obtenons quelque chose comme ceci :

[
  {
    "id": "{1D1905C4-18F9-4506-AD8B-A0CDEC396F4D}"
  }
]

Il s'agit d'un tableau d'objets JSON, chaque objet contenant l'identifiant de l'entrée du RTPC. Ce n'est utile que si vous connaissez déjà ces GUIDs, ou si vous faites une requête supplémentaire pour en savoir plus sur les GUIDs. Par défaut, lorsque WAQL retourne des objets Wwise, il retourne l'ID et le nom de l'objet. Dans ce cas, les objets RTPC n'ont pas de nom, donc seul l'ID est retourné.

Supposons que nous voulions savoir le nom de la propriété à laquelle le RTPC est attaché, ainsi que le nom du paramètre d'entrée qui pilote le RTPC. Dans la version 2023.1, il existe une nouvelle syntaxe qui permet de renvoyer de nouveaux objets JSON par composition :

["name", "volume", "rtpc.{controlinput, propertyname}"]

Cela retourne quelque chose comme ceci pour la dernière colonne :

[
  {
    "controlinput": {
      "id": "{CEC3FD56-5B7C-44AF-B635-5C3A0C36825E}",
      "name": "Distance_to_Camera"
    },
    "propertyname": "Volume"
  }
]

Vous voyez que, là encore, nous obtenons à la fois l'id et le name pour la référence ControlInput, qui est la référence par défaut. Si l'ID du paramètre d'entrée ne nous intéresse pas, nous pouvons utiliser ce tableau d'expressions :

["name", "volume", "rtpc.{controlinput.name, propertyname}"]

Et nous obtenons ceci, qui est plus compact et va droit au but :

[
  {
    "controlinput.name": "Distance_to_Camera",
    "propertyname": "Volume"
  }
]

Le problème que nous avons maintenant est que le code nécessaire pour accéder à cette colonne utilise l'expression de retour comme clé dans l'objet JSON, ce qui est très verbeux. Par exemple, pour accéder aux champs RTPC que nous avons demandés, sur la première ligne, nous avons besoin de ce code Python :

myRTPCs = results[0]['rtpc.{controlinput.name, propertyname}']

Pour pallier ce problème, introduisons le concept d'alias avec le mot-clé as, qui nous permet de renommer l'expression :

["name", "volume", "rtpc.{controlinput.name, propertyname} as rtpcs"]

Le code est maintenant plus court et ressemble à ceci :

myRTPCs = results[0]['rtpcs']

Concaténation de listes

Le dernier sujet que nous allons aborder est la concaténation de listes. Par exemple, commençons par récupérer tous les Events du projet :

$ from type event

Et voici l'expression magique pour obtenir tous les fichiers WAV originaux associés à chacun des Events individuels :

["name as event", "children.target.[this, descendants].where(type=\"Sound\").originalRelativeFilePath as originals"]

Les résultats :

Event

Fichiers sources

Ambient_Region_PineForest

[
"SFX\\Ambient\\Ambient_Background\\treesVillage_001.wav",
"SFX\\Ambient\\Ambient_Background\\treesVillage_001.wav",
"SFX\\Ambient\\Ambient_Background\\BAS_amb_pineforest_night_background_loop_01.wav",
"SFX\\Ambient\\Ambient_Background\\BAS_amb_pineforest_night_background_loop_01.wav"
]

Ambient_River

[
"SFX\\Ambient\\Ambient_Emitters\\Water_RiverLoop.wav"
]

Que se passe-t-il ici ? Il y a beaucoup de concepts entremêlés. Décortiquons l'expression :

children

Renvoie la liste des enfants de l'Event, qui sont les actions

.target

Pour chaque action, sélectionne l'objet target de l'action. Il s'agit normalement d'un objet de l'Actor-Mixer Hierarchy.

.[this, descendants]

Pour chaque target, construit et sélectionne un nouveau tableau, qui est la concaténation de la target elle-même (this) et de ses descendants.

.where(type=\"Sound\")

Filtre les objets en ne conservant que les objets Sound. Notez que nous avons échappé les guillemets doubles parce que nous sommes à l'intérieur d'une valeur JSON.

.originalRelativeFilePath

Pour chaque Sound, sélectionne le chemin d'accès du fichier WAV original par rapport au dossier Originals.

Autres listes

Puisque nous aimons les listes, voici la liste des listes que vous pouvez utiliser dans WAQL :

Listes spécialisées :

  • Effects dans de nombreux objets (NOUVEAU !)
  • RTPCs dans de nombreux objets
  • Playlists dans les Random/Sequence Containers (NOUVEAU !)
  • Markers dans les fichiers audio sources (NOUVEAU !)
  • Métadonnées dans les objets de l'Actor-Mixer Hierarchy
  • Entrées, Arguments dans les Music Switch Containers (NOUVEAU !)
  • Entrées, Arguments dans les Dialog Events (NOUVEAU !)
  • Stingers dans les objets musicaux
  • Cues dans les Music Segments
  • Sequences dans les Music Tracks
  • Clips dans les Music Sequences (également appelées subtrack)

Listes génériques :

  • children
  • ancestors
  • descendants
  • referencesTo

Notes de conclusion

Cela fait beaucoup de choses à assimiler. Si vous souhaitez en savoir plus et l'essayer, vous pouvez utiliser le WAQL Playground (https://github.com/ak-brodrigue/waql-playground), qui a été mis à jour pour supporter les nouvelles fonctionnalités que nous avons présentées ici. Téléchargez Wwise 2023.1 et essayez-le avec votre propre projet. C'est la meilleure façon de l'apprendre et de le comprendre.

L'idée derrière WAQL est de donner du contrôle et de la visibilité à vos données. Et ces nouvelles fonctionnalités poussent l'idée encore plus loin.

N'oubliez pas non plus que vous pouvez utiliser WAQL directement dans la zone de recherche du Project Explorer, la zone de recherche de la List View, dans la Schematic View, la recherche Toolbar, et aussi directement à l'intérieur du Query Editor.

Il y a aussi la Référence WAQL (https://www.audiokinetic.com/en/library/edge/?source=SDK&id=waql_reference.html) et la Référence des Objets Wwise (https://www.audiokinetic.com/en/library/edge/?source=SDK&id=wobjects_index.html), toujours utiles pour découvrir les joyaux cachés de WAQL et de notre modèle d'objet.

Bernard Rodrigue

Directeur, Wwise Experience

Audiokinetic

Bernard Rodrigue

Directeur, Wwise Experience

Audiokinetic

Bernard Rodrigue est Directeur, Wwise Experience chez Audiokinetic. Il s'est joint à Audiokinetic en 2005 et a participé activement à l'élaboration des fondements de Wwise. Aujourd'hui, Bernard continue de diriger plusieurs projets liés au développement et à l'expansion de Wwise.

 @decasteljau

Commentaires

Laisser une réponse

Votre adresse électronique ne sera pas publiée.

Plus d'articles

Hitman 2 : Améliorer la réverbération sur les processeurs modernes

La popularisation des processeurs à six et huit cœurs signifie qu'une puissance de traitement...

19.5.2022 - Par Stepan Boev

Impacter et Unreal Engine | Comment contrôler le plugiciel Impacter en utilisant la physique du moteur de jeu

Introduction Impacter est un nouveau prototype de plugiciel de modélisation de sons d'impacts pour...

10.11.2022 - Par Sean Soraghan

Visualiser les variations issues de la synthèse croisée d'Impacter

Bienvenue à nouveau dans notre série d'articles sur le plugiciel Impacter. Dans les deux articles...

24.11.2022 - Par Ryan Done

Travailler en équipe avec WAAPI et Python, et exemples pratiques

Dans cet article, j'aimerais décrire une approche de travail avec WAAPI un peu particulière,...

7.11.2023 - Par Eugene Cherny

Nouveauté de Wwise Spatial Audio 2023.1 | Zones de réverbération

Introduction aux Zones de réverbération Wwise 23.1 introduit une nouvelle fonctionnalité à Wwise...

10.1.2024 - Par Thomas Hansen

Nouveauté de Wwise Spatial Audio 2023.1 | Réduction de l'effet de phasing

Dans l'article d'aujourd'hui, nous allons plonger en profondeur dans un phénomène acoustique...

25.1.2024 - Par Allen Lee

Plus d'articles

Hitman 2 : Améliorer la réverbération sur les processeurs modernes

La popularisation des processeurs à six et huit cœurs signifie qu'une puissance de traitement...

Impacter et Unreal Engine | Comment contrôler le plugiciel Impacter en utilisant la physique du moteur de jeu

Introduction Impacter est un nouveau prototype de plugiciel de modélisation de sons d'impacts pour...

Visualiser les variations issues de la synthèse croisée d'Impacter

Bienvenue à nouveau dans notre série d'articles sur le plugiciel Impacter. Dans les deux articles...