1 #include "sound_manager.hpp"
8 #include "sound_file.hpp"
9 #include "sound_source.hpp"
10 #include "stream_sound_source.hpp"
12 SoundManager* sound_manager;
14 SoundManager::SoundManager()
15 : device(0), context(0), sound_enabled(false), music_source(0),
19 device = alcOpenDevice(0);
21 print_openal_version();
22 throw std::runtime_error("Couldn't open audio device.");
25 int attributes[] = { 0 };
26 context = alcCreateContext(device, attributes);
27 check_alc_error("Couldn't create audio context: ");
28 alcMakeContextCurrent(context);
29 check_alc_error("Couldn't select audio context: ");
31 check_al_error("Audio error after init: ");
33 } catch(std::exception& e) {
36 std::cerr << "Couldn't initialize audio device:" << e.what() << "\n";
37 print_openal_version();
41 SoundManager::~SoundManager()
44 delete next_music_source;
46 for(SoundSources::iterator i = sources.begin(); i != sources.end(); ++i) {
50 for(SoundBuffers::iterator i = buffers.begin(); i != buffers.end(); ++i) {
51 ALuint buffer = i->second;
52 alDeleteBuffers(1, &buffer);
56 alcDestroyContext(context);
59 alcCloseDevice(device);
64 SoundManager::load_file_into_buffer(const std::string& filename)
67 std::auto_ptr<SoundFile> file (load_sound_file(filename));
69 ALenum format = get_sample_format(file.get());
71 alGenBuffers(1, &buffer);
72 check_al_error("Couldn't create audio buffer: ");
73 char* samples = new char[file->size];
75 file->read(samples, file->size);
76 alBufferData(buffer, format, samples,
77 static_cast<ALsizei> (file->size),
78 static_cast<ALsizei> (file->rate));
79 check_al_error("Couldn't fill audio buffer: ");
90 SoundManager::create_sound_source(const std::string& filename)
97 // reuse an existing static sound buffer
98 SoundBuffers::iterator i = buffers.find(filename);
99 if(i != buffers.end()) {
102 buffer = load_file_into_buffer(filename);
103 buffers.insert(std::make_pair(filename, buffer));
106 SoundSource* source = new SoundSource();
107 alSourcei(source->source, AL_BUFFER, buffer);
112 SoundManager::play(const std::string& filename, const Vector& pos)
115 SoundSource* source = create_sound_source(filename);
118 if(pos == Vector(-1, -1)) {
119 alSourcef(source->source, AL_ROLLOFF_FACTOR, 0);
121 source->set_position(pos);
124 sources.push_back(source);
125 } catch(std::exception& e) {
126 std::cout << "Couldn't play sound " << filename << ": " << e.what() << "\n";
131 SoundManager::enable_sound(bool enable)
135 sound_enabled = enable;
139 SoundManager::enable_music(bool enable)
143 music_enabled = enable;
145 play_music(current_music);
155 SoundManager::play_music(const std::string& filename, bool fade)
157 if(filename == current_music)
159 current_music = filename;
164 StreamSoundSource* newmusic
165 = new StreamSoundSource(load_sound_file(filename));
167 alSourcef(newmusic->source, AL_ROLLOFF_FACTOR, 0);
171 music_source->setFading(StreamSoundSource::FadingOff, .25f);
172 delete next_music_source;
173 next_music_source = newmusic;
176 music_source = newmusic;
177 music_source->play();
178 next_music_source = 0;
180 } catch(std::exception& e) {
181 std::cerr << "Couldn't play music file '" << filename << "': "
187 SoundManager::set_listener_position(Vector pos)
189 alListener3f(AL_POSITION, pos.x, pos.y, 0);
193 SoundManager::set_listener_velocity(Vector vel)
195 alListener3f(AL_VELOCITY, vel.x, vel.y, 0);
199 SoundManager::update()
201 // check for finished sound sources
202 for(SoundSources::iterator i = sources.begin(); i != sources.end(); ) {
203 SoundSource* source = *i;
204 if(!source->playing()) {
206 i = sources.erase(i);
211 // check streaming sounds
213 music_source->update();
216 if(next_music_source && !music_source || !music_source->playing()) {
218 music_source = next_music_source;
219 //music_source->setFading(StreamSoundSource::FadingOn, 1.0f);
220 music_source->play();
221 next_music_source = 0;
224 alcProcessContext(context);
225 check_alc_error("Error while processing audio context: ");
229 SoundManager::get_sample_format(SoundFile* file)
231 if(file->channels == 2) {
232 if(file->bits_per_sample == 16) {
233 return AL_FORMAT_STEREO16;
234 } else if(file->bits_per_sample == 8) {
235 return AL_FORMAT_STEREO8;
237 throw std::runtime_error("Only 16 and 8 bit samples supported");
239 } else if(file->channels == 1) {
240 if(file->bits_per_sample == 16) {
241 return AL_FORMAT_MONO16;
242 } else if(file->bits_per_sample == 8) {
243 return AL_FORMAT_MONO8;
245 throw std::runtime_error("Only 16 and 8 bit samples supported");
249 throw std::runtime_error("Only 1 and 2 channel samples supported");
253 SoundManager::print_openal_version()
255 std::cout << "OpenAL Vendor: " << alGetString(AL_VENDOR) << "\n"
256 << "OpenAL Version: " << alGetString(AL_VERSION) << "\n"
257 << "OpenAL Renderer: " << alGetString(AL_RENDERER) << "\n"
258 << "OpenAl Extensions: " << alGetString(AL_RENDERER) << "\n";
262 SoundManager::check_alc_error(const char* message)
264 int err = alcGetError(device);
265 if(err != ALC_NO_ERROR) {
266 std::stringstream msg;
267 msg << message << alcGetString(device, err);
268 throw std::runtime_error(msg.str());
273 SoundManager::check_al_error(const char* message)
275 int err = alGetError();
276 if(err != AL_NO_ERROR) {
277 std::stringstream msg;
278 msg << message << alGetString(err);
279 throw std::runtime_error(msg.str());