ReaWwise에서 잘 알려지지 않은 기능 중 하나는 원시적 WAAPI 함수를 REAPER에 노출하여 사용자 정의 ReaScript에서 사용할 수 있다는 것입니다. 이 블로그 글에서는 ReaScript Development Environment를 통해 WAAPI를 사용하여 몇 가지 기본적인 Wwise 관련 기능을 구현하는 방법을 살펴보겠습니다
사전 요구 사항
WAAPI & Lua
시작하기 전에 먼저 WAAPI, Lua, ReaScript에 대한 기본적인 이해를 갖추는 것이 좋습니다. 다음은 이를 위한 몇몇 자료입니다.
ReaWwise
ReaScript 안에서 WAAPI 명령을 실행하려면 ReaWwise를 설치해야 합니다.
시작하기
ReaScript Development Environment (ReaScript 개발 환경)
ReaScript Development Environment로 가기 위해서는 먼저 REAPER를 여세요. REAPER 메뉴에서 Actions > Show action list를 선택하세요. Actions 대화창의 오른쪽 아래 모서리에서 New action > New ReaScript를 클릭하세요. 여기서 파일을 저장하라는 메시지가 뜹니다. ReaScript 파일의 이름을 지정하고 Save를 클릭하세요. 저장 후 ReaScript Development Environment가 열립니다. 바로 여기에서 코드를 작성하게 되죠.
Hello Wworld
-- Waapi Hello World.lua
if(reaper.AK_Waapi_Connect("127.0.0.1", 8080)) then
reaper.ShowConsoleMsg("Successfully connected to Wwise!")
reaper.AK_Waapi_Disconnect()
end
앞의 코드 조각에서는 먼저 AK_Waapi_Connect를 호출합니다. 이 함수는 WAAPI가 Wwise와 통신해야 하는 IP와 PORT를 가져오죠. 이 함수는 불리언 값을 반환하며, 연결이 성공적일 경우 true, 그렇지 않을 경우 false를 반환합니다. 이 if 구문의 끝에서는 AK_Waapi_Disconnect를 호출하여 연결을 종료해야 합니다. 스크립트가 성공적으로 실행되면 REAPER 콘솔 출력 창에 다음과 같은 메시지가 뜹니다.
기본 예제 (Get Selected Objects)
다음 예제를 통해 Wwise에서 현재 선택된 오브젝트를 쿼리하는 방법을 살펴봅시다.
-- 선택한 오브젝트 가져오기.lua
if(reaper.AK_Waapi_Connect("127.0.0.1", 8080)) then
local fieldsToReturn = reaper.AK_AkJson_Array()
reaper.AK_AkJson_Array_Add(fieldsToReturn, reaper.AK_AkVariant_String("path"))
local options = reaper.AK_AkJson_Map()
reaper.AK_AkJson_Map_Set(options, "return", fieldsToReturn)
local result = reaper.AK_Waapi_Call("ak.wwise.ui.getSelectedObjects",
reaper.AK_AkJson_Map(), options)
local status = reaper.AK_AkJson_GetStatus(result)
if(status) then
local objects = reaper.AK_AkJson_Map_Get(result, "objects")
local numObjects = reaper.AK_AkJson_Array_Size(objects)
for i=0, numObjects - 1 do
local item = reaper.AK_AkJson_Array_Get(objects, i)
local path = reaper.AK_AkJson_Map_Get(item, "path")
local pathStr = reaper.AK_AkVariant_GetString(path)
reaper.ShowConsoleMsg(pathStr .. "\n")
end
end
reaper.AK_AkJson_ClearAll()
reaper.AK_Waapi_Disconnect()
end
AkJson
JSON 객체 생성을 용이하게 하기 위해서 ReaWwise는 다양한 헬퍼 함수를 내보냅니다. 이러한 함수는 ReaScript가 스크립트의 필요에 따라 JSON 객체를 동적으로 생성할 수 있게 해줍니다.
WAAPI 호출은 전달인자, 옵션, 명령 문자열이라는 세 가지 요소를 필요로 합니다. 이 예제에서 명령 문자열은 ak.wwise.ui.getSelectedObjects입니다. WAAPI 명령의 전체 목록은 WAAPI Reference에서 찾을 수 있습니다.
이 특정 명령에서 WAAPI는 비어 있는 맵을 인자로 요구합니다. 이제 옵션 맵을 구성하기만 하면 됩니다.
만들고자 하는 옵션 맵은 다음과 같습니다.
{
"return": [
"path"
]
}
REAPER의 Lua 콘텍스트와 ReaWwise 백엔드 간에는 값의 유형과 포인터만 전달될 수 있기 때문에 이 옵션 맵은 여러 단계로 생성해야 합니다.
먼저 fieldsToReturn 배열을 생성합니다.
local fieldsToReturn = reaper.AK_AkJson_Array()
fieldsToReturn 변수에서 반환되는 것은 바로 ReaWwise 백엔드에 있는 배열에 대한 포인터입니다. 이 포인터를 사용하여 배열을 작동시킬 수 있죠.
그런 다음 'path' 문자열을 fieldsToReturn의 구성 요소로 추가합니다.
reaper.AK_AkJson_Array_Add(fieldsToReturn, reaper
.AK_AkVariant_String("path"))
마지막으로 옵션 맵을 생성하고 fieldsToReturn 배열을 'return' 키가 있는 값으로 추가합니다.
local options = reaper.AK_AkJson_Map()
reaper.AK_AkJson_Map_Set(options, "return", fieldsToReturn)
WAAPI로의 호출
필요한 모든 매개 변수를 생성한 후에는 이를 WAAPI 호출 시 입력으로 사용합니다.
local result = reaper.AK_Waapi_Call("ak.wwise.ui.getSelectedObjects",
reaper.AK_AkJson_Map(), options)
그런 다음 결과를 검토하여 WAAPI 호출이 성공했는지 확인할 수 있죠. 복잡한 데이터 구조체는 ReaWwise 백엔드에서 Lua 콘텍스트로 바로 전달할 수 없습니다. 결과 변수는 포인터입니다.
상태를 쿼리할 수 있습니다.
local status = reaper.AK_AkJson_GetStatus(result)
상태가 true일 경우 WAAPI 호출에서 반환된 실제 데이터의 쿼리를 진행할 수 있습니다.
local objects = reaper.AK_AkJson_Map_Get(result, "objects")
local numObjects = reaper.AK_AkJson_Array_Size(objects)
그런 다음 numObjects를 반복하고 필요한 데이터를 추출합니다.
for i=0, numObjects - 1 do
...
end
각 오브젝트는 맵으로서 표현됩니다. 객체의 특정 속성에 접근하기 위해서는 ReaWwise 백엔드가 제공하는 헬퍼 함수를 사용합니다.
객체 배열에서 단일 객체를 얻기 위해서는 객체 포인터와 색인 값을 사용합니다.
local item = reaper.AK_AkJson_Array_Get(objects, i)
변수 요소는 객체 배열의 단일 객체를 나타내는 맵 객체로의 포인터입니다. 그런 다음 경로 변수를 추출할 수 있습니다.
local path = reaper.AK_AkJson_Map_Get(item, "path")
맵과 배열 값은 변형 객체로서 내부적으로 저장됩니다. 최종 값을 추출해내기 위해서는 값이 어떤 데이터를 나타내는지 알아야 합니다. 이 경우 문자열을 얻어야 하죠. 다음 헬퍼 함수를 사용하여 변형 객체 유형에서 문자열을 가져옵니다.
local pathStr = reaper.AK_AkVariant_GetString(path)
pathStr 변수는 나머지 스크립트 부분에서 사용할 수 있는 일반 Lua 문자열입니다. 이 스크립트는 단순히 REAPER 콘솔에 pathStr을 출력합니다.
reaper.ShowConsoleMsg(pathStr .. "\n")
ReaWwise 백엔드가 Lua 코드 전체에서 사용되는 참조 유형 객체를 추적해야 하기 때문에 더 이상 필요하지 않을 경우 이를 삭제해야 합니다.
reaper.AK_AkJson_ClearAll()
Advanced Example (Import)
다음 예제에서는 조금 더 복잡한 작업을 해볼까요? REAPER 렌더 디렉터리에서 오디오 파일을 Wwise로 전송해봅시다. 각 오디오 파일은 스크립트에 하드코딩된 가져오기 도착지 아래 Sound SFX로서 가져옵니다. 사용될 기본 WAAPI 명령은 ak.wwise.core.audio.import입니다.
API에 대한 대부분의 개념을 이전 예제에서 설명드렸기 때문에 여기에서는 각 코드 줄이 어떤 작업을 하는지 설명하지 않겠습니다. 하지만 코드의 각 섹션이 수행하는 작업에 대한 일반적인 설명을 해드릴게요.
줄 3-13: WAAPI에 연결하고, importDestination을 구성한 다음, 렌더 디렉터리를 추론합니다. 이 스크립트에서는 렌더 디렉터리가 프로젝트 파일의 상위 디렉터리와 같다고 가정합니다.
줄 15-41: AK_Waapi_Call 함수에 대한 입력으로 전달될 모든 AkJson 구조체를 빌드합니다.
줄 44-70: 렌더 디렉터리를 반복하여 발견한 모든 WAV 파일을 가져올 오디오 파일 목록에 추가합니다.
줄 74-101: AK_WAAPI_Call 함수를 실행하고 REAPER 콘솔에 결과를 표시합니다. 또한 이 줄에는 오류가 생길 경우 결과에서 오류 정보를 추출하는 논리도 들어있습니다.
결론
이 글에서는 Lua ReaScript에서 직접 사용되는 WAAPI의 몇 가지 예제를 살펴보았습니다. Wwise로의 기본 연결부터 Wwise 쿼리, 그리고 오디오 파일 가져오기와 같은 꽤나 복잡한 작업까지 살펴보았죠. 이 API가 여러분의 작업 과정에 도움이 되길 바랍니다. 여러분이 ReaScript에서 WAAPI를 사용하여 어떤 놀라운 것들을 만들어낼지 기대됩니다.
댓글