CSound.cpp 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. #include <SDL.h>
  2. #include "CSound.h"
  3. #include "WallpaperEngine/FileSystem/Container.h"
  4. #include <algorithm>
  5. using namespace WallpaperEngine::Render::Objects;
  6. CSound::CSound (Wallpapers::CScene& scene, const Sound& sound) :
  7. CObject (scene, sound), m_sound (sound), m_playing (scene.getSoundPlayRequest (sound.id).value_or (!sound.startsilent.value_or (false))) {
  8. if (this->getContext ().getApp ().getContext ().settings.audio.enabled) {
  9. this->load ();
  10. }
  11. }
  12. CSound::~CSound () {
  13. for (const auto& stream : this->m_audioStreams) {
  14. this->getScene ().getAudioContext ().removeStream (stream.first);
  15. delete stream.second;
  16. }
  17. this->m_audioStreams.clear ();
  18. }
  19. void CSound::load () {
  20. for (const auto& cur : this->m_sound.sounds) {
  21. auto stream
  22. = new Audio::AudioStream (this->getScene ().getAudioContext (), this->getAssetLocator ().read (cur));
  23. stream->setRepeat (this->m_sound.playbackmode == PlaybackMode_Loop);
  24. this->m_audioStreams.insert_or_assign (this->getScene ().getAudioContext ().addStream (stream), stream);
  25. }
  26. }
  27. void CSound::render () { this->applyEffectiveVolume (); }
  28. void CSound::play () {
  29. this->m_playing = true;
  30. this->applyEffectiveVolume ();
  31. }
  32. void CSound::stop () {
  33. this->m_playing = false;
  34. this->applyEffectiveVolume ();
  35. }
  36. void CSound::setVolumeOverride (std::optional<int> volume) {
  37. this->m_screenVolumeOverride = volume;
  38. this->applyEffectiveVolume ();
  39. }
  40. void CSound::applyEffectiveVolume () {
  41. // The screen-level policy (mute/ambient-volume, set via setVolumeOverride from
  42. // CScene::setAudioPolicy) and the wallpaper author's own per-object "volume" property (e.g.
  43. // picking which of several alternate music tracks plays) are independent inputs that have to
  44. // combine, not overwrite each other - otherwise picking a track would undo screen muting, or
  45. // muting a screen would make track selection pointless.
  46. const int base = this->m_screenVolumeOverride.value_or (
  47. this->getContext ().getApp ().getContext ().state.audio.volume
  48. );
  49. const float fraction = this->m_sound.volume && this->m_sound.volume->value
  50. ? std::clamp (this->m_sound.volume->value->getFloat (), 0.0f, 1.0f)
  51. : 1.0f;
  52. const int effective = this->m_playing ? static_cast<int> (static_cast<float> (base) * fraction) : 0;
  53. for (const auto& entry : this->m_audioStreams) {
  54. this->getScene ().getAudioContext ().setStreamVolume (entry.first, effective);
  55. }
  56. }