1) Bugfix: sfx could not be disabled

2) Bugfix: certain sfx (esp. engine sound) would not get started
   correctly when changing sfx settings during a race.
3) Bugfix: Engine sound would be played if the in-race-menu was shown.
3) Allocating and deallocating SFX objects is now completely done
   in SXFManager (and not allocated in SFXmanager, but deallocated
   via a normal delete call).


git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/trunk/supertuxkart@2285 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hikerstk
2008-09-20 14:23:20 +00:00
parent f8646b5ed6
commit 548c35f7e1
14 changed files with 208 additions and 96 deletions

View File

@@ -2,6 +2,7 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2006 Patrick Ammann <pammann@aro.ch>
// Copyright (C) 2008 Joerg Henrichs, Patrick Ammann
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
@@ -20,19 +21,30 @@
#ifndef HEADER_SFX_HPP
#define HEADER_SFX_HPP
#include "user_config.hpp"
#include "audio/sfx_manager.hpp"
class Vec3;
/** The base class for sound effects. It gets a sound buffer from the sound
* manager, which is shared between all instances. Do create a new sound
* effect object, use sfx_manager->getSFX(...); do not create an instance
* with new, since SFXManager makes sure to stop/restart all SFX (esp.
* looping sfx like engine sounds) when necessary.
*/
class SFXBase
{
public:
virtual ~SFXBase() {};
virtual void play() = 0;
virtual void loop() = 0;
virtual void stop() = 0;
virtual void speed(float factor) = 0;
void position(const Vec3 &position) {};
virtual int getStatus() = 0;
virtual ~SFXBase() {}
void position(const Vec3 &position) {};
virtual void loop() = 0;
virtual void play() = 0;
virtual void stop() = 0;
virtual void pause() = 0;
virtual void resume() = 0;
virtual void speed(float factor) = 0;
virtual SFXManager::SFXStatus
getStatus() = 0;
}; // SfxBase

View File

@@ -20,6 +20,7 @@
#include <assert.h>
#include <fstream>
#include <stdexcept>
#include <algorithm>
#if defined(WIN32) && !defined(__CYGWIN__)
# define strcasecmp _strcmpi
# define snprintf _snprintf
@@ -41,10 +42,14 @@
SFXManager* sfx_manager= NULL;
/** Initialises the SFX manager and loads the sfx from a config file.
*/
SFXManager::SFXManager()
{
m_initialized = sound_manager->sfxAllowed();
// The sound manager initialises OpenAL
m_initialized = sound_manager->initialized();
m_sfx_buffers.resize(NUM_SOUNDS);
if(!m_initialized) return;
loadSfx();
} // SoundManager
@@ -168,11 +173,68 @@ void SFXManager::loadSingleSfx(const lisp::Lisp* lisp,
} // loadSingleSfx
//----------------------------------------------------------------------------
SFXBase *SFXManager::getSfx(SFXType id)
/** Creates a new SFX object. The memory for this object is managed completely
* by the SFXManager. This makes it easy to use different implementations of
* SFX - since newSFX can return whatever type is used. To free the memory,
* call deleteSFX().
* \param id Identifier of the sound effect to create.
*/
SFXBase *SFXManager::newSFX(SFXType id)
{
SFXBase *p=new SFXOpenAL(m_sfx_buffers[id]);
m_all_sfx.push_back(p);
return p;
} // getSfx
} // newSFX
//----------------------------------------------------------------------------
/** Delete a sound effect object, and removes it from the internal list of
* all SFXs. This call deletes the object, and removes it from the list of
* all SFXs.
* \param sfx SFX object to delete.
*/
void SFXManager::deleteSFX(SFXBase *sfx)
{
std::vector<SFXBase*>::iterator i;
i=std::find(m_all_sfx.begin(), m_all_sfx.end(), sfx);
delete sfx;
if(i==m_all_sfx.end())
{
fprintf(stderr, "Warning: sfx not found in list.\n");
return;
}
m_all_sfx.erase(i);
} // deleteSFX
//----------------------------------------------------------------------------
/** Pauses all looping SFXs. Non-looping SFX will be finished, since it's
* otherwise not possible to determine which SFX must be resumed (i.e. were
* actually playing at the time pause was called.
*/
void SFXManager::pauseAll()
{
for(std::vector<SFXBase*>::iterator i=m_all_sfx.begin();
i!=m_all_sfx.end(); i++)
{
(*i)->pause();
} // for i in m_all_sfx
} // pauseAll
//----------------------------------------------------------------------------
/** Resumes all paused SFXs.
*/
void SFXManager::resumeAll()
{
for(std::vector<SFXBase*>::iterator i=m_all_sfx.begin();
i!=m_all_sfx.end(); i++)
{
SFXStatus status = (*i)->getStatus();
// Initial happens when
if(status==SFX_PAUSED || status==SFX_INITIAL)
(*i)->resume();
} // for i in m_all_sfx
} // resumeAll
//----------------------------------------------------------------------------
bool SFXManager::checkError(const std::string &context)
@@ -184,7 +246,6 @@ bool SFXManager::checkError(const std::string &context)
{
fprintf(stdout, "SFXOpenAL OpenAL error while %s: %s\n",
context.c_str(), SFXManager::getErrorString(error).c_str());
//m_loaded = 0;//prevents further usage of this sound effect
return false;
}
return true;
@@ -204,3 +265,5 @@ const std::string SFXManager::getErrorString(int err)
default: return std::string("UNKNOWN");
};
} // getErrorString
//-----------------------------------------------------------------------------

