namespace QuikDawEditor.SampleProviders; public class BufferedSampleProvider : ISampleProvider { private CircularFloatBuffer circularFloatBuffer; private readonly WaveFormat waveFormat; public WaveFormat WaveFormat => waveFormat; public BufferedSampleProvider(WaveFormat waveFormat) { this.waveFormat = waveFormat; BufferLength = waveFormat.SampleRate * 5; ReadFully = true; } public bool ReadFully { get; set; } public int BufferLength { get; set; } public TimeSpan BufferDuration { get { return TimeSpan.FromSeconds((double)BufferLength / waveFormat.SampleRate); } set { BufferLength = (int)(value.TotalSeconds * waveFormat.SampleRate); } } public bool DiscardOnBufferOverflow { get; set; } public int BufferedSamples { get { return circularFloatBuffer == null ? 0 : circularFloatBuffer.Count; } } public TimeSpan BufferedDuration { get { return TimeSpan.FromSeconds((double)BufferedSamples / waveFormat.SampleRate); } } public void AddSamples(float[] buffer, int offset, int count) { // create buffer here to allow user to customise buffer length if (circularFloatBuffer == null) circularFloatBuffer = new CircularFloatBuffer(BufferLength); var written = circularFloatBuffer.Write(buffer, offset, count); if (written < count && !DiscardOnBufferOverflow) throw new InvalidOperationException("Buffer full"); } public int Read(float[] buffer, int offset, int count) { int read = 0; if (circularFloatBuffer != null) // not yet created read = circularFloatBuffer.Read(buffer, offset, count); if (ReadFully && read < count) { // zero the end of the buffer Array.Clear(buffer, offset + read, count - read); read = count; } return read; } public void ClearBuffer() { if (circularFloatBuffer != null) { circularFloatBuffer.Reset(); } } public void ClearBufferTapered() { if (circularFloatBuffer != null) { circularFloatBuffer.ResetTaper(); } } }