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 |
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() |
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 |
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 |
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 :
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 |
[ |
Ambient_River |
[ |
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.
Commentaires