#include "sound_source.hpp"
#include "stream_sound_source.hpp"
-SoundManager* sound_manager;
+SoundManager* sound_manager = 0;
SoundManager::SoundManager()
: device(0), context(0), sound_enabled(false), music_source(0),
- next_music_source(0)
+ music_enabled(true)
{
try {
device = alcOpenDevice(0);
SoundManager::~SoundManager()
{
delete music_source;
- delete next_music_source;
for(SoundSources::iterator i = sources.begin(); i != sources.end(); ++i) {
delete *i;
}
void
+SoundManager::stop_music(bool fade)
+{
+ if(fade) {
+ if(music_source
+ && music_source->get_fade_state() != StreamSoundSource::FadingOff)
+ music_source->set_fading(StreamSoundSource::FadingOff, .5f);
+ } else {
+ delete music_source;
+ music_source = 0;
+ }
+ current_music = "";
+}
+
+void
SoundManager::play_music(const std::string& filename, bool fade)
{
if(filename == current_music)
return;
try {
- StreamSoundSource* newmusic
- = new StreamSoundSource(load_sound_file(filename));
-
+ std::auto_ptr<StreamSoundSource> newmusic (new StreamSoundSource());
alSourcef(newmusic->source, AL_ROLLOFF_FACTOR, 0);
-
- if(fade) {
- if(music_source)
- music_source->setFading(StreamSoundSource::FadingOff, .25f);
- delete next_music_source;
- next_music_source = newmusic;
- } else {
- delete music_source;
- music_source = newmusic;
- music_source->play();
- next_music_source = 0;
- }
+ newmusic->set_sound_file(load_sound_file(filename));
+ if(fade)
+ newmusic->set_fading(StreamSoundSource::FadingOn, .5f);
+ newmusic->play();
+
+ delete music_source;
+ music_source = newmusic.release();
} catch(std::exception& e) {
std::cerr << "Couldn't play music file '" << filename << "': "
<< e.what() << "\n";
}
void
-SoundManager::set_listener_position(Vector pos)
+SoundManager::set_listener_position(const Vector& pos)
{
alListener3f(AL_POSITION, pos.x, pos.y, 0);
}
void
-SoundManager::set_listener_velocity(Vector vel)
+SoundManager::set_listener_velocity(const Vector& vel)
{
alListener3f(AL_VELOCITY, vel.x, vel.y, 0);
}
music_source->update();
}
- if(next_music_source && !music_source || !music_source->playing()) {
- delete music_source;
- music_source = next_music_source;
- //music_source->setFading(StreamSoundSource::FadingOn, 1.0f);
- music_source->play();
- next_music_source = 0;
- }
-
alcProcessContext(context);
check_alc_error("Error while processing audio context: ");
}
#ifndef __SOUND_MANAGER_H__
#define __SOUND_MANAGER_H__
-#include "math/vector.hpp"
#include <string>
#include <vector>
#include <map>
#include <AL/alc.h>
#include <AL/al.h>
+#include "math/vector.hpp"
typedef void* SoundHandle;
*/
void play(const std::string& name, const Vector& pos = Vector(-1, -1));
- void set_listener_position(Vector position);
- void set_listener_velocity(Vector velocity);
+ void set_listener_position(const Vector& position);
+ void set_listener_velocity(const Vector& velocity);
void enable_music(bool music_enabled);
- void play_music(const std::string& filename, bool fade = true);
+ void play_music(const std::string& filename, bool fade = false);
+ void stop_music(bool fade = true);
void update();
SoundSources sources;
StreamSoundSource* music_source;
- StreamSoundSource* next_music_source;
bool music_enabled;
std::string current_music;
#include "sound_manager.hpp"
#include "sound_file.hpp"
-StreamSoundSource::StreamSoundSource(SoundFile* file)
+StreamSoundSource::StreamSoundSource()
+ : file(0), fade_state(NoFading)
{
- this->file = file;
alGenBuffers(STREAMFRAGMENTS, buffers);
SoundManager::check_al_error("Couldn't allocate audio buffers: ");
- format = SoundManager::get_sample_format(file);
- try {
- for(size_t i = 0; i < STREAMFRAGMENTS; ++i) {
- fillBufferAndQueue(buffers[i]);
- }
- } catch(...) {
- alDeleteBuffers(STREAMFRAGMENTS, buffers);
- }
}
StreamSoundSource::~StreamSoundSource()
{
+ delete file;
alDeleteBuffers(STREAMFRAGMENTS, buffers);
SoundManager::check_al_error("Couldn't delete audio buffers: ");
}
void
-StreamSoundSource::update()
+StreamSoundSource::set_sound_file(SoundFile* newfile)
{
- if(!playing())
- return;
+ delete file;
+ file = newfile;
+ ALint queued;
+ alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
+ for(size_t i = 0; i < STREAMFRAGMENTS - queued; ++i) {
+ fillBufferAndQueue(buffers[i]);
+ }
+}
+
+void
+StreamSoundSource::update()
+{
ALint processed = 0;
alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
- while(processed > 0) {
- processed--;
-
+ for(ALint i = 0; i < processed; ++i) {
ALuint buffer;
alSourceUnqueueBuffers(source, 1, &buffer);
SoundManager::check_al_error("Couldn't unqueu audio buffer: ");
fillBufferAndQueue(buffer);
}
-
- // we might have to restart the source if we had a buffer underrun
+
if(!playing()) {
+ if(processed == 0)
+ return;
+
+ // we might have to restart the source if we had a buffer underrun
std::cerr << "Restarting audio source because of buffer underrun.\n";
- alSourcePlay(source);
- SoundManager::check_al_error("Couldn't restart audio source: ");
+ play();
}
+#ifdef DEBUG
+ ALint queued;
+ alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
+ assert(queued == (ALint) STREAMFRAGMENTS);
+#endif
+
if(fade_state == FadingOn) {
Uint32 ticks = SDL_GetTicks();
float time = (ticks - fade_start_ticks) / 1000.0;
} else if(fade_state == FadingOff) {
Uint32 ticks = SDL_GetTicks();
float time = (ticks - fade_start_ticks) / 1000.0;
- if(time >= fade_time) {
+ if(time >= fade_time) {
stop();
fade_state = NoFading;
} else {
}
void
-StreamSoundSource::setFading(FadeState state, float fade_time)
+StreamSoundSource::set_fading(FadeState state, float fade_time)
{
this->fade_state = state;
this->fade_time = fade_time;
}
} while(bytesread < STREAMFRAGMENTSIZE);
+ ALenum format = SoundManager::get_sample_format(file);
alBufferData(buffer, format, bufferdata, STREAMFRAGMENTSIZE, file->rate);
delete[] bufferdata;
SoundManager::check_al_error("Couldn't refill audio buffer: ");
class StreamSoundSource : public SoundSource
{
public:
- StreamSoundSource(SoundFile* file);
+ StreamSoundSource();
virtual ~StreamSoundSource();
+ void set_sound_file(SoundFile* file);
+
enum FadeState { NoFading, FadingOn, FadingOff };
- void setFading(FadeState state, float fadetime);
+ void set_fading(FadeState state, float fadetime);
+ FadeState get_fade_state() const
+ {
+ return fade_state;
+ }
void update();
private:
- static const size_t STREAMBUFFERSIZE = 1024 * 500;
+ //static const size_t STREAMBUFFERSIZE = 1024 * 500;
+ static const size_t STREAMBUFFERSIZE = 1024 * 20;
static const size_t STREAMFRAGMENTS = 5;
static const size_t STREAMFRAGMENTSIZE
= STREAMBUFFERSIZE / STREAMFRAGMENTS;
void fillBufferAndQueue(ALuint buffer);
SoundFile* file;
ALuint buffers[STREAMFRAGMENTS];
- ALenum format;
FadeState fade_state;
Uint32 fade_start_ticks;
void
GameSession::levelintro()
{
- //sound_manager->halt_music();
-
char str[60];
DrawingContext context;
// update sounds
sound_manager->set_listener_position(currentsector->player->get_pos());
- sound_manager->update();
}
void
if(!skipdraw)
draw();
+ // update sounds
+ sound_manager->update();
+
/* Time stops in pause mode */
if(game_pause || Menu::current())
{
stream << slot;
std::string slotfile = "save/slot" + stream.str() + ".stsg";
+ sound_manager->stop_music();
fadeout(256);
DrawingContext context;
context.draw_text(white_text, "Loading...",
Uint32 min = (Uint32) (min_delay * 1000);
Uint32 max = (Uint32) (max_delay * 1000);
- SDL_Delay(min);
+ Uint32 ticks = SDL_GetTicks();
+ while(SDL_GetTicks() - ticks < min) {
+ SDL_Delay(10);
+ sound_manager->update();
+ }
// clear even queue
SDL_Event event;
/* Handle events: */
bool running = false;
- Uint32 ticks = SDL_GetTicks();
+ ticks = SDL_GetTicks();
while(running) {
while(SDL_PollEvent(&event)) {
switch(event.type) {
main_menu->add_submenu(_("Start Game"), load_game_menu, MNID_STARTGAME);
main_menu->add_submenu(_("Contrib Levels"), contrib_menu, MNID_LEVELS_CONTRIB);
main_menu->add_submenu(_("Options"), options_menu);
- main_menu->add_entry(MNID_LEVELEDITOR, _("Level Editor"));
+ //main_menu->add_entry(MNID_LEVELEDITOR, _("Level Editor"));
main_menu->add_entry(MNID_CREDITS, _("Credits"));
main_menu->add_entry(MNID_QUITMAINMENU, _("Quit"));
{
local sources = [ SearchSource $(>) ] ;
local cppfile = [ LocateTarget $(<) : $(SUBDIR) ] ;
- local headerfile = [ LocateTarget $(<:S=.h) : $(SUBDIR) ] ;
+ local headerfile = [ LocateTarget $(<:S=.hpp) : $(SUBDIR) ] ;
SEARCH on $(headerfile) = $(SOURCH_SOURCE) ;
Depends $(cppfile) : $(headerfile) ;
}
}
-wrapper_sources = [ Filter [ Wildcard *.cpp *.h ] : wrapper.cpp wrapper.h ] ;
+wrapper_sources = [ Filter [ Wildcard *.cpp *.hpp ] : wrapper.cpp wrapper.hpp ] ;
if ! $(MINISWIG)
{
wrapper_sources += [ SearchSource wrapper.cpp ] ;
if(subset.has_worldmap) {
WorldMapNS::WorldMap worldmap;
worldmap.set_map_filename(subset.get_worldmap_filename());
+ sound_manager->stop_music();
// some fading
fadeout(256);
int index = contrib_subset_menu->check();
if (index != -1) {
if (contrib_subset_menu->get_item_by_id(index).kind == MN_ACTION) {
+ sound_manager->stop_music();
GameSession session(
current_contrib_subset->get_level_filename(index), ST_GL_PLAY);
session.run();
}
#endif
case MNID_CREDITS:
+ sound_manager->stop_music();
fadeout(500);
sound_manager->play_music("music/credits.ogg");
display_text_file("credits.txt");
+ sound_manager->stop_music();
fadeout(500);
Menu::set_current(main_menu);
break;
#include "screen.hpp"
#include "main.hpp"
#include "video/drawing_context.hpp"
+#include "audio/sound_manager.hpp"
#include "math/vector.hpp"
static const float LOOP_DELAY = 20.0;
DrawingContext context; // ugly...
context.do_drawing();
+ sound_manager->update();
SDL_Delay(int(LOOP_DELAY));
}
fillrect(0, SCREEN_HEIGHT - down_cor, SCREEN_WIDTH, down_cor+1, 0,0,0); // down side
DrawingContext context; // ugly...
context.do_drawing();
-
+
+ sound_manager->update();
SDL_Delay(int(LOOP_DELAY));
}
}
if (level->pos == tux->get_tile_pos())
{
+ sound_manager->stop_music();
PlayerStatus old_player_status = player_status;
// do a shriking fade to the level