LoopProvider.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using NAudio.Wave;
  7. namespace Client.MirSounds.Libraries
  8. {
  9. internal class LoopProvider : ISoundLibrary, IDisposable
  10. {
  11. public int Index { get; set; }
  12. public long ExpireTime { get; set; }
  13. private WaveOutEvent outputDevice;
  14. private AudioFileReader audioFile;
  15. private int _unscaledVolume;
  16. private string _fileName;
  17. private bool _loop;
  18. private bool _isDisposing;
  19. public static LoopProvider TryCreate(int index, string fileName, int volume, bool loop)
  20. {
  21. fileName = Path.Combine(Settings.SoundPath, fileName);
  22. string fileType = Path.GetExtension(fileName);
  23. // attempt to find file
  24. if (String.IsNullOrEmpty(fileType))
  25. {
  26. foreach (String ext in SoundManager.SupportedFileTypes)
  27. {
  28. if (File.Exists($"{fileName}{ext}"))
  29. {
  30. fileName = $"{fileName}{ext}";
  31. fileType = ext;
  32. break;
  33. }
  34. }
  35. }
  36. if (SoundManager.SupportedFileTypes.Contains(fileType) &&
  37. File.Exists(fileName))
  38. {
  39. return new LoopProvider(index, fileName, volume, loop);
  40. }
  41. else
  42. {
  43. return null;
  44. }
  45. }
  46. public LoopProvider(int index, string fileName, int volume, bool loop)
  47. {
  48. Index = index;
  49. _loop = loop;
  50. _fileName = fileName;
  51. Play(volume);
  52. }
  53. public bool IsPlaying()
  54. {
  55. return outputDevice.PlaybackState == PlaybackState.Playing;
  56. }
  57. public void Play(int volume)
  58. {
  59. if (outputDevice?.PlaybackState == PlaybackState.Playing)
  60. {
  61. return;
  62. }
  63. ExpireTime = CMain.Time + Settings.SoundCleanMinutes * 60 * 1000;
  64. if (outputDevice == null)
  65. {
  66. outputDevice = new WaveOutEvent();
  67. outputDevice.PlaybackStopped += (_,_) => OutputDevice_PlaybackStopped();
  68. }
  69. if (audioFile == null)
  70. {
  71. audioFile = new AudioFileReader(_fileName);
  72. outputDevice.Init(audioFile);
  73. }
  74. // loop or sound already cached
  75. if (outputDevice?.PlaybackState == PlaybackState.Stopped)
  76. {
  77. try
  78. {
  79. audioFile.Seek(0, SeekOrigin.Begin);
  80. }
  81. catch
  82. {
  83. audioFile = new AudioFileReader(_fileName);
  84. outputDevice.Init(audioFile);
  85. }
  86. }
  87. outputDevice.Volume = ScaleVolume(volume);
  88. outputDevice.Play();
  89. }
  90. public void SetVolume(int vol)
  91. {
  92. outputDevice.Volume = ScaleVolume(vol);
  93. }
  94. public void Stop()
  95. {
  96. Dispose();
  97. }
  98. private void OutputDevice_PlaybackStopped()
  99. {
  100. if (_loop &&
  101. !_isDisposing)
  102. {
  103. Play(_unscaledVolume);
  104. }
  105. }
  106. public void Dispose()
  107. {
  108. _isDisposing = true;
  109. outputDevice?.Dispose();
  110. audioFile?.Dispose();
  111. }
  112. private float ScaleVolume(int volume)
  113. {
  114. _unscaledVolume = volume;
  115. float scaled = 0.0f + (float)(volume - 0) / (100 - 0) * (1.0f - 0.0f);
  116. return scaled;
  117. }
  118. }
  119. }