WAQL 2.0

오디오 프로그래밍 / Wwise에 대한 팁과 도구

Wwise Authoring Query Language (WAQL, 와클) 첫 번째 버전이 출시된 지 벌써 몇 년이 지났습니다. 첫 버전 이후 크게 변경된 점은 없습니다. 가장 눈에 띄는 변화로는 Wwise 2022.1의 Project Explorer Search에 WAQL이 통합되었다는 부분이었죠. 이 블로그에서 곧 출시될 2023.1 출시와 더불어 쿼리 언어를 한 단계 높은 수준으로 끌어올리는 방법에 대해 다뤄보겠습니다.

먼저 WAQL이 무엇인지 알아보려면 다음 블로그를 읽어보세요. https://blog.audiokinetic.com/ko/introducing-waql/

자세한 내용을 다루기 전에 Wwise Authoring 2023.1 업데이트 작업 중 일부를 요약해 보겠습니다. 지난 몇 년 동안 Wwise Authoring (Wwise 저작)의 가장 오래된 데이터 모델 중 일부를 일반 객체 모델(generic object model)로 변환했습니다. 그러면 기본적으로 Wwise의 모든 객체를 동일한 방식으로 처리할 수 있게 됩니다. 예를 들어 각 객체에는 볼륨(volume) 같은 속성이나 출력 버스(output bus)와 같은 다른 객체에 대한 참조가 있습니다. 이를 이용하면 특정한 함수를 만들 필요 없이 WAQL이나 WAAPI에 일반적인 모든 것을 노출할 수 있죠. 이를테면 WAAPI에는 setVolume 함수가 없습니다. 그래서 볼륨을 설정하려면 ak.wwise.core.object.setProperty 또는 ak.wwise.core.object.set을 호출하고 속성 이름으로 'volume'을 전달하면 됩니다.

객체 목록의 개념(concept of object lists) 이라는, 다소 새로운 부분이 추가되었는데요. 이 객체 목록을 사용하면 모든 객체 내부에 있는 가변 수의 객체나 객체에 대한 참조를 저장할 수 있습니다. 예를 들어 Actor-Mixer Hierarchy의 각 객체에는 이제 RTPC 객체 목록과 Effect Slots 목록이 존재합니다. 이는 볼륨을 설정할 때와 마찬가지로 ak.wwise.core.object.set
로 RTPC 객체나 효과를 설정할 수 있습니다.
효과와 WAQL에 대해 더 자세히 알아볼까요. 2022.1 이하 버전에서 0번 슬롯에 EQ가 있는 모든 객체를 쿼리하려면 다음을 수행하면 됩니다.

$ where effect0.pluginname : "EQ"

이렇게 하면 첫 번째 효과의 플러그인 이름에 'EQ'가 포함된 프로젝트의 모든 객체가 반환됩니다. 흠, 효과 슬롯의 경우에는 쿼리가 좀 덜 깔끔해 보이네요.

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

또한 2023.1에서는 이렇게 4개로 고정된 효과 슬롯을 제거하고 객체 목록으로 대체합니다. WAQL을 사용해서 어떻게 객체 목록의 효과를 쿼리할 수 있는 지 알아볼까요? 이전에는 WAQL에서 객체 목록에 대한 지원을 적절히 추가해야 했습니다.

List 함수 소개

WAQL에서 where statement, select문(statement)이나 반환 식(return expression) 안에서 사용할 수 있는 다양한 접근자의 타입이 다를 수 있습니다. 타입 목록.

Accessor 타입

반환

예시

Property (속성)

Variant (integer, float, boolean, string).

Volume, Pitch, IsLoopingEnabled

Reference (참조)

Wwise Object

Output Bus, User Aux Send 0, Attenuation

Object List (객체 목록) - 신규!

Wwise Object의 배열

RTPC, Effects, children, descendants

JSON 객체

키 값이 있는 JSON 객체.

duration.max, duration.min, loudness.integrated

객체 목록은 이제 WAQL에서 기본적으로 지원되며 이를 이용해서 할 수 있는 작업이 몇 가지 있습니다. 그 중 새롭게 추가된 하나는 목록에 있는 모든 요소에 한 번에 작동하는 함수입니다.

count() 함수부터 살펴보겠습니다. count() 함수는 목록의 요소 개수를 반환합니다. 이 숫자는 다른 숫자와 비교할 수 있습니다. 예제:

