mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-11 09:48:26 -04:00
Killed history
This commit is contained in:
142
src/ayu/Ayu.Discord.Voice/PoopyBufferImmortalized.cs
Normal file
142
src/ayu/Ayu.Discord.Voice/PoopyBufferImmortalized.cs
Normal file
@@ -0,0 +1,142 @@
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
#nullable enable
|
||||
namespace Ayu.Discord.Voice
|
||||
{
|
||||
public sealed class PoopyBufferImmortalized : ISongBuffer
|
||||
{
|
||||
private readonly int _frameSize;
|
||||
private readonly byte[] _buffer;
|
||||
private readonly byte[] _outputArray;
|
||||
private CancellationToken _cancellationToken;
|
||||
private bool _isStopped;
|
||||
|
||||
public int ReadPosition { get; private set; }
|
||||
public int WritePosition { get; private set; }
|
||||
|
||||
public int ContentLength => WritePosition >= ReadPosition
|
||||
? WritePosition - ReadPosition
|
||||
: (_buffer.Length - ReadPosition) + WritePosition;
|
||||
|
||||
public int FreeSpace => _buffer.Length - ContentLength;
|
||||
|
||||
public bool Stopped => _cancellationToken.IsCancellationRequested || _isStopped;
|
||||
|
||||
public PoopyBufferImmortalized(int frameSize)
|
||||
{
|
||||
_frameSize = frameSize;
|
||||
_buffer = ArrayPool<byte>.Shared.Rent(1_000_000);
|
||||
_outputArray = new byte[frameSize];
|
||||
|
||||
ReadPosition = 0;
|
||||
WritePosition = 0;
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
_isStopped = true;
|
||||
}
|
||||
|
||||
// this method needs a rewrite
|
||||
public Task<bool> BufferAsync(ITrackDataSource source, CancellationToken cancellationToken)
|
||||
{
|
||||
_cancellationToken = cancellationToken;
|
||||
var bufferingCompleted = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var output = ArrayPool<byte>.Shared.Rent(38400);
|
||||
try
|
||||
{
|
||||
int read;
|
||||
while (!Stopped && (read = source.Read(output)) > 0)
|
||||
{
|
||||
while (!Stopped && FreeSpace <= read)
|
||||
{
|
||||
bufferingCompleted.TrySetResult(true);
|
||||
await Task.Delay(100, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (Stopped)
|
||||
break;
|
||||
|
||||
Write(output, read);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(output);
|
||||
bufferingCompleted.TrySetResult(true);
|
||||
}
|
||||
}, cancellationToken);
|
||||
|
||||
return bufferingCompleted.Task;
|
||||
}
|
||||
|
||||
private void Write(byte[] input, int writeCount)
|
||||
{
|
||||
if (WritePosition + writeCount < _buffer.Length)
|
||||
{
|
||||
Buffer.BlockCopy(input, 0, _buffer, WritePosition, writeCount);
|
||||
WritePosition += writeCount;
|
||||
return;
|
||||
}
|
||||
|
||||
var wroteNormally = _buffer.Length - WritePosition;
|
||||
Buffer.BlockCopy(input, 0, _buffer, WritePosition, wroteNormally);
|
||||
var wroteFromStart = writeCount - wroteNormally;
|
||||
Buffer.BlockCopy(input, wroteNormally, _buffer, 0, wroteFromStart);
|
||||
WritePosition = wroteFromStart;
|
||||
}
|
||||
|
||||
public Span<byte> Read(int count, out int length)
|
||||
{
|
||||
var toRead = Math.Min(ContentLength, count);
|
||||
var wp = WritePosition;
|
||||
|
||||
if (ContentLength == 0)
|
||||
{
|
||||
length = 0;
|
||||
return Span<byte>.Empty;
|
||||
}
|
||||
|
||||
if (wp > ReadPosition || ReadPosition + toRead <= _buffer.Length)
|
||||
{
|
||||
// thsi can be achieved without copying if
|
||||
// writer never writes until the end,
|
||||
// but leaves a single chunk free
|
||||
Span<byte> toReturn = _outputArray;
|
||||
((Span<byte>) _buffer).Slice(ReadPosition, toRead).CopyTo(toReturn);
|
||||
ReadPosition += toRead;
|
||||
length = toRead;
|
||||
return toReturn;
|
||||
}
|
||||
else
|
||||
{
|
||||
Span<byte> toReturn = _outputArray;
|
||||
var toEnd = _buffer.Length - ReadPosition;
|
||||
var bufferSpan = (Span<byte>) _buffer;
|
||||
|
||||
bufferSpan.Slice(ReadPosition, toEnd).CopyTo(toReturn);
|
||||
var fromStart = toRead - toEnd;
|
||||
bufferSpan.Slice(0, fromStart).CopyTo(toReturn.Slice(toEnd));
|
||||
ReadPosition = fromStart;
|
||||
length = toEnd + fromStart;
|
||||
return toReturn;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(_buffer);
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
ReadPosition = 0;
|
||||
WritePosition = 0;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user