View File

@@ -55,13 +55,15 @@ public:
/** Status of a sound effect. */
enum SFXStatus
{
SFX_UNKNOWN = -1, SFX_STOPED = 0, SFX_PAUSED = 1, SFX_PLAYING = 2
SFX_UNKNOWN = -1, SFX_STOPED = 0, SFX_PAUSED = 1, SFX_PLAYING = 2,
SFX_INITIAL = 3
};
private:
/** The buffers for all sound effects. These are shared among all
* instances of SFXOpenal. */
std::vector<ALuint> m_sfx_buffers;
std::vector<SFXBase*> m_all_sfx;
bool m_initialized;
void loadSfx();
void loadSingleSfx(const lisp::Lisp *lisp,
@@ -71,7 +73,10 @@ public:
SFXManager();
virtual ~SFXManager();
bool sfxAllowed();
SFXBase *getSfx(SFXType id);
SFXBase *newSFX(SFXType id);
void deleteSFX(SFXBase *sfx);
void pauseAll();
void resumeAll();
static bool checkError(const std::string &context);
static const std::string getErrorString(int err);
};

View File

@@ -37,11 +37,11 @@
#include "file_manager.hpp"
#include "user_config.hpp"
SFXOpenAL::SFXOpenAL(ALuint buffer)
SFXOpenAL::SFXOpenAL(ALuint buffer) : SFXBase()
{
m_soundBuffer = buffer;
m_soundSource = 0;
m_loaded = 0;
m_ok = false;
alGenSources(1, &m_soundSource );
if(!SFXManager::checkError("generating a source")) return;
@@ -54,21 +54,22 @@ SFXOpenAL::SFXOpenAL(ALuint buffer)
alSourcef (m_soundSource, AL_ROLLOFF_FACTOR, 0.2f );
alSourcei (m_soundSource, AL_SOURCE_RELATIVE, AL_TRUE );
m_loaded = SFXManager::checkError("setting up the source");
m_ok = SFXManager::checkError("setting up the source");
} // SFXOpenAL
//-----------------------------------------------------------------------------
SFXOpenAL::~SFXOpenAL()
{
alDeleteBuffers(1, &m_soundBuffer);
alDeleteSources(1, &m_soundSource);
}
} // ~SFXOpenAL
//-----------------------------------------------------------------------------
/** Changes the pitch of a sound effect.
* \param factor Speedup/slowdown between 0.5 and 2.0
*/
void SFXOpenAL::speed(float factor)
{
if(!m_loaded)
return;
if(!sfx_manager->sfxAllowed()||!m_ok) return;
//OpenAL only accepts pitches in the range of 0.5 to 2.0
if(factor > 2.0f)
@@ -81,55 +82,84 @@ void SFXOpenAL::speed(float factor)
}
alSourcef(m_soundSource,AL_PITCH,factor);
SFXManager::checkError("changing the speed");
}
} // speed
//-----------------------------------------------------------------------------
/** Loops this sound effect.
*/
void SFXOpenAL::loop()
{
if(!m_loaded)
return;
if(!m_ok) return;
alSourcei(m_soundSource, AL_LOOPING, AL_TRUE);
SFXManager::checkError("looping");
}
} // loop
//-----------------------------------------------------------------------------
/** Stops playing this sound effect.
*/
void SFXOpenAL::stop()
{
if(!m_loaded)
return;
if(!sfx_manager->sfxAllowed()||!m_ok) return;
alSourcei(m_soundSource, AL_LOOPING, AL_FALSE);
alSourceStop(m_soundSource);
SFXManager::checkError("stoping");
}
} // stop
//-----------------------------------------------------------------------------
/** Pauses a SFX that's currently played. Nothing happens it the effect is
* currently not being played.
*/
void SFXOpenAL::pause()
{
alSourcePause(m_soundSource);
SFXManager::checkError("pausing");
} // pause
//-----------------------------------------------------------------------------
/** Resumes a sound effect.
*/
void SFXOpenAL::resume()
{
if(!sfx_manager->sfxAllowed()||!m_ok) return;
alSourcef(m_soundSource,AL_GAIN,user_config->m_sfx_volume);
alSourcePlay(m_soundSource);
SFXManager::checkError("resuming");
} // resume
//-----------------------------------------------------------------------------
/** Plays this sound effect.
*/
void SFXOpenAL::play()
{
if(!m_loaded)
return;
if(!sfx_manager->sfxAllowed()||!m_ok) return;
alSourcef(m_soundSource,AL_GAIN,user_config->m_sfx_volume);
alSourcePlay(m_soundSource);
SFXManager::checkError("playing");
}
} // play
//-----------------------------------------------------------------------------
/** Sets the position where this sound effects is played.
* \param position Position of the sound effect.
*/
void SFXOpenAL::position(Vec3 position)
{
if(!m_loaded)
return;
if(!sfx_manager->sfxAllowed()||!m_ok) return;
alSource3f(m_soundSource, AL_POSITION, position.getX(), position.getY(), position.getZ());
alSource3f(m_soundSource, AL_POSITION,
position.getX(), position.getY(), position.getZ());
SFXManager::checkError("positioning");
}
} // position
//-----------------------------------------------------------------------------
int SFXOpenAL::getStatus()
/** Returns the status of this sound effect.
*/
SFXManager::SFXStatus SFXOpenAL::getStatus()
{
if(!m_loaded)
return SFXManager::SFX_UNKNOWN;
if(!sfx_manager->sfxAllowed()||!m_ok) return SFXManager::SFX_UNKNOWN;
int state = 0;
alGetSourcei(m_soundSource, AL_SOURCE_STATE, &state);
@@ -138,6 +168,7 @@ int SFXOpenAL::getStatus()
case AL_STOPPED: return SFXManager::SFX_STOPED;
case AL_PLAYING: return SFXManager::SFX_PLAYING;
case AL_PAUSED: return SFXManager::SFX_PAUSED;
case AL_INITIAL: return SFXManager::SFX_INITIAL;
default: return SFXManager::SFX_UNKNOWN;
}
} // getStatus

