SongDataWaveProvider.cs 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. using NAudio.Wave;
  2. using System;
  3. using System.Collections.Generic;
  4. namespace SongVocalSectionAnalyser.AudioAnalysis
  5. {
  6. public class SongDataWaveProvider : IWaveProvider
  7. {
  8. private readonly IReadOnlyList<short> _samples;
  9. private readonly int _endSample;
  10. public event Action<int> Playing;
  11. public SongDataWaveProvider(SongData data, TimeSpan? begin = null, TimeSpan? end = null)
  12. {
  13. WaveFormat = new WaveFormat(data.SampleRate, 16, 1);
  14. _samples = data.Samples;
  15. var maxTime = (float)_samples.Count / data.SampleRate;
  16. if (begin.HasValue)
  17. {
  18. if (begin.Value.TotalSeconds > maxTime) throw new ArgumentOutOfRangeException(nameof(begin));
  19. _currentSample = (int)(begin.Value.TotalSeconds * data.SampleRate);
  20. }
  21. else
  22. {
  23. _currentSample = 0;
  24. }
  25. _endSample = end.HasValue && end.Value.TotalSeconds < maxTime
  26. ? (int)Math.Ceiling(end.Value.TotalSeconds * data.SampleRate)
  27. : _samples.Count;
  28. }
  29. private int _currentSample;
  30. private bool _hiByte;
  31. public int Read(byte[] buffer, int offset, int count)
  32. {
  33. if (_currentSample == _endSample)
  34. {
  35. OnPlaying();
  36. return 0;
  37. }
  38. OnPlaying();
  39. var read = 0;
  40. for (var i = 0; i < count; i++)
  41. {
  42. if (_currentSample == _endSample) break;
  43. buffer[i] = _hiByte
  44. ? (byte)(_samples[_currentSample] >> 8)
  45. : (byte)(_samples[_currentSample]);
  46. if (_hiByte)
  47. {
  48. OnPlaying();
  49. ++_currentSample;
  50. }
  51. _hiByte = !_hiByte;
  52. ++read;
  53. }
  54. return read;
  55. }
  56. public WaveFormat WaveFormat { get; }
  57. protected virtual void OnPlaying()
  58. {
  59. Playing?.Invoke(_currentSample);
  60. }
  61. }
  62. }