phonon: setGeometry test;

This commit is contained in:
bjorn 2021-02-18 20:46:14 -07:00 committed by Bjorn
parent 00a71870c2
commit 87bbec7018
10 changed files with 142 additions and 4 deletions

View File

@ -249,7 +249,8 @@ ifneq (@(CMAKE_DEPS),)
# Phonon
CFLAGS_@(STEAM_AUDIO) += -I@(STEAM_AUDIO_PATH)/include
LIBS_@(STEAM_AUDIO)_$(win32) += @(STEAM_AUDIO_PATH)/lib/Windows/x64/phonon.dll
LIBS_@(STEAM_AUDIO)_$(win32) += @(STEAM_AUDIO_PATH)/bin/Windows/x64/phonon.dll
LIBS_@(STEAM_AUDIO)_$(macos) += @(STEAM_AUDIO_PATH)/lib/OSX/libphonon.dylib
LIBS_@(STEAM_AUDIO)_$(linux) += @(STEAM_AUDIO_PATH)/lib/Linux/x64/libphonon.so
LIBS_@(STEAM_AUDIO)_$(android) += @(STEAM_AUDIO_PATH)/lib/Android/arm64/libphonon.so
endif

View File

@ -341,3 +341,32 @@ void luax_readcolor(lua_State* L, int index, Color* color) {
luaL_error(L, "Invalid color, expected a hexcode, 3 numbers, 4 numbers, or a table");
}
}
int luax_readtriangles(lua_State* L, int index, float** vertices, uint32_t* vertexCount, uint32_t** indices, uint32_t* indexCount, bool* shouldFree) {
if (lua_istable(L, index)) {
luaL_checktype(L, index + 1, LUA_TTABLE);
*vertexCount = luax_len(L, index) / 3;
*indexCount = luax_len(L, index + 1);
lovrAssert(*indexCount % 3 == 0, "Index count must be a multiple of 3");
*vertices = malloc(sizeof(float) * *vertexCount * 3);
*indices = malloc(sizeof(uint32_t) * *indexCount);
lovrAssert(vertices && indices, "Out of memory");
*shouldFree = true;
for (uint32_t i = 0; i < *vertexCount * 3; i++) {
lua_rawgeti(L, index, i + 1);
(*vertices)[i] = luax_checkfloat(L, -1);
lua_pop(L, 1);
}
for (uint32_t i = 0; i < *indexCount; i++) {
lua_rawgeti(L, index + 1, i + 1);
(*indices)[i] = luaL_checkinteger(L, -1) - 1;
lua_pop(L, 1);
}
return index + 2;
}
return luaL_argerror(L, index, "table or Model");
}

View File

@ -1,5 +1,6 @@
#include <lua.h>
#include <lauxlib.h>
#include <stdbool.h>
#include <stdint.h>
#pragma once
@ -158,6 +159,7 @@ int luax_setconf(lua_State* L);
void luax_setmainthread(lua_State* L);
void luax_atexit(lua_State* L, void (*destructor)(void));
void luax_readcolor(lua_State* L, int index, struct Color* color);
int luax_readtriangles(lua_State* L, int index, float** vertices, uint32_t* vertexCount, uint32_t** indices, uint32_t* indexCount, bool* shouldFree);
// Module helpers

View File

