X-Git-Url: https://git.octo.it/?p=supertux.git;a=blobdiff_plain;f=src%2Faudio%2Fsound_manager.cpp;h=ace96c1290d18acc3e92e28fe4a261edac86d38a;hp=dc26cd83126000521fa0486e6f8efd2f22cf6fab;hb=8e52a5b000d732e96b1cc461163c4778b434dc27;hpb=2ef3ada0e542f6e08a96fb1071c92bc24f19dea6 diff --git a/src/audio/sound_manager.cpp b/src/audio/sound_manager.cpp index dc26cd831..ace96c129 100644 --- a/src/audio/sound_manager.cpp +++ b/src/audio/sound_manager.cpp @@ -1,25 +1,46 @@ -#include "sound_manager.hpp" - +// SuperTux +// Copyright (C) 2006 Matthias Braun +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "audio/sound_manager.hpp" + +#include +#include #include -#include #include #include -#include "sound_file.hpp" -#include "sound_source.hpp" -#include "stream_sound_source.hpp" -#include "msg.hpp" - -SoundManager* sound_manager = 0; - -SoundManager::SoundManager() - : device(0), context(0), sound_enabled(false), music_source(0), - music_enabled(true) +#include "audio/dummy_sound_source.hpp" +#include "audio/sound_file.hpp" +#include "audio/stream_sound_source.hpp" +#include "util/log.hpp" + +SoundManager::SoundManager() : + device(0), + context(0), + sound_enabled(false), + buffers(), + sources(), + update_list(), + music_source(), + music_enabled(false), + current_music() { try { device = alcOpenDevice(0); - if(device == 0) { - print_openal_version(); + if (device == NULL) { throw std::runtime_error("Couldn't open audio device."); } @@ -31,129 +52,206 @@ SoundManager::SoundManager() check_al_error("Audio error after init: "); sound_enabled = true; + music_enabled = true; } catch(std::exception& e) { - device = 0; - context = 0; - msg_warning("Couldn't initialize audio device:" << e.what()); + if(context != NULL) { + alcDestroyContext(context); + context = NULL; + } + if(device != NULL) { + alcCloseDevice(device); + device = NULL; + } + log_warning << "Couldn't initialize audio device: " << e.what() << std::endl; print_openal_version(); - throw e; } } SoundManager::~SoundManager() { - delete music_source; - - for(SoundSources::iterator i = sources.begin(); i != sources.end(); ++i) { - delete *i; - } + music_source.reset(); + sources.clear(); for(SoundBuffers::iterator i = buffers.begin(); i != buffers.end(); ++i) { ALuint buffer = i->second; alDeleteBuffers(1, &buffer); } - if(context != 0) { + if(context != NULL) { alcDestroyContext(context); + context = NULL; } - if(device != 0) { + if(device != NULL) { alcCloseDevice(device); + device = NULL; } } ALuint -SoundManager::load_file_into_buffer(SoundFile* file) +SoundManager::load_file_into_buffer(SoundFile& file) { ALenum format = get_sample_format(file); ALuint buffer; alGenBuffers(1, &buffer); check_al_error("Couldn't create audio buffer: "); - char* samples = new char[file->size]; - try { - file->read(samples, file->size); - alBufferData(buffer, format, samples, - static_cast (file->size), - static_cast (file->rate)); - check_al_error("Couldn't fill audio buffer: "); - } catch(...) { - delete[] samples; - throw; - } - delete[] samples; + std::unique_ptr samples(new char[file.size]); + file.read(samples.get(), file.size); + alBufferData(buffer, format, samples.get(), + static_cast(file.size), + static_cast(file.rate)); + check_al_error("Couldn't fill audio buffer: "); return buffer; } -SoundSource* -SoundManager::create_sound_source(const std::string& filename) +std::unique_ptr +SoundManager::intern_create_sound_source(const std::string& filename) { - if(!sound_enabled) - return 0; + assert(sound_enabled); + + std::unique_ptr source(new OpenALSoundSource); ALuint buffer; - - // reuse an existing static sound buffer + + // reuse an existing static sound buffer SoundBuffers::iterator i = buffers.find(filename); if(i != buffers.end()) { buffer = i->second; } else { // Load sound file - std::auto_ptr file (load_sound_file(filename)); + std::unique_ptr file(load_sound_file(filename)); if(file->size < 100000) { - buffer = load_file_into_buffer(file.get()); + buffer = load_file_into_buffer(*file); buffers.insert(std::make_pair(filename, buffer)); } else { - StreamSoundSource* source = new StreamSoundSource(); - source->set_sound_file(file.release()); - return source; + std::unique_ptr source_(new StreamSoundSource); + source_->set_sound_file(std::move(file)); + return std::move(source_); } + + log_debug << "Uncached sound \"" << filename << "\" requested to be played" << std::endl; } - - SoundSource* source = new SoundSource(); + alSourcei(source->source, AL_BUFFER, buffer); - return source; + return std::move(source); +} + +std::unique_ptr +SoundManager::create_sound_source(const std::string& filename) +{ + if(!sound_enabled) + return create_dummy_sound_source(); + + try { + return intern_create_sound_source(filename); + } catch(std::exception &e) { + log_warning << "Couldn't create audio source: " << e.what() << std::endl; + return create_dummy_sound_source(); + } } void -SoundManager::play(const std::string& filename, const Vector& pos) +SoundManager::preload(const std::string& filename) { + if(!sound_enabled) + return; + + SoundBuffers::iterator i = buffers.find(filename); + // already loaded? + if(i != buffers.end()) + return; try { - SoundSource* source = create_sound_source(filename); - if(source == 0) + std::unique_ptr file (load_sound_file(filename)); + // only keep small files + if(file->size >= 100000) return; - if(pos == Vector(-1, -1)) { - alSourcef(source->source, AL_ROLLOFF_FACTOR, 0); + + ALuint buffer = load_file_into_buffer(*file); + buffers.insert(std::make_pair(filename, buffer)); + } catch(std::exception& e) { + log_warning << "Error while preloading sound file: " << e.what() << std::endl; + } +} + +void +SoundManager::play(const std::string& filename, const Vector& pos) +{ + if(!sound_enabled) + return; + + try { + std::unique_ptr source(intern_create_sound_source(filename)); + + if(pos.x < 0 || pos.y < 0) { + source->set_relative(true); } else { source->set_position(pos); } source->play(); - sources.push_back(source); + sources.push_back(std::move(source)); } catch(std::exception& e) { - msg_warning("Couldn't play sound " << filename << ": " << e.what()); + log_warning << "Couldn't play sound " << filename << ": " << e.what() << std::endl; + } +} + +void +SoundManager::manage_source(std::unique_ptr source) +{ + assert(source); + if (dynamic_cast(source.get())) + { + std::unique_ptr openal_source(dynamic_cast(source.release())); + sources.push_back(std::move(openal_source)); + } +} + +void +SoundManager::register_for_update(StreamSoundSource* sss) +{ + if (sss) + { + update_list.push_back(sss); + } +} + +void +SoundManager::remove_from_update(StreamSoundSource* sss) +{ + if (sss) + { + StreamSoundSources::iterator i = update_list.begin(); + while( i != update_list.end() ){ + if( *i == sss ){ + i = update_list.erase(i); + } else { + ++i; + } + } } } void SoundManager::enable_sound(bool enable) { - if(device == 0) + if(device == NULL) return; + sound_enabled = enable; } void SoundManager::enable_music(bool enable) { - if(device == 0) + if(device == NULL) return; + music_enabled = enable; if(music_enabled) { play_music(current_music); } else { if(music_source) { - delete music_source; - music_source = 0; + music_source.reset(); } } } @@ -163,11 +261,10 @@ SoundManager::stop_music(float fadetime) { if(fadetime > 0) { if(music_source - && music_source->get_fade_state() != StreamSoundSource::FadingOff) + && music_source->get_fade_state() != StreamSoundSource::FadingOff) music_source->set_fading(StreamSoundSource::FadingOff, fadetime); } else { - delete music_source; - music_source = 0; + music_source.reset(); } current_music = ""; } @@ -182,37 +279,60 @@ SoundManager::play_music(const std::string& filename, bool fade) return; if(filename == "") { - delete music_source; - music_source = 0; + music_source.reset(); return; } try { - std::auto_ptr newmusic (new StreamSoundSource()); - alSourcef(newmusic->source, AL_ROLLOFF_FACTOR, 0); + std::unique_ptr newmusic (new StreamSoundSource()); newmusic->set_sound_file(load_sound_file(filename)); newmusic->set_looping(true); + newmusic->set_relative(true); if(fade) newmusic->set_fading(StreamSoundSource::FadingOn, .5f); newmusic->play(); - delete music_source; - music_source = newmusic.release(); + music_source = std::move(newmusic); } catch(std::exception& e) { - msg_warning("Couldn't play music file '" << filename << "': " - << e.what()); + log_warning << "Couldn't play music file '" << filename << "': " << e.what() << std::endl; + // When this happens, previous music continued playing, stop it, just in case. + stop_music(0); + } +} + +void +SoundManager::pause_music(float fadetime) +{ + if(fadetime > 0) { + if(music_source + && music_source->get_fade_state() != StreamSoundSource::FadingPause) + music_source->set_fading(StreamSoundSource::FadingPause, fadetime); + } else { + music_source->pause(); + } +} + +void +SoundManager::resume_music(float fadetime) +{ + if(fadetime > 0) { + if(music_source + && music_source->get_fade_state() != StreamSoundSource::FadingResume) + music_source->set_fading(StreamSoundSource::FadingResume, fadetime); + } else { + music_source->resume(); } } void SoundManager::set_listener_position(const Vector& pos) { - static Uint32 lastticks = 0; + static Uint32 lastticks = SDL_GetTicks(); Uint32 current_ticks = SDL_GetTicks(); if(current_ticks - lastticks < 300) return; - lastticks = current_ticks; + lastticks = current_ticks; alListener3f(AL_POSITION, pos.x, pos.y, 0); } @@ -226,21 +346,20 @@ SoundManager::set_listener_velocity(const Vector& vel) void SoundManager::update() { - static Uint32 lastticks = 0; + static Uint32 lasttime = SDL_GetTicks(); + Uint32 now = SDL_GetTicks(); - Uint32 current_ticks = SDL_GetTicks(); - if(current_ticks - lastticks < 300) + if(now - lasttime < 300) return; - lastticks = current_ticks; + lasttime = now; // update and check for finished sound sources for(SoundSources::iterator i = sources.begin(); i != sources.end(); ) { - SoundSource* source = *i; + auto& source = *i; source->update(); - + if(!source->playing()) { - delete source; i = sources.erase(i); } else { ++i; @@ -250,42 +369,52 @@ SoundManager::update() if(music_source) { music_source->update(); } - - alcProcessContext(context); - check_alc_error("Error while processing audio context: "); + + if (context) + { + alcProcessContext(context); + check_alc_error("Error while processing audio context: "); + } + + //run update() for stream_sound_source + StreamSoundSources::iterator s = update_list.begin(); + while( s != update_list.end() ){ + (*s)->update(); + ++s; + } } ALenum -SoundManager::get_sample_format(SoundFile* file) +SoundManager::get_sample_format(const SoundFile& file) { - if(file->channels == 2) { - if(file->bits_per_sample == 16) { + if(file.channels == 2) { + if(file.bits_per_sample == 16) { return AL_FORMAT_STEREO16; - } else if(file->bits_per_sample == 8) { + } else if(file.bits_per_sample == 8) { return AL_FORMAT_STEREO8; } else { throw std::runtime_error("Only 16 and 8 bit samples supported"); } - } else if(file->channels == 1) { - if(file->bits_per_sample == 16) { + } else if(file.channels == 1) { + if(file.bits_per_sample == 16) { return AL_FORMAT_MONO16; - } else if(file->bits_per_sample == 8) { + } else if(file.bits_per_sample == 8) { return AL_FORMAT_MONO8; } else { throw std::runtime_error("Only 16 and 8 bit samples supported"); } } - + throw std::runtime_error("Only 1 and 2 channel samples supported"); } void SoundManager::print_openal_version() { - msg_info("OpenAL Vendor: " << alGetString(AL_VENDOR)); - msg_info("OpenAL Version: " << alGetString(AL_VERSION)); - msg_info("OpenAL Renderer: " << alGetString(AL_RENDERER)); - msg_info("OpenAl Extensions: " << alGetString(AL_EXTENSIONS)); + log_info << "OpenAL Vendor: " << alGetString(AL_VENDOR) << std::endl; + log_info << "OpenAL Version: " << alGetString(AL_VERSION) << std::endl; + log_info << "OpenAL Renderer: " << alGetString(AL_RENDERER) << std::endl; + log_info << "OpenAl Extensions: " << alGetString(AL_EXTENSIONS) << std::endl; } void @@ -296,7 +425,7 @@ SoundManager::check_alc_error(const char* message) std::stringstream msg; msg << message << alcGetString(device, err); throw std::runtime_error(msg.str()); - } + } } void @@ -307,6 +436,7 @@ SoundManager::check_al_error(const char* message) std::stringstream msg; msg << message << alGetString(err); throw std::runtime_error(msg.str()); - } + } } +/* EOF */