Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UnityEngine.AudioClip support #238

Merged
merged 6 commits into from
Aug 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
49 changes: 38 additions & 11 deletions SMLHelper/Handlers/CustomSoundHandler.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
using System;
using FMOD;
using SMLHelper.V2.Interfaces;
using SMLHelper.V2.Patchers;
using SMLHelper.V2.Utility;

namespace SMLHelper.V2.Handlers
namespace SMLHelper.V2.Handlers
{
using FMOD;
using Interfaces;
using Patchers;
using UnityEngine;
using Utility;

/// <summary>
/// A handler class for adding and overriding Sounds.
/// </summary>
Expand All @@ -30,7 +30,7 @@ private 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="soundChannel">The sound channel to get the volume to play the sound at. defaults to <see cref="SoundChannel.Master"/></param>
/// <returns>Returns the <see cref="Sound"/> loaded</returns>
/// <returns>the <see cref="Sound"/> loaded</returns>

Sound ICustomSoundHandler.RegisterCustomSound(string id, string filePath, SoundChannel soundChannel)
{
Expand All @@ -40,6 +40,21 @@ Sound ICustomSoundHandler.RegisterCustomSound(string id, string filePath, SoundC
return sound;
}

/// <summary>
/// Register a custom sound by an <see cref="AudioClip"/> instance. Some vanilla game sounds can be overridden by matching the id to the <see cref="FMODAsset.path"/>.
/// </summary>
/// <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="soundChannel">The sound channel to get the volume to play the sound at. defaults to <see cref="SoundChannel.Master"/></param>
/// <returns>the <see cref="Sound"/> registered.</returns>
Sound ICustomSoundHandler.RegisterCustomSound(string id, AudioClip audio, SoundChannel soundChannel)
{
var sound = AudioUtils.CreateSound(audio);
CustomSoundPatcher.CustomSounds[id] = sound;
CustomSoundPatcher.CustomSoundChannels[id] = soundChannel;
return sound;
}

/// <summary>
/// Register a Custom sound that has been loaded using AudioUtils. Some vanilla game sounds can be overridden by matching the id to the <see cref="FMODAsset.path"/>.
/// </summary>
Expand Down Expand Up @@ -70,7 +85,7 @@ void ICustomSoundHandler.TryPlayCustomSound(string id)
/// </summary>
/// <param name="id">The Id of the custom sound</param>
/// <param name="sound">Outputs the <see cref="Sound"/> if found and null if not found.</param>
/// <returns>Returns true or false depending on if the id was found</returns>
/// <returns>true or false depending on if the id was found</returns>
bool ICustomSoundHandler.TryGetCustomSound(string id, out Sound sound)
{
return CustomSoundPatcher.CustomSounds.TryGetValue(id, out sound);
Expand All @@ -86,13 +101,25 @@ bool ICustomSoundHandler.TryGetCustomSound(string id, out Sound sound)
/// <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="soundChannel">The sound channel to get the volume to play the sound at. defaults to <see cref="SoundChannel.Master"/></param>
/// <returns>Returns the <see cref="Sound"/> loaded</returns>
/// <returns>the <see cref="Sound"/> loaded</returns>

public static Sound RegisterCustomSound(string id, string filePath, SoundChannel soundChannel = SoundChannel.Master)
{
return Main.RegisterCustomSound(id, filePath, soundChannel);
}

/// <summary>
/// Register a custom sound by an <see cref="AudioClip"/> instance. Some vanilla game sounds can be overridden by matching the id to the <see cref="FMODAsset.path"/>.
/// </summary>
/// <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="soundChannel">The sound channel to get the volume to play the sound at. defaults to <see cref="SoundChannel.Master"/></param>
/// <returns>the <see cref="Sound"/> registered.</returns>
public static Sound RegisterCustomSound(string id, AudioClip audio, SoundChannel soundChannel = SoundChannel.Master)
{
return Main.RegisterCustomSound(id, audio, soundChannel);
}

/// <summary>
/// Register a Custom sound that has been loaded using AudioUtils. Some vanilla game sounds can be overridden by matching the id to the <see cref="FMODAsset.path"/>.
/// </summary>
Expand All @@ -119,7 +146,7 @@ public static void TryPlayCustomSound(string id)
/// </summary>
/// <param name="id">The Id of the custom sound</param>
/// <param name="sound">Outputs the <see cref="Sound"/> if found and null if not found.</param>
/// <returns>Returns true or false depending on if the id was found</returns>
/// <returns>true or false depending on if the id was found</returns>
public static bool TryGetCustomSound(string id, out Sound sound)
{
return Main.TryGetCustomSound(id, out sound);
Expand Down
22 changes: 16 additions & 6 deletions SMLHelper/Interfaces/ICustomSoundHandler.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
using FMOD;
using SMLHelper.V2.Utility;

namespace SMLHelper.V2.Interfaces
namespace SMLHelper.V2.Interfaces
{
using FMOD;
using UnityEngine;
using Utility;

/// <summary>
/// A handler class for adding and overriding Sounds.
/// </summary>
Expand All @@ -14,9 +15,18 @@ public interface ICustomSoundHandler
/// <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="soundChannel">The sound channel to get the volume to play the sound at. defaults to <see cref="SoundChannel.Master"/></param>
/// <returns>Returns the <see cref="Sound"/> loaded</returns>
/// <returns>the <see cref="Sound"/> loaded</returns>
Sound RegisterCustomSound(string id, string filePath, SoundChannel soundChannel = SoundChannel.Master);

/// <summary>
/// Register a custom sound by an <see cref="AudioClip"/> instance. Some vanilla game sounds can be overridden by matching the id to the <see cref="FMODAsset.path"/>.
/// </summary>
/// <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="soundChannel">The sound channel to get the volume to play the sound at. defaults to <see cref="SoundChannel.Master"/></param>
/// <returns>the <see cref="Sound"/> registered.</returns>
Sound RegisterCustomSound(string id, AudioClip audio, SoundChannel soundChannel = SoundChannel.Master);

/// <summary>
/// Register a Custom sound that has been loaded using AudioUtils. Some vanilla game sounds can be overridden by matching the id to the <see cref="FMODAsset.path"/>.
/// </summary>
Expand All @@ -36,7 +46,7 @@ public interface ICustomSoundHandler
/// </summary>
/// <param name="id">The Id of the custom sound</param>
/// <param name="sound">Outputs the <see cref="Sound"/> if found and null if not found.</param>
/// <returns>Returns true or false depending on if the id was found</returns>
/// <returns>true or false depending on if the id was found</returns>
bool TryGetCustomSound(string id, out Sound sound);
}
}
4 changes: 4 additions & 0 deletions SMLHelper/SMLHelper.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@
<HintPath>$(Dependencies)\UnityEngine.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.AudioModule">
<HintPath>$(Dependencies)\UnityEngine.AudioModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="UnityEngine.CoreModule">
<HintPath>$(Dependencies)\UnityEngine.CoreModule.dll</HintPath>
<Private>False</Private>
Expand Down
70 changes: 70 additions & 0 deletions SMLHelper/Utility/AudioUtils.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
namespace SMLHelper.V2.Utility
{
using System.Runtime.InteropServices;
using FMOD;
using FMODUnity;
using UnityEngine;

/// <summary>
/// Utilities for audio and sound
Expand All @@ -25,6 +27,40 @@ public static Sound CreateSound(string path, MODE mode = MODE.DEFAULT)
return sound;
}

/// <summary>
/// Creates a <see cref="Sound"/> instance from an <see cref="AudioClip"/>. Can be stored and later used with <see cref="PlaySound(Sound)"/>
/// </summary>
/// <param name="audio">the AudioClip to make a Sound instance of.</param>
/// <param name="mode"></param>
/// <returns>The <see cref="Sound"/> instance.</returns>
public static Sound CreateSound(AudioClip audio, MODE mode = MODE.DEFAULT)
{
return CreateSoundFromAudioClip(audio, mode);
}

/// <summary>
/// Plays a <see cref="Sound"/> from an <see cref="AudioClip"/>.
/// </summary>
/// <param name="audio">The AudioClip of the sound.</param>
/// <param name="mode"></param>
/// <returns>The channel on which the sound was created.</returns>
public static Channel PlaySound(AudioClip audio, MODE mode = MODE.DEFAULT)
{
return PlaySound(CreateSound(audio, mode));
}

/// <summary>
/// Plays a <see cref="Sound"/> from an <see cref="AudioClip"/>. Has overload for controlling volume.
/// </summary>
/// <param name="audio">The AudioClip of the sound.</param>
/// <param name="mode"></param>
/// <param name="volumeControl">Which volume control to adjust sound levels by. How loud sound is.</param>
/// <returns>The channel on which the sound was created</returns>
public static Channel PlaySound(AudioClip audio, SoundChannel volumeControl, MODE mode = MODE.DEFAULT)
{
return PlaySound(CreateSound(audio, mode), volumeControl);
}

/// <summary>
/// Plays a <see cref="Sound"/> globally from a path. Must be a .wav file
/// </summary>
Expand Down Expand Up @@ -85,5 +121,39 @@ public static Channel PlaySound(Sound sound, SoundChannel volumeControl)

return channel;
}

private static Sound CreateSoundFromAudioClip(AudioClip audioClip, MODE mode)
{
var samplesSize = audioClip.samples * audioClip.channels;
var samples = new float[samplesSize];
audioClip.GetData(samples, 0);

var bytesLength = (uint) (samplesSize * sizeof(float));

var soundInfo = new CREATESOUNDEXINFO
{
cbsize = Marshal.SizeOf(typeof(CREATESOUNDEXINFO)),
length = bytesLength,
format = SOUND_FORMAT.PCMFLOAT,
defaultfrequency = audioClip.frequency,
numchannels = audioClip.channels
};

FMOD_System.createSound("", MODE.OPENUSER, ref soundInfo, out var sound);

sound.@lock(0, bytesLength, out var ptr1, out var ptr2, out var len1, out var len2);

var samplesLength = (int) (len1 / sizeof(float));
Marshal.Copy(samples, 0, ptr1, samplesLength);
if (len2 > 0)
{
Marshal.Copy(samples, samplesLength, ptr2, (int) (len2 / sizeof(float)));
}

sound.unlock(ptr1, ptr2, len1, len2);
sound.setMode(mode);

return sound;
}
}
}