| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- using Ryujinx.Common;
- using System;
- namespace Ryujinx.Audio.Backends.Common
- {
- /// <summary>
- /// A ring buffer that grow if data written to it is too big to fit.
- /// </summary>
- public class DynamicRingBuffer
- {
- private const int RingBufferAlignment = 2048;
- private object _lock = new object();
- private byte[] _buffer;
- private int _size;
- private int _headOffset;
- private int _tailOffset;
- public int Length => _size;
- public DynamicRingBuffer(int initialCapacity = RingBufferAlignment)
- {
- _buffer = new byte[initialCapacity];
- }
- public void Clear()
- {
- _size = 0;
- _headOffset = 0;
- _tailOffset = 0;
- }
- public void Clear(int size)
- {
- lock (_lock)
- {
- if (size > _size)
- {
- size = _size;
- }
- if (size == 0)
- {
- return;
- }
- _headOffset = (_headOffset + size) % _buffer.Length;
- _size -= size;
- if (_size == 0)
- {
- _headOffset = 0;
- _tailOffset = 0;
- }
- }
- }
- private void SetCapacityLocked(int capacity)
- {
- byte[] buffer = new byte[capacity];
- if (_size > 0)
- {
- if (_headOffset < _tailOffset)
- {
- Buffer.BlockCopy(_buffer, _headOffset, buffer, 0, _size);
- }
- else
- {
- Buffer.BlockCopy(_buffer, _headOffset, buffer, 0, _buffer.Length - _headOffset);
- Buffer.BlockCopy(_buffer, 0, buffer, _buffer.Length - _headOffset, _tailOffset);
- }
- }
- _buffer = buffer;
- _headOffset = 0;
- _tailOffset = _size;
- }
- public void Write<T>(T[] buffer, int index, int count)
- {
- if (count == 0)
- {
- return;
- }
- lock (_lock)
- {
- if ((_size + count) > _buffer.Length)
- {
- SetCapacityLocked(BitUtils.AlignUp(_size + count, RingBufferAlignment));
- }
- if (_headOffset < _tailOffset)
- {
- int tailLength = _buffer.Length - _tailOffset;
- if (tailLength >= count)
- {
- Buffer.BlockCopy(buffer, index, _buffer, _tailOffset, count);
- }
- else
- {
- Buffer.BlockCopy(buffer, index, _buffer, _tailOffset, tailLength);
- Buffer.BlockCopy(buffer, index + tailLength, _buffer, 0, count - tailLength);
- }
- }
- else
- {
- Buffer.BlockCopy(buffer, index, _buffer, _tailOffset, count);
- }
- _size += count;
- _tailOffset = (_tailOffset + count) % _buffer.Length;
- }
- }
- public int Read<T>(T[] buffer, int index, int count)
- {
- lock (_lock)
- {
- if (count > _size)
- {
- count = _size;
- }
- if (count == 0)
- {
- return 0;
- }
- if (_headOffset < _tailOffset)
- {
- Buffer.BlockCopy(_buffer, _headOffset, buffer, index, count);
- }
- else
- {
- int tailLength = _buffer.Length - _headOffset;
- if (tailLength >= count)
- {
- Buffer.BlockCopy(_buffer, _headOffset, buffer, index, count);
- }
- else
- {
- Buffer.BlockCopy(_buffer, _headOffset, buffer, index, tailLength);
- Buffer.BlockCopy(_buffer, 0, buffer, index + tailLength, count - tailLength);
- }
- }
- _size -= count;
- _headOffset = (_headOffset + count) % _buffer.Length;
- if (_size == 0)
- {
- _headOffset = 0;
- _tailOffset = 0;
- }
- return count;
- }
- }
- }
- }
|