public override int ReadSamples(double[] buffer, int count) { if (BufferingTask.Status == TaskStatus.Created) { BufferingTask.Start(); } var targetRange = new IntRange(SamplePosition, Math.Min(SamplePosition + count, SampleCount - 1)); while (!Disposed) { var exists = false; lock (BufferedRange) { exists = BufferedRange.Exists((r) => r.IsInclude(targetRange)); } if (exists) { break; } else { if (Stream.SamplePosition > SamplePosition || Stream.SamplePosition + BufferingSampleCount < SamplePosition) { lock (Stream) { Stream.SamplePosition = SamplePosition; } } Thread.Sleep(10); } } var copyCount = Math.Min(count, SampleCount - SamplePosition); Buffer.BlockCopy(Samples, SamplePosition * sizeof(double), buffer, 0, copyCount * sizeof(double)); Position += copyCount * sizeof(double); return(copyCount); }
public WaveCacheStream(WaveDataStream stream) { Stream = stream; Samples = new double[stream.SampleCount]; BufferingTaskCancellationToken = new CancellationTokenSource(); var token = BufferingTaskCancellationToken.Token; BufferingTask = new Task(() => { var totalRange = new IntRange(0, Samples.Length - 1); while (!BufferedRange.Any(r => r.IsInclude(totalRange))) { if (token.IsCancellationRequested) { token.ThrowIfCancellationRequested(); } var currentSamplePosition = 0; var nextSamplePosition = 0; var sampleCount = 0; var buffer = new double[BufferingSampleCount]; lock (Stream) { currentSamplePosition = Stream.SamplePosition; var alreadyProcessedRange = BufferedRange.Find(r => r.IsInclude(currentSamplePosition)); if (alreadyProcessedRange != null) { Stream.SamplePosition = alreadyProcessedRange.End; continue; } sampleCount = Stream.ReadSamples(buffer, BufferingSampleCount); nextSamplePosition = Stream.SamplePosition; } if (sampleCount == 0 || Samples.Length <= currentSamplePosition) { Stream.SamplePosition = 0; continue; } var copyCount = Math.Min(sampleCount, Samples.Length - currentSamplePosition); Buffer.BlockCopy(buffer, 0, Samples, currentSamplePosition * sizeof(double), copyCount * sizeof(double)); var processedRange = new IntRange(currentSamplePosition, nextSamplePosition); var nearRange = BufferedRange.Where((r) => r.IsInclude(currentSamplePosition) || r.IsInclude(nextSamplePosition) || r.End == currentSamplePosition).ToArray(); lock (BufferedRange) { if (nearRange.Length > 0) { var newRange = nearRange.Aggregate(processedRange, (r, m) => m.Union(r)); BufferedRange.Add(newRange); BufferedRange.RemoveAll(r => nearRange.Any(br => ReferenceEquals(br, r))); } else { BufferedRange.Add(processedRange); } } } }, token); }