Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
a461e36
Add phonon submodule;
bjornbytes Feb 3, 2026
f8c3a9f
Build Steam Audio before OpenXR;
bjornbytes Feb 3, 2026
a6a3aa5
Remove old phonon spatializer; Reorganize spatializer interface;
bjornbytes Feb 4, 2026
24f64e0
Create phonon context; Build fixes;
bjornbytes Feb 4, 2026
665b87d
Update phonon;
bjornbytes Feb 5, 2026
7f03523
Move phonon lib on Linux;
bjornbytes Feb 5, 2026
409d2b4
t.audio.debug;
bjornbytes Feb 5, 2026
2f1f288
Create phonon simulator;
bjornbytes Feb 5, 2026
cc26545
lovr.audio.setHRTF;
bjornbytes Feb 5, 2026
a07b340
AudioMesh;
bjornbytes Feb 5, 2026
b22f1e1
Refactoring;
bjornbytes Feb 6, 2026
0d0ecd0
Initial lock-free spatializer implementation;
bjornbytes Feb 12, 2026
3f676f0
Add conf.lua parameters to configure reverb;
bjornbytes Feb 13, 2026
0828458
lovr.audio.update gets dt;
bjornbytes Feb 13, 2026
9a149bb
Reflection simulation;
bjornbytes Feb 13, 2026
41b8f42
Update phonon;
bjornbytes Feb 14, 2026
a4966c8
Reverb;
bjornbytes Feb 15, 2026
3caac57
Refactoring phonon ifdefs;
bjornbytes Feb 15, 2026
c0790da
Refactoring;
bjornbytes Feb 16, 2026
f983c9f
Listener-centric reverb;
bjornbytes Feb 18, 2026
3ff52b4
Update phonon;
bjornbytes Feb 19, 2026
fd63ba5
Improve HRTF handling; Optimize reverb;
bjornbytes Feb 19, 2026
f14fdc5
Clean up pitch stuff;
bjornbytes Feb 19, 2026
63e3bbe
t.audio.start starts lazily;
bjornbytes Feb 20, 2026
91e5b99
Sketch out new effect API;
bjornbytes Feb 20, 2026
291287b
Fixups;
bjornbytes Feb 20, 2026
ceaab1c
Update phonon;
bjornbytes Feb 21, 2026
d40476c
Implement cone/falloff;
bjornbytes Feb 21, 2026
20f6b34
Update phonon;
bjornbytes Feb 21, 2026
5525278
Reset effects when source starts playing;
bjornbytes Feb 21, 2026
0f4fec6
Fixes for setHRTF;
bjornbytes Feb 21, 2026
854ebc0
Update phonon;
bjornbytes Feb 21, 2026
bf940ee
Add missing cast;
bjornbytes Feb 22, 2026
749e257
Rework mixer to support reverb gain and spatial blend;
bjornbytes Feb 23, 2026
effb284
Cleanup;
bjornbytes Feb 24, 2026
e6ba142
rm pitchChanged flag;
bjornbytes Feb 24, 2026
8100913
More cleanup;
bjornbytes Feb 24, 2026
76ac1df
Fix initial source params;
bjornbytes Feb 24, 2026
0f06959
Bugfixes; Cleanup;
bjornbytes Feb 24, 2026
9a26235
rm callback sounds;
bjornbytes Feb 25, 2026
aa8736b
Make ChannelLayout less real;
bjornbytes Feb 25, 2026
f304ccb
Simplify sound constructor a bit;
bjornbytes Feb 25, 2026
4676835
AudioStream;
bjornbytes Feb 26, 2026
32f68cb
lovr.audio.getStream; Easier sink creation;
bjornbytes Feb 27, 2026
2ac8682
Ambisonic source playback;
bjornbytes Feb 27, 2026
445286a
Sound:get/setFrame;
bjornbytes Feb 28, 2026
992483d
Fix windows;
bjornbytes Feb 28, 2026
38a01f2
Convert ambisonics from SN3D to N3D before mixing;
bjornbytes Feb 28, 2026
ffe65ff
Source spatial defaults to false;
bjornbytes Feb 28, 2026
446d07d
Rework effect parameters a bit;
bjornbytes Feb 28, 2026
713f8b3
lovr.audio.start/stop return error messages;
bjornbytes Feb 28, 2026
9098a25
stream fixes;
bjornbytes Feb 28, 2026
bc0fc77
lovr.audio.update is a noop when nothing changed;
bjornbytes Mar 1, 2026
10a213b
Cleanup;
bjornbytes Mar 1, 2026
b880432
Ambisonic sources default to spatial;
bjornbytes Mar 1, 2026
e2ddf84
Update changelog;
bjornbytes Mar 1, 2026
2f94933
Update phonon;
bjornbytes Mar 1, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,6 @@
[submodule "deps/luau"]
path = deps/luau
url = https://github.com/bjornbytes/luau.git
[submodule "deps/phonon"]
path = deps/phonon
url = https://github.com/bjornbytes/steam-audio
27 changes: 27 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,21 @@ dev
- Add support for non-uniform scale in `ConvexShape` and `MeshShape`.
- Add `VertexUV2` builtin vertex attribute and `UV2` shader variable.
- Add support for two sets of UVs in `ModelData`.
- Add `t.audio.debug` and `t.audio.reverb` settings to `lovr.conf`.
- Add `lovr.audio.update`.
- Add `lovr.audio.setHRTF`.
- Add `lovr.audio.get/setReverb`.
- Add `Source:get/setAbsorption`.
- Add `Source:get/setCone`.
- Add `Source:get/setFalloff`.
- Add `Source:get/setOcclusion`.
- Add `Source:get/setReverb`.
- Add `Source:get/setSpatialization`.
- Add support for ambisonic source playback.
- Add `AudioMesh`.
- Add `lovr.audio.getStream`.
- Add `AudioStream`.
- Add `Sound:get/setFrame`.

