Des mondes qui réagissent à la musique avec Pulse
Pulse écoute la musique de ton monde et la transforme en valeurs que tes shaders lisent à chaque image : le niveau de quatre bandes (des basses aux aigus) et leurs 1,4 dernières secondes, le spectre, des niveaux lissés, un temps musical qui avance plus vite sur les temps forts, et quatre couleurs tirées des notes qui dominent. Le paquet a aussi une tablette que les joueurs prennent en main pour tout régler pendant la soirée.
C’est le paquet Unity NodeWorld Pulse (com.nodeworld.pulse), sous licence MIT. Il demande NodeWorld SDK Worlds, qu’il apporte.
Ajouter le paquet
- Ajoute le registre NodeWorld à ton projet, comme pour le SDK (installer le SDK).
- Ouvre Window, Package Manager, choisis My Registries, sélectionne NodeWorld Pulse, puis Install.
- Dans le NW World Config de ton monde, ajoute à Flux Sharp Sources les sept scripts de
Packages/com.nodeworld.pulse/Runtime/Flux/(dans la fenêtre Project, ils sont sous Packages, NodeWorld Pulse, Runtime, Flux) :PulseAudio,PulseTablet,PulseHandle,PulseSharedSlider,PulseSharedToggle,PulseThemeColors,PulseLabels.
Brancher la musique
- Glisse le prefab Pulse (Packages, NodeWorld Pulse, Runtime, Prefabs) dans ta scène. Il porte le moteur : un composant FL# Script de classe
Pulse.PulseAudio. - Dans son champ
source, mets l’Audio Source qui joue ta musique : une enceinte de la scène, ou la sortie son d’un écran vidéo.
Pulse lit ce que joue la source, quel que soit son volume : un joueur qui baisse la musique voit toujours les lumières réagir. Quand la source se tait ou s’arrête, toutes les valeurs retombent à 0.
Un seul moteur par monde suffit : tous les shaders de la scène lisent les mêmes valeurs.
Poser la tablette dans le monde
- Glisse le prefab PulseTablet dans ta scène et place-le : son socle se pose sur une table, à environ 1 m du sol.
- Sur la racine du prefab, le FL# Script de classe
Pulse.PulseTableta un champpulse: mets-y l’objet Pulse de ta scène.
La tablette reste sur son socle jusqu’à ce qu’on la prenne. Un joueur la prend par une des deux poignées du bas, ou par les deux, une dans chaque main ; lâchée, elle reste là où elle est. Sa place est la même pour tous les joueurs.
Ce que fait l’écran :
| À l’écran | Ce que ça règle |
|---|---|
| Bandes : les quatre colonnes de couleur | Tire le bouton blanc en haut d’une colonne : le seuil de la bande. Une bande au-dessus de son seuil allume son bouton. |
| Bandes : le rail sous les colonnes | Tire un bouton : là où une bande s’arrête et où la suivante commence sur le spectre. |
| Signal : Gain | Le niveau auquel la musique est lue. Le petit repère au milieu est le niveau normal ; tout à droite, il est doublé. |
| Signal : Fondu | Le temps que met une bande à retomber après un coup. |
| Signal : Courbe | La forme de cette retombée. |
| Signal : Gain automatique | Suit tout seul le volume de la musique. |
| Le bouton rond en haut à gauche | Allume ou éteint l’analyse : éteinte, tes shaders voient la musique arrêtée. |
| Le bouton rond en bas à gauche | Remet les réglages et les couleurs comme au chargement du monde (le bouton marche ne change pas). |
| Couleurs : les quatre pastilles rondes | Choisis-en une, puis règle-la avec les curseurs de teinte, de saturation et de luminosité en dessous. Choisir ou régler une pastille coupe Auto. |
| Couleurs : Auto | Les quatre couleurs suivent les notes de la musique au lieu des pastilles. |
La carte du bas montre les 1,4 dernières secondes de chaque bande (quatre rangées de points, le présent à droite) et, en dessous, une onde qui grandit avec la musique.
Les textes de l’écran suivent la langue du jeu de chaque joueur (français ou anglais).
Qui règle quoi
Les réglages sont partagés : quand un joueur bouge un curseur, toute l’instance voit et entend la même chose. Le champ controllerSyncMode de Pulse.PulseTablet choisit ce qui est partagé :
controllerSyncMode | Partagé avec l’instance |
|---|---|
0 (par défaut) | tout |
1 | tout sauf le bouton marche |
2 | tout sauf le bouton marche et Gain |
3 | rien : chaque joueur règle pour lui |
Lire la musique dans un shader
Inclus Pulse.cginc du paquet, puis lis les valeurs. Un shader complet, à enregistrer dans un fichier .shader de ton projet : la première couleur de la musique brille avec les basses.
Shader "MyWorld/Pulse Glow"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Glow ("Glow", Range(0, 4)) = 1
}
SubShader
{
Tags { "RenderType" = "Opaque" }
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
#include "Packages/com.nodeworld.pulse/Runtime/Shaders/Pulse.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
float _Glow;
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
UNITY_VERTEX_OUTPUT_STEREO
};
v2f vert (appdata v)
{
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_OUTPUT(v2f, o);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
float4 frag (v2f i) : SV_Target
{
float4 col = tex2D(_MainTex, i.uv);
if (PulseIsOn())
col.rgb += PulseThemeColor(0) * PulseSmooth(0, 8) * _Glow; // la première couleur de la musique, avec les basses lissées
return col;
}
ENDCG
}
}
}| Fonction | Ce qu’elle rend |
|---|---|
PulseIsAvailable() | true dès que le moteur tourne dans le monde. Dans l’éditeur Unity hors Play mode, elle rend false et toutes les fonctions rendent 0. |
PulseIsOn() | true quand le moteur tourne et que l’analyse est allumée (bouton marche de la tablette). |
PulseBand(band, delay) | Le niveau d’une bande (0 basses, 1 bas médiums, 2 hauts médiums, 3 aigus), de 0 à 1, il y a delay pas de 1/90 s (0 maintenant, jusqu’à 127 : 1,41 s). |
PulseSmooth(band, smoothing) | Le niveau d’une bande, lissé : de 0 très lisse (il reste 0,55 d’un changement au bout d’une seconde) à 15 vif. |
PulseChrono(mode, band, wrap) | Un temps musical (mode de 0 à 7) qui avance plus vite quand la bande est forte. wrap vaut 14400000 ou 628319 : la valeur repart de 0 à ce nombre. |
PulseThemeColor(i) | La couleur i (0 à 3) : les notes qui dominent la musique, ou les pastilles de la tablette. |
PulsePhase() | Où en est l’horloge à 90 Hz de l’historique entre deux pas (0 à 1) : pour lire l’historique au même endroit d’une image à l’autre. |
PulseData(xy) | Le texel brut (x, y) de la texture de données (tableau ci-dessous). |
PulseLerp(xy) | Pareil, entre deux texels d’une ligne (x avec une partie décimale). |
La texture de données
Le moteur calcule à chaque image la texture globale _PulseTex (128 × 32 flottants) sur la carte graphique, comme AudioLink : son script envoie seulement les échantillons de la musique et les réglages. Les bandes, les couleurs de thème et l’autocorrélation suivent les notes avec une image de retard. Ses places, en #define dans Pulse.cginc :
| Place | Contenu |
|---|---|
PULSE_POS_BANDS (lignes 0 à 3) | La bande b sur la ligne b ; x = retard en pas de 1/90 s ; r = niveau. |
PULSE_POS_SPECTRUM (lignes 4 et 5) | La note n (0 à 239, 24 par octave depuis 13,75 Hz) en (n % 128, 4 + n / 128) ; r brut, g filtré et égalisé, b filtré. |
PULSE_POS_THEME (ligne 23, x de 0 à 3) | Les quatre couleurs de thème (rgb). |
PULSE_POS_PHASE (23, x 4) | r = phase de l’horloge de l’historique. |
PULSE_POS_STATE (23, x 5) | r = 1 analyse allumée, 0 éteinte. |
PULSE_POS_AUTOCORR (ligne 27) | Autocorrélation du spectre (r). |
PULSE_POS_SMOOTH (lignes 28 à 31, x de 0 à 15) | La bande b sur la ligne 28 + b ; x = lissage ; r = niveau. |
PULSE_POS_CHRONO (lignes 28 à 31, x de 16 à 23) | La bande b sur la ligne 28 + b ; x = 16 + mode ; r = temps modulo 14 400 000, g = modulo 628 319. |
PULSE_POS_VU (28, x de 24 à 27) | Niveau RMS, quatre vitesses (r). |
Les champs du moteur
Le FL# Script du prefab Pulse (Pulse.PulseAudio) démarre avec ces valeurs ; la tablette les change pendant la partie.
| Champ | Ce qu’il fait |
|---|---|
source | L’Audio Source de la musique. |
engine | La custom render texture PulseEngine du paquet (Runtime/Textures), déjà mise dans le prefab : la carte graphique y calcule _PulseTex. |
gain | Niveau d’entrée (1 par défaut). |
bass, treble | Poids des notes graves et aiguës du spectre (1 par défaut). |
x0 à x3 | Où chaque bande commence sur le spectre. |
threshold0 à threshold3 | Seuil de chaque bande. |
fadeLength, fadeExpFalloff | Combien de temps et avec quelle courbe une bande retombe. |
autogain, autogainDerate | Gain automatique, et combien il se retient. |
actif | Analyse allumée (true) ou éteinte. |
themeColorMode, customThemeColor0 à customThemeColor3 | 0 : couleurs des notes ; 1 : les quatre couleurs choisies. |
Licence
Le paquet est sous licence MIT. Son LICENSE.md contient aussi les notices du code dont il dérive (MIT) et de sa police, Geist (SIL Open Font License).
