using Pcie8586Probe.Models; namespace Pcie8586Probe.Acquisition; public sealed class Recorder { private readonly object _gate = new(); private readonly List _blocks = new(); private long _targetSamplesPerChannel; private bool _armed; private bool _completed; private double _sampleRateHz; public bool IsRecording { get { lock (_gate) { return _armed && !_completed; } } } public double Progress { get { lock (_gate) { if (_targetSamplesPerChannel <= 0) { return 0; } var count = _blocks.Sum(static block => (long)block.SamplesPerChannel); return Math.Clamp((double)count / _targetSamplesPerChannel, 0, 1); } } } public void Start(TimeSpan duration, double sampleRateHz) { if (duration <= TimeSpan.Zero) throw new ArgumentOutOfRangeException(nameof(duration)); if (sampleRateHz <= 0) throw new ArgumentOutOfRangeException(nameof(sampleRateHz)); lock (_gate) { _blocks.Clear(); _sampleRateHz = sampleRateHz; _targetSamplesPerChannel = Math.Max(1, (long)Math.Round(sampleRateHz * duration.TotalSeconds)); _armed = true; _completed = false; } } public SampleBlock? Add(SampleBlock block) { lock (_gate) { if (!_armed || _completed) { return null; } _blocks.Add(block); var count = _blocks.Sum(static item => (long)item.SamplesPerChannel); if (count < _targetSamplesPerChannel) { return null; } _completed = true; _armed = false; var merged = SampleBlockAssembler.Concat(_blocks); return SampleBlockAssembler.Slice(merged, 0, (int)_targetSamplesPerChannel) with { SampleRateHz = _sampleRateHz }; } } }