View File

@@ -32,19 +32,20 @@
class SFXOpenAL : public SFXBase
{
private:
unsigned int m_loaded;
ALuint m_soundBuffer; // Buffers hold sound data.
ALuint m_soundSource; // Sources are points emitting sound.
bool m_ok;
public:
SFXOpenAL(ALuint buffer);
virtual ~SFXOpenAL();
virtual void play();
virtual void loop();
virtual void stop();
virtual void speed(float factor);
virtual void position(Vec3 position);
virtual int getStatus();
SFXOpenAL(ALuint buffer);
virtual ~SFXOpenAL();
virtual void play();
virtual void loop();
virtual void stop();
virtual void pause();
virtual void resume();
virtual void speed(float factor);
virtual void position(Vec3 position);
virtual SFXManager::SFXStatus getStatus();
}; // SFXOpenAL

View File

@@ -171,10 +171,4 @@ void SoundManager::positionListener(Vec3 position)
if(!user_config->doSFX() || !m_initialized) return;
alListener3f(AL_POSITION, position.getX(), position.getY(), position.getZ());
}
//----------------------------------------------------------------------------
bool SoundManager::sfxAllowed()
{
return user_config->doSFX() && m_initialized;
} // sfxAllowed
}

View File

@@ -48,10 +48,9 @@ public:
virtual ~SoundManager();
void positionListener(Vec3 position);
bool sfxAllowed();
void startMusic(MusicInformation* mi);
void stopMusic();
bool initialized() const {return m_initialized; }
void update(float dt) {if(m_current_music)
m_current_music->update(dt); }
void pauseMusic() {if(m_current_music)

View File

@@ -34,9 +34,9 @@
Collectable::Collectable(Kart* kart_)
{
m_owner = kart_;
m_sound_shot = sfx_manager->getSfx(SFXManager::SOUND_SHOT);
m_sound_use_anvil = sfx_manager->getSfx(SFXManager::SOUND_USE_ANVIL);
m_sound_use_parachute = sfx_manager->getSfx(SFXManager::SOUND_USE_PARACHUTE);
m_sound_shot = sfx_manager->newSFX(SFXManager::SOUND_SHOT);
m_sound_use_anvil = sfx_manager->newSFX(SFXManager::SOUND_USE_ANVIL);
m_sound_use_parachute = sfx_manager->newSFX(SFXManager::SOUND_USE_PARACHUTE);
reset();
} // Collectable
@@ -45,9 +45,9 @@ Collectable::Collectable(Kart* kart_)
*/
Collectable::~Collectable()
{
delete m_sound_shot;
delete m_sound_use_anvil;
delete m_sound_use_parachute;
sfx_manager->deleteSFX(m_sound_shot);
sfx_manager->deleteSFX(m_sound_use_anvil);
sfx_manager->deleteSFX(m_sound_use_parachute);
} // ~Collectable

View File

@@ -31,14 +31,14 @@ Explosion::Explosion(const Vec3& coord) : ssgTransform()
addKid(cut); // derefing the explosion will free the cutout
m_seq = projectile_manager->getExplosionModel();
cut->addKid(m_seq);
m_explode_sound = sfx_manager->getSfx(SFXManager::SOUND_EXPLOSION);
m_explode_sound = sfx_manager->newSFX(SFXManager::SOUND_EXPLOSION);
init(coord);
} // Explosion
//-----------------------------------------------------------------------------
Explosion::~Explosion()
{
delete m_explode_sound;
sfx_manager->deleteSFX(m_explode_sound);
// cut will be cleaned up when the explosion is rerefed by plib
}
//-----------------------------------------------------------------------------