$ where effects.count() > 0

매우 유용한 이 작업과 함께, count() 함수는 선택적 조건을 인자로 사용할 수도 있습니다. 따라서 특정 조건과 일치하는 요소의 수를 셀 수도 있죠. 효과 목록에서 EQ가 있는 객체를 검색해 보겠습니다.

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

하나의 요소가 조건을 충족하는 즉시 true를 반환하는 any() 함수로 이 쿼리를 작성할 수도 있습니다. 그러면 더 효과적이겠죠.

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

목록에서 사용할 수 있는 함수는 다음과 같습니다.

함수

설명

예시

count

조건과 일치하는 목록의 요소 수를 반환하고 그렇지 않으면 false를 반환합니다. 조건문은 선택적으로 사용할 수 있습니다.

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

any

조건과 일치하는 요소가 발견되면 true를 반환하고 그렇지 않으면 false를 반환합니다. 비어 있으면 false를 반환합니다. 조건문은 선택적으로 사용할 수 있습니다.

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

all

목록의 모든 요소가 해당 조건과 일치하면 true를 반환하고 그렇지 않으면 false를 반환합니다. 비어 있으면 false를 반환합니다. 여기서 조건문은 필수입니다.

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

first

해당 조건과 일치하는 첫 번째 요소를 반환합니다. 조건문은 선택적으로 사용할 수 있습니다.

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

last

해당 조건과 일치하는 마지막 요소를 반환합니다. 조건문은 선택적으로 사용할 수 있습니다.

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

take

특정 개수의 요소를 가져와서 새 목록에 반환합니다. 

$ select children.take(2)

skip

특정 개수의 요소를 건너뛰고 나머지 요소를 새 목록으로 반환합니다. 

$ select effects.skip(1)

at

목록의 지정된 인덱스에 있는 요소를 반환합니다.

$ select effects.at(0)

where

새 목록에서 해당 조건과 일치하는 요소를 반환합니다.

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

효과와 관련하여 더 알아보기

이제 효과에 대해 좀 더 이야기해 볼까요? 2023.1에서 Sound Engine 단에서 최대 효과의 수가 4개에서 255개로 늘어났습니다. 그러나 Wwise Authoring에서는 그 수에 제한이 없습니다 (특정 시점에서 메모리와 같은 시스템 리소스는 제외). 그래서 효과를 목록에 보관해야 하는것이죠. 다음은 Sound 객체의 효과에 대한 데이터 모델의 UML 다이어그램입니다.

img1

또한 EffectSlot이라는 새로운 객체 유형이 나왔습니다. EffectSlot은 BypassRender 속성을 저장하고 ShareSet이나 Custom 효과에 대한 Effect 참조를 저장하는 작은 객체입니다.

Sound 오브젝트는 EffectSlot 객체 목록을 저장하고 Sound에 대한 모든 효과를 한 번에 바이패스하는 BypassEffects 속성도 저장합니다.

아래처럼 실제 프로젝트의 모든 EffectSlot 객체를 쿼리할 수 있죠.

$ from type effectslot

Return Expression의 더 강력한 기능

WAAPI와 함께 WAQL을 사용하면 반환 표현식을 사용해서 반환된 객체에 대해 특정 데이터를 쿼리할 수 있습니다. 예를 들어 프로젝트에서 모든 Sound 오브젝트를 반환하는 다음과 같은 WAQL 쿼리를 사용할 수 있습니다.

$ from type sound

반환 표현식의 JSON 배열 사용.

["name", "volume"]

다음 표를 JSON 형식으로 반환하게 됩니다.

이름

볼륨

Silence

0

Ambient_Day_Element_01_01

0

Ambient_Day_Element_01_02

0

waterdrop_05

-4

Ambient_Water_River

-20

이제 해당 사운드에 대한 RTPC를 얻으려고 한다고 가정해 보죠. Wwise 2022.1에서 가능했던 다음과 같은 표현식을 사용할 수 있습니다.

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

하지만 이렇게 하면 rtpc 열의 경우 각 행에 대해 다음과 같은 결과가 나타납니다.

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

