diff --git a/.gitignore b/.gitignore
index ccc307f..0ba4271 100644
--- a/.gitignore
+++ b/.gitignore
@@ -60,4 +60,7 @@ TestResult.xml
nunit-*.xml
publish
-publish.sh
\ No newline at end of file
+publish.sh
+
+# Desktop specific
+.DS_Store
diff --git a/GraphAudio.Kit/GraphAudio.Kit.csproj b/GraphAudio.Kit/GraphAudio.Kit.csproj
index c4085f1..bf64d38 100644
--- a/GraphAudio.Kit/GraphAudio.Kit.csproj
+++ b/GraphAudio.Kit/GraphAudio.Kit.csproj
@@ -32,7 +32,7 @@
-
+
diff --git a/GraphAudio.SteamAudio/GraphAudio.SteamAudio.csproj b/GraphAudio.SteamAudio/GraphAudio.SteamAudio.csproj
index 46c80a9..d9f2c46 100644
--- a/GraphAudio.SteamAudio/GraphAudio.SteamAudio.csproj
+++ b/GraphAudio.SteamAudio/GraphAudio.SteamAudio.csproj
@@ -12,7 +12,7 @@
the-byte-bender
Spatial audio for GraphAudio using Steam Audio
2025
- 0.4.2
+ 0.4.3
GraphAudio.SteamAudio
https://github.com/the-byte-bender/GraphAudio
https://github.com/the-byte-bender/GraphAudio
diff --git a/GraphAudio.SteamAudio/SteamAudioContext.cs b/GraphAudio.SteamAudio/SteamAudioContext.cs
index 53ed808..9af9e61 100644
--- a/GraphAudio.SteamAudio/SteamAudioContext.cs
+++ b/GraphAudio.SteamAudio/SteamAudioContext.cs
@@ -63,6 +63,7 @@ private static SteamAudioResources GetOrCreate(AudioContextBase context)
{
return _contextMap.GetOrAdd(context, ctx =>
{
+ SteamAudioNativeLoader.EnsureLoaded();
var resources = new SteamAudioResources(ctx.SampleRate, AudioBuffer.FramesPerBlock);
var contextSettings = new IPL.ContextSettings
diff --git a/GraphAudio.SteamAudio/SteamAudioNativeLoader.cs b/GraphAudio.SteamAudio/SteamAudioNativeLoader.cs
new file mode 100644
index 0000000..00b1757
--- /dev/null
+++ b/GraphAudio.SteamAudio/SteamAudioNativeLoader.cs
@@ -0,0 +1,99 @@
+using System;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+namespace GraphAudio.SteamAudio;
+
+///
+/// Handles native library loading for SteamAudio on macOS where the NuGet package
+/// uses osx-universal RID instead of osx-arm64/osx-x64.
+///
+internal static class SteamAudioNativeLoader
+{
+ private static bool _isRegistered = false;
+ private static readonly object _lock = new object();
+
+ ///
+ /// Registers the DllImport resolver for SteamAudio native libraries.
+ ///
+ internal static void EnsureLoaded()
+ {
+ lock (_lock)
+ {
+ if (_isRegistered) return;
+
+ var steamAudioAssembly = AppDomain.CurrentDomain.GetAssemblies()
+ .FirstOrDefault(a => a.GetName().Name == "SteamAudio.NET");
+
+ if (steamAudioAssembly != null)
+ {
+ NativeLibrary.SetDllImportResolver(steamAudioAssembly, DllImportResolver);
+ }
+
+ _isRegistered = true;
+ }
+ }
+
+ private static IntPtr DllImportResolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)
+ {
+ if (!libraryName.Equals("phonon.dll", StringComparison.OrdinalIgnoreCase) &&
+ !libraryName.Equals("phonon", StringComparison.OrdinalIgnoreCase))
+ {
+ return IntPtr.Zero;
+ }
+
+ // Try base directory first (for .app bundles where dylibs are in MacOS/)
+ var baseDirectoryPath = GetBaseDirectoryPath();
+ if (baseDirectoryPath != null && File.Exists(baseDirectoryPath))
+ {
+ if (NativeLibrary.TryLoad(baseDirectoryPath, out var handle))
+ return handle;
+ }
+
+ var archSpecificPath = GetArchitectureSpecificPath();
+ if (archSpecificPath != null && File.Exists(archSpecificPath))
+ {
+ if (NativeLibrary.TryLoad(archSpecificPath, out var handle))
+ return handle;
+ }
+
+ var universalPath = GetUniversalPath();
+ if (universalPath != null && File.Exists(universalPath))
+ {
+ if (NativeLibrary.TryLoad(universalPath, out var handle))
+ return handle;
+ }
+
+ return IntPtr.Zero;
+ }
+
+ private static string? GetBaseDirectoryPath()
+ {
+ if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
+ return null;
+
+ return Path.Combine(AppContext.BaseDirectory, "libphonon.dylib");
+ }
+
+ private static string? GetArchitectureSpecificPath()
+ {
+ if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
+ return null;
+
+ var baseDir = AppContext.BaseDirectory;
+ var arch = RuntimeInformation.ProcessArchitecture;
+ var rid = arch == Architecture.Arm64 ? "osx-arm64" : "osx-x64";
+
+ return Path.Combine(baseDir, "runtimes", rid, "native", "libphonon.dylib");
+ }
+
+ private static string? GetUniversalPath()
+ {
+ if (!RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
+ return null;
+
+ return Path.Combine(AppContext.BaseDirectory, "runtimes", "osx-universal", "native", "libphonon.dylib");
+ }
+}
diff --git a/pack-local.sh b/pack-local.sh
old mode 100644
new mode 100755