Skip to content
This repository has been archived by the owner on Jan 19, 2025. It is now read-only.

Commit

Permalink
GameEntity & Update Coroutine
Browse files Browse the repository at this point in the history
  • Loading branch information
xNexusACS committed Jul 24, 2024
1 parent e8294de commit 7999fd8
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 31 deletions.
80 changes: 49 additions & 31 deletions Exiled.API/Features/Audio/AudioPlayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ namespace Exiled.API.Features.Audio

using Exiled.API.Features.Attributes;
using Exiled.API.Features.Audio.EventArgs;
using Exiled.API.Features.Core;
using Exiled.API.Features.DynamicEvents;
using MEC;
using Mirror;
Expand All @@ -26,12 +27,14 @@ namespace Exiled.API.Features.Audio
/// <summary>
/// Represents a NPC that can play audios.
/// </summary>
public class AudioPlayer : MonoBehaviour
public class AudioPlayer : GameEntity
{
private readonly Queue<float> streamBuffer = new();

private CoroutineHandle playbackHandler;

private CoroutineHandle playbackUpdater;

private MemoryStream memoryStream;

private VorbisReader vorbisReader;

Check failure on line 40 in Exiled.API/Features/Audio/AudioPlayer.cs

View workflow job for this annotation

GitHub Actions / build

The type or namespace name 'VorbisReader' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 40 in Exiled.API/Features/Audio/AudioPlayer.cs

View workflow job for this annotation

GitHub Actions / build

The type or namespace name 'VorbisReader' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 40 in Exiled.API/Features/Audio/AudioPlayer.cs

View workflow job for this annotation

GitHub Actions / build

The type or namespace name 'VorbisReader' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 40 in Exiled.API/Features/Audio/AudioPlayer.cs

View workflow job for this annotation

GitHub Actions / build

The type or namespace name 'VorbisReader' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 40 in Exiled.API/Features/Audio/AudioPlayer.cs

View workflow job for this annotation

GitHub Actions / build

The type or namespace name 'VorbisReader' could not be found (are you missing a using directive or an assembly reference?)
Expand All @@ -44,6 +47,17 @@ public class AudioPlayer : MonoBehaviour

private float[] readBuffer;

/// <summary>
/// Initializes a new instance of the <see cref="AudioPlayer"/> class.
/// </summary>
/// <param name="npc">The npc that will be allowed to play audios from files..</param>
internal AudioPlayer(Npc npc)
: base(npc.GameObject)
{
Owner = npc;
Dictionary.Add(npc, this);
}

/// <summary>
/// Gets all the audio players present in the server in the form of dictionary.
/// </summary>
Expand All @@ -52,7 +66,7 @@ public class AudioPlayer : MonoBehaviour
/// <summary>
/// Gets all the audio players present in the server in the form of list.
/// </summary>
public static IEnumerable<AudioPlayer> List => Dictionary.Values.ToList();
public static new IEnumerable<AudioPlayer> List => Dictionary.Values.ToList();

/// <summary>
/// Gets or sets the <see cref="TDynamicEventDispatcher{T}"/> which handles all delegates to be fired before selecting an audio file.
Expand Down Expand Up @@ -122,15 +136,7 @@ public class AudioPlayer : MonoBehaviour
/// <returns>The Audio Player instance of the npc.</returns>
public static AudioPlayer GetOrCreate(Npc npc)
{
if (Dictionary.TryGetValue(npc, out AudioPlayer player))
return player;

player = npc.GameObject.AddComponent<AudioPlayer>();
player.Owner = npc;

Dictionary.Add(npc, player);

return player;
return Dictionary.TryGetValue(npc, out AudioPlayer audioPlayer) ? audioPlayer : new AudioPlayer(npc);
}

/// <summary>
Expand Down Expand Up @@ -307,6 +313,8 @@ private IEnumerator<float> AudioPlayback(AudioFile audioFile)
yield break;
}

playbackUpdater = Timing.RunCoroutine(UpdatePlayback());

Log.Debug($"Playing {audioFile.FilePath}");

samplesPerSecond = VoiceChatSettings.SampleRate * VoiceChatSettings.Channels;
Expand Down Expand Up @@ -353,40 +361,50 @@ private IEnumerator<float> AudioPlayback(AudioFile audioFile)
CurrentAudio = null;
PlayerType = AudioPlayerType.None;

Timing.KillCoroutines(playbackUpdater);

if (DestroyWhenFinishing)
Destroy();
}

private void Update()
private IEnumerator<float> UpdatePlayback()
{
if (Owner is null || streamBuffer.Count is 0 || !ShouldPlay)
return;

allowedSamples += Time.deltaTime * samplesPerSecond;
int samplesToCopy = Mathf.Min(Mathf.FloorToInt(allowedSamples), streamBuffer.Count);

if (samplesToCopy > 0)
while (true)
{
for (int i = 0; i < samplesToCopy; i++)
if (Owner is null || streamBuffer.Count == 0 || !ShouldPlay)
{
PlaybackBuffer.Write(streamBuffer.Dequeue() * (CurrentAudio.Volume / 100f));
yield return Timing.WaitForOneFrame;
continue;
}
}

allowedSamples -= samplesToCopy;
allowedSamples += Time.deltaTime * samplesPerSecond;
int samplesToCopy = Mathf.Min(Mathf.FloorToInt(allowedSamples), streamBuffer.Count);

while (PlaybackBuffer.Length >= 480)
{
PlaybackBuffer.ReadTo(sendBuffer, 480L, 0L);
int encodedData = Encoder.Encode(sendBuffer, EncodedBytes, 480);
if (samplesToCopy > 0)
{
for (int i = 0; i < samplesToCopy; i++)
{
PlaybackBuffer.Write(streamBuffer.Dequeue() * (CurrentAudio.Volume / 100f));
}
}

allowedSamples -= samplesToCopy;

foreach (Player player in Player.List)
while (PlaybackBuffer.Length >= 480)
{
if (player.Connection is null || !player.IsVerified)
continue;
PlaybackBuffer.ReadTo(sendBuffer, 480L, 0L);
int encodedData = Encoder.Encode(sendBuffer, EncodedBytes, 480);

player.Connection.Send(new VoiceMessage(Owner.ReferenceHub, CurrentAudio.Channel, EncodedBytes, encodedData, false));
foreach (Player player in Player.List)
{
if (player.Connection is null || !player.IsVerified)
continue;

player.Connection.Send(new VoiceMessage(Owner.ReferenceHub, CurrentAudio.Channel, EncodedBytes, encodedData, false));
}
}

yield return Timing.WaitForOneFrame;
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions Exiled.API/Features/Audio/AudioStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,13 @@ namespace Exiled.API.Features.Audio
/// </summary>
public class AudioStream : AudioPlayer
{
/// <summary>
/// Initializes a new instance of the <see cref="AudioStream"/> class.
/// </summary>
/// <param name="npc">The npc that will be allowed to play audios from urls.</param>
internal AudioStream(Npc npc)
: base(npc)
{
}
}
}

0 comments on commit 7999fd8

Please sign in to comment.