### Change

Expand All @@ -63,6 +78,12 @@ dev
- Change `Mat4` to be a regular object instead of a vector type.
- Change `lovr.graphics.submit` to have better performance when called multiple times per frame.
- Change `Pass:text` and Font methods to also take nested tables of multicolor strings.
- Change `lovr.audio.start` sink parameter to be a `boolean` or an `AudioStream`.
- Change `lovr.audio.start/stop` to return error messages if they fail.
- Change `lovr.audio.newSource` to create non-spatial sources by default.
- Change `lovr.audio.newSource` to also accept and `AudioStream`.
- Change audio device to start when playing a Source for the first time, instead of immediately.
- Change `lovr.data.newSound` to take a channel count instead of a channel layout.

### Fix

Expand Down Expand Up @@ -118,6 +139,12 @@ dev
- Remove `Model:getData` (create and keep a `ModelData` around as needed).
- Remove userdata vector types (use tables, and the `vector` and `quaternion` modules).
- Remove `lovr.headset.getHandles` (use FFI).
- Remove `lovr.audio.getSpatializer` (SteamAudio is always active).
- Remove `lovr.audio.setGeometry` (use `AudioMesh`).
- Remove `lovr.audio.get/setAbsorption` (use `Source:get/setAbsorption`).
- Remove `Source:get/setDirectivity` (use `Source:get/setCone`).
- Remove `Source:is/setEffectEnabled` (use new effect getters/setters).
- Remove "stream" `Sound`s, `Sound:getCapacity`, and `Sound:isStream` (use `AudioStream`).

v0.18.0 - 2025-02-14
---
Expand Down
72 changes: 33 additions & 39 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ option(LOVR_USE_LUAU "Use Luau instead of Lua" OFF)
option(LOVR_USE_GLSLANG "Use glslang to compile GLSL shaders" ON)
option(LOVR_USE_VULKAN "Use the Vulkan renderer" ON)
option(LOVR_USE_WEBGPU "Use the WebGPU renderer" OFF)
option(LOVR_USE_STEAM_AUDIO "Enable the Steam Audio spatializer (be sure to also set LOVR_STEAM_AUDIO_PATH)" OFF)
option(LOVR_USE_STEAM_AUDIO "Use Steam Audio for audio spatialization" ON)

option(LOVR_SANITIZE "Enable Address Sanitizer" OFF)
option(LOVR_PROFILE "Enable Tracy integration" OFF)
Expand Down Expand Up @@ -195,6 +195,29 @@ if(LOVR_ENABLE_PHYSICS)
set(LOVR_JOLT joltc)
endif()

