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 "AudioMixer.h"
11
12 #include "../Context.h"
13 #include "../config/Config.h"
14 #include "AudioChannel.h"
15 #include "AudioContext.h"
16 #include "AudioSource.h"
17 #include "audio.h"
18
19 #include <cmath>
20
21 using namespace OpenRCT2;
22 using namespace OpenRCT2::Audio;
23
GetMixer()24 static IAudioMixer* GetMixer()
25 {
26 auto audioContext = GetContext()->GetAudioContext();
27 return audioContext->GetMixer();
28 }
29
Mixer_Init(const char * device)30 void Mixer_Init(const char* device)
31 {
32 auto audioContext = GetContext()->GetAudioContext();
33 if (device == nullptr)
34 {
35 device = "";
36 }
37 audioContext->SetOutputDevice(std::string(device));
38 }
39
Mixer_Play_Effect(SoundId id,int32_t loop,int32_t volume,float pan,double rate,int32_t deleteondone)40 void* Mixer_Play_Effect(SoundId id, int32_t loop, int32_t volume, float pan, double rate, int32_t deleteondone)
41 {
42 IAudioChannel* channel = nullptr;
43 if (gConfigSound.sound_enabled)
44 {
45 if (static_cast<uint32_t>(id) >= RCT2SoundCount)
46 {
47 log_error("Tried to play an invalid sound id. %i", id);
48 }
49 else
50 {
51 IAudioMixer* mixer = GetMixer();
52 if (mixer != nullptr)
53 {
54 mixer->Lock();
55 IAudioSource* source = mixer->GetSoundSource(id);
56 channel = mixer->Play(source, loop, deleteondone != 0, false);
57 if (channel != nullptr)
58 {
59 channel->SetVolume(volume);
60 channel->SetPan(pan);
61 channel->SetRate(rate);
62 }
63 mixer->Unlock();
64 }
65 }
66 }
67 return channel;
68 }
69
Mixer_Stop_Channel(void * channel)70 void Mixer_Stop_Channel(void* channel)
71 {
72 auto mixer = GetMixer();
73 if (mixer != nullptr)
74 {
75 mixer->Stop(static_cast<IAudioChannel*>(channel));
76 }
77 }
78
Mixer_Channel_Volume(void * channel,int32_t volume)79 void Mixer_Channel_Volume(void* channel, int32_t volume)
80 {
81 IAudioMixer* audioMixer = GetMixer();
82 if (audioMixer != nullptr)
83 {
84 audioMixer->Lock();
85 static_cast<IAudioChannel*>(channel)->SetVolume(volume);
86 audioMixer->Unlock();
87 }
88 }
89
Mixer_Channel_Pan(void * channel,float pan)90 void Mixer_Channel_Pan(void* channel, float pan)
91 {
92 IAudioMixer* audioMixer = GetMixer();
93 if (audioMixer != nullptr)
94 {
95 audioMixer->Lock();
96 static_cast<IAudioChannel*>(channel)->SetPan(pan);
97 audioMixer->Unlock();
98 }
99 }
100
Mixer_Channel_Rate(void * channel,double rate)101 void Mixer_Channel_Rate(void* channel, double rate)
102 {
103 IAudioMixer* audioMixer = GetMixer();
104 if (audioMixer != nullptr)
105 {
106 audioMixer->Lock();
107 static_cast<IAudioChannel*>(channel)->SetRate(rate);
108 audioMixer->Unlock();
109 }
110 }
111
Mixer_Channel_IsPlaying(void * channel)112 int32_t Mixer_Channel_IsPlaying(void* channel)
113 {
114 return static_cast<IAudioChannel*>(channel)->IsPlaying();
115 }
116
Mixer_Channel_GetOffset(void * channel)117 uint64_t Mixer_Channel_GetOffset(void* channel)
118 {
119 return static_cast<IAudioChannel*>(channel)->GetOffset();
120 }
121
Mixer_Channel_SetOffset(void * channel,uint64_t offset)122 int32_t Mixer_Channel_SetOffset(void* channel, uint64_t offset)
123 {
124 return static_cast<IAudioChannel*>(channel)->SetOffset(offset);
125 }
126
Mixer_Channel_SetGroup(void * channel,MixerGroup group)127 void Mixer_Channel_SetGroup(void* channel, MixerGroup group)
128 {
129 static_cast<IAudioChannel*>(channel)->SetGroup(group);
130 }
131
PlayMusic(T && src,int32_t loop)132 template<typename T> static void* PlayMusic(T&& src, int32_t loop)
133 {
134 auto* mixer = GetMixer();
135 if (mixer == nullptr)
136 return nullptr;
137
138 auto audioContext = GetContext()->GetAudioContext();
139 auto stream = audioContext->CreateStreamFromWAV(std::forward<T&&>(src));
140 if (stream == nullptr)
141 return nullptr;
142
143 auto* channel = mixer->Play(stream, loop, false, true);
144 if (channel == nullptr)
145 {
146 delete stream;
147 return nullptr;
148 }
149
150 channel->SetGroup(MixerGroup::RideMusic);
151 return channel;
152 }
153
Mixer_Play_Music(int32_t pathId,int32_t loop,int32_t streaming)154 void* Mixer_Play_Music(int32_t pathId, int32_t loop, int32_t streaming)
155 {
156 IAudioChannel* channel = nullptr;
157 IAudioMixer* mixer = GetMixer();
158 if (mixer != nullptr)
159 {
160 if (streaming)
161 {
162 const utf8* path = context_get_path_legacy(pathId);
163
164 auto audioContext = GetContext()->GetAudioContext();
165 IAudioSource* source = audioContext->CreateStreamFromWAV(path);
166 if (source != nullptr)
167 {
168 channel = mixer->Play(source, loop, false, true);
169 if (channel == nullptr)
170 {
171 delete source;
172 }
173 }
174 }
175 else
176 {
177 if (mixer->LoadMusic(pathId))
178 {
179 IAudioSource* source = mixer->GetMusicSource(pathId);
180 channel = mixer->Play(source, MIXER_LOOP_INFINITE, false, false);
181 }
182 }
183 }
184 if (channel != nullptr)
185 {
186 channel->SetGroup(MixerGroup::RideMusic);
187 }
188 return channel;
189 }
190
Mixer_Play_Music(const char * path,int32_t loop)191 void* Mixer_Play_Music(const char* path, int32_t loop)
192 {
193 return PlayMusic(path, loop);
194 }
195
Mixer_Play_Music(std::unique_ptr<IStream> stream,int32_t loop)196 void* Mixer_Play_Music(std::unique_ptr<IStream> stream, int32_t loop)
197 {
198 return PlayMusic(std::move(stream), loop);
199 }
200
Mixer_SetVolume(float volume)201 void Mixer_SetVolume(float volume)
202 {
203 GetMixer()->SetVolume(volume);
204 }
205
DStoMixerVolume(int32_t volume)206 int32_t DStoMixerVolume(int32_t volume)
207 {
208 return static_cast<int32_t>(MIXER_VOLUME_MAX * (std::pow(10.0f, static_cast<float>(volume) / 2000)));
209 }
210
DStoMixerPan(int32_t pan)211 float DStoMixerPan(int32_t pan)
212 {
213 return ((static_cast<float>(pan) + -DSBPAN_LEFT) / DSBPAN_RIGHT) / 2;
214 }
215
DStoMixerRate(int32_t frequency)216 double DStoMixerRate(int32_t frequency)
217 {
218 return static_cast<double>(frequency) / 22050;
219 }
220