SHA256
Deactivate Mapped Effect Sources During Render
This commit is contained in:
1 parent
69d098e04c
commit
ab8164a735
2 files changed
+45
-4
No files matched your search
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using ADOFAIRenderer.Core;
|
||||
using ADOFAIRenderer.Util.Audio;
|
||||
using ADOFAIRenderer.Util.Audio.Clip;
|
||||
@@ -51,7 +52,10 @@ public static class AudioManagerPlayPatch
|
||||
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, RenderManager.Instance.AudioTime);
|
||||
var mixer = RenderManager.Instance.AudioMixer;
|
||||
if (mixer == null) return;
|
||||
mixer.RegisterSoundEvent(__result, snd, relativeStartTime, -1.0, volume, 1.0f, RenderManager.Instance.AudioTime);
|
||||
EffectSource.DeactivateAtFrameEnd(__result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -103,18 +107,53 @@ public static class AudioManagerMakeSourcePatch
|
||||
var state = PlayWithEndTimePatch.PendingState;
|
||||
if (state == null || !__result) return;
|
||||
PlayWithEndTimePatch.PendingState = null;
|
||||
RenderManager.Instance.AudioMixer?.MapSource(__result, state);
|
||||
var mixer = RenderManager.Instance.AudioMixer;
|
||||
if (mixer == null) return;
|
||||
mixer.MapSource(__result, state);
|
||||
EffectSource.DeactivateAtFrameEnd(__result);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// AudioSource members of an effect source mapped to a <see cref="SourceState"/> during rendering: the patches below skip the
|
||||
/// Unity implementation and read or change the state instead (isPlaying, time, timeSamples, pitch, SetScheduledEndTime, Stop).
|
||||
/// Sources without a mapping (the song, menu sounds) use the Unity implementation.
|
||||
/// The patches apply only while <see cref="TryGet"/> returns true: rendering is capturing (RenderManager.IsCapturingActive,
|
||||
/// stage Render), the render has an audio mixer (created when the render starts, cleared when it ends), and the source is mapped
|
||||
/// in that mixer (mappings are created only when RenderAudio is on). Otherwise they run the Unity implementation, so sources
|
||||
/// without a mapping (the song, menu sounds) and all sources outside rendering behave as in the game.
|
||||
///
|
||||
/// The game object of a mapped source is deactivated at the end of the frame it was mapped in: the mixer produces its sound and the
|
||||
/// state answers every member above, so Unity does not process the source. The game activates it again when AudioManager.MakeSource
|
||||
/// reuses it. Active AudioSources add main-thread time per frame in proportion to their count, and dense levels keep thousands of
|
||||
/// scheduled effect sources alive.
|
||||
/// </summary>
|
||||
internal static class EffectSource
|
||||
{
|
||||
/// <summary>State mapped to <paramref name="source"/> while capturing, with the current render time in <paramref name="now"/>.</summary>
|
||||
/// <summary>Sources mapped during the current frame, deactivated by <see cref="DeactivateMappedSources"/>. Main thread only.</summary>
|
||||
private static readonly List<AudioSource> PendingDeactivation = new();
|
||||
|
||||
/// <summary>Deactivates the game object of <paramref name="source"/> at the end of the current frame (<see cref="DeactivateMappedSources"/>).</summary>
|
||||
public static void DeactivateAtFrameEnd(AudioSource source) => PendingDeactivation.Add(source);
|
||||
|
||||
/// <summary>
|
||||
/// Deactivates the game objects of the sources mapped this frame that are still mapped and not destroyed.
|
||||
/// Called by RenderManager.OnPostFrame after the audio commands of the frame are committed, which runs only in stage Render with
|
||||
/// an audio mixer; sources are added only by the render-time registrations (AudioManager._Play and scrConductor.PlayWithEndTime
|
||||
/// patches with RenderAudio on).
|
||||
/// </summary>
|
||||
public static void DeactivateMappedSources(OfflineAudioMixer mixer)
|
||||
{
|
||||
foreach (var source in PendingDeactivation)
|
||||
{
|
||||
if (source && mixer.TryGetSourceState(source, out _)) source.gameObject.SetActive(false);
|
||||
}
|
||||
PendingDeactivation.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// State mapped to <paramref name="source"/> in the mixer of the current render, with the current render time in <paramref name="now"/>.
|
||||
/// False outside rendering (stage below Render), without a mixer, or for a source that is not mapped.
|
||||
/// </summary>
|
||||
public static bool TryGet(AudioSource source, out SourceState state, out double now)
|
||||
{
|
||||
state = null!;
|
||||
|
||||
Reference in new issue
Block a user