|
|
@@ -10,6 +10,8 @@ namespace Ryujinx.Audio.OpenAL
|
|
|
{
|
|
|
private const int MaxTracks = 256;
|
|
|
|
|
|
+ private const int MaxReleased = 32;
|
|
|
+
|
|
|
private AudioContext Context;
|
|
|
|
|
|
private class Track : IDisposable
|
|
|
@@ -26,6 +28,8 @@ namespace Ryujinx.Audio.OpenAL
|
|
|
|
|
|
private Queue<long> QueuedTagsQueue;
|
|
|
|
|
|
+ private Queue<long> ReleasedTagsQueue;
|
|
|
+
|
|
|
private bool Disposed;
|
|
|
|
|
|
public Track(int SampleRate, ALFormat Format)
|
|
|
@@ -40,38 +44,36 @@ namespace Ryujinx.Audio.OpenAL
|
|
|
Buffers = new ConcurrentDictionary<long, int>();
|
|
|
|
|
|
QueuedTagsQueue = new Queue<long>();
|
|
|
+
|
|
|
+ ReleasedTagsQueue = new Queue<long>();
|
|
|
}
|
|
|
|
|
|
- public int GetBufferId(long Tag)
|
|
|
+ public bool ContainsBuffer(long Tag)
|
|
|
{
|
|
|
- if (Disposed)
|
|
|
- {
|
|
|
- throw new ObjectDisposedException(nameof(Track));
|
|
|
- }
|
|
|
-
|
|
|
- int Id = AL.GenBuffer();
|
|
|
+ SyncQueuedTags();
|
|
|
|
|
|
- Buffers.AddOrUpdate(Tag, Id, (Key, OldId) =>
|
|
|
+ foreach (long QueuedTag in QueuedTagsQueue)
|
|
|
{
|
|
|
- AL.DeleteBuffer(OldId);
|
|
|
-
|
|
|
- return Id;
|
|
|
- });
|
|
|
-
|
|
|
- QueuedTagsQueue.Enqueue(Tag);
|
|
|
+ if (QueuedTag == Tag)
|
|
|
+ {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- return Id;
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
- public long[] GetReleasedBuffers()
|
|
|
+ public long[] GetReleasedBuffers(int MaxCount)
|
|
|
{
|
|
|
ClearReleased();
|
|
|
|
|
|
List<long> Tags = new List<long>();
|
|
|
|
|
|
- foreach (long Tag in Buffers.Keys)
|
|
|
+ HashSet<long> Unique = new HashSet<long>();
|
|
|
+
|
|
|
+ while (MaxCount-- > 0 && ReleasedTagsQueue.TryDequeue(out long Tag))
|
|
|
{
|
|
|
- if (!ContainsBuffer(Tag))
|
|
|
+ if (Unique.Add(Tag))
|
|
|
{
|
|
|
Tags.Add(Tag);
|
|
|
}
|
|
|
@@ -80,31 +82,37 @@ namespace Ryujinx.Audio.OpenAL
|
|
|
return Tags.ToArray();
|
|
|
}
|
|
|
|
|
|
- public void ClearReleased()
|
|
|
+ public int AppendBuffer(long Tag)
|
|
|
{
|
|
|
- SyncQueuedTags();
|
|
|
+ if (Disposed)
|
|
|
+ {
|
|
|
+ throw new ObjectDisposedException(nameof(Track));
|
|
|
+ }
|
|
|
|
|
|
- AL.GetSource(SourceId, ALGetSourcei.BuffersProcessed, out int ReleasedCount);
|
|
|
+ int Id = AL.GenBuffer();
|
|
|
|
|
|
- if (ReleasedCount > 0)
|
|
|
+ Buffers.AddOrUpdate(Tag, Id, (Key, OldId) =>
|
|
|
{
|
|
|
- AL.SourceUnqueueBuffers(SourceId, ReleasedCount);
|
|
|
- }
|
|
|
+ AL.DeleteBuffer(OldId);
|
|
|
+
|
|
|
+ return Id;
|
|
|
+ });
|
|
|
+
|
|
|
+ QueuedTagsQueue.Enqueue(Tag);
|
|
|
+
|
|
|
+ return Id;
|
|
|
}
|
|
|
|
|
|
- public bool ContainsBuffer(long Tag)
|
|
|
+ public void ClearReleased()
|
|
|
{
|
|
|
SyncQueuedTags();
|
|
|
|
|
|
- foreach (long QueuedTag in QueuedTagsQueue)
|
|
|
+ AL.GetSource(SourceId, ALGetSourcei.BuffersProcessed, out int ReleasedCount);
|
|
|
+
|
|
|
+ if (ReleasedCount > 0)
|
|
|
{
|
|
|
- if (QueuedTag == Tag)
|
|
|
- {
|
|
|
- return true;
|
|
|
- }
|
|
|
+ AL.SourceUnqueueBuffers(SourceId, ReleasedCount);
|
|
|
}
|
|
|
-
|
|
|
- return false;
|
|
|
}
|
|
|
|
|
|
private void SyncQueuedTags()
|
|
|
@@ -116,7 +124,12 @@ namespace Ryujinx.Audio.OpenAL
|
|
|
|
|
|
while (QueuedTagsQueue.Count > QueuedCount)
|
|
|
{
|
|
|
- QueuedTagsQueue.Dequeue();
|
|
|
+ ReleasedTagsQueue.Enqueue(QueuedTagsQueue.Dequeue());
|
|
|
+ }
|
|
|
+
|
|
|
+ while (ReleasedTagsQueue.Count > MaxReleased)
|
|
|
+ {
|
|
|
+ ReleasedTagsQueue.Dequeue();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -202,38 +215,38 @@ namespace Ryujinx.Audio.OpenAL
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public void AppendBuffer(int Track, long Tag, byte[] Buffer)
|
|
|
+ public bool ContainsBuffer(int Track, long Tag)
|
|
|
{
|
|
|
if (Tracks.TryGetValue(Track, out Track Td))
|
|
|
{
|
|
|
- int BufferId = Td.GetBufferId(Tag);
|
|
|
-
|
|
|
- AL.BufferData(BufferId, Td.Format, Buffer, Buffer.Length, Td.SampleRate);
|
|
|
-
|
|
|
- AL.SourceQueueBuffer(Td.SourceId, BufferId);
|
|
|
-
|
|
|
- StartPlaybackIfNeeded(Td);
|
|
|
+ return Td.ContainsBuffer(Tag);
|
|
|
}
|
|
|
+
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
- public bool ContainsBuffer(int Track, long Tag)
|
|
|
+ public long[] GetReleasedBuffers(int Track, int MaxCount)
|
|
|
{
|
|
|
if (Tracks.TryGetValue(Track, out Track Td))
|
|
|
{
|
|
|
- return Td.ContainsBuffer(Tag);
|
|
|
+ return Td.GetReleasedBuffers(MaxCount);
|
|
|
}
|
|
|
|
|
|
- return false;
|
|
|
+ return null;
|
|
|
}
|
|
|
|
|
|
- public long[] GetReleasedBuffers(int Track)
|
|
|
+ public void AppendBuffer(int Track, long Tag, byte[] Buffer)
|
|
|
{
|
|
|
if (Tracks.TryGetValue(Track, out Track Td))
|
|
|
{
|
|
|
- return Td.GetReleasedBuffers();
|
|
|
+ int BufferId = Td.AppendBuffer(Tag);
|
|
|
+
|
|
|
+ AL.BufferData(BufferId, Td.Format, Buffer, Buffer.Length, Td.SampleRate);
|
|
|
+
|
|
|
+ AL.SourceQueueBuffer(Td.SourceId, BufferId);
|
|
|
+
|
|
|
+ StartPlaybackIfNeeded(Td);
|
|
|
}
|
|
|
-
|
|
|
- return null;
|
|
|
}
|
|
|
|
|
|
public void Start(int Track)
|