SHA256
Document Audio Pipeline
This commit is contained in:
1 parent
7bb47e4974
commit
19d0e258ac
22 files changed
+634
-12
No files matched your search
@@ -18,6 +18,7 @@ namespace ADOFAIRenderer.Patch.Engine;
|
||||
[HarmonyPatch(typeof(AudioManager), nameof(AudioManager.FindOrLoadAudioClipExternal))]
|
||||
public static class AudioManagerFindOrLoadAudioClipExternalPatch
|
||||
{
|
||||
/// <summary>Records <paramref name="path"/> in <see cref="AudioClipPaths"/> when its audioLib key is not loaded yet. Runs the original always.</summary>
|
||||
[HarmonyPrefix]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public static void Prefix(AudioManager __instance, string path)
|
||||
@@ -28,9 +29,18 @@ public static class AudioManagerFindOrLoadAudioClipExternalPatch
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// AudioManager._Play (private; AudioManager.Play forwards to it): registers each scheduled effect sound (hit sounds, PlaySound
|
||||
/// events, hold sounds without an end time) as an effect voice of the offline mixer and maps the returned AudioSource to it.
|
||||
/// Active while capturing (RenderManager.IsCapturingActive) with RenderAudio on. The original always runs: it creates the
|
||||
/// AudioSource the game keeps using (its PlayScheduled call is blocked during rendering by another patch), and the game sets
|
||||
/// time/pitch/SetScheduledEndTime on it afterwards, which the <see cref="EffectSource"/> patches forward to the mapped state.
|
||||
/// The game volume is passed through; the start pitch is 1 because _Play sets pitch = 1 before PlayScheduled.
|
||||
/// </summary>
|
||||
[HarmonyPatch(typeof(AudioManager), "_Play")]
|
||||
public static class AudioManagerPlayPatch
|
||||
{
|
||||
/// <summary>Opens the clip's source so its first chunk starts loading. Returns true (the original runs).</summary>
|
||||
[HarmonyPrefix]
|
||||
public static bool Prefix(string snd, double time, AudioMixerGroup group, float volume, int priority)
|
||||
{
|
||||
@@ -42,6 +52,10 @@ public static class AudioManagerPlayPatch
|
||||
return true; // Let the original method execute to prevent NullReferenceException
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers the sound at <paramref name="time"/> (absolute DSP time, converted to render time) as a non-looping effect voice,
|
||||
/// maps <paramref name="__result"/> to it and queues the source's game object for deactivation at the end of the frame.
|
||||
/// </summary>
|
||||
[HarmonyPostfix]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public static void Postfix(AudioSource __result, string snd, double time, AudioMixerGroup group, float volume, int priority)
|
||||
@@ -63,6 +77,10 @@ public static class AudioManagerPlayPatch
|
||||
/// <summary>
|
||||
/// scrConductor.PlayWithEndTime: registers a looping effect voice until the end time. The AudioSource it creates with
|
||||
/// AudioManager.MakeSource is mapped to that voice (<see cref="AudioManagerMakeSourcePatch"/>).
|
||||
/// Active while capturing (RenderManager.IsCapturingActive) with RenderAudio on; the original always runs. The game calls it for
|
||||
/// hold sounds with an end time above 0 (scrConductor hold sound scheduling); it sets loop = true, pitch = 1, PlayScheduled(time) and
|
||||
/// SetScheduledEndTime(endTime) on the new source. pitch and SetScheduledEndTime reach the mapped state through the
|
||||
/// <see cref="EffectSource"/> patches; PlayScheduled is blocked during rendering by another patch.
|
||||
/// </summary>
|
||||
[HarmonyPatch(typeof(scrConductor), "PlayWithEndTime")]
|
||||
public static class PlayWithEndTimePatch
|
||||
@@ -70,9 +88,14 @@ public static class PlayWithEndTimePatch
|
||||
/// <summary>State registered by the running PlayWithEndTime call, until its MakeSource returns. Main thread only.</summary>
|
||||
internal static SourceState? PendingState;
|
||||
|
||||
/// <summary>Clears <see cref="PendingState"/> when PlayWithEndTime returns or throws, so it cannot map a later MakeSource call.</summary>
|
||||
[HarmonyFinalizer]
|
||||
public static void Finalizer() => PendingState = null;
|
||||
|
||||
/// <summary>
|
||||
/// Opens the clip's source and registers a looping voice from <paramref name="time"/> to <paramref name="endTime"/>
|
||||
/// (absolute DSP times, converted to render time); the state waits in <see cref="PendingState"/>. Returns true (the original runs).
|
||||
/// </summary>
|
||||
[HarmonyPrefix]
|
||||
public static bool Prefix(string snd, double time, double endTime, float volume, int priority)
|
||||
{
|
||||
@@ -96,10 +119,18 @@ public static class PlayWithEndTimePatch
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Maps the AudioSource created inside scrConductor.PlayWithEndTime to its state (<see cref="PlayWithEndTimePatch.PendingState"/>).</summary>
|
||||
/// <summary>
|
||||
/// Maps the AudioSource created inside scrConductor.PlayWithEndTime to its state (<see cref="PlayWithEndTimePatch.PendingState"/>).
|
||||
/// Active only while a PlayWithEndTime call registered a state (capturing with RenderAudio on); every other MakeSource call
|
||||
/// (including the one inside AudioManager._Play) is left unchanged.
|
||||
/// </summary>
|
||||
[HarmonyPatch(typeof(AudioManager), nameof(AudioManager.MakeSource))]
|
||||
public static class AudioManagerMakeSourcePatch
|
||||
{
|
||||
/// <summary>
|
||||
/// Takes the pending state, maps <paramref name="__result"/> to it and queues the source's game object for deactivation at
|
||||
/// the end of the frame.
|
||||
/// </summary>
|
||||
[HarmonyPostfix]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public static void Postfix(AudioSource __result)
|
||||
@@ -173,6 +204,7 @@ internal static class EffectSource
|
||||
[HarmonyPatch(typeof(AudioSource), "isPlaying", MethodType.Getter)]
|
||||
public static class AudioSourceIsPlayingPatch
|
||||
{
|
||||
/// <summary>When <see cref="EffectSource.TryGet"/> finds a mapped state, uses it and returns false (Unity is skipped); otherwise returns true.</summary>
|
||||
[HarmonyPrefix]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public static bool Prefix(AudioSource __instance, ref bool __result)
|
||||
@@ -187,6 +219,7 @@ public static class AudioSourceIsPlayingPatch
|
||||
[HarmonyPatch(typeof(AudioSource), "time", MethodType.Getter)]
|
||||
public static class AudioSourceTimeGetterPatch
|
||||
{
|
||||
/// <summary>When <see cref="EffectSource.TryGet"/> finds a mapped state, uses it and returns false (Unity is skipped); otherwise returns true.</summary>
|
||||
[HarmonyPrefix]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public static bool Prefix(AudioSource __instance, ref float __result)
|
||||
@@ -204,6 +237,7 @@ public static class AudioSourceTimeGetterPatch
|
||||
[HarmonyPatch(typeof(AudioSource), "time", MethodType.Setter)]
|
||||
public static class AudioSourceTimePatch
|
||||
{
|
||||
/// <summary>When <see cref="EffectSource.TryGet"/> finds a mapped state, uses it and returns false (Unity is skipped); otherwise returns true.</summary>
|
||||
[HarmonyPrefix]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public static bool Prefix(AudioSource __instance, float value)
|
||||
@@ -214,10 +248,14 @@ public static class AudioSourceTimePatch
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>AudioSource.timeSamples getter (<see cref="EffectSource"/>): clip position in samples of the clip.</summary>
|
||||
/// <summary>
|
||||
/// AudioSource.timeSamples getter (<see cref="EffectSource"/>): clip position in samples of the clip while playing; while not playing,
|
||||
/// the last value set through time or timeSamples (0 after Stop()).
|
||||
/// </summary>
|
||||
[HarmonyPatch(typeof(AudioSource), "timeSamples", MethodType.Getter)]
|
||||
public static class AudioSourceTimeSamplesGetterPatch
|
||||
{
|
||||
/// <summary>When <see cref="EffectSource.TryGet"/> finds a mapped state, uses it and returns false (Unity is skipped); otherwise returns true.</summary>
|
||||
[HarmonyPrefix]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public static bool Prefix(AudioSource __instance, ref int __result)
|
||||
@@ -232,6 +270,7 @@ public static class AudioSourceTimeSamplesGetterPatch
|
||||
[HarmonyPatch(typeof(AudioSource), "timeSamples", MethodType.Setter)]
|
||||
public static class AudioSourceTimeSamplesPatch
|
||||
{
|
||||
/// <summary>When <see cref="EffectSource.TryGet"/> finds a mapped state, uses it and returns false (Unity is skipped); otherwise returns true.</summary>
|
||||
[HarmonyPrefix]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public static bool Prefix(AudioSource __instance, int value)
|
||||
@@ -246,6 +285,7 @@ public static class AudioSourceTimeSamplesPatch
|
||||
[HarmonyPatch(typeof(AudioSource), "pitch", MethodType.Getter)]
|
||||
public static class AudioSourcePitchGetterPatch
|
||||
{
|
||||
/// <summary>When <see cref="EffectSource.TryGet"/> finds a mapped state, uses it and returns false (Unity is skipped); otherwise returns true.</summary>
|
||||
[HarmonyPrefix]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public static bool Prefix(AudioSource __instance, ref float __result)
|
||||
@@ -260,6 +300,7 @@ public static class AudioSourcePitchGetterPatch
|
||||
[HarmonyPatch(typeof(AudioSource), "pitch", MethodType.Setter)]
|
||||
public static class AudioSourcePitchPatch
|
||||
{
|
||||
/// <summary>When <see cref="EffectSource.TryGet"/> finds a mapped state, uses it and returns false (Unity is skipped); otherwise returns true.</summary>
|
||||
[HarmonyPrefix]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public static bool Prefix(AudioSource __instance, float value)
|
||||
@@ -274,6 +315,7 @@ public static class AudioSourcePitchPatch
|
||||
[HarmonyPatch(typeof(AudioSource), "SetScheduledEndTime", typeof(double))]
|
||||
public static class AudioSourceSetScheduledEndTimePatch
|
||||
{
|
||||
/// <summary>When <see cref="EffectSource.TryGet"/> finds a mapped state, uses it and returns false (Unity is skipped); otherwise returns true.</summary>
|
||||
[HarmonyPrefix]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public static bool Prefix(AudioSource __instance, double time)
|
||||
@@ -292,6 +334,7 @@ public static class AudioSourceSetScheduledEndTimePatch
|
||||
[HarmonyPatch(typeof(AudioSource), "Stop", new Type[0])]
|
||||
public static class AudioSourceStopPatch
|
||||
{
|
||||
/// <summary>When <see cref="EffectSource.TryGet"/> finds a mapped state, uses it and returns false (Unity is skipped); otherwise returns true.</summary>
|
||||
[HarmonyPrefix]
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public static bool Prefix(AudioSource __instance)
|
||||
@@ -306,11 +349,13 @@ public static class AudioSourceStopPatch
|
||||
/// AudioManager.StopAllSounds destroys every source in liveSources (all AudioManager._Play and scrConductor.PlayWithEndTime sources),
|
||||
/// so every effect voice stops at the current render time, including ones scheduled to start later.
|
||||
/// Callers include scrConductor.PlayHitTimes (from its second call), ScrubMusicToTile/Time, KillAllSoundsCoroutine,
|
||||
/// scrController.FailAction and scnGame.Play.
|
||||
/// scrController.FailAction, scrController.DebugUpdate, scnGame.Play and PauseMenu.Choose.
|
||||
/// Active while capturing (RenderManager.IsCapturingActive) with RenderAudio on; the original always runs (it destroys the sources).
|
||||
/// </summary>
|
||||
[HarmonyPatch(typeof(AudioManager), nameof(AudioManager.StopAllSounds))]
|
||||
public static class AudioManagerStopAllSoundsPatch
|
||||
{
|
||||
/// <summary>Stops every effect voice while capturing with RenderAudio on. The original always runs (no return value).</summary>
|
||||
[HarmonyPrefix]
|
||||
public static void Prefix()
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user