View File

@@ -54,7 +54,7 @@ enum WidgetTokens
GrandPrixEnd::GrandPrixEnd()
: m_kart(0)
{
m_winner_sound = sfx_manager->getSfx(SFXManager::SOUND_WINNER);
m_winner_sound = sfx_manager->newSFX(SFXManager::SOUND_WINNER);
// for some strange reasons plib calls makeCurrent() in ssgContext
// constructor, so we have to save the old one here and restore it
ssgContext* oldContext = ssgGetCurrentContext();
@@ -176,7 +176,7 @@ GrandPrixEnd::GrandPrixEnd()
//-----------------------------------------------------------------------------
GrandPrixEnd::~GrandPrixEnd()
{
delete m_winner_sound;
sfx_manager->deleteSFX(m_winner_sound);
widget_manager->reset();
ssgDeRefDelete(m_kart);

View File

@@ -68,8 +68,8 @@ MenuManager::MenuManager()
m_current_menu = NULL;
m_RaceGUI = NULL;
m_change_menu = false;
m_select_sound = sfx_manager->getSfx(SFXManager::SOUND_SELECT_MENU);
m_back_sound = sfx_manager->getSfx(SFXManager::SOUND_BACK_MENU);
m_select_sound = sfx_manager->newSFX(SFXManager::SOUND_SELECT_MENU);
m_back_sound = sfx_manager->newSFX(SFXManager::SOUND_BACK_MENU);
} // MenuManager
//-----------------------------------------------------------------------------
@@ -78,8 +78,8 @@ MenuManager::MenuManager()
MenuManager::~MenuManager()
{
delete m_current_menu;
delete m_back_sound;
delete m_select_sound;
sfx_manager->deleteSFX(m_back_sound);
sfx_manager->deleteSFX(m_select_sound);
}
//-----------------------------------------------------------------------------

View File

@@ -105,7 +105,7 @@ Kart::Kart (const std::string& kart_name, int position,
m_wheel_rear_r = NULL;
m_lap_start_time = -1.0f;
m_engine_sound = sfx_manager->getSfx(SFXManager::SOUND_ENGINE);
m_engine_sound = sfx_manager->newSFX(SFXManager::SOUND_ENGINE);
if(!m_engine_sound)
{
@@ -136,8 +136,9 @@ btTransform Kart::getKartHeading(const float customPitch)
trans.setBasis(m);
return trans;
}
} // getKartHeading
// ----------------------------------------------------------------------------
void Kart::createPhysics(ssgEntity *obj)
{
// First: Create the chassis of the kart
@@ -269,7 +270,7 @@ Kart::~Kart()
{
m_engine_sound->stop();
}
delete m_engine_sound;
sfx_manager->deleteSFX(m_engine_sound);
if(m_smokepuff) delete m_smokepuff;
if(m_smoke_system != NULL) delete m_smoke_system;
@@ -957,11 +958,13 @@ void Kart::updatePhysics (float dt)
m_max_gear_rpm = m_current_gear_ratio * max_speed;
// 8 is magic number again.
m_rpm = ((m_speed * gear_ratio) / (8*tire_diameter));
if(m_engine_sound)
if(m_engine_sound && sfx_manager->sfxAllowed())
{
m_engine_sound->speed((float)((m_rpm * 2) / m_max_gear_rpm));
//m_engine_sound->position(m_curr_track_coords);
}
// FIXME: what if sfx are disabled in the option menu??
// The engine sound will still play!
} // updatePhysics
//-----------------------------------------------------------------------------

View File

@@ -41,13 +41,13 @@ PlayerKart::PlayerKart(const std::string& kart_name, int position, Player *playe
m_camera = scene->createCamera(player_index, this);
m_camera->setMode(Camera::CM_NORMAL);
m_bzzt_sound = sfx_manager->getSfx(SFXManager::SOUND_BZZT );
m_beep_sound = sfx_manager->getSfx(SFXManager::SOUND_BEEP );
m_crash_sound = sfx_manager->getSfx(SFXManager::SOUND_CRASH);
m_wee_sound = sfx_manager->getSfx(SFXManager::SOUND_WEE );
m_ugh_sound = sfx_manager->getSfx(SFXManager::SOUND_UGH );
m_grab_sound = sfx_manager->getSfx(SFXManager::SOUND_GRAB );
m_full_sound = sfx_manager->getSfx(SFXManager::SOUND_FULL );
m_bzzt_sound = sfx_manager->newSFX(SFXManager::SOUND_BZZT );
m_beep_sound = sfx_manager->newSFX(SFXManager::SOUND_BEEP );
m_crash_sound = sfx_manager->newSFX(SFXManager::SOUND_CRASH);
m_wee_sound = sfx_manager->newSFX(SFXManager::SOUND_WEE );
m_ugh_sound = sfx_manager->newSFX(SFXManager::SOUND_UGH );
m_grab_sound = sfx_manager->newSFX(SFXManager::SOUND_GRAB );
m_full_sound = sfx_manager->newSFX(SFXManager::SOUND_FULL );
reset();
} // PlayerKart
@@ -55,15 +55,15 @@ PlayerKart::PlayerKart(const std::string& kart_name, int position, Player *playe
//-----------------------------------------------------------------------------
PlayerKart::~PlayerKart()
{
delete m_bzzt_sound;
delete m_beep_sound;
delete m_crash_sound;
delete m_wee_sound;
delete m_ugh_sound;
delete m_grab_sound;
delete m_full_sound;
sfx_manager->deleteSFX(m_bzzt_sound);
sfx_manager->deleteSFX(m_beep_sound);
sfx_manager->deleteSFX(m_crash_sound);
sfx_manager->deleteSFX(m_wee_sound);
sfx_manager->deleteSFX(m_ugh_sound);
sfx_manager->deleteSFX(m_grab_sound);
sfx_manager->deleteSFX(m_full_sound);
} // ~PlayerKart
}
//-----------------------------------------------------------------------------
void PlayerKart::reset()
{

View File

@@ -176,8 +176,8 @@ World::World()
callback_manager->initAll();
menu_manager->switchToRace();
m_prestart_sound = sfx_manager->getSfx(SFXManager::SOUND_PRESTART);
m_start_sound = sfx_manager->getSfx(SFXManager::SOUND_START);
m_prestart_sound = sfx_manager->newSFX(SFXManager::SOUND_PRESTART);
m_start_sound = sfx_manager->newSFX(SFXManager::SOUND_START);
m_track->startMusic();
@@ -216,8 +216,8 @@ World::~World()
delete m_physics;
sound_manager -> stopMusic();
delete m_prestart_sound;
delete m_start_sound;
sfx_manager->deleteSFX(m_prestart_sound);
sfx_manager->deleteSFX(m_start_sound);
sgVec3 sun_pos;
sgVec4 ambient_col, specular_col, diffuse_col;
@@ -797,6 +797,8 @@ void World::restartRace()
resetAllKarts();
sound_manager->stopMusic(); // Start music from beginning
m_track->startMusic();
// Enable SFX again
sfx_manager->resumeAll();
herring_manager->reset();
projectile_manager->cleanup();
race_manager->reset();
@@ -841,7 +843,8 @@ Kart* World::loadRobot(const std::string& kart_name, int position,
//-----------------------------------------------------------------------------
void World::pause()
{
sound_manager -> pauseMusic() ;
sound_manager->pauseMusic();
sfx_manager->pauseAll();
m_previous_phase = m_phase;
m_phase = LIMBO_PHASE;
}
@@ -849,7 +852,8 @@ void World::pause()
//-----------------------------------------------------------------------------
void World::unpause()
{
sound_manager -> resumeMusic() ;
sound_manager->resumeMusic() ;
sfx_manager->resumeAll();
m_phase = m_previous_phase;
}