Rewritten Audio Module on top of SFML2

git-svn-id: https://svn.code.sf.net/p/extremetuxracer/code/branches/SFML2@466 0420edf4-82e4-42fc-9478-35b55e6d67a3
master
pkeus 2013-10-05 17:21:21 +00:00
parent 2f8e31577d
commit c904a766f7
20 changed files with 98 additions and 208 deletions

View File

@ -92,7 +92,7 @@
<PrecompiledHeaderFile>bh.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<AdditionalDependencies>freetype.lib;sdl.lib;sdl_mixer.lib;sdl_image.lib;sdlmain.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>freetype.lib;sdl.lib;sfml-audio-d.lib;sdl_image.lib;sdlmain.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<IgnoreSpecificDefaultLibraries>libcmtd.lib;libcmt.lib;msvcrt.lib</IgnoreSpecificDefaultLibraries>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -109,7 +109,7 @@
<PrecompiledHeaderFile>bh.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<AdditionalDependencies>freetype.lib;sdl.lib;sdl_mixer.lib;sdl_image.lib;sdlmain.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>freetype.lib;sdl.lib;sfml-audio-d-64.lib;sdl_image.lib;sdlmain.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<IgnoreSpecificDefaultLibraries>libcmtd.lib;libcmt.lib;msvcrt.lib</IgnoreSpecificDefaultLibraries>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -132,7 +132,7 @@
<PrecompiledHeaderFile>bh.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<AdditionalDependencies>freetype.lib;sdl.lib;sdl_mixer.lib;sdl_image.lib;sdlmain.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>freetype.lib;sdl.lib;sfml-audio.lib;sdl_image.lib;sdlmain.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<IgnoreSpecificDefaultLibraries>libcmt.lib</IgnoreSpecificDefaultLibraries>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>
@ -157,7 +157,7 @@
<PrecompiledHeaderFile>bh.h</PrecompiledHeaderFile>
</ClCompile>
<Link>
<AdditionalDependencies>freetype.lib;sdl.lib;sdl_mixer.lib;sdl_image.lib;sdlmain.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>freetype.lib;sdl.lib;sfml-audio-64.lib;sdl_image.lib;sdlmain.lib;opengl32.lib;glu32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<IgnoreSpecificDefaultLibraries>libcmt.lib</IgnoreSpecificDefaultLibraries>
<SubSystem>Console</SubSystem>
<OptimizeReferences>true</OptimizeReferences>

View File

