AudioSystem.h 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. #pragma once
  2. #include "AudioConstants.h"
  3. #include <atomic>
  4. #include <chrono>
  5. #include <condition_variable>
  6. #include <memory>
  7. #include <mutex>
  8. #include <queue>
  9. #include <string>
  10. #include <thread>
  11. #include <unordered_map>
  12. #include <unordered_set>
  13. #include <utility>
  14. #include <vector>
  15. class Sound;
  16. namespace Game::Audio {
  17. class MusicPlayer;
  18. }
  19. enum class AudioEventType {
  20. PLAY_SOUND,
  21. PLAY_MUSIC,
  22. STOP_SOUND,
  23. STOP_MUSIC,
  24. SET_VOLUME,
  25. PAUSE,
  26. RESUME,
  27. SHUTDOWN,
  28. UNLOAD_RESOURCE,
  29. CLEANUP_INACTIVE
  30. };
  31. enum class AudioCategory { SFX, VOICE, MUSIC };
  32. struct AudioEvent {
  33. AudioEventType type;
  34. std::string resourceId;
  35. float volume = AudioConstants::DEFAULT_VOLUME;
  36. bool loop = false;
  37. int priority = AudioConstants::DEFAULT_PRIORITY;
  38. AudioCategory category = AudioCategory::SFX;
  39. AudioEvent(AudioEventType t, std::string id = "",
  40. float vol = AudioConstants::DEFAULT_VOLUME, bool l = false,
  41. int p = AudioConstants::DEFAULT_PRIORITY,
  42. AudioCategory cat = AudioCategory::SFX)
  43. : type(t), resourceId(std::move(id)), volume(vol), loop(l), priority(p),
  44. category(cat) {}
  45. };
  46. class AudioSystem {
  47. public:
  48. static auto getInstance() -> AudioSystem &;
  49. auto initialize() -> bool;
  50. void shutdown();
  51. void playSound(const std::string &soundId,
  52. float volume = AudioConstants::DEFAULT_VOLUME,
  53. bool loop = false,
  54. int priority = AudioConstants::DEFAULT_PRIORITY,
  55. AudioCategory category = AudioCategory::SFX);
  56. void playMusic(const std::string &musicId,
  57. float volume = AudioConstants::DEFAULT_VOLUME,
  58. bool crossfade = true);
  59. void stopSound(const std::string &soundId);
  60. void stopMusic();
  61. void setMasterVolume(float volume);
  62. void setSoundVolume(float volume);
  63. void setMusicVolume(float volume);
  64. void setVoiceVolume(float volume);
  65. void pauseAll();
  66. void resumeAll();
  67. auto loadSound(const std::string &soundId, const std::string &filePath,
  68. AudioCategory category = AudioCategory::SFX) -> bool;
  69. auto loadMusic(const std::string &musicId,
  70. const std::string &filePath) -> bool;
  71. void unloadSound(const std::string &soundId);
  72. void unloadMusic(const std::string &musicId);
  73. void unloadAllSounds();
  74. void unloadAllMusic();
  75. void setMaxChannels(size_t maxChannels);
  76. auto getActiveChannelCount() const -> size_t;
  77. auto getMasterVolume() const -> float { return masterVolume; }
  78. auto getSoundVolume() const -> float { return soundVolume; }
  79. auto getMusicVolume() const -> float { return musicVolume; }
  80. auto getVoiceVolume() const -> float { return voiceVolume; }
  81. private:
  82. AudioSystem();
  83. ~AudioSystem();
  84. AudioSystem(const AudioSystem &) = delete;
  85. auto operator=(const AudioSystem &) -> AudioSystem & = delete;
  86. void audioThreadFunc();
  87. void processEvent(const AudioEvent &event);
  88. void cleanupInactiveSounds();
  89. auto canPlaySound(int priority) -> bool;
  90. void evictLowestPrioritySound();
  91. void evictLowestPrioritySoundLocked();
  92. auto getEffectiveVolume(AudioCategory category,
  93. float eventVolume) const -> float;
  94. std::unordered_map<std::string, std::unique_ptr<Sound>> sounds;
  95. std::unordered_map<std::string, AudioCategory> soundCategories;
  96. std::unordered_set<std::string> activeResources;
  97. mutable std::mutex resourceMutex;
  98. Game::Audio::MusicPlayer *m_musicPlayer{nullptr};
  99. std::thread audioThread;
  100. std::queue<AudioEvent> eventQueue;
  101. mutable std::mutex queueMutex;
  102. std::condition_variable queueCondition;
  103. std::atomic<bool> isRunning;
  104. std::atomic<float> masterVolume;
  105. std::atomic<float> soundVolume;
  106. std::atomic<float> musicVolume;
  107. std::atomic<float> voiceVolume;
  108. size_t maxChannels{AudioConstants::DEFAULT_MAX_CHANNELS};
  109. struct ActiveSound {
  110. std::string id;
  111. int priority;
  112. bool loop;
  113. AudioCategory category;
  114. std::chrono::steady_clock::time_point startTime;
  115. };
  116. std::vector<ActiveSound> activeSounds;
  117. mutable std::mutex activeSoundsMutex;
  118. };