1 #include "sound_manager.h"
8 #include "sound_file.h"
9 #include "sound_source.h"
10 #include "stream_sound_source.h"
12 SoundManager::SoundManager()
13 : device(0), context(0), sound_enabled(false), music_source(0)
16 device = alcOpenDevice(0);
18 print_openal_version();
19 throw std::runtime_error("Couldn't open audio device.");
22 int attributes[] = { 0 };
23 context = alcCreateContext(device, attributes);
24 check_alc_error("Couldn't create audio context: ");
25 alcMakeContextCurrent(context);
26 check_alc_error("Couldn't select audio context: ");
28 check_al_error("Audio error after init: ");
30 } catch(std::exception& e) {
33 std::cerr << "Couldn't initialize audio device:" << e.what() << "\n";
34 print_openal_version();
38 SoundManager::~SoundManager()
42 for(SoundSources::iterator i = sources.begin(); i != sources.end(); ++i) {
46 for(SoundBuffers::iterator i = buffers.begin(); i != buffers.end(); ++i) {
47 ALuint buffer = i->second;
48 alDeleteBuffers(1, &buffer);
52 alcMakeContextCurrent(0);
53 alcDestroyContext(context);
56 alcCloseDevice(device);
61 SoundManager::load_file_into_buffer(const std::string& filename)
64 std::auto_ptr<SoundFile> file (load_sound_file(filename));
66 ALenum format = get_sample_format(file.get());
68 alGenBuffers(1, &buffer);
69 check_al_error("Couldn't create audio buffer: ");
70 char* samples = new char[file->size];
72 file->read(samples, file->size);
73 alBufferData(buffer, format, samples,
74 static_cast<ALsizei> (file->size),
75 static_cast<ALsizei> (file->rate));
76 check_al_error("Couldn't fill audio buffer: ");
87 SoundManager::create_sound_source(const std::string& filename)
94 // reuse an existing static sound buffer
95 SoundBuffers::iterator i = buffers.find(filename);
96 if(i != buffers.end()) {
99 buffer = load_file_into_buffer(filename);
100 buffers.insert(std::make_pair(filename, buffer));
103 SoundSource* source = new SoundSource();
104 alSourcei(source->source, AL_BUFFER, buffer);
109 SoundManager::play(const std::string& filename, const Vector& pos)
112 SoundSource* source = create_sound_source(filename);
115 if(pos == Vector(-1, -1)) {
116 alSourcef(source->source, AL_ROLLOFF_FACTOR, 0);
118 source->set_position(pos);
121 sources.push_back(source);
122 } catch(std::exception& e) {
123 std::cout << "Couldn't play sound " << filename << ": " << e.what() << "\n";
128 SoundManager::enable_sound(bool enable)
132 sound_enabled = enable;
136 SoundManager::enable_music(bool enable)
140 music_enabled = enable;
142 play_music(current_music);
152 SoundManager::play_music(const std::string& filename)
154 if(filename == current_music)
156 current_music = filename;
161 StreamSoundSource* newmusic
162 = new StreamSoundSource(load_sound_file(filename));
164 alSourcef(newmusic->source, AL_ROLLOFF_FACTOR, 0);
168 music_source = newmusic;
169 } catch(std::exception& e) {
170 std::cerr << "Couldn't play music file '" << filename << "': "
176 SoundManager::set_listener_position(Vector pos)
178 alListener3f(AL_POSITION, pos.x, pos.y, 0);
182 SoundManager::set_listener_velocity(Vector vel)
184 alListener3f(AL_VELOCITY, vel.x, vel.y, 0);
188 SoundManager::update()
190 // check for finished sound sources
191 for(SoundSources::iterator i = sources.begin(); i != sources.end(); ) {
192 SoundSource* source = *i;
193 if(!source->playing()) {
195 i = sources.erase(i);
200 // check streaming sounds
202 music_source->update();
204 alcProcessContext(context);
205 check_alc_error("Error while processing audio context: ");
209 SoundManager::get_sample_format(SoundFile* file)
211 if(file->channels == 2) {
212 if(file->bits_per_sample == 16) {
213 return AL_FORMAT_STEREO16;
214 } else if(file->bits_per_sample == 8) {
215 return AL_FORMAT_STEREO8;
217 throw std::runtime_error("Only 16 and 8 bit samples supported");
219 } else if(file->channels == 1) {
220 if(file->bits_per_sample == 16) {
221 return AL_FORMAT_MONO16;
222 } else if(file->bits_per_sample == 8) {
223 return AL_FORMAT_MONO8;
225 throw std::runtime_error("Only 16 and 8 bit samples supported");
229 throw std::runtime_error("Only 1 and 2 channel samples supported");
233 SoundManager::print_openal_version()
235 std::cout << "OpenAL Vendor: " << alGetString(AL_VENDOR) << "\n"
236 << "OpenAL Version: " << alGetString(AL_VERSION) << "\n"
237 << "OpenAL Renderer: " << alGetString(AL_RENDERER) << "\n"
238 << "OpenAl Extensions: " << alGetString(AL_RENDERER) << "\n";
242 SoundManager::check_alc_error(const char* message)
244 int err = alcGetError(device);
245 if(err != ALC_NO_ERROR) {
246 std::stringstream msg;
247 msg << message << alcGetString(device, err);
248 throw std::runtime_error(msg.str());
253 SoundManager::check_al_error(const char* message)
255 int err = alGetError();
256 if(err != AL_NO_ERROR) {
257 std::stringstream msg;
258 msg << message << alGetString(err);
259 throw std::runtime_error(msg.str());