Max/MSP, un descendent Pure Data, a devenit în unul dintre cele mai notabile limbaje de programare pentru sound design și muzică experimentală, datorită formatului vizual, ce permite utilizatorilor să urmărească mai ușor flow-ul într-un program ("patch") prin conexiunile dintre obiecte. Pentru cei curioși, Ovidiu Mățan prezintă o bază solidă a workflow-ului în Pure Data[^1], articole publicate în Today Software Magazine.
Patchurile Max sunt realizate conectând diferite objects, iar principalele tipuri de date, cum ar fi float și integer, urmăresc tipologia comună limbajelor de programare.
Fiecare obiect Max are inlets (intrări) și outlets (ieșiri), ce permit utilizatorului să stabilească un flux prin interconectarea acestora.
Unul dintre punctele forte ale programului Max este documentația: un click dreapta pe orice obiect dintr-un patcher, permite utilizatorului să acceseze Reference și Help, unde poate găsi documentația completă a obiectului și patchuri demonstrative.
În plus, online se pot găsi proiecte gratuite, forumuri și alte resurse excelente pentru Max/MSP, resursa principală fiind chiar site-ul oficial al Cycling '74.
Cycling '74, compania dezvoltatoare a programului Max/MSP, a lansat recent versiunea 9, care include un update important ce permite rularea codului js în patchurile Max, deblocând un potențial imens.
În continuare vom analiza software-ul Wwise și vom explora cum putem lega cele două programe și care sunt avantajele.
Wave Works Interactive Sound Engine sau pe scurt Wwise este un audio engine și una dintre cele mai populare soluții middleware din industria jocurilor. Pentru oricine activează în industrie, Wwise nu are nevoie de o introducere, însă merită menționat faptul că Wwise le permite sound designerilor să eficientizeze procesul de integrare a sunetului într-un joc, oferind un singur mediu (environment) în care utilizatorii pot importa fișiere, simula spații acustice, defini game states și parametri de control în timp real (RTPC-uri) și, bineînțeles, mixa toate acestea.
Un game engine trimite event calls către Wwise pentru a declanșa sunete, împreună cu informații despre mediul simulat, cum ar fi dimensiunea camerei, ceea ce permite audio engine-ului să calculeze o reverberație. În plus game engine-ul mai trimite și alți parametri RTPC personalizați și game states prin care transmite informații despre modul în care Wwise trebuie să proceseze fișierele. Aceste informații și această procesare permit obținerea unei redări realiste a sunetului în joc. În Wwise, pentru fiecare event trebuie definită o acțiune (action), iar denumirea eventului trebuie să corespundă exact cu cea trimisă de game engine.
Pentru a înțelege mai bine cum funcționează Wwise, vom analiza o configurație de sistem foley. În exemplul de mai jos, evenimentul selectat "Foot_Player" are o acțiune de tip "Play" care vizează Switch Container-ul "Footsteps". În partea stângă, în tabul Audio, putem vedea că containerul Footsteps conține patru sub-foldere de tip Random Containers în arborele său de directoare, numite Concrete, Dirt, Gravel și Tile, fiecare conținând trei fișiere audio. Există și un material switch asociat containerului Footsteps, care va selecta materialul specificat de game engine, iar în cadrul Switch Container-ului, respectivele Random Containers sunt atribuite fiecărei valori ale switchului.
În acest proiect, cele patru Random Containers conțin câte trei fișiere audio, denumite în Wwise SFX objects. Mai putem observa și că modul de redare al fiecărui Random Container (Play Mode) este setat pe Step și că fiecare fișier de tip Sound SFX redă exact un singur sunet de pas.
Privind această configurație, ne putem aștepta ca game engine-ul să trimită un event "Foot_Player" pentru fiecare pas făcut de caracter în joc, în timp ce informația despre suprafața pe care merge jucătorul va fi trimisă doar atunci când aceasta se schimbă (de exemplu, jucătorul pășește pe beton după ce a mers pe pământ). În Wwise, când se primește un event "Foot_Player", acesta va apela mai întâi Switch Container-ul "Footsteps", care în funcție de valoarea curentă a Material Switchului va selecta unul dintre Random Containers, care la rândul său va reda aleatoriu unul dintre cele trei SFX objects pe care le conține.
Din cauza naturii neliniare a jocurilor, unde jucătorul poate alege dintr-o varietate de acțiuni și interacțiuni, în orice ordine dorește, mai multe sunete pot fi redate simultan, iar noi trebuie să ne asigurăm că orice combinație sună bine. Spre deosebire de filme sau alte medii liniare, unde conținutul audio este plasat cronologic pe un timeline, jocurile variază în complexitate audio în funcție de acțiunile jucătorului, ceea ce înseamnă că sound designerii trebuie să țină cont de toate posibilitățile atunci când integrează sunete, mai ales în etapa de mixaj.
Pentru a simula event calls dintr-un game engine, Wwise are propriul său tool, numit Soundcaster.
Soundcaster permite utilizatorilor să creeze Transport Controls pentru orice obiect din Wwise și să le adauge într-o grilă. Acest lucru facilitează declanșarea mai multor sunete în succesiune rapidă, precum și modificarea RTPC-urilor, switchurilor și a game state-urilor. Wwise permite, de asemenea, conectarea dispozitivelor MIDI și atribuirea oricărui buton, tastă sau potențiometru pentru redare, oprire, mutare sau declanșarea eventurilor, direct într-o sesiune Soundcaster. Acest sistem este crucial în faza de prototipare, deoarece uneori în timpul dezvoltării jocului, anumite aspecte nu sunt încă implementate și altfel, nu ar fi posibilă testarea unor sisteme audio complexe.
Cu toate acestea, Wwise nu oferă funcționalitatea de automatizare a unei sesiuni Soundcaster; Fiecare sunet trebuie declanșat manual, iar parametrii RTPC sau game states trebuie de asemenea modificate manual. Acest lucru poate deveni problematic pe măsură ce proiectele cresc în complexitate și dimensiune. De exemplu, în cele mai multe cazuri, declanșarea unui "footstep event" va reda exact un singur sunet de pas, deoarece aceste game calls sunt tagate în animații, iar un game call este trimis de game engine de fiecare dată când piciorul jucătorului atinge o suprafață. Pentru a obține o simulare utilă a mersului personajului în Soundcaster, utilizatorul ar trebui să apese repetat butonul de redare al eventului "footstep", schimbând în același timp valorile Material Switch-ului pentru a trece, de exemplu, de la beton la iarbă. Dar ce facem cu săriturile, împușcăturile, ambianța și muzica? Deși unele dintre aceste sunete durează mai mult (precum ambianța sau muzica), ele pot fi modificate radical prin schimbările valorilor game state-urilor sau a RTPC-urilor. Așadar, este nevoie de controlul simultan al mai multor parametri și declanșarea a numeroase sunete în succesiune rapidă
Pentru a conecta dispozitive MIDI, în Wwise se poate crea o nouă sesiune Control Surface în tab-ul Sessions, sub Control Surface Sessions și Default Work Unit. Asta le va permite utilizatorilor să asocieze mesajele MIDI primite din Max/MSP cu diferite events din Wwise.
În Windows, există un pas în plus, necesar pentru a permite trimiterea informațiilor MIDI de la Max către Wwise, și anume instalarea LoopMIDI și crearea unui nou port MIDI. LoopMIDI este un software gratuit creat de Tobias Erichsen, conceput pentru a crea porturi MIDI virtuale care interconectează aplicații - un tool esențial pentru oricine lucrează cu MIDI în Windows.
În Max, obiectele fundamentale ale patchului la care vom lucra sunt metro și ctlout. Metro este folosit pentru a genera un mesaj bang la un interval regulat specificat în milisecunde. Intuitiv, acesta va fi motorul care va declanșa mesaje succesive pentru eventurile repetitive, precum pașii sau focul de armă în Wwise. Ctlout este obiectul care ne permite să trimitem mesaje MIDI de control continuu (Continuous Control - CC) către Wwise, acesta acceptând ca argumente portul, controllerul și canalul.
În acest caz, argumentele pentru ctlout vor fi "Max2Wwise", adică numele portului așa cum a fost configurat în loopMIDI, urmat de un număr care reprezintă controllerul (fiecare având 16 canale). Ultimul argument este canalul MIDI, care va fi atribuit individual fiecărui event din Wwise. Este important ca fiecare event să aibă atribuită propria combinație unică de controller și canal pentru a preveni declanșări multiple accidentale.
O configurație inițială ar arăta astfel:
Pentru a declanșa un event precum play sau stop în Wwise, putem trimite un mesaj MIDI care conține un număr între 1 și 127 (ideal același număr pentru consistență; am ales intenționat 127 deoarece este limita superioară a range-ului MIDI, astfel indicând clar un mesaj MIDI, pentru a evita confuzii). Pentru RTPC-uri se poate configura un obiect slider care trimite valori între 0 și 127. De ținut cont că acest interval va fi scalat automat pentru a corespunde intervalului RTPC din Wwise.
În exemplul din figura alăturată, parametrul EnemyAware are un interval de la -1 la 101 în Wwise, iar Max trimite mesaje MIDI în intervalul 0-127. Trimiterea valorii 120 din Max este scalată automat la intervalul parametrului EnemyAware, rezultând o valoare nouă: 95.378.
În cadrul cursului Fundamentals, Audiokinetic oferă un proiect Wwise aproape finalizat în Lecția 8, rulat împreună cu jocul Cube. Pentru a extinde exercițiu, vom folosi aceste resurse, lucru ce ne va permite să explorăm și mai mult posibilitățile de automatizare și să folosim tehnici de randomizare pentru a simula mai bine gameplay-ul real.
În sesiunea Control Surface din Wwise, au fost create următoarele asocieri legate de Max:
În următorul patch Max, explorăm soluții de complexitate variabilă, cu și fără eforturi de randomizare. Pentru events precum pași și sărituri, un toggle simplu on/off cu setări de viteză ajustabile este suficient.
Deoarece eventul de pași declanșează un Switch Container, în Wwise a fost creat un game parameter suplimentar denumit "MaterialSwitch" pentru switch-ul "Material".
Acum, materialele pot fi controlate și din Max/MSP, iar randomizarea suprafeței pe care calcă jucătorul poate fi activată printr-un toggle sau pur și simplu se poate selecta materialul dorit.
Pentru acțiuni mai complexe, precum tras cu arma, care constă în mai multe evenimente secvențiale, va fi necesară configurarea de delays pentru a obține un rezultat care să reflecte gameplay-ul real.
În acest exemplu, am configurat mai multe seturi de delays pentru a imita tragerea cu una dintre armele eroului și a obține timpi de zbor diferiți pentru proiectil, inclusiv o opțiune de mute pentru fiecare event individual.
În final, eventul care declanșează muzica în joc, are un toggle on/off și este însoțit de mai multe triggere care schimbă game states în funcție de evenimentele din timpul gameplay-ului. Eventuri precum, o luptă cu un boss, începutul și sfârșitul unei secțiuni din joc etc. sunt declanșate aleatoriu, însă sistemul muzical este influențat și de RTPC-urile "PlayerHealth" și "EnemyAware". Randomizarea acestor 2 RTPC-uri și a music states va oferi o simulare a gameplay-ului, redând astfel comportamentul sistemului muzical din joc.
Jocul Cube oferit de Audiokinetic în cursurile Wwise este o replică a faimosului Quake II, care după standardele actuale este destul de simplu. Prin urmare, abordarea utilizată pentru construirea diferitelor sisteme de arme, foley și de muzică din jocul Cube este foarte simplă, în comparație cu jocurile AAA moderne. De exemplu, sistemele de pași vor fi rareori atât de simple precum un singur event modificat printr-un material switch; complexitatea efectelor foley ale eroului în jocurile moderne include events de start și stop pentru pașii jucătorului, pivotări, asset-uri audio pentru urcat și coborât scările, eventuri separate pentru foșnirea hainelor superioare și inferioare în mișcare etc.
În ceea ce privește sistemele muzicale, inamicii NPC pot avea ponderi individuale per dificultate, iar scorurile lor cumulative pot determina condițiile de pre-combat și combat pentru a declanșa tranziții muzicale într-un peisaj sonor muzical mult mai complex.
În concluzie, sper că această scurtă incursiune în posibilitățile oferite de Max/MSP, să fi oferit o soluție pentru unii, sau cel puțin să fi stârnit curiozitatea ori să fi generat alte idei. De asemenea, merită menționat că tot ceea ce am făcut aici în Max/MSP poate fi scris și în Pure Data sau Plug Data, unde aceeași abordare va funcționa, uneori cu puține sau chiar fără modificări.
AI vs. Tradițional, alternative
de Ovidiu Mățan
de Alin Turcu
de Ovidiu Mățan