using NAudio.Wave; using System; using System.Collections.Generic; namespace SongVocalSectionAnalyser.AudioAnalysis { public class SongDataWaveProvider : IWaveProvider { private readonly IReadOnlyList _samples; private readonly int _endSample; public event Action Playing; public SongDataWaveProvider(SongData data, TimeSpan? begin = null, TimeSpan? end = null) { WaveFormat = new WaveFormat(data.SampleRate, 16, 1); _samples = data.Samples; var maxTime = (float)_samples.Count / data.SampleRate; if (begin.HasValue) { if (begin.Value.TotalSeconds > maxTime) throw new ArgumentOutOfRangeException(nameof(begin)); _currentSample = (int)(begin.Value.TotalSeconds * data.SampleRate); } else { _currentSample = 0; } _endSample = end.HasValue && end.Value.TotalSeconds < maxTime ? (int)Math.Ceiling(end.Value.TotalSeconds * data.SampleRate) : _samples.Count; } private int _currentSample; private bool _hiByte; public int Read(byte[] buffer, int offset, int count) { if (_currentSample == _endSample) { OnPlaying(); return 0; } OnPlaying(); var read = 0; for (var i = 0; i < count; i++) { if (_currentSample == _endSample) break; buffer[i] = _hiByte ? (byte)(_samples[_currentSample] >> 8) : (byte)(_samples[_currentSample]); if (_hiByte) { OnPlaying(); ++_currentSample; } _hiByte = !_hiByte; ++read; } return read; } public WaveFormat WaveFormat { get; } protected virtual void OnPlaying() { Playing?.Invoke(_currentSample); } } }