1 #include <stdio.h>
2 #include <string.h>
3 #include <SFML/Network.hpp>
4 #include <iostream>
5 #include <iomanip>
6 #include <sstream>
7 
8 #include "vectorUtils.h"
9 #include "resources.h"
10 #include "soundManager.h"
11 #include "random.h"
12 
13 #define MAX_SOUNDS 16
14 
15 SoundManager* soundManager;
16 
SoundManager()17 SoundManager::SoundManager()
18 {
19     // By creating a SoundBuffer we force SFML to load the sound subsystem.
20     // Else this is done when the first sound is loaded, causing a delay at that
21     // point.
22     sf::SoundBuffer forceLoadBuffer;
23 
24     for(unsigned int n = 0; n < MAX_SOUNDS; n++)
25         activeSoundList.push_back(sf::Sound());
26 
27     master_sound_volume = 100.0;
28     music_volume = 100.0;
29     positional_sound_enabled = false;
30     music_channel.mode = None;
31 }
32 
~SoundManager()33 SoundManager::~SoundManager()
34 {
35 }
36 
playMusic(string name)37 void SoundManager::playMusic(string name)
38 {
39     music_set.clear();
40     P<ResourceStream> stream = getResourceStream(name);
41     if (stream)
42         startMusic(stream, true);
43 }
44 
playMusicSet(std::vector<string> filenames)45 void SoundManager::playMusicSet(std::vector<string> filenames)
46 {
47     music_set = filenames;
48     if (music_set.size() > 0)
49         startMusic(getResourceStream(music_set[irandom(0, static_cast<int>(music_set.size()) - 1)]), false);
50     else
51         stopMusic();
52 }
53 
stopMusic()54 void SoundManager::stopMusic()
55 {
56     music_set.clear();
57     music_channel.music.stop();
58 }
59 
setMusicVolume(float volume)60 void SoundManager::setMusicVolume(float volume)
61 {
62     if (music_volume != volume)
63     {
64         music_volume = volume;
65         if (music_channel.mode == None && music_channel.music.getStatus() != sf::Music::Stopped)
66             music_channel.music.setVolume(music_volume);
67     }
68 }
69 
getMusicVolume()70 float SoundManager::getMusicVolume()
71 {
72     return music_volume;
73 }
74 
stopSound(int index)75 void SoundManager::stopSound(int index)
76 {
77     if (index < 0 || index >= MAX_SOUNDS)
78         return;
79     sf::Sound& sound = activeSoundList[index];
80     if (sound.getStatus() == sf::Sound::Playing)
81     {
82         sound.setLoop(false);
83         sound.stop();
84     }
85 }
86 
setMasterSoundVolume(float volume)87 void SoundManager::setMasterSoundVolume(float volume)
88 {
89     // Set factor by which sound effect playback is multiplied.
90     // Bound volume between 0.0f and 100.0f.
91     master_sound_volume = std::max(0.0f, std::min(100.0f, volume));
92 }
93 
getMasterSoundVolume()94 float SoundManager::getMasterSoundVolume()
95 {
96     return master_sound_volume;
97 }
98 
setSoundVolume(int index,float volume)99 void SoundManager::setSoundVolume(int index, float volume)
100 {
101     sf::Sound& sound = activeSoundList[index];
102     if (sound.getStatus() == sf::Sound::Playing)
103     {
104         // Bound volume between 0.0f and 100.0f.
105         volume = std::max(0.0f, std::min(100.0f, volume));
106         sound.setVolume(volume);
107     }
108 }
109 
getSoundVolume(int index)110 float SoundManager::getSoundVolume(int index)
111 {
112     sf::Sound& sound = activeSoundList[index];
113     if (sound.getStatus() == sf::Sound::Playing)
114     {
115         return sound.getVolume();
116     } else {
117         return 0.0f;
118     }
119 }
120 
setSoundPitch(int index,float pitch)121 void SoundManager::setSoundPitch(int index, float pitch)
122 {
123     sf::Sound& sound = activeSoundList[index];
124     if (sound.getStatus() == sf::Sound::Playing)
125     {
126         // Bound pitch to 0.0f or greater.
127         pitch = std::max(0.0f, pitch);
128         sound.setPitch(pitch);
129     }
130 }
131 
getSoundPitch(int index)132 float SoundManager::getSoundPitch(int index)
133 {
134     sf::Sound& sound = activeSoundList[index];
135     if (sound.getStatus() == sf::Sound::Playing)
136     {
137         return sound.getPitch();
138     } else {
139         return 0.0f;
140     }
141 }
142 
playSound(string name,float pitch,float volume,bool loop)143 int SoundManager::playSound(string name, float pitch, float volume, bool loop)
144 {
145     sf::SoundBuffer* data = soundMap[name];
146     if (data == NULL)
147         data = loadSound(name);
148 
149     // Return the sound's index in activeSoundList[].
150     // Returns -1 if the list was full of playing sounds.
151     return playSoundData(data, pitch, volume * (master_sound_volume / 100.f), loop);
152 }
153 
setListenerPosition(sf::Vector2f position,float angle)154 void SoundManager::setListenerPosition(sf::Vector2f position, float angle)
155 {
156     sf::Vector2f listen_vector = sf::vector2FromAngle(angle);
157     sf::Listener::setPosition(position.x, 0, position.y);
158     sf::Listener::setDirection(listen_vector.x, 0, listen_vector.y);
159     positional_sound_enabled = true;
160 }
161 
disablePositionalSound()162 void SoundManager::disablePositionalSound()
163 {
164     positional_sound_enabled = false;
165 }
166 
playSound(string name,sf::Vector2f position,float min_distance,float attenuation,float pitch,float volume,bool loop)167 int SoundManager::playSound(string name, sf::Vector2f position, float min_distance, float attenuation, float pitch, float volume, bool loop)
168 {
169     if (!positional_sound_enabled)
170         return -1;
171     sf::SoundBuffer* data = soundMap[name];
172     if (data == NULL)
173         data = loadSound(name);
174     if (data->getChannelCount() > 1)
175         LOG(WARNING) << name << ": Used as positional sound but has more than 1 channel.";
176 
177     for(unsigned int n = 0; n < activeSoundList.size(); n++)
178     {
179         sf::Sound& sound = activeSoundList[n];
180         if (sound.getStatus() == sf::Sound::Stopped)
181         {
182             sound.setBuffer(*data);
183             sound.setRelativeToListener(false);
184             sound.setMinDistance(min_distance);
185             sound.setAttenuation(attenuation);
186             sound.setPosition(position.x, 0, position.y);
187             sound.setPitch(pitch);
188             sound.setVolume(volume * (master_sound_volume / 100.f));
189             sound.setLoop(loop);
190             sound.play();
191             return int(n);
192         }
193     }
194 
195     // No room in activeSoundList; return -1.
196     return -1;
197 }
198 
setTextToSpeachVoice(string name)199 void SoundManager::setTextToSpeachVoice(string name)
200 {
201 }
202 
url_encode(const string & value)203 string url_encode(const string &value) {
204     std::ostringstream escaped;
205     escaped.fill('0');
206     escaped << std::hex;
207 
208     for (string::const_iterator i = value.begin(), n = value.end(); i != n; ++i) {
209         string::value_type c = (*i);
210         if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') {
211             escaped << c;
212         }
213         else if (c == ' ') {
214             escaped << '+';
215         }
216         else {
217             escaped << '%' << std::setw(2) << ((int) c) << std::setw(0);
218         }
219     }
220 
221     return escaped.str();
222 }
223 
playTextToSpeech(string text)224 void SoundManager::playTextToSpeech(string text)
225 {
226     string name = "TTS:" + text;
227     sf::SoundBuffer* data = soundMap[name];
228     if (data != NULL)
229     {
230         playSoundData(data, 1.0, 100.0, false);
231         return;
232     }
233 
234     sf::Http http("localhost", 59125);
235     sf::Http::Request request("process?INPUT_TEXT=" + url_encode(text) + "&INPUT_TYPE=TEXT&OUTPUT_TYPE=AUDIO&AUDIO=WAVE_FILE&LOCALE=en_US&VOICE=dfki-prudence");
236     sf::Http::Response response = http.sendRequest(request);
237 
238     sf::Http::Response::Status status = response.getStatus();
239     if (status == sf::Http::Response::Ok)
240     {
241         string wave = response.getBody();
242         sf::SoundBuffer* soundbuffer = new sf::SoundBuffer();
243         data->loadFromMemory(wave.data(), wave.size());
244         soundMap[name] = soundbuffer;
245         playSoundData(soundbuffer, 1.f, 100.f, false);
246     }
247     else
248     {
249         std::cout << "Error requesting text to speech from Mary server: " << status << std::endl;
250     }
251 }
252 
playSoundData(sf::SoundBuffer * data,float pitch,float volume,bool loop)253 int SoundManager::playSoundData(sf::SoundBuffer* data, float pitch, float volume, bool loop)
254 {
255     for(unsigned int n = 0; n < activeSoundList.size(); n++)
256     {
257         sf::Sound& sound = activeSoundList[n];
258         if (sound.getStatus() == sf::Sound::Stopped)
259         {
260             sound.setBuffer(*data);
261             sound.setRelativeToListener(true);
262             sound.setMinDistance(1);
263             sound.setAttenuation(0);
264             sound.setPitch(pitch);
265             sound.setVolume(volume);
266             sound.setPosition(0, 0, 0);
267             sound.setLoop(loop);
268             sound.play();
269             return int(n);
270         }
271     }
272 
273     // No room in activeSoundList; return -1.
274     return -1;
275 }
276 
loadSound(string name)277 sf::SoundBuffer* SoundManager::loadSound(string name)
278 {
279     sf::SoundBuffer* data = soundMap[name];
280     if (data)
281         return data;
282 
283     data = new sf::SoundBuffer();
284 
285     P<ResourceStream> stream = getResourceStream(name);
286     if (!stream) stream = getResourceStream(name + ".wav");
287     if (!stream || !data->loadFromStream(**stream))
288     {
289         LOG(WARNING) << "Failed to load sound: " << name;
290         soundMap[name] = data;
291         return data;
292     }
293 
294     LOG(INFO) << "Loaded: " << name << " of " << data->getDuration().asSeconds() << " seconds";
295     soundMap[name] = data;
296     return data;
297 }
298 
startMusic(P<ResourceStream> stream,bool loop)299 void SoundManager::startMusic(P<ResourceStream> stream, bool loop)
300 {
301     if (!stream)
302         return;
303 
304     if (music_channel.music.getStatus() == sf::Music::Playing)
305     {
306         music_channel.next_stream = stream;
307         music_channel.mode = FadeOut;
308         music_channel.fade_delay = fade_music_time;
309     }else{
310         music_channel.mode = FadeIn;
311         music_channel.fade_delay = fade_music_time;
312 
313         music_channel.music.openFromStream(**stream);
314         music_channel.stream = stream;
315         music_channel.music.setLoop(loop);
316         music_channel.music.setVolume(0);
317         music_channel.music.play();
318     }
319 }
320 
updateTick()321 void SoundManager::updateTick()
322 {
323     float delta = clock.restart().asSeconds();
324     updateChannel(music_channel, delta);
325 
326     if (music_set.size() > 0)
327     {
328         if (music_channel.music.getStatus() == sf::Music::Playing && music_channel.mode == None)
329         {
330             if (!music_channel.next_stream)
331             {
332                 if (music_channel.music.getPlayingOffset() > music_channel.music.getDuration() - sf::seconds(fade_music_time))
333                 {
334                     startMusic(getResourceStream(music_set[irandom(0, static_cast<int>(music_set.size()) - 1)]), false);
335                 }
336             }
337         }
338     }
339 }
340 
updateChannel(MusicChannel & channel,float delta)341 void SoundManager::updateChannel(MusicChannel& channel, float delta)
342 {
343     switch(channel.mode)
344     {
345     case None:
346         break;
347     case FadeIn:
348         channel.fade_delay -= delta;
349         if (channel.fade_delay > 0.f)
350         {
351             channel.music.setVolume(music_volume * (1.f - (channel.fade_delay / fade_music_time)));
352         }else{
353             channel.music.setVolume(music_volume);
354             channel.mode = None;
355         }
356         break;
357     case FadeOut:
358         channel.fade_delay -= delta;
359         if (channel.fade_delay > 0.f)
360         {
361             channel.music.setVolume(music_volume * (channel.fade_delay / fade_music_time));
362         }else{
363             channel.music.stop();
364             channel.mode = None;
365             if (channel.next_stream)
366             {
367                 channel.music.openFromStream(**channel.next_stream);
368                 channel.stream = channel.next_stream;
369                 channel.next_stream = nullptr;
370                 channel.mode = FadeIn;
371                 channel.fade_delay = fade_music_time;
372                 channel.music.setVolume(0);
373                 channel.music.play();
374             }
375         }
376         break;
377     }
378 }
379