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