# Steam Audio (aka phonon)
if(LOVR_USE_STEAM_AUDIO AND LOVR_ENABLE_AUDIO)
set(BUILD_SHARED_LIBS ON)
set(STEAMAUDIO_ENABLE_SERIALIZATION OFF CACHE BOOL "")
set(STEAMAUDIO_ENABLE_DEFAULT_HRTF OFF CACHE BOOL "")
set(STEAMAUDIO_ENABLE_VALIDATION OFF CACHE BOOL "")
set(STEAMAUDIO_BUILD_TESTS OFF CACHE BOOL "")
set(STEAMAUDIO_BUILD_BENCHMARKS OFF CACHE BOOL "")
set(STEAMAUDIO_BUILD_SAMPLES OFF CACHE BOOL "")
set(STEAMAUDIO_BUILD_ITESTS OFF CACHE BOOL "")
set(STEAMAUDIO_BUILD_DOCS OFF CACHE BOOL "")
set(STEAMAUDIO_STATIC_RUNTIME OFF CACHE BOOL "")
set(STEAMAUDIO_ENABLE_IPP OFF CACHE BOOL "")
set(STEAMAUDIO_ENABLE_MKL OFF CACHE BOOL "")
set(STEAMAUDIO_ENABLE_EMBREE OFF CACHE BOOL "")
set(STEAMAUDIO_ENABLE_FFTS OFF CACHE BOOL "")
set(STEAMAUDIO_ENABLE_RADEONRAYS OFF CACHE BOOL "")
set(STEAMAUDIO_ENABLE_TRUEAUDIONEXT OFF CACHE BOOL "")
add_subdirectory(deps/phonon/core phonon)
set(LOVR_PHONON phonon)
set(BUILD_SHARED_LIBS OFF)
endif()

# glslang
if(LOVR_USE_GLSLANG)
set(ENABLE_HLSL OFF CACHE BOOL "")
Expand Down Expand Up @@ -239,28 +262,6 @@ if(LOVR_ENABLE_THREAD AND NOT (WIN32 OR EMSCRIPTEN))
set(LOVR_PTHREADS Threads::Threads)
endif()

# Steam Audio (aka Phonon)
if(LOVR_USE_STEAM_AUDIO)
if(NOT LOVR_STEAM_AUDIO_PATH)
message(FATAL_ERROR "LOVR_USE_STEAM_AUDIO requires the LOVR_STEAM_AUDIO_PATH to be set to the location of the Steam Audio folder")
endif()
add_library(Phonon SHARED IMPORTED)
target_include_directories(Phonon INTERFACE "${LOVR_STEAM_AUDIO_PATH}/include")
if(ANDROID)
set_target_properties(Phonon PROPERTIES IMPORTED_LOCATION "${LOVR_STEAM_AUDIO_PATH}/lib/Android/arm64/libphonon.so")
elseif(WIN32)
set_target_properties(Phonon PROPERTIES IMPORTED_IMPLIB "${LOVR_STEAM_AUDIO_PATH}/lib/Windows/x64/phonon.lib")
set_target_properties(Phonon PROPERTIES IMPORTED_LOCATION "${LOVR_STEAM_AUDIO_PATH}/bin/Windows/x64/phonon.dll")
elseif(APPLE)
set_target_properties(Phonon PROPERTIES IMPORTED_LOCATION "${LOVR_STEAM_AUDIO_PATH}/lib/OSX/libphonon.dylib"
IMPORTED_SONAME "@rpath/libphonon.dylib") # It doesn't make sense this line is required, but it is
else() # Assume Linux. Note: This has *not* been tested. FIXME: When is the .so copied?
set_target_properties(Phonon PROPERTIES IMPORTED_LOCATION "${LOVR_STEAM_AUDIO_PATH}/lib/Linux/x64/libphonon.so")
endif()

set(LOVR_PHONON Phonon)
endif()

# LÖVR

