-// $Id$
-//
// SuperTux
// Copyright (C) 2006 Matthias Braun <matze@braunis.de>
//
-// 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
// 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.
-#include <config.h>
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
-#include "sound_manager.hpp"
+#include "audio/sound_manager.hpp"
+#include <SDL.h>
+#include <assert.h>
#include <stdexcept>
-#include <iostream>
#include <sstream>
#include <memory>
-#include <assert.h>
-#include <SDL.h>
-#include "sound_file.hpp"
-#include "sound_source.hpp"
-#include "openal_sound_source.hpp"
-#include "stream_sound_source.hpp"
-#include "dummy_sound_source.hpp"
-#include "log.hpp"
-#include "timer.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(false)
+#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);
sound_enabled = true;
music_enabled = true;
} catch(std::exception& e) {
- if(context != NULL)
+ if(context != NULL) {
alcDestroyContext(context);
- context = NULL;
- if(device != NULL)
+ context = NULL;
+ }
+ if(device != NULL) {
alcCloseDevice(device);
- device = NULL;
+ device = NULL;
+ }
log_warning << "Couldn't initialize audio device: " << e.what() << std::endl;
print_openal_version();
}
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;
if(context != NULL) {
alcDestroyContext(context);
+ context = NULL;
}
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<ALsizei> (file->size),
- static_cast<ALsizei> (file->rate));
- check_al_error("Couldn't fill audio buffer: ");
- } catch(...) {
- delete[] samples;
- throw;
- }
- delete[] samples;
+ std::unique_ptr<char[]> samples(new char[file.size]);
+ file.read(samples.get(), file.size);
+ alBufferData(buffer, format, samples.get(),
+ static_cast<ALsizei>(file.size),
+ static_cast<ALsizei>(file.rate));
+ check_al_error("Couldn't fill audio buffer: ");
return buffer;
}
-OpenALSoundSource*
+std::unique_ptr<OpenALSoundSource>
SoundManager::intern_create_sound_source(const std::string& filename)
{
- if(!sound_enabled)
- throw std::runtime_error("sound disabled");
+ assert(sound_enabled);
- std::auto_ptr<OpenALSoundSource> source (new OpenALSoundSource());
+ std::unique_ptr<OpenALSoundSource> source(new OpenALSoundSource);
ALuint buffer;
buffer = i->second;
} else {
// Load sound file
- std::auto_ptr<SoundFile> file (load_sound_file(filename));
-
+ std::unique_ptr<SoundFile> 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<StreamSoundSource> 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;
}
alSourcei(source->source, AL_BUFFER, buffer);
- return source.release();
+ return std::move(source);
}
-SoundSource*
+std::unique_ptr<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) {
// already loaded?
if(i != buffers.end())
return;
+ try {
+ std::unique_ptr<SoundFile> file (load_sound_file(filename));
+ // only keep small files
+ if(file->size >= 100000)
+ return;
- std::auto_ptr<SoundFile> 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));
+ 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
return;
try {
- std::auto_ptr<OpenALSoundSource> source
- (intern_create_sound_source(filename));
+ std::unique_ptr<OpenALSoundSource> source(intern_create_sound_source(filename));
- if(pos == Vector(-1, -1)) {
- source->set_rollof_factor(0);
+ if(pos.x < 0 || pos.y < 0) {
+ source->set_relative(true);
} else {
source->set_position(pos);
}
source->play();
- sources.push_back(source.release());
+ sources.push_back(std::move(source));
} catch(std::exception& e) {
log_warning << "Couldn't play sound " << filename << ": " << e.what() << std::endl;
}
}
void
-SoundManager::manage_source(SoundSource* source)
+SoundManager::manage_source(std::unique_ptr<SoundSource> source)
{
- assert(source != NULL);
-
- OpenALSoundSource* openal_source = dynamic_cast<OpenALSoundSource*> (source);
- if(openal_source != NULL) {
- sources.push_back(openal_source);
+ assert(source);
+ if (dynamic_cast<OpenALSoundSource*>(source.get()))
+ {
+ std::unique_ptr<OpenALSoundSource> openal_source(dynamic_cast<OpenALSoundSource*>(source.release()));
+ sources.push_back(std::move(openal_source));
}
}
void
-SoundManager::register_for_update( StreamSoundSource* sss ){
- if( sss != NULL ){
- update_list.push_back( sss );
+SoundManager::register_for_update(StreamSoundSource* sss)
+{
+ if (sss)
+ {
+ update_list.push_back(sss);
}
}
void
-SoundManager::remove_from_update( StreamSoundSource* sss ){
- if( sss != NULL ){
+SoundManager::remove_from_update(StreamSoundSource* sss)
+{
+ if (sss)
+ {
StreamSoundSources::iterator i = update_list.begin();
- while( i != update_list.end() ){
+ while( i != update_list.end() ){
if( *i == sss ){
i = update_list.erase(i);
} else {
- i++;
+ ++i;
}
}
}
play_music(current_music);
} else {
if(music_source) {
- delete music_source;
- music_source = 0;
+ music_source.reset();
}
}
}
{
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 = NULL;
+ music_source.reset();
}
current_music = "";
}
return;
if(filename == "") {
- delete music_source;
- music_source = NULL;
+ music_source.reset();
return;
}
try {
- std::auto_ptr<StreamSoundSource> newmusic (new StreamSoundSource());
- alSourcef(newmusic->source, AL_ROLLOFF_FACTOR, 0);
+ std::unique_ptr<StreamSoundSource> 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) {
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(music_source == NULL)
+ return;
+
+ 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(music_source == NULL)
+ return;
+
+ if(fadetime > 0) {
+ if(music_source
+ && music_source->get_fade_state() != StreamSoundSource::FadingResume)
+ music_source->set_fading(StreamSoundSource::FadingResume, fadetime);
+ } else {
+ music_source->resume();
}
}
// update and check for finished sound sources
for(SoundSources::iterator i = sources.begin(); i != sources.end(); ) {
- OpenALSoundSource* source = *i;
+ auto& source = *i;
source->update();
if(!source->playing()) {
- delete source;
i = sources.erase(i);
} else {
++i;
StreamSoundSources::iterator s = update_list.begin();
while( s != update_list.end() ){
(*s)->update();
- s++;
+ ++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(msg.str());
}
}
+
+/* EOF */