@ -105,6 +105,21 @@ static int l_lovrAudioSetPose(lua_State *L) {
return 0;
}
static int l_lovrAudioSetGeometry(lua_State* L) {
float* vertices;
uint32_t* indices;
uint32_t vertexCount, indexCount;
bool shouldFree;
luax_readtriangles(L, 1, &vertices, &vertexCount, &indices, &indexCount, &shouldFree);
bool success = lovrAudioSetGeometry(vertices, indices, vertexCount, indexCount);
if (shouldFree) {
free(vertices);
free(indices);
}
lua_pushboolean(L, success);
return 1;
}
static int l_lovrAudioGetSpatializer(lua_State *L) {
lua_pushstring(L, lovrAudioGetSpatializer());
return 1;
@ -151,6 +166,7 @@ static const luaL_Reg lovrAudio[] = {
{ "setVolume", l_lovrAudioSetVolume },
{ "getPose", l_lovrAudioGetPose },
{ "setPose", l_lovrAudioSetPose },
{ "setGeometry", l_lovrAudioSetGeometry },
{ "getSpatializer", l_lovrAudioGetSpatializer },
{ "getCaptureStream", l_lovrAudioGetCaptureStream },
{ "newSource", l_lovrAudioNewSource },

View File

@ -328,6 +328,10 @@ void lovrAudioSetPose(float position[4], float orientation[4]) {
state.spatializer->setListenerPose(position, orientation);
}
bool lovrAudioSetGeometry(float* vertices, uint32_t* indices, uint32_t vertexCount, uint32_t indexCount) {
return state.spatializer->setGeometry(vertices, indices, vertexCount, indexCount);
}
const char* lovrAudioGetSpatializer() {
return state.spatializer->name;
}

View File

@ -34,6 +34,7 @@ float lovrAudioGetVolume(void);
void lovrAudioSetVolume(float volume);
void lovrAudioGetPose(float position[4], float orientation[4]);
void lovrAudioSetPose(float position[4], float orientation[4]);
bool lovrAudioSetGeometry(float* vertices, uint32_t* indices, uint32_t vertexCount, uint32_t indexCount);
const char* lovrAudioGetSpatializer(void);
struct Sound* lovrAudioGetCaptureStream(void);

View File

@ -19,6 +19,7 @@ typedef struct {
// return value is number of stereo frames written.
uint32_t (*tail)(float* scratch, float* output, uint32_t frames);
void (*setListenerPose)(float position[4], float orientation[4]);
bool (*setGeometry)(float* vertices, uint32_t* indices, uint32_t vertexCount, uint32_t indexCount);
void (*sourceCreate)(Source* source);
void (*sourceDestroy)(Source* source);
const char* name;

View File

@ -279,6 +279,10 @@ static void oculus_spatializer_setListenerPose(float position[4], float orientat
ma_mutex_unlock(&state.poseLock);
}
bool oculus_setGeometry(float* vertices, uint32_t* indices, uint32_t vertexCount, uint32_t indexCount) {
return false;
}
static void oculus_spatializer_source_create(Source* source) {
intptr_t* spatializerMemo = lovrSourceGetSpatializerMemoField(source);
*spatializerMemo = -1;
@ -297,6 +301,7 @@ Spatializer oculusSpatializer = {
.apply = oculus_spatializer_source_apply,
.tail = oculus_spatializer_tail,
.setListenerPose = oculus_spatializer_setListenerPose,
.setGeometry = oculus_setGeometry,
.sourceCreate = oculus_spatializer_source_create,
.sourceDestroy = oculus_spatializer_source_destroy, // Need noop
.name = "oculus"

View File

@ -12,7 +12,11 @@ static FARPROC phonon_dlsym(void* library, const char* symbol) { return GetProcA
static void phonon_dlclose(void* library) { FreeLibrary(library); }
#else
#include <dlfcn.h>
#if __APPLE__
#define PHONON_LIBRARY "libphonon.dylib"
#else
#define PHONON_LIBRARY "libphonon.so"
#endif
static void* phonon_dlopen(const char* library) { return dlopen(library, RTLD_NOW | RTLD_LOCAL); }
static void* phonon_dlsym(void* library, const char* symbol) { return dlsym(library, symbol); }
static void phonon_dlclose(void* library) { dlclose(library); }
@ -21,6 +25,11 @@ static void phonon_dlclose(void* library) { dlclose(library); }
typedef IPLerror fn_iplCreateContext(IPLLogFunction logCallback, IPLAllocateFunction allocateCallback, IPLFreeFunction freeCallback, IPLhandle* context);
typedef IPLvoid fn_iplDestroyContext(IPLhandle* context);
typedef IPLvoid fn_iplCleanup(void);
typedef IPLerror fn_iplCreateScene(IPLhandle context, IPLhandle computeDevice, IPLSceneType sceneType, IPLint32 numMaterials, IPLMaterial* materials, IPLClosestHitCallback closestHitCallback, IPLAnyHitCallback anyHitCallback, IPLBatchedClosestHitCallback batchedClosestHitCallback, IPLBatchedAnyHitCallback batchedAnyHitCallback, IPLvoid* userData, IPLhandle* scene);
typedef IPLerror fn_iplDestroyScene(IPLhandle* scene);
typedef IPLvoid fn_iplSaveSceneAsObj(IPLhandle scene, IPLstring fileBaseName);
typedef IPLerror fn_iplCreateStaticMesh(IPLhandle scene, IPLint32 numVertices, IPLint32 numTriangles, IPLVector3* vertices, IPLTriangle* triangles, IPLint32* materialIndices, IPLhandle* staticMesh);
typedef IPLerror fn_iplDestroyStaticMesh(IPLhandle* staticMesh);
typedef IPLerror fn_iplCreateEnvironment(IPLhandle context, IPLhandle computeDevice, IPLSimulationSettings simulationSettings, IPLhandle scene, IPLhandle probeManager, IPLhandle* environment);
typedef IPLvoid fn_iplDestroyEnvironment(IPLhandle* environment);
typedef IPLerror fn_iplCreateDirectSoundEffect(IPLAudioFormat inputFormat, IPLAudioFormat outputFormat, IPLRenderingSettings renderingSettings, IPLhandle* effect);
@ -39,6 +48,11 @@ typedef IPLvoid fn_iplApplyBinauralEffect(IPLhandle effect, IPLhandle binauralRe
X(iplCreateContext)\
X(iplDestroyContext)\
X(iplCleanup)\
X(iplCreateScene)\
X(iplDestroyScene)\
X(iplSaveSceneAsObj)\
X(iplCreateStaticMesh)\
X(iplDestroyStaticMesh)\
X(iplCreateEnvironment)\
X(iplDestroyEnvironment)\
X(iplCreateDirectSoundEffect)\
@ -56,6 +70,8 @@ PHONON_FOREACH(PHONON_DECLARE)
static struct {
void* library;
IPLhandle context;
IPLhandle scene;
IPLhandle mesh;
IPLhandle environment;
IPLhandle directSoundEffect;
IPLhandle binauralRenderer;
@ -124,6 +140,8 @@ void phonon_destroy() {
if (state.binauralRenderer) phonon_iplDestroyBinauralRenderer(&state.binauralRenderer);
if (state.directSoundEffect) phonon_iplDestroyDirectSoundEffect(&state.directSoundEffect);
if (state.environment) phonon_iplDestroyEnvironment(&state.environment);
if (state.mesh) phonon_iplDestroyStaticMesh(&state.mesh);
if (state.scene) phonon_iplDestroyStaticMesh(&state.scene);
if (state.context) phonon_iplDestroyContext(&state.context);
phonon_iplCleanup();
phonon_dlclose(state.library);
@ -171,9 +189,9 @@ uint32_t phonon_apply(Source* source, const float* input, float* output, uint32_
.airAbsorptionModel.coefficients = { absorption[0], absorption[1], absorption[2] }
};
IPLDirectOcclusionMode occlusionMode = IPL_DIRECTOCCLUSION_NONE;
IPLDirectOcclusionMethod occlusionMethod = IPL_DIRECTOCCLUSION_RAYCAST;
IPLDirectSoundPath path = phonon_iplGetDirectSoundPath(state.environment, listenerPosition, listenerForward, listenerUp, iplSource, 0.f, 1, occlusionMode, occlusionMethod);
IPLDirectOcclusionMode occlusionMode = IPL_DIRECTOCCLUSION_TRANSMISSIONBYFREQUENCY;
IPLDirectOcclusionMethod occlusionMethod = IPL_DIRECTOCCLUSION_VOLUMETRIC;
IPLDirectSoundPath path = phonon_iplGetDirectSoundPath(state.environment, listenerPosition, listenerForward, listenerUp, iplSource, .5f, 32, occlusionMode, occlusionMethod);
IPLDirectSoundEffectOptions options = {
.applyDistanceAttenuation = falloff > 0.f ? IPL_TRUE : IPL_FALSE,
@ -230,6 +248,61 @@ void phonon_setListenerPose(float position[4], float orientation[4]) {
memcpy(state.listenerOrientation, orientation, sizeof(state.listenerOrientation));
}
bool phonon_setGeometry(float* vertices, uint32_t* indices, uint32_t vertexCount, uint32_t indexCount) {
if (state.mesh) phonon_iplDestroyStaticMesh(&state.mesh);
if (state.scene) phonon_iplDestroyScene(&state.scene);
if (state.environment) phonon_iplDestroyEnvironment(&state.environment);
IPLMaterial material = (IPLMaterial) {
.lowFreqAbsorption = .1f,
.midFreqAbsorption = .2f,
.highFreqAbsorption = .3f,
.scattering = .05f,
.lowFreqTransmission = .1f,
.midFreqTransmission = .05f,
.highFreqTransmission = .03f
};
IPLSimulationSettings settings = (IPLSimulationSettings) {
.sceneType = IPL_SCENETYPE_PHONON,
.maxNumOcclusionSamples = 32,
.numRays = 4096,
.numDiffuseSamples = 1024,
.numBounces = 8,
.numThreads = 1,
.irDuration = 1.f,
.ambisonicsOrder = 1,
.maxConvolutionSources = 64,
.bakingBatchSize = 1,
.irradianceMinDistance = .1f
};
IPLint32* materials = malloc(indexCount / 3 * sizeof(IPLint32));
if (!materials) goto fail;
memset(materials, 0, indexCount / 3 * sizeof(IPLint32));
IPLerror status;
status = phonon_iplCreateScene(state.context, NULL, IPL_SCENETYPE_PHONON, 1, &material, NULL, NULL, NULL, NULL, NULL, &state.scene);
if (status != IPL_STATUS_SUCCESS) goto fail;
status = phonon_iplCreateStaticMesh(state.scene, vertexCount, indexCount / 3, (IPLVector3*) vertices, (IPLTriangle*) indices, materials, &state.mesh);
if (status != IPL_STATUS_SUCCESS) goto fail;
status = phonon_iplCreateEnvironment(state.context, NULL, settings, state.scene, NULL, &state.environment);
if (status != IPL_STATUS_SUCCESS) goto fail;
free(materials);
return true;
fail:
free(materials);
if (state.mesh) phonon_iplDestroyStaticMesh(&state.mesh);
if (state.scene) phonon_iplDestroyScene(&state.scene);
if (state.environment) phonon_iplDestroyEnvironment(&state.environment);
phonon_iplCreateEnvironment(state.context, NULL, settings, NULL, NULL, &state.environment);
return false;
}
void phonon_sourceCreate(Source* source) {
//
}
@ -244,6 +317,7 @@ Spatializer phononSpatializer = {
.apply = phonon_apply,
.tail = phonon_tail,
.setListenerPose = phonon_setListenerPose,
.setGeometry = phonon_setGeometry,
.sourceCreate = phonon_sourceCreate,
.sourceDestroy = phonon_sourceDestroy,
.name = "phonon"

View File

@ -51,6 +51,10 @@ void simple_spatializer_setListenerPose(float position[4], float orientation[4])
mat4_rotateQuat(state.listener, orientation);
}
bool simple_setGeometry(float* vertices, uint32_t* indices, uint32_t vertexCount, uint32_t indexCount) {
return false;
}
void simple_spatializer_source_create(Source* source) {
//
}
@ -65,6 +69,7 @@ Spatializer simpleSpatializer = {
.apply = simple_spatializer_source_apply,
.tail = simple_spatializer_tail,
.setListenerPose = simple_spatializer_setListenerPose,
.setGeometry = simple_setGeometry,
.sourceCreate = simple_spatializer_source_create,
.sourceDestroy = simple_spatializer_source_destroy,
.name = "simple"