1 /***************************************************************************** 2 * Copyright (c) 2014-2020 OpenRCT2 developers 3 * 4 * For a complete list of all authors, please refer to contributors.md 5 * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 6 * 7 * OpenRCT2 is licensed under the GNU General Public License version 3. 8 *****************************************************************************/ 9 10 #include "AudioContext.h" 11 #include "AudioFormat.h" 12 13 #include <algorithm> 14 #include <cmath> 15 #include <openrct2/audio/AudioSource.h> 16 #include <openrct2/common.h> 17 #include <speex/speex_resampler.h> 18 19 namespace OpenRCT2::Audio 20 { 21 template<typename AudioSource_ = ISDLAudioSource> class AudioChannelImpl : public ISDLAudioChannel 22 { 23 static_assert(std::is_base_of_v<IAudioSource, AudioSource_>); 24 25 private: 26 AudioSource_* _source = nullptr; 27 SpeexResamplerState* _resampler = nullptr; 28 29 MixerGroup _group = MixerGroup::Sound; 30 double _rate = 0; 31 uint64_t _offset = 0; 32 int32_t _loop = 0; 33 34 int32_t _volume = 1; 35 float _volume_l = 0.f; 36 float _volume_r = 0.f; 37 float _oldvolume_l = 0.f; 38 float _oldvolume_r = 0.f; 39 int32_t _oldvolume = 0; 40 float _pan = 0; 41 42 bool _stopping = false; 43 bool _done = true; 44 bool _deleteondone = false; 45 bool _deletesourceondone = false; 46 47 public: AudioChannelImpl()48 AudioChannelImpl() 49 { 50 AudioChannelImpl::SetRate(1); 51 AudioChannelImpl::SetVolume(MIXER_VOLUME_MAX); 52 AudioChannelImpl::SetPan(0.5f); 53 } 54 ~AudioChannelImpl()55 ~AudioChannelImpl() override 56 { 57 if (_resampler != nullptr) 58 { 59 speex_resampler_destroy(_resampler); 60 _resampler = nullptr; 61 } 62 if (_deletesourceondone) 63 { 64 delete _source; 65 } 66 } 67 GetSource() const68 [[nodiscard]] IAudioSource* GetSource() const override 69 { 70 return _source; 71 } 72 GetResampler() const73 [[nodiscard]] SpeexResamplerState* GetResampler() const override 74 { 75 return _resampler; 76 } 77 SetResampler(SpeexResamplerState * value)78 void SetResampler(SpeexResamplerState* value) override 79 { 80 _resampler = value; 81 } 82 GetGroup() const83 [[nodiscard]] MixerGroup GetGroup() const override 84 { 85 return _group; 86 } 87 SetGroup(MixerGroup group)88 void SetGroup(MixerGroup group) override 89 { 90 _group = group; 91 } 92 GetRate() const93 [[nodiscard]] double GetRate() const override 94 { 95 return _rate; 96 } 97 SetRate(double rate)98 void SetRate(double rate) override 99 { 100 _rate = std::max(0.001, rate); 101 } 102 GetOffset() const103 [[nodiscard]] uint64_t GetOffset() const override 104 { 105 return _offset; 106 } 107 SetOffset(uint64_t offset)108 bool SetOffset(uint64_t offset) override 109 { 110 if (_source != nullptr && offset < _source->GetLength()) 111 { 112 AudioFormat format = _source->GetFormat(); 113 int32_t samplesize = format.channels * format.BytesPerSample(); 114 _offset = (offset / samplesize) * samplesize; 115 return true; 116 } 117 return false; 118 } 119 GetLoop() const120 [[nodiscard]] int32_t GetLoop() const override 121 { 122 return _loop; 123 } 124 SetLoop(int32_t value)125 void SetLoop(int32_t value) override 126 { 127 _loop = value; 128 } 129 GetVolume() const130 [[nodiscard]] int32_t GetVolume() const override 131 { 132 return _volume; 133 } 134 GetVolumeL() const135 [[nodiscard]] float GetVolumeL() const override 136 { 137 return _volume_l; 138 } 139 GetVolumeR() const140 [[nodiscard]] float GetVolumeR() const override 141 { 142 return _volume_r; 143 } 144 GetOldVolumeL() const145 [[nodiscard]] float GetOldVolumeL() const override 146 { 147 return _oldvolume_l; 148 } 149 GetOldVolumeR() const150 [[nodiscard]] float GetOldVolumeR() const override 151 { 152 return _oldvolume_r; 153 } 154 GetOldVolume() const155 [[nodiscard]] int32_t GetOldVolume() const override 156 { 157 return _oldvolume; 158 } 159 SetVolume(int32_t volume)160 void SetVolume(int32_t volume) override 161 { 162 _volume = std::clamp(volume, 0, MIXER_VOLUME_MAX); 163 } 164 GetPan() const165 [[nodiscard]] float GetPan() const override 166 { 167 return _pan; 168 } 169 SetPan(float pan)170 void SetPan(float pan) override 171 { 172 _pan = std::clamp(pan, 0.0f, 1.0f); 173 double decibels = (std::abs(_pan - 0.5) * 2.0) * 100.0; 174 double attenuation = pow(10, decibels / 20.0); 175 if (_pan <= 0.5) 176 { 177 _volume_l = 1.0; 178 _volume_r = static_cast<float>(1.0 / attenuation); 179 } 180 else 181 { 182 _volume_r = 1.0; 183 _volume_l = static_cast<float>(1.0 / attenuation); 184 } 185 } 186 IsStopping() const187 [[nodiscard]] bool IsStopping() const override 188 { 189 return _stopping; 190 } 191 SetStopping(bool value)192 void SetStopping(bool value) override 193 { 194 _stopping = value; 195 } 196 IsDone() const197 [[nodiscard]] bool IsDone() const override 198 { 199 return _done; 200 } 201 SetDone(bool value)202 void SetDone(bool value) override 203 { 204 _done = value; 205 } 206 DeleteOnDone() const207 [[nodiscard]] bool DeleteOnDone() const override 208 { 209 return _deleteondone; 210 } 211 SetDeleteOnDone(bool value)212 void SetDeleteOnDone(bool value) override 213 { 214 _deleteondone = value; 215 } 216 SetDeleteSourceOnDone(bool value)217 void SetDeleteSourceOnDone(bool value) override 218 { 219 _deletesourceondone = value; 220 } 221 IsPlaying() const222 [[nodiscard]] bool IsPlaying() const override 223 { 224 return !_done; 225 } 226 Play(IAudioSource * source,int32_t loop)227 void Play(IAudioSource* source, int32_t loop) override 228 { 229 _source = static_cast<AudioSource_*>(source); 230 _loop = loop; 231 _offset = 0; 232 _done = false; 233 } 234 UpdateOldVolume()235 void UpdateOldVolume() override 236 { 237 _oldvolume = _volume; 238 _oldvolume_l = _volume_l; 239 _oldvolume_r = _volume_r; 240 } 241 GetFormat() const242 [[nodiscard]] AudioFormat GetFormat() const override 243 { 244 AudioFormat result = {}; 245 // The second check is there because NullAudioSource does not implement GetFormat. Avoid calling it. 246 if (_source != nullptr && _source->GetLength() > 0) 247 { 248 result = _source->GetFormat(); 249 } 250 return result; 251 } 252 Read(void * dst,size_t len)253 size_t Read(void* dst, size_t len) override 254 { 255 size_t bytesRead = 0; 256 size_t bytesToRead = len; 257 while (bytesToRead > 0 && !_done) 258 { 259 size_t readLen = _source->Read(dst, _offset, bytesToRead); 260 if (readLen > 0) 261 { 262 dst = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(dst) + readLen); 263 bytesToRead -= readLen; 264 bytesRead += readLen; 265 _offset += readLen; 266 } 267 if (_offset >= _source->GetLength()) 268 { 269 if (_loop == 0) 270 { 271 _done = true; 272 } 273 else if (_loop == MIXER_LOOP_INFINITE) 274 { 275 _offset = 0; 276 } 277 else 278 { 279 _loop--; 280 _offset = 0; 281 } 282 } 283 } 284 return bytesRead; 285 } 286 }; 287 Create()288 ISDLAudioChannel* AudioChannel::Create() 289 { 290 return new (std::nothrow) AudioChannelImpl(); 291 } 292 } // namespace OpenRCT2::Audio 293