이는 JSON 객체의 배열로, 각 객체에는 RTPC 항목의 ID가 포함되어 있습니다. 해당 GUID에 대해 이미 알고 있거나 GUID에 대해 더 알아보기 위해 추가적인 쿼리를 수행하는 경우에만 유용합니다. 기본적으로 WAQL은 Wwise 객체를 반환할 때 객체의 ID와 이름을 반환합니다. 이 경우 RTPC 객체에는 이름이 없기 때문에 ID만 반환되죠.

RTPC가 연결된 속성 이름과 RTPC를 제어하는 입력 이름을 얻으려고 한다고 가정해 볼까요? 2023.1에는 컴포지션별로 새 JSON 객체를 반환할 수 있는 새로운 구문이 존재합니다.

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

마지막 열에 대해 다음과 같이 반환합니다.

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

ControlInput 참조에 대한 idname을 모두 가져오는 것을 다시 볼 수 있습니다. 기본값으로 되어있네요. 제어 입력(control input)의 ID가 필요 없는 경우 다음과 같은 식의 배열을 사용할 수 있습니다.

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

그러면 다음처럼 더 간결하고 명쾌한 결과를 얻을 수 있습니다.

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

이제 문제는 이 열에 접근하는 데 필요한 코드가 JSON 객체의 키로 매우 장황한 반환식을 사용한다는 것입니다. 예를 들어 요청한 RTPC 입력란에 액세스하려면 첫 번째 행에서 다음과 같은 Python 코드가 필요합니다.

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

이 문제를 완화하기 위해서 키워드 as를 사용하여 별칭 개념(concept of aliases) 도입으로 식의 이름을 바꿀 수 있도록 하겠습니다.

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

이렇게 더 간략해진 코드는 다음과 같이 나타납니다.

myRTPCs = results[0]['rtpcs']

목록 연결 (Concatenation of Lists)

마지막으로 소개할 내용는 목록 연결입니다. 예를 들어 프로젝트에서 모든 이벤트를 가져온다고 가정해봅시다.

$ from type event

다음은 각 개별 이벤트와 관련된 모든 원본 WAV 파일을 가져올 수 있는 마법의 표현입니다.

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

결과:

이벤트

원본

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"
]

정확히 어떠한 일이 일어나고 있을까요? 여기에는 많은 개념이 숨어 있습니다. 표현을 분석해 보겠습니다.

children

actions인 이벤트의 하위 목록을 반환합니다. 

.target

각 작업의 target 객체를 선택합니다. 이것은 일반적으로 Actor-Mixer Hierarchy의 객체를 말합니다.

.[this, descendants]

각 대상의 대상 자체(this)와 해당 descendant의 연결(concatenation)인 새로운 배열을 빌드하고 선택합니다.

