using System; using ADOFAIRenderer.Core; using HarmonyLib; using UnityEngine; using UnityEngine.Audio; namespace ADOFAIRenderer.Patch.Engine { [HarmonyPatch(typeof(AudioManager), "_Play")] public static class AudioManagerPlayPatch { [HarmonyPrefix] public static bool Prefix(string snd, double time, AudioMixerGroup group, float volume, int priority) { if (RenderManager.IsCapturingActive && RenderManager.Instance.Configuration.AudioConfig.RenderAudio) { // Cache the clip on the main thread RenderManager.Instance.AudioMixer?.CacheClip(snd); } return true; // Let the original method execute to prevent NullReferenceException } [HarmonyPostfix] public static void Postfix(AudioSource __result, string snd, double time, AudioMixerGroup group, float volume, int priority) { if (RenderManager.IsCapturingActive && RenderManager.Instance.Configuration.AudioConfig.RenderAudio && __result != null) { // Convert absolute DSP time to relative time in seconds from render start double relativeStartTime = time - RenderManager.Instance.dspTimeBase; // Register event to the offline mixer (default pitch = 1.0f) and map it to the AudioSource RenderManager.Instance.AudioMixer?.RegisterSoundEvent(__result, snd, relativeStartTime, -1.0, volume, 1.0f); } } } [HarmonyPatch(typeof(scrConductor), "PlayWithEndTime")] public static class PlayWithEndTimePatch { [HarmonyPrefix] public static bool Prefix(string snd, double time, double endTime, float volume, int priority) { if (RenderManager.IsCapturingActive && RenderManager.Instance.Configuration.AudioConfig.RenderAudio) { var mixer = RenderManager.Instance.AudioMixer; if (mixer != null) { // Cache the clip on the main thread mixer.CacheClip(snd); // Convert absolute DSP times to relative times in seconds from render start double relativeStartTime = time - RenderManager.Instance.dspTimeBase; double relativeEndTime = endTime - RenderManager.Instance.dspTimeBase; // Register looping sound event to the offline mixer (default pitch = 1.0f) mixer.RegisterSoundEvent(snd, relativeStartTime, relativeEndTime, volume, 1.0f); } } return true; // Let the original method execute } } [HarmonyPatch(typeof(AudioSource), "pitch", MethodType.Setter)] public static class AudioSourcePitchPatch { [HarmonyPostfix] // ReSharper disable once InconsistentNaming public static void Postfix(AudioSource __instance, float value) { if (RenderManager.IsCapturingActive && RenderManager.Instance.Configuration.AudioConfig.RenderAudio) { var mixer = RenderManager.Instance.AudioMixer; if (mixer != null && mixer.TryGetSoundEvent(__instance, out var soundEvent)) { soundEvent.Pitch = value; } } } } [HarmonyPatch(typeof(AudioSource), "SetScheduledEndTime", typeof(double))] public static class AudioSourceSetScheduledEndTimePatch { [HarmonyPostfix] public static void Postfix(AudioSource __instance, double time) { if (RenderManager.IsCapturingActive && RenderManager.Instance.Configuration.AudioConfig.RenderAudio) { var mixer = RenderManager.Instance.AudioMixer; if (mixer != null && mixer.TryGetSoundEvent(__instance, out var soundEvent)) { soundEvent.EndTime = time - RenderManager.Instance.dspTimeBase; } } } } [HarmonyPatch(typeof(AudioSource), "Stop", new Type[0])] public static class AudioSourceStopPatch { [HarmonyPostfix] public static void Postfix(AudioSource __instance) { if (RenderManager.IsCapturingActive && RenderManager.Instance.Configuration.AudioConfig.RenderAudio) { RenderManager.Instance.AudioMixer?.RemoveSourceMapping(__instance); } } } }