X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Faudio%2Fsound_manager.cpp;h=a5a47ae0398f775f5bba48b192a470fe0d380ac2;hb=25da12d34b356745dcf3669f234e17ee5bfa6b80;hp=5b65fe4b5f8437a66fc3904847243d65fafb412b;hpb=db7dbb66619413e3469e75e6db0aad75e5c3301d;p=supertux.git diff --git a/src/audio/sound_manager.cpp b/src/audio/sound_manager.cpp index 5b65fe4b5..a5a47ae03 100644 --- a/src/audio/sound_manager.cpp +++ b/src/audio/sound_manager.cpp @@ -1,12 +1,10 @@ -// $Id$ -// // 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 2 -// of the License, or (at your option) any later version. +// 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 @@ -14,31 +12,47 @@ // 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, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// along with this program. If not, see . -#include "sound_manager.hpp" +#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 "log.hpp" -#include "timer.hpp" +#include "audio/dummy_sound_source.hpp" +#include "audio/sound_file.hpp" +#include "audio/stream_sound_source.hpp" +#include "util/log.hpp" + +#ifndef DEBUG +/** Older openal versions often miss this function and it isn't that vital for + * supertux... + */ +#ifdef alcGetString +#undef alcGetString +#endif +#define alcGetString(x,y) "" +#endif SoundManager* sound_manager = 0; -SoundManager::SoundManager() - : device(0), context(0), sound_enabled(false), music_source(0), - music_enabled(true) +SoundManager::SoundManager() : + device(0), + context(0), + sound_enabled(false), + buffers(), + sources(), + update_list(), + music_source(0), + music_enabled(false), + current_music() { try { device = alcOpenDevice(0); - if (device == 0) { + if (device == NULL) { throw std::runtime_error("Couldn't open audio device."); } @@ -50,9 +64,14 @@ SoundManager::SoundManager() check_al_error("Audio error after init: "); sound_enabled = true; + music_enabled = true; } catch(std::exception& e) { - device = 0; - context = 0; + 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(); } @@ -71,10 +90,10 @@ SoundManager::~SoundManager() alDeleteBuffers(1, &buffer); } - if(context != 0) { + if(context != NULL) { alcDestroyContext(context); } - if(device != 0) { + if(device != NULL) { alcCloseDevice(device); } } @@ -90,8 +109,8 @@ SoundManager::load_file_into_buffer(SoundFile* file) try { file->read(samples, file->size); alBufferData(buffer, format, samples, - static_cast (file->size), - static_cast (file->rate)); + static_cast (file->size), + static_cast (file->rate)); check_al_error("Couldn't fill audio buffer: "); } catch(...) { delete[] samples; @@ -102,15 +121,17 @@ SoundManager::load_file_into_buffer(SoundFile* file) return buffer; } -SoundSource* -SoundManager::create_sound_source(const std::string& filename) +OpenALSoundSource* +SoundManager::intern_create_sound_source(const std::string& filename) { if(!sound_enabled) - return 0; + throw std::runtime_error("sound disabled"); + + std::auto_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; @@ -126,45 +147,120 @@ SoundManager::create_sound_source(const std::string& filename) source->set_sound_file(file.release()); return 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 source.release(); +} + +SoundSource* +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::auto_ptr file (load_sound_file(filename)); + // only keep small files + if(file->size >= 100000) return; + + ALuint buffer = load_file_into_buffer(file.get()); + 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::auto_ptr source + (intern_create_sound_source(filename)); + if(pos == Vector(-1, -1)) { - alSourcef(source->source, AL_ROLLOFF_FACTOR, 0); + source->set_rollof_factor(0); } else { source->set_position(pos); } source->play(); - sources.push_back(source); + sources.push_back(source.release()); } catch(std::exception& e) { log_warning << "Couldn't play sound " << filename << ": " << e.what() << std::endl; } } void +SoundManager::manage_source(SoundSource* source) +{ + assert(source != NULL); + + OpenALSoundSource* openal_source = dynamic_cast (source); + if(openal_source != NULL) { + sources.push_back(openal_source); + } +} + +void +SoundManager::register_for_update( StreamSoundSource* sss ){ + if( sss != NULL ){ + update_list.push_back( sss ); + } +} + +void +SoundManager::remove_from_update( StreamSoundSource* sss ){ + if( sss != NULL ){ + 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); @@ -181,11 +277,11 @@ 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 = NULL; } current_music = ""; } @@ -201,7 +297,7 @@ SoundManager::play_music(const std::string& filename, bool fade) if(filename == "") { delete music_source; - music_source = 0; + music_source = NULL; return; } @@ -224,12 +320,12 @@ SoundManager::play_music(const std::string& filename, bool fade) 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); } @@ -243,18 +339,19 @@ SoundManager::set_listener_velocity(const Vector& vel) void SoundManager::update() { - static float lasttime = real_time; + static Uint32 lasttime = SDL_GetTicks(); + Uint32 now = SDL_GetTicks(); - if(real_time - lasttime < 0.3) + if(now - lasttime < 300) return; - lasttime = real_time; + lasttime = now; // update and check for finished sound sources for(SoundSources::iterator i = sources.begin(); i != sources.end(); ) { - SoundSource* source = *i; + OpenALSoundSource* source = *i; source->update(); - + if(!source->playing()) { delete source; i = sources.erase(i); @@ -272,6 +369,13 @@ SoundManager::update() 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 @@ -294,7 +398,7 @@ SoundManager::get_sample_format(SoundFile* file) throw std::runtime_error("Only 16 and 8 bit samples supported"); } } - + throw std::runtime_error("Only 1 and 2 channel samples supported"); } @@ -315,7 +419,7 @@ SoundManager::check_alc_error(const char* message) std::stringstream msg; msg << message << alcGetString(device, err); throw std::runtime_error(msg.str()); - } + } } void @@ -326,6 +430,7 @@ SoundManager::check_al_error(const char* message) std::stringstream msg; msg << message << alGetString(err); throw std::runtime_error(msg.str()); - } + } } +/* EOF */