Skip to content

Commit

Permalink
fix!: Resolve issues with custom audio not playing (#432)
Browse files Browse the repository at this point in the history
* started working on a fix.

* Fixed the custom sounds handler.

A gigantic thanks to @Metious for researching the issues and the errors because I was too dumb and unexperienced with FMOD to do that, really !

Co-Authored-By: Metious <[email protected]>

* Added a new input in RegisterCustomSound, you can now give a MODE input in case you don't want to deal with AudioUtils.CreateSound(sound, MODE).
Added constant optimal Sound Modes to AudioUtils.
Based on what ROTA researches gave.

* safety removed, it will be patched with the fix in #429

* removed some debug logs

* Change MODE names to be more consistent

* Use stream mode by default for PDA voices

* Reference AudioUtils modes in XML docs

---------

Co-authored-by: Metious <[email protected]>
Co-authored-by: LeeTwentyThree <[email protected]>
  • Loading branch information
3 people committed Jul 4, 2023
1 parent 64432d4 commit 356b4d7
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 14 deletions.
38 changes: 29 additions & 9 deletions Nautilus/Handlers/CustomSoundHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ public static class CustomSoundHandler
/// <param name="id">The Id of your custom sound which is used when checking which sounds to play.</param>
/// <param name="filePath">The file path on disk of the sound file to load.</param>
/// <param name="busPath">The bus path to play the sound on.</param>
/// <param name="mode">The audio MODE of the sound.
/// Standard values of this property can be found in the <see cref="AudioUtils"/> class (i.e. <see cref="AudioUtils.StandardSoundModes_3D"/>).</param>
/// <returns>the <see cref="Sound"/> loaded</returns>
public static Sound RegisterCustomSound(string id, string filePath, string busPath)
public static Sound RegisterCustomSound(string id, string filePath, string busPath, MODE mode = MODE.DEFAULT)
{
Bus bus = RuntimeManager.GetBus(busPath);
return RegisterCustomSound(id, filePath, bus);
return RegisterCustomSound(id, filePath, bus, mode);
}

/// <summary>
Expand All @@ -32,10 +34,16 @@ public static Sound RegisterCustomSound(string id, string filePath, string busPa
/// <param name="id">The Id of your custom sound which is used when checking which sounds to play.</param>
/// <param name="filePath">The file path on disk of the sound file to load.</param>
/// <param name="bus">The bus to play the sound on.</param>
/// <param name="mode">The audio MODE of the sound.
/// Standard values of this property can be found in the <see cref="AudioUtils"/> class (i.e. <see cref="AudioUtils.StandardSoundModes_3D"/>).</param>
/// <returns>the <see cref="Sound"/> loaded</returns>
public static Sound RegisterCustomSound(string id, string filePath, Bus bus)
public static Sound RegisterCustomSound(string id, string filePath, Bus bus, MODE mode = MODE.DEFAULT)
{
Sound sound = AudioUtils.CreateSound(filePath);
if (bus.getChannelGroup(out _) != RESULT.OK)
{
bus.lockChannelGroup().CheckResult();
}
Sound sound = AudioUtils.CreateSound(filePath, mode);
CustomSoundPatcher.CustomSounds[id] = sound;
CustomSoundPatcher.CustomSoundBuses[id] = bus;
return sound;
Expand All @@ -47,11 +55,13 @@ public static Sound RegisterCustomSound(string id, string filePath, Bus bus)
/// <param name="id">The Id of your custom sound which is used when checking which sounds to play.</param>
/// <param name="audio">The AudioClip to register.</param>
/// <param name="busPath">The bus path to play the sound on.</param>
/// <param name="mode">The audio MODE of the sound.
/// Standard values of this property can be found in the <see cref="AudioUtils"/> class (i.e. <see cref="AudioUtils.StandardSoundModes_3D"/>).</param>
/// <returns>the <see cref="Sound"/> loaded</returns>
public static Sound RegisterCustomSound(string id, AudioClip audio, string busPath)
public static Sound RegisterCustomSound(string id, AudioClip audio, string busPath, MODE mode = MODE.DEFAULT)
{
Bus bus = RuntimeManager.GetBus(busPath);
return RegisterCustomSound(id, audio, bus);
return RegisterCustomSound(id, audio, bus, mode);
}

/// <summary>
Expand All @@ -60,10 +70,16 @@ public static Sound RegisterCustomSound(string id, AudioClip audio, string busPa
/// <param name="id">The Id of your custom sound which is used when checking which sounds to play.</param>
/// <param name="audio">The AudioClip to register.</param>
/// <param name="bus">The bus to play the sound on.</param>
/// <param name="mode">The audio MODE of the sound.
/// Standard values of this property can be found in the <see cref="AudioUtils"/> class (i.e. <see cref="AudioUtils.StandardSoundModes_3D"/>).</param>
/// <returns>the <see cref="Sound"/> loaded</returns>
public static Sound RegisterCustomSound(string id, AudioClip audio, Bus bus)
public static Sound RegisterCustomSound(string id, AudioClip audio, Bus bus, MODE mode = MODE.DEFAULT)
{
Sound sound = AudioUtils.CreateSound(audio);
if (bus.getChannelGroup(out _) != RESULT.OK)
{
bus.lockChannelGroup().CheckResult();
}
Sound sound = AudioUtils.CreateSound(audio, mode);
CustomSoundPatcher.CustomSounds[id] = sound;
CustomSoundPatcher.CustomSoundBuses[id] = bus;
return sound;
Expand Down Expand Up @@ -99,6 +115,10 @@ public static void RegisterCustomSound(string id, Sound sound, string busPath)
/// <param name="bus">The bus to play the sound on.</param>
public static void RegisterCustomSound(string id, Sound sound, Bus bus)
{
if (bus.getChannelGroup(out _) != RESULT.OK)
{
bus.lockChannelGroup().CheckResult();
}
CustomSoundPatcher.CustomSounds[id] = sound;
CustomSoundPatcher.CustomSoundBuses[id] = bus;
}
Expand All @@ -107,7 +127,7 @@ public static void RegisterCustomSound(string id, Sound sound, Bus bus)
/// Try to find and play a custom <see cref="Sound"/> that has been registered.
/// </summary>
/// <param name="id">The Id of the custom sound</param>
/// <param name="channel">the <see cref="Channel"/>the sound is playing on.</param>
/// <param name="channel">the <see cref="Channel"/> the sound is playing on.</param>
public static bool TryPlayCustomSound(string id, out Channel channel)
{
channel = default;
Expand Down
4 changes: 2 additions & 2 deletions Nautilus/Handlers/PDAHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ public static void AddLogEntry(string key, string languageKey, Sound sound, Spri
/// <param name="icon">The icon that will be used in the Log tab for this entry. if unassigned, it will use the default log entry icon.</param>
public static void AddLogEntry(string key, string languageKey, AudioClip audioClip, Sprite icon = null)
{
AddLogEntry(key, languageKey, CustomSoundHandler.RegisterCustomSound(key, audioClip, AudioUtils.BusPaths.PDAVoice), icon);
AddLogEntry(key, languageKey, CustomSoundHandler.RegisterCustomSound(key, audioClip, AudioUtils.BusPaths.PDAVoice, AudioUtils.StandardSoundModes_Stream), icon);
}

/// <summary>
Expand All @@ -192,7 +192,7 @@ public static void AddLogEntry(string key, string languageKey, AudioClip audioCl
/// <param name="icon">The icon that will be used in the Log tab for this entry. if unassigned, it will use the default log entry icon.</param>
public static void AddLogEntry(string key, string languageKey, string soundFilePath, Sprite icon = null)
{
AddLogEntry(key, languageKey, CustomSoundHandler.RegisterCustomSound(key, soundFilePath, AudioUtils.BusPaths.PDAVoice), icon);
AddLogEntry(key, languageKey, CustomSoundHandler.RegisterCustomSound(key, soundFilePath, AudioUtils.BusPaths.PDAVoice, AudioUtils.StandardSoundModes_Stream), icon);
}

/// <summary>
Expand Down
43 changes: 40 additions & 3 deletions Nautilus/Patchers/CustomSoundPatcher.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Collections.Generic;
using System.Collections.Generic;
using FMOD;
using FMOD.Studio;
using FMODUnity;
Expand Down Expand Up @@ -32,6 +32,43 @@ public static void PDASounds_Deinitialize_Postfix()
PlayedChannels.Clear();
}

[HarmonyPrefix]
[HarmonyPatch(typeof(FMODExtensions), nameof(FMODExtensions.GetLength))]
public static bool FMODExtension_GetLength_Prefix(string path, ref int __result)
{
if(string.IsNullOrEmpty(path))
{
__result = 0;
return false;
}

InternalLogger.Debug($"FMODExtensions.GetLength(\"{path}\") executed. Checking if it's a custom sound...");

if (!CustomSounds.ContainsKey(path))
return true;

InternalLogger.Debug($"FMODExtensions.GetLength(\"{path}\") executed. It was a custom sound.");

if(CustomSounds.TryGetValue(path, out Sound sound))
{
RESULT res = sound.getLength(out uint length, TIMEUNIT.MS);
if(res == RESULT.OK)
{
__result = (int)length;
return false;
}
else
{
InternalLogger.Log($"An error occured while trying to get length of a sound.\n{res}");
}
res.CheckResult();
}

InternalLogger.Debug($"FMODExtensions.GetLength(\"{path}\") executed. It was maybe not a CustomSounds but a CustomFModSounds ?");
__result = 0;
return false;
}

#if SUBNAUTICA

[HarmonyPatch(typeof(FMODUWE), nameof(FMODUWE.PlayOneShotImpl))]
Expand Down Expand Up @@ -409,15 +446,15 @@ public static bool SoundQueue_Update_Prefix(SoundQueue __instance)
return true;
}
#if BELOWZERO
if (SoundQueue.GetPlaybackState(__instance.eventInstance) is not PLAYBACK_STATE.STARTING or PLAYBACK_STATE.PLAYING)
if (SoundQueue.GetPlaybackState(__instance.eventInstance) is not (PLAYBACK_STATE.STARTING or PLAYBACK_STATE.PLAYING))
{
return true;
}
#else
if (!SoundQueue.GetIsStartingOrPlaying(__instance.eventInstance)) return true;
#endif

ATTRIBUTES_3D attributes = Player.main.transform.To3DAttributes();
ATTRIBUTES_3D attributes = Player.main.transform.To3DAttributes();
channel.set3DAttributes(ref attributes.position, ref attributes.velocity);
channel.getPosition(out uint position, TIMEUNIT.MS);
instanceCurrent.position = (int)position;
Expand Down
21 changes: 21 additions & 0 deletions Nautilus/Utility/AudioUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,19 @@ namespace Nautilus.Utility;
/// </summary>
public static partial class AudioUtils
{
/// <summary>
/// 3D sounds
/// </summary>
public const MODE StandardSoundModes_3D = MODE.DEFAULT | MODE._3D | MODE.ACCURATETIME | MODE._3D_LINEARSQUAREROLLOFF;
/// <summary>
/// 2D sounds
/// </summary>
public const MODE StandardSoundModes_2D = MODE.DEFAULT | MODE._2D | MODE.ACCURATETIME;
/// <summary>
/// For music, PDA voices and any 2D sounds that can have more than one instance at a time.
/// </summary>
public const MODE StandardSoundModes_Stream = StandardSoundModes_2D | MODE.CREATESTREAM;

private static FMOD.System FMOD_System => RuntimeManager.CoreSystem;

/// <summary>
Expand Down Expand Up @@ -72,6 +85,10 @@ public static bool TryPlaySound(Sound sound, string busPath, out Channel channel
{
channel = default;
Bus bus = RuntimeManager.GetBus(busPath);
if (bus.getChannelGroup(out _) != RESULT.OK)
{
bus.lockChannelGroup().CheckResult();
}
return bus.getChannelGroup(out ChannelGroup channelGroup) == RESULT.OK &&
channelGroup.getPaused(out bool paused) == RESULT.OK &&
FMOD_System.playSound(sound, channelGroup, paused, out channel) == RESULT.OK;
Expand All @@ -87,6 +104,10 @@ public static bool TryPlaySound(Sound sound, string busPath, out Channel channel
public static bool TryPlaySound(Sound sound, Bus bus, out Channel channel)
{
channel = default;
if (bus.getChannelGroup(out _) != RESULT.OK)
{
bus.lockChannelGroup().CheckResult();
}
return bus.getChannelGroup(out ChannelGroup channelGroup) == RESULT.OK &&
channelGroup.getPaused(out bool paused) == RESULT.OK &&
FMOD_System.playSound(sound, channelGroup, paused, out channel) == RESULT.OK;
Expand Down

0 comments on commit 356b4d7

Please sign in to comment.