.where(type=\"Sound\")

Sound 객체만 유지해서 객체를 필터링합니다. JSON 값 안에 있기 때문에 큰따옴표를 이스케이프했음을 참고하세요.

.originalRelativeFilePath

각 Sound의 Originals 폴더에 상대적인 원본 WAV 파일 경로를 선택합니다.

기타 목록

WAQL에서 사용할 수 있는 목록은 다음과 같습니다.

특정 목록:

  • 많은 객체의 Effects (신규!)
  • 많은 객체의 RTPC
  • Random/Sequence Container의 Playlists (신규!)
  • Audio File Source의 Markers (신규!)
  • Actor-Mixer Hierarchy 객체의 Metadata
  • Music Switch Container의 Entries, Arguments (신규!)
  • Dialog Event의 Entries, Arguments (신규!)
  • Music 객체의 Stingers
  • Music Segment의 Cues
  • Music Track의 Sequences
  • Music Sequence의 Clips (서브트랙)

일반 목록:

  • children
  • ancestors
  • descendants
  • referencesTo

글을 마치며.

정말 많은 것들을 다루었네요. 이 블로그 내용과 관련해서 더 자세히 알아보고 직접 사용해 보고싶다면 WAQL Playground(https://github.com/ak-brodrigue/waql-playground)를 참고해 주세요. 여기서 보여드린 많은 기능들을 확인할 수 있습니다. Wwise 2023.1을 다운로드하고 프로젝트에 직접 사용해 보세요. 새로운 기능을 배우고 이해할 때 직접 사용해 보는 것보다 더 좋은 방법은 없답니다.

WAQL의 기본 방향은 데이터에 대한 제어와 가시성을 제공하는 것입니다. 그리고 이러한 새로운 기능은 아이디어를 더욱 발전시키죠.

Project Explorer 검색, List View 검색, Schematic View, Toolbar 검색, Query Editor에서 직접 WAQL을 사용할 수 있다는 점을 기억해주세요.

또한 WAQL Reference (https://www.audiokinetic.com/ko/library/edge/?source=SDK&id=waql_reference.html)와 Wwise 오브젝트 레퍼런스 (https://www.audiokinetic.com/ko/library/edge/?source=SDK&id=wobjects_index.html)는 WAQL과 객체 모델의 숨겨진 보석을 발견하는 데 항상 유용합니다.

베르나르 로드리그 (Bernard Rodrigue)

베르나르 로드리그 (Bernard Rodrigue)

Audiokinetic개발 감독Bernard Rodrigue는 Audiokinetic의 개발 감독입니다. Bernard는 2005년 Audiokinetic에 입사했으며 Wwise의 기초를 개발하는 데 큰 공헌을 했습니다. 현재 Bernard는 계속해서 Wwise의 발전과 확장에 관한 여러 프로젝트를 이끌어 나가고 있습니다.

 @decasteljau

댓글

댓글 달기

이메일 주소는 공개되지 않습니다.

다른 글

소규모 게임 프로젝트가 Wwise로부터 혜택을 받을 수 있는 5가지 이유

여러분이 게임 오디오 분야에 종사하고 있으며 이전에 소규모 게임 프로젝트를 수행한 적이 있는 경우. 다음과 같은 대화를 나눈 적이 있을 수 있습니다. "근데, 와이즈와 같은...

7.7.2020 - 작성자: 알렉스 메이 (ALEX MAY)

WAAPI 간소화하기

Wwise 저작 API (Wwise Authoring API, WAAPI)를 사용하신 적이 없으시다면 이 글을 통해 사용해볼 기회가 생기기를 바랍니다. 네, 프로그래머가 아닌...

4.11.2020 - 작성자: Adam T. Croft

Wwise 2021.1에서 시도해볼 10 가지

Wwise 런처에서 Wwise 2021.1을 다운로드할 수 있게 되었다는 소식입니다. 오브젝트 기반 파이프라인, 방사 이미터(radial emitter), WAQL을 포함한 다양한...

9.6.2021 - 작성자: 매스 마라티 소노로 (MADS MARETTY SØNDERUP)

Impacter의 교차 합성 변형음 시각화하기

Impacter 플러그인 블로그 시리즈에 다시 오신 것을 환영합니다. 이전 두 블로그에서는 플러그인의 물리적 매개 변수와 이 매개 변수가 게임의 물리 시스템과 잘 통합될 수 있는...

2.2.2022 - 작성자: 라이언 돈 (RYAN DONE)

Wwise Spatial Audio 2023.1의 새로운 기능 | Reverb Zone (리버브 존)

Reverb Zone 소개 Wwise 2023.1은 Wwise Spatial Audio에 Reverb Zone (리버브 존)이라는 새로운 도구를 추가했습니다. Reverb...

10.1.2024 - 작성자: 토마스 한슨 (Thomas Hansen)

Wwise Spatial Audio 2023.1의 새로운 기능 | 위상 완화 (Phasing Mitigation)

오늘 이 글에서는 '위상(phasing)'이라는 흥미로운 음향적인 현상에 대해 알아보겠습니다. 이 현상은 특정 환경에서 음향을 모델링할 때 나타날 수 있죠. Wwise 23.1의...

25.1.2024 - 작성자: Allen Lee

다른 글

소규모 게임 프로젝트가 Wwise로부터 혜택을 받을 수 있는 5가지 이유

여러분이 게임 오디오 분야에 종사하고 있으며 이전에 소규모 게임 프로젝트를 수행한 적이 있는 경우. 다음과 같은 대화를 나눈 적이 있을 수 있습니다. "근데, 와이즈와 같은...

WAAPI 간소화하기

Wwise 저작 API (Wwise Authoring API, WAAPI)를 사용하신 적이 없으시다면 이 글을 통해 사용해볼 기회가 생기기를 바랍니다. 네, 프로그래머가 아닌...

Wwise 2021.1에서 시도해볼 10 가지

Wwise 런처에서 Wwise 2021.1을 다운로드할 수 있게 되었다는 소식입니다. 오브젝트 기반 파이프라인, 방사 이미터(radial emitter), WAQL을 포함한 다양한...