diff --git a/src/bstone/src/bstone_oal_audio_mixer.cpp b/src/bstone/src/bstone_oal_audio_mixer.cpp index 52bea64a..49a59a9d 100644 --- a/src/bstone/src/bstone_oal_audio_mixer.cpp +++ b/src/bstone/src/bstone_oal_audio_mixer.cpp @@ -1004,6 +1004,12 @@ const char* OalAudioMixer::get_oal_default_library_file_name() return #if _WIN32 "OpenAL32.dll" +#elif defined(__APPLE__) + // Apple ships OpenAL as a framework, and the loader only finds it by its + // full path: neither the bare library name nor a relative framework path + // resolves. Someone with a newer implementation installed can still point + // at it with the custom library setting. + "/System/Library/Frameworks/OpenAL.framework/OpenAL" #else "libopenal.so" #endif // _WIN32 @@ -1023,10 +1029,42 @@ void OalAudioMixer::initialize_oal(const AudioMixerInitParam& param) std::string oal_library_string{}; const std::string_view oal_library = sd_get_oal_library(); if (oal_library.empty()) - oal_library_string = get_oal_default_library_file_name(); + { +#if defined(__APPLE__) + // Apple's own framework is deprecated and renders silence for some + // sources on modern macOS, so an installed openal-soft gets first + // refusal before falling back to it. + static constexpr const char* candidate_library_file_names[] = { + "/opt/homebrew/opt/openal-soft/lib/libopenal.dylib", // Homebrew, Apple Silicon. + "/usr/local/opt/openal-soft/lib/libopenal.dylib", // Homebrew, Intel. + }; + for (const char* candidate_library_file_name : candidate_library_file_names) + { + try + { + oal_loader_ = make_oal_loader(candidate_library_file_name); + oal_library_string = candidate_library_file_name; + break; + } + catch (...) + { + } + } +#endif // __APPLE__ + if (oal_loader_ == nullptr) + { + oal_library_string = get_oal_default_library_file_name(); + } + } else + { oal_library_string.append(oal_library.data(), oal_library.size()); - oal_loader_ = make_oal_loader(oal_library_string.c_str()); + } + if (oal_loader_ == nullptr) + { + oal_loader_ = make_oal_loader(oal_library_string.c_str()); + } + log(std::string{"Using library: \""} + oal_library_string + '\"'); oal_loader_->load_alc_symbols(); detect_alc_extensions(); log_oal_devices(); diff --git a/src/bstone/src/id_sd.cpp b/src/bstone/src/id_sd.cpp index 1df5e3a0..1843d8f0 100644 --- a/src/bstone/src/id_sd.cpp +++ b/src/bstone/src/id_sd.cpp @@ -492,8 +492,18 @@ void sd_startup() if (user_driver_type == AudioDriverType::auto_detect) { +#if defined(__APPLE__) + // Apple's OpenAL framework initializes cleanly and reports every + // source as playing, yet renders silence for some of them on modern + // macOS, so a successful OpenAL start-up proves nothing here and + // auto-detection goes straight to the system mixer. OpenAL remains + // available by explicit choice, which prefers openal-soft when that + // is installed. + driver_types.emplace_back(AudioDriverType::system); +#else driver_types.emplace_back(AudioDriverType::openal); driver_types.emplace_back(AudioDriverType::system); +#endif } else {