@ -20,75 +20,51 @@ GNU General Public License for more details.
#include "audio.h"
#include "spx.h"
#include <SDL/SDL.h>
#include <SFML/Audio.hpp>
// the global instances of the 3 audio classes
CAudio Audio;
CMusic Music;
// the global instances of the 2 audio classes
CSound Sound;
CMusic Music;
#define MIX_MAX_VOLUME 100
// --------------------------------------------------------------------
// class CAudio
// --------------------------------------------------------------------
CAudio::CAudio () {
IsOpen = false;
}
void CAudio::Open () {
// first initialize audio (SDL, not SDL_Mixer).
if (SDL_Init (SDL_INIT_AUDIO) < 0) {
Message ("Couldn't initialize SDL Audio", SDL_GetError());
return;
struct TSound {
sf::SoundBuffer data;
sf::Sound player;
TSound(int volume)
{
setVolume(volume);
}
Uint16 format = AUDIO_S16SYS;
int channels = 2;
if (Mix_OpenAudio (param.audio_freq, format, channels, param.audio_buffer_size) < 0)
Message ("Couldn't open SDL_mixer", Mix_GetError());
IsOpen = CheckOpen ();
Mix_AllocateChannels (8);
}
void CAudio::Close () {
if (IsOpen) {
Music.FreeMusics ();
Sound.FreeSounds ();
Mix_CloseAudio();
IsOpen = false;
void setVolume(int volume) {
player.setVolume(volume);
}
}
bool CAudio::CheckOpen() {
int freq;
Uint16 format;
int channels;
int ret = Mix_QuerySpec (&freq, &format, &channels);
return (ret > 0);
}
void TSound::Play(bool loop) {
if (player.getStatus() == sf::Sound::Playing) return;
player.setLoop(loop);
player.play();
}
};
// --------------------------------------------------------------------
// class CSound
// --------------------------------------------------------------------
bool CSound::LoadChunk (const std::string& name, const char *filename) {
if (Audio.IsOpen == false) return false;
sounds.push_back(TSound());
sounds.back().chunk = Mix_LoadWAV (filename);
if (sounds.back().chunk == NULL) return false;
sounds.back().channel = -1; // default: no channel
sounds.back().loop_count = 0; // default: playing once
CSound::~CSound()
{
FreeSounds();
}
Mix_VolumeChunk (sounds.back().chunk, param.sound_volume);
bool CSound::LoadChunk (const std::string& name, const std::string& filename) {
sounds.push_back(new TSound(param.sound_volume));
if (!sounds.back()->data.loadFromFile(filename)) // Try loading sound buffer
return false;
sounds.back()->player.setBuffer(sounds.back()->data);
SoundIndex[name] = sounds.size()-1;
return true;
}
// Load all soundfiles listed in "/sounds/sounds.lst"
void CSound::LoadSoundList () {
if (!Audio.IsOpen) {
Message ("cannot load music, first open Audio");
return;
}
CSPList list(200);
if (list.Load (param.sounds_dir, "sounds.lst")) {
for (size_t i=0; i<list.Count(); i++) {
@ -96,22 +72,20 @@ void CSound::LoadSoundList () {
string name = SPStrN (line, "name");
string soundfile = SPStrN (line, "file");
string path = MakePathStr (param.sounds_dir, soundfile);
LoadChunk (name, path.c_str());
LoadChunk (name, path);
}
}
}
void CSound::FreeSounds () {
HaltAll ();
for (size_t i=0; i<sounds.size(); i++)
if (sounds[i].chunk != NULL)
Mix_FreeChunk (sounds[i].chunk);
HaltAll();
for (size_t i = 0; i < sounds.size(); i++)
delete sounds[i];
sounds.clear();
SoundIndex.clear();
}
size_t CSound::GetSoundIdx (const string& name) const {
if (Audio.IsOpen == false) return -1;
try {
return SoundIndex.at(name);
} catch (...) {
@ -120,12 +94,10 @@ size_t CSound::GetSoundIdx (const string& name) const {
}
void CSound::SetVolume (size_t soundid, int volume) {
if (Audio.IsOpen == false) return;
if (soundid >= sounds.size()) return;
volume = clamp(0, volume, MIX_MAX_VOLUME);
if (sounds[soundid].chunk == NULL) return;
Mix_VolumeChunk (sounds[soundid].chunk, volume);
sounds[soundid]->setVolume(volume);
}
void CSound::SetVolume (const string& name, int volume) {
@ -134,51 +106,34 @@ void CSound::SetVolume (const string& name, int volume) {
// ------------------- play -------------------------------------------
void TSound::Play(int loop) {
if (active == true) return;
if (chunk == NULL) return;
channel = Mix_PlayChannel (-1, chunk, loop);
loop_count = loop;
if (loop < 0) active = true;
}
void CSound::Play (size_t soundid, int loop) {
if (!Audio.IsOpen) return;
void CSound::Play(size_t soundid, bool loop) {
if (soundid >= sounds.size()) return;
sounds[soundid].Play(loop);
sounds[soundid]->Play(loop);
}
void CSound::Play (const string& name, int loop) {
void CSound::Play(const string& name, bool loop) {
Play (GetSoundIdx (name), loop);
}
void CSound::Play (size_t soundid, int loop, int volume) {
if (!Audio.IsOpen) return;
void CSound::Play(size_t soundid, bool loop, int volume) {
if (soundid >= sounds.size()) return;
volume = clamp(0, volume, MIX_MAX_VOLUME);
Mix_VolumeChunk (sounds[soundid].chunk, volume);
sounds[soundid].Play(loop);
sounds[soundid]->setVolume(volume);
sounds[soundid]->Play(loop);
}
void CSound::Play (const string& name, int loop, int volume) {
void CSound::Play(const string& name, bool loop, int volume) {
Play (GetSoundIdx (name), loop, volume);
}
void CSound::Halt (size_t soundid) {
if (!Audio.IsOpen) return;
if (soundid >= sounds.size()) return;
if (sounds[soundid].chunk == NULL) return;
// loop_count must be -1 (endless loop) for halt
if (sounds[soundid].loop_count < 0) {
Mix_HaltChannel (sounds[soundid].channel);
sounds[soundid].loop_count = 0;
sounds[soundid].channel = -1;
sounds[soundid].active = false;
}
if (sounds[soundid]->player.getLoop())
sounds[soundid]->player.stop();
}
void CSound::Halt (const string& name) {
@ -186,12 +141,8 @@ void CSound::Halt (const string& name) {
}
void CSound::HaltAll () {
if (!Audio.IsOpen) return;
Mix_HaltChannel (-1);
for (size_t i=0; i<sounds.size(); i++) {
sounds[i].loop_count = 0;
sounds[i].channel = -1;
sounds[i].active = false;
for (size_t i = 0; i < sounds.size(); i++) {
sounds[i]->player.stop();
}
}
@ -199,22 +150,17 @@ void CSound::HaltAll () {
// class CMusic
// --------------------------------------------------------------------
void Hook () {
Mix_HaltMusic();
PrintStr ("halted");
}
CMusic::CMusic () {
CMusic::CMusic() {
curr_music = 0;
curr_volume = 10;
loop_count = 0;
// Mix_HookMusicFinished (Hook);
}
CMusic::~CMusic() {
FreeMusics();
}
bool CMusic::LoadPiece (const string& name, const char *filename) {
if (!Audio.IsOpen) return -1;
Mix_Music* m = Mix_LoadMUS (filename);
if (m == NULL) {
bool CMusic::LoadPiece(const string& name, const string& filename) {
sf::Music* m = new sf::Music();
if (!m->openFromFile(filename)) {
Message ("could not load music", filename);
return false;
}
@ -224,10 +170,6 @@ bool CMusic::LoadPiece (const string& name, const char *filename) {
}
void CMusic::LoadMusicList () {
if (!Audio.IsOpen) {
Message ("cannot load music, first open audio");
return;
}
// --- music ---
CSPList list(200);
if (list.Load (param.music_dir, "music.lst")) {
@ -236,7 +178,7 @@ void CMusic::LoadMusicList () {
string name = SPStrN (line, "name");
string musicfile = SPStrN (line, "file");
string path = MakePathStr (param.music_dir, musicfile);
LoadPiece (name, path.c_str());
LoadPiece (name, path);
}
} else {
Message ("could not load music.lst");
@ -264,21 +206,18 @@ void CMusic::LoadMusicList () {
void CMusic::FreeMusics () {
Halt ();
for (size_t i=0; i<musics.size(); i++)
if (musics[i] != NULL)
Mix_FreeMusic (musics[i]);
for (size_t i = 0; i < musics.size(); i++)
delete musics[i];
musics.clear();
MusicIndex.clear();
themes.clear();
ThemesIndex.clear();
curr_music = 0;
curr_volume = 10;
curr_music = NULL;
}
size_t CMusic::GetMusicIdx (const string& name) const {
if (Audio.IsOpen == false) return -1;
try {
return MusicIndex.at(name);
} catch (...) {
@ -287,7 +226,6 @@ size_t CMusic::GetMusicIdx (const string& name) const {
}
size_t CMusic::GetThemeIdx (const string& theme) const {
if (Audio.IsOpen == false) return -1;
try {
return ThemesIndex.at(theme);
} catch (...) {
@ -297,64 +235,55 @@ size_t CMusic::GetThemeIdx (const string& theme) const {
void CMusic::SetVolume (int volume) {
int vol = clamp(0, volume, MIX_MAX_VOLUME);
Mix_VolumeMusic (vol);
if (curr_music)
curr_music->setVolume(volume);
curr_volume = vol;
}
// If the piece is played in a loop, the volume adjustment gets lost.
// probably a bug in SDL_mixer. Help: we have to refresh the volume
// in each (!) frame.
void CMusic::Update () {
Mix_VolumeMusic (curr_volume);
}
bool CMusic::Play (Mix_Music* music, int loop, int volume) {
bool CMusic::Play (sf::Music* music, bool loop, int volume) {
if (!music)
return false;
int vol = clamp(0, volume, MIX_MAX_VOLUME);
if (music != curr_music) {
Halt ();
Mix_PlayMusic (music, loop);
music->setVolume(volume);
music->setLoop(loop);
if (curr_music)
curr_music->stop();
curr_music = music;
loop_count = loop;
music->play();
}
Mix_VolumeMusic (vol);
return true;
}
bool CMusic::Play (size_t musid, int loop) {
if (!Audio.IsOpen) return false;
bool CMusic::Play(size_t musid, bool loop) {
if (musid >= musics.size()) return false;
Mix_Music *music = musics[musid];
sf::Music* music = musics[musid];
return Play(music, loop, curr_volume);
}
bool CMusic::Play (const string& name, int loop) {
bool CMusic::Play(const string& name, bool loop) {
return Play (GetMusicIdx(name), loop);
}
bool CMusic::Play (size_t musid, int loop, int volume) {
if (!Audio.IsOpen) return false;
bool CMusic::Play(size_t musid, bool loop, int volume) {
if (musid >= musics.size()) return false;
Mix_Music *music = musics[musid];
sf::Music* music = musics[musid];
return Play(music, loop, volume);
}
bool CMusic::Play (const string& name, int loop, int volume) {
bool CMusic::Play(const string& name, bool loop, int volume) {
return Play (GetMusicIdx (name), loop, volume);
}
bool CMusic::PlayTheme (size_t theme, ESituation situation) {
if (theme >= themes.size()) return false;
if (situation >= SITUATION_COUNT) return false;
Mix_Music *music = themes [theme].situation[situation];
sf::Music* music = themes[theme].situation[situation];
return Play (music, -1, curr_volume);
}
void CMusic::Halt () {
if (Mix_PlayingMusic ()) Mix_HaltMusic();
loop_count = -1;
curr_music = 0;
curr_music->stop();
curr_music = NULL;
}

View File

@ -20,52 +20,31 @@ GNU General Public License for more details.
#include "bh.h"
#include <vector>
#include <map>
#include <SDL/SDL_mixer.h>
// --------------------------------------------------------------------
// class CAudio
// --------------------------------------------------------------------
class CAudio {
private:
public:
CAudio ();
void Open ();
void Close ();
static bool CheckOpen ();
bool IsOpen;
};
// --------------------------------------------------------------------
// class CSound
// --------------------------------------------------------------------
struct TSound {
Mix_Chunk *chunk;
int channel;
int loop_count;
bool active;
void Play (int loop);
};
struct TSound;
class CSound {
private:
vector<TSound> sounds;
vector<TSound*> sounds;
map<string, size_t> SoundIndex;
public:
bool LoadChunk (const std::string& name, const char *filename);
~CSound();
bool LoadChunk (const std::string& name, const std::string& filename);
void LoadSoundList ();
size_t GetSoundIdx (const string& name) const;
void SetVolume (size_t soundid, int volume);
void SetVolume (const string& name, int volume);
void Play (size_t soundid, int loop);
void Play (const string& name, int loop); // -1 infinite, 0 once, 1 twice ...
void Play (size_t soundid, int loop, int volume);
void Play (const string& name, int loop, int volume);
void Play(size_t soundid, bool loop);
void Play(const string& name, bool loop);
void Play(size_t soundid, bool loop, int volume);
void Play(const string& name, bool loop, int volume);
void Halt (size_t soundid);
void Halt (const string& name);
@ -85,34 +64,37 @@ enum ESituation {
SITUATION_COUNT
};
namespace sf {
class Music;
};
class CMusic {
private:
vector<Mix_Music*> musics;
vector<sf::Music*> musics;
map<string, size_t> MusicIndex;
struct Situation {Mix_Music* situation[SITUATION_COUNT];};
struct Situation { sf::Music* situation[SITUATION_COUNT]; };
vector<Situation> themes;
map<string, size_t> ThemesIndex;
int loop_count; // we need only 1 variable for all pieces
Mix_Music* curr_music; // current music piece
sf::Music* curr_music; // current music piece
int curr_volume;
bool Play (Mix_Music* music, int loop, int volume);
bool Play(sf::Music* music, bool loop, int volume);
public:
CMusic ();
CMusic();
~CMusic();
bool LoadPiece (const string& name, const char *filename);
bool LoadPiece(const string& name, const string& filename);
void LoadMusicList ();
size_t GetMusicIdx (const string& name) const;
size_t GetThemeIdx (const string& theme) const;
void SetVolume (int volume);
void Update ();
bool Play (size_t musid, int loop);
bool Play (const string& name, int loop);
bool Play (size_t musid, int loop, int volume);
bool Play (const string& name, int loop, int volume);
bool Play(size_t musid, bool loop);
bool Play(const string& name, bool loop);
bool Play(size_t musid, bool loop, int volume);
bool Play(const string& name, bool loop, int volume);
bool PlayTheme (size_t theme, ESituation situation);
void Halt ();
void FreeMusics ();
@ -120,7 +102,6 @@ public:
// --------------------------------------------------------------------
extern CAudio Audio;
extern CMusic Music;
extern CSound Sound;

View File

@ -189,10 +189,7 @@ void CGameConfig::Loop (double time_step) {
int ww = Winsys.resolution.width;
int hh = Winsys.resolution.height;
Music.Update ();
check_gl_error();
Music.Update ();
ScopedRenderMode rm(GUI);
ClearRenderContext ();
SetupGuiDisplay ();

View File

@ -142,7 +142,6 @@ void CCredits::Loop(double time_step) {
int ww = Winsys.resolution.width;
int hh = Winsys.resolution.height;
Music.Update ();
check_gl_error();
ClearRenderContext ();
ScopedRenderMode rm(GUI);

View File

@ -182,7 +182,6 @@ void CEvent::Loop (double timestep) {
check_gl_error();
ScopedRenderMode rm(GUI);
Music.Update ();
ClearRenderContext ();
SetupGuiDisplay ();

View File

@ -122,7 +122,6 @@ void CEventSelect::Loop (double timestep) {
check_gl_error();
ScopedRenderMode rm(GUI);
Music.Update ();
ClearRenderContext ();
SetupGuiDisplay ();

View File

@ -197,8 +197,6 @@ void CGameOver::Loop(double time_step) {
int height = Winsys.resolution.height;
check_gl_error();
Music.Update ();
ClearRenderContext ();
Env.SetupFog ();

View File

@ -125,7 +125,6 @@ void CGameTypeSelect::Loop (double time_step) {
int hh = Winsys.resolution.height;
check_gl_error();
Music.Update ();
ScopedRenderMode rm(GUI);
ClearRenderContext ();
SetupGuiDisplay ();

View File

@ -53,7 +53,6 @@ void CHelp::Enter() {
}
void CHelp::Loop(double timestep) {
Music.Update ();
check_gl_error();
ClearRenderContext ();
ScopedRenderMode rm(GUI);

View File

@ -108,7 +108,6 @@ void CIntro::Loop (double time_step) {
update_view (ctrl, time_step);
SetupViewFrustum (ctrl);
Music.Update ();
Env.DrawSkybox (ctrl->viewpos);
Env.DrawFog ();

View File

@ -88,7 +88,6 @@ int main( int argc, char **argv ) {
Tex.LoadTextureList ();
FT.LoadFontlist ();
Winsys.SetFonttype ();
Audio.Open ();
Music.LoadMusicList ();
Music.SetVolume (param.music_volume);

View File

@ -111,7 +111,6 @@ void CNewPlayer::Loop(double timestep) {
int hh = Winsys.resolution.height;
TColor col;
Music.Update ();
check_gl_error();
ClearRenderContext ();
ScopedRenderMode rm(GUI);

View File

@ -76,7 +76,6 @@ void CPaused::Loop (double time_step) {
int height = Winsys.resolution.height;
check_gl_error();
Music.Update ();
ClearRenderContext ();
Env.SetupFog ();
update_view (ctrl, 0);

View File

@ -185,7 +185,6 @@ void CRaceSelect::Loop(double timestep) {
ClearRenderContext ();
SetupGuiDisplay ();
Music.Update ();
if (param.ui_snow) {
update_ui_snow (timestep);
draw_ui_snow ();

View File

@ -345,7 +345,6 @@ void CRacing::Loop (double time_step) {
check_gl_error();
ClearRenderContext ();
Env.SetupFog ();
Music.Update ();
CalcTrickControls (ctrl, time_step, airborne);
if (!g_game.finish) CalcSteeringControls (ctrl, time_step);

View File

@ -110,7 +110,6 @@ void CRegist::Enter() {
void CRegist::Loop (double timestep) {
int ww = Winsys.resolution.width;
int hh = Winsys.resolution.height;
Music.Update ();
check_gl_error();
ClearRenderContext ();
ScopedRenderMode rm(GUI);

View File

@ -244,7 +244,6 @@ void CScore::Loop (double timestep) {
int ww = Winsys.resolution.width;
int hh = Winsys.resolution.height;
Music.Update ();
check_gl_error();
ClearRenderContext ();
ScopedRenderMode rm(GUI);

View File

@ -58,7 +58,6 @@ void CSplashScreen::Enter() {
}
void CSplashScreen::Loop(double timestep) {
Music.Update ();
check_gl_error();
ClearRenderContext ();
ScopedRenderMode rm(GUI);

View File

@ -198,7 +198,6 @@ void CWinsys::Quit () {
CloseJoystick ();
Score.SaveHighScore ();
SaveMessages ();
Audio.Close (); // frees music and sound as well
FT.Clear ();
if (g_game.argument < 1) Players.SavePlayers ();
SDL_Quit ();