set(LOVR_SRC
Expand Down Expand Up @@ -309,6 +310,7 @@ target_link_libraries(lovr
${LOVR_LUA}
${LOVR_MSDF}
${LOVR_JOLT}
${LOVR_PHONON}
${LOVR_GLSLANG}
${LOVR_OPENXR}
${LOVR_PTHREADS}
Expand Down Expand Up @@ -341,25 +343,19 @@ if(LOVR_USE_LUAU)
target_compile_definitions(lovr PRIVATE LOVR_USE_LUAU)
endif()

if(LOVR_ENABLE_AUDIO OR LOVR_ENABLE_DATA)
target_sources(lovr PRIVATE
src/lib/miniaudio/miniaudio.c
)
endif()

if(LOVR_ENABLE_AUDIO)
target_sources(lovr PRIVATE
src/modules/audio/audio.c
src/modules/audio/spatializer_simple.c
src/api/l_audio.c
src/api/l_audio_source.c
src/api/l_audio_audioMesh.c
src/lib/miniaudio/miniaudio.c
)

if(LOVR_USE_STEAM_AUDIO)
target_compile_definitions(lovr PRIVATE LOVR_ENABLE_PHONON_SPATIALIZER)
target_sources(lovr PRIVATE src/modules/audio/spatializer_phonon.c)
# Dynamically linked at runtime, so this is not otherwise a dependency
add_dependencies(lovr ${LOVR_PHONON})
target_include_directories(lovr PRIVATE deps/phonon/core/src/core)
target_include_directories(lovr PRIVATE "${PROJECT_BINARY_DIR}/phonon/src/core")
target_compile_definitions(lovr PRIVATE LOVR_USE_PHONON)
endif()
else()
target_compile_definitions(lovr PRIVATE LOVR_DISABLE_AUDIO)
Expand All @@ -376,6 +372,7 @@ if(LOVR_ENABLE_DATA)
src/modules/data/rasterizer.c
src/modules/data/sound.c
src/api/l_data.c
src/api/l_data_audioStream.c
src/api/l_data_blob.c
src/api/l_data_image.c
src/api/l_data_modelData.c
Expand Down Expand Up @@ -771,6 +768,7 @@ elseif(ANDROID)
${LOVR_MSDF}
${LOVR_LUA}
${LOVR_GLSLANG}
${LOVR_PHONON}
PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/raw/lib/${ANDROID_ABI}"
)

Expand All @@ -792,11 +790,6 @@ elseif(ANDROID)

configure_file("${ANDROID_NDK}/toolchains/llvm/prebuilt/${ANDROID_HOST_TAG}/sysroot/usr/lib/aarch64-linux-android/libc++_shared.so" "raw/lib/${ANDROID_ABI}/libc++_shared.so" COPYONLY)

if(LOVR_USE_STEAM_AUDIO)
get_target_property(PHONON_LIB ${LOVR_PHONON} IMPORTED_LOCATION)
file(COPY ${PHONON_LIB} DESTINATION raw/lib/${ANDROID_ABI})
endif()

# Make an apk
add_custom_target(
buildAPK ALL
Expand Down Expand Up @@ -896,6 +889,7 @@ elseif(UNIX)
move_lib(${LOVR_JOLT})
move_lib(${LOVR_GLSLANG})
move_lib(${LOVR_OPENXR})
move_lib(${LOVR_PHONON})
foreach(target ${ALL_PLUGIN_TARGETS})
move_lib(${target})
endforeach()
Expand Down
1 change: 1 addition & 0 deletions deps/phonon
Submodule phonon added at ff3db5
10 changes: 9 additions & 1 deletion etc/boot.lua
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,15 @@ local conf = {
timer = true
},
audio = {
debug = false,
start = true,
spatializer = nil
reverb = {
type = 'convolution',
rays = 4096,
bounces = 16,
duration = 2,
rate = .1
}
},
graphics = {
debug = false,
Expand Down Expand Up @@ -195,6 +202,7 @@ function lovr.run()
if not lovr.headset.isActive() then lovr.simulate(dt) end
end
if lovr.update then lovr.update(dt) end
if lovr.audio then lovr.audio.update(dt) end
if lovr.graphics then
local window = lovr.graphics.getWindowPass()
local headset = lovr.headset and lovr.headset.getPass()
Expand Down
1 change: 1 addition & 0 deletions etc/nogame/arg.lua
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ function lovr.arg(arg)

return function(conf)
if arg.debug then
conf.audio.debug = true
conf.graphics.debug = true
conf.headset.debug = true
end
Expand Down
2 changes: 2 additions & 0 deletions src/api/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,8 @@ void luax_vlog(void* context, int level, const char* tag, const char* format, va
lua_pushstring(L, levels[level]);
lua_pushstring(L, tag);
lua_call(L, 3, 0);
} else {
lua_pop(L, 1);
}
lua_pop(L, 1);
}
Expand Down
2 changes: 2 additions & 0 deletions src/api/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ extern StringEntry lovrOpenMode[];
extern StringEntry lovrOriginType[];
extern StringEntry lovrPassType[];
extern StringEntry lovrPermission[];
extern StringEntry lovrReverbMode[];
extern StringEntry lovrReverbType[];
extern StringEntry lovrSampleFormat[];
extern StringEntry lovrShaderStage[];
extern StringEntry lovrShaderType[];
Expand Down
Loading
Loading