SHA256
Document Audio Pipeline
This commit is contained in:
22 files changed
+634
-12
No files matched your search
@@ -11,19 +11,38 @@ namespace ADOFAIRenderer.Util.Audio.Clip;
|
||||
/// </summary>
|
||||
internal sealed class MemoryPCMReader : IPCMReader
|
||||
{
|
||||
/// <summary>Block arrays; an entry is set to null when the block is released.</summary>
|
||||
private readonly float[]?[] _blocks;
|
||||
|
||||
/// <summary>Called with each released block (for example to uncount its memory in the store); may be null.</summary>
|
||||
private readonly Action<float[]>? _onBlockReleased;
|
||||
|
||||
private int _releasedCount; // Blocks [0, _releasedCount) are released
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int Channels { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int SampleRate { get; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public long TotalFrames { get; }
|
||||
|
||||
/// <summary>True: blocks are released as they are read.</summary>
|
||||
public bool IsForwardOnly => true;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public long Position { get; private set; }
|
||||
|
||||
/// <summary>Frames per block (all blocks except the last).</summary>
|
||||
public int FramesPerBlock { get; }
|
||||
|
||||
/// <param name="blocks">Interleaved blocks in frame order; the reader takes ownership of the arrays (the list is copied).</param>
|
||||
/// <param name="framesPerBlock">Frames in every block except possibly the last (positive).</param>
|
||||
/// <param name="channels">Channel count (positive).</param>
|
||||
/// <param name="sampleRate">Sample rate in Hz.</param>
|
||||
/// <param name="totalFrames">Frame count; the blocks must hold at least this many frames.</param>
|
||||
/// <param name="onBlockReleased">Called with each block when it is released; may be null.</param>
|
||||
public MemoryPCMReader(IReadOnlyList<float[]> blocks, int framesPerBlock, int channels, int sampleRate, long totalFrames,
|
||||
Action<float[]>? onBlockReleased)
|
||||
{
|
||||
@@ -40,6 +59,8 @@ internal sealed class MemoryPCMReader : IPCMReader
|
||||
TotalFrames = totalFrames;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
/// <exception cref="InvalidOperationException"><paramref name="frame"/> lies in a block that was already released.</exception>
|
||||
public void Seek(long frame)
|
||||
{
|
||||
if (frame < 0 || frame > TotalFrames) throw new ArgumentOutOfRangeException(nameof(frame));
|
||||
@@ -48,6 +69,8 @@ internal sealed class MemoryPCMReader : IPCMReader
|
||||
Position = frame;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
/// <remarks>Blocks whose end the position has passed are released after each copy.</remarks>
|
||||
public int Read(float[] buffer, int frameCount)
|
||||
{
|
||||
var total = (int)Math.Min(frameCount, TotalFrames - Position);
|
||||
@@ -68,6 +91,7 @@ internal sealed class MemoryPCMReader : IPCMReader
|
||||
return written;
|
||||
}
|
||||
|
||||
/// <summary>Releases every block with an index below <paramref name="blockIndex"/> that is not released yet, in order.</summary>
|
||||
private void ReleaseBlocksBefore(int blockIndex)
|
||||
{
|
||||
while (_releasedCount < blockIndex && _releasedCount < _blocks.Length)
|
||||
@@ -79,5 +103,6 @@ internal sealed class MemoryPCMReader : IPCMReader
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Releases every remaining block. Safe to call more than once.</summary>
|
||||
public void Dispose() => ReleaseBlocksBefore(_blocks.Length);
|
||||
}
|
||||
Reference in new issue
Block a user