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