diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/game.cpp | 15 | ||||
-rw-r--r-- | src/gui/setup.cpp | 2 | ||||
-rw-r--r-- | src/main.cpp | 11 | ||||
-rw-r--r-- | src/sound.cpp | 240 | ||||
-rw-r--r-- | src/sound.h | 127 |
5 files changed, 224 insertions, 171 deletions
diff --git a/src/game.cpp b/src/game.cpp index 4ec83d5d..3ddd72a9 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -224,8 +224,8 @@ void do_input() } else if ((keysym.sym == SDLK_F7)) { - SOUND_SID id = sound.loadItem("data/sfx/fist-swish.ogg"); - sound.startItem(id, 120); + SOUND_ID id = sound.loadSfx("data/sfx/fist-swish.ogg"); + sound.playSfx(id); } // Emotions, Skill dialog @@ -373,7 +373,7 @@ void do_input() - } + } } else if (event.type == SDL_QUIT) { @@ -532,13 +532,8 @@ void do_input() player_node->y, player_node->direction); player_node->walk_time = tick_time; - - if (config.getValue("sound", 0) == 1) { // Temp fix - ResourceManager *resman = ResourceManager::getInstance(); - SoundEffect *sample = resman->getSoundEffect( - "sfx/fist-swish.ogg"); - sample->play(0, 120); - } + + sound.playSfx("sfx/fist-swish.ogg"); } } diff --git a/src/gui/setup.cpp b/src/gui/setup.cpp index 9f304b61..6d4dade4 100644 --- a/src/gui/setup.cpp +++ b/src/gui/setup.cpp @@ -230,7 +230,7 @@ void Setup::action(const std::string &eventId) if (soundCheckBox->isMarked()) { config.setValue("sound", 1); try { - sound.init(32, 20); + sound.init(); } catch (const char *err) { new OkDialog(this, "Sound Engine", err); diff --git a/src/main.cpp b/src/main.cpp index 8a32f043..b6a3b4fa 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -291,11 +291,10 @@ void init_engine() // initialize sound-engine and start playing intro-theme /-kth5 try { - if (config.getValue("sound", 0) == 1) { - SDL_InitSubSystem(SDL_INIT_AUDIO); - sound.init(32, 20); + if (config.getValue("sound", 0) == 1) { + sound.init(); } - sound.setVolume(64); + //sound.setVolume(64); } catch (const char *err) { state = ERROR; @@ -351,7 +350,7 @@ int main(int argc, char *argv[]) switch (state) { case LOGIN: logger.log("State: LOGIN"); - sound.startBgm("data/music/Ivano(de)Jeanette.ogg"); + sound.playMusic("data/music/Ivano(de)Jeanette.ogg"); /*bgm = resman->getMusic("music/Ivano(de)Jeanette.ogg"); bgm->play(-1);*/ login(); @@ -365,7 +364,7 @@ int main(int argc, char *argv[]) charSelect(); break; case GAME: - sound.stopBgm(); + sound.fadeOutMusic(3000); //bgm->stop(); logger.log("State: GAME"); try { diff --git a/src/sound.cpp b/src/sound.cpp index cdd9de49..98fef632 100644 --- a/src/sound.cpp +++ b/src/sound.cpp @@ -25,144 +25,214 @@ #include "log.h" #include "main.h" -void Sound::init(int voices, int mod_voices) +void Sound::init() { // Don't initialize sound engine twice - if (isOk == 0) return; - - bgm = NULL; - int audio_rate = 44100; - Uint16 audio_format = MIX_DEFAULT_FORMAT; - int audio_channels = 2; - int audio_buffers = 4096; - - if (Mix_OpenAudio(audio_rate, audio_format, audio_channels, audio_buffers)) - { -#ifndef __DEBUG - throw("Unable to open audio device!"); -#else - throw(Mix_GetError()); -#endif - } + if (installed) return; - Mix_QuerySpec(&audio_rate, &audio_format, &audio_channels); - char *format_str="Unknown"; - switch (audio_format) { - case AUDIO_U8: format_str="U8"; break; - case AUDIO_S8: format_str="S8"; break; - case AUDIO_U16LSB: format_str="U16LSB"; break; - case AUDIO_S16LSB: format_str="S16LSB"; break; - case AUDIO_U16MSB: format_str="U16MSB"; break; - case AUDIO_S16MSB: format_str="S16MSB"; break; - } + logger.log("Sound::init() Initializing sound..."); - pan = 128; + if (SDL_InitSubSystem(SDL_INIT_AUDIO) == -1) { + logger.log("Sound::init() Failed to initialize audio subsystem"); + return; + } + + const size_t audioBuffer = 4096; + + const int res = Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, + 2, audioBuffer); + if (res >= 0) { + Mix_AllocateChannels(16); + } else { + logger.log("Sound::init Could not initialize audio: %s", + Mix_GetError()); + return; + } + + info(); + + music = NULL; items = -1; - isOk = 0; + + installed = true; +} - logger.log("Sound::init() Initializing Sound"); - char driver[40]; - logger.log("Sound::init() Driver name: %s", SDL_AudioDriverName(driver, 40)); - logger.log("Sound::init() Spec: %i %s %i", audio_rate, format_str, - audio_channels); +void Sound::info() { + SDL_version compiledVersion; + const SDL_version *linkedVersion; + char driver[40] = "Unknown"; + char *format = "Unknown"; + int rate = 0; + Uint16 audioFormat = 0; + int channels = 0; + + MIX_VERSION(&compiledVersion); + linkedVersion = Mix_Linked_Version(); + + SDL_AudioDriverName(driver, 40); + + Mix_QuerySpec(&rate, &audioFormat, &channels); + switch (audioFormat) { + case AUDIO_U8: format = "U8"; break; + case AUDIO_S8: format = "S8"; break; + case AUDIO_U16LSB: format = "U16LSB"; break; + case AUDIO_S16LSB: format = "S16LSB"; break; + case AUDIO_U16MSB: format = "U16MSB"; break; + case AUDIO_S16MSB: format = "S16MSB"; break; + } + + logger.log("Sound::info() SDL_mixer: %i.%i.%i (compiled)", + compiledVersion.major, + compiledVersion.minor, + compiledVersion.patch); + logger.log("Sound::info() SDL_mixer: %i.%i.%i (linked)", + linkedVersion->major, + linkedVersion->minor, + linkedVersion->patch); + logger.log("Sound::info() Driver: %s", driver); + logger.log("Sound::init() Format: %s", format); + logger.log("Sound::init() Rate: %i", rate); + logger.log("Sound::init() Channels: %i", channels); } -void Sound::setVolume(int music) +void Sound::setMusicVolume(int volume) { - if (isOk == -1) return; + if (!installed) return; - if (!isMaxVol(music)) { - vol_music = music; - Mix_VolumeMusic(vol_music); - } + musicVolume = volume; + Mix_VolumeMusic(volume); } -void Sound::adjustVolume(int amusic) +void Sound::setSfxVolume(int volume) { - if (isOk == -1) return; + if (!installed) return; - if (!isMaxVol(vol_music + amusic)) { - vol_music += amusic; - Mix_VolumeMusic(vol_music); - } + sfxVolume = volume; + Mix_Volume(-1, volume); } -void Sound::startBgm(char *in, int loop) +void Sound::playMusic(const char *path, int loop) { - if (isOk == -1) return; + if (!installed) return; - if (bgm != NULL) { - stopBgm(); + if (music != NULL) { + stopMusic(); } - logger.log("Sound::startBgm() playing \"%s\" %d times", in, loop); + logger.log("Sound::startMusic() Playing \"%s\" %i times", path, loop); - bgm = Mix_LoadMUS(in); - if (bgm) { - Mix_PlayMusic(bgm, loop); + music = Mix_LoadMUS(path); + if (music) { + Mix_PlayMusic(music, loop); } else { - logger.log("Sound::startBgm() warning: error loading file."); + logger.log("Sound::startMusic() Warning: error loading file."); } } -void Sound::stopBgm() +void Sound::stopMusic() { - if (isOk == -1) return; + if (!installed) return; - logger.log("Sound::stopBgm()"); + logger.log("Sound::stopMusic()"); - if (bgm != NULL) { + if (music != NULL) { Mix_HaltMusic(); - Mix_FreeMusic(bgm); - bgm = NULL; + Mix_FreeMusic(music); + music = NULL; } } -SOUND_SID Sound::loadItem(char *fpath) +void Sound::fadeInMusic(const char *path, int loop, int ms) { - logger.log("Sound::loadItem() precaching \"%s\"", fpath); + if (!installed) return; + + if (music != NULL) { + stopMusic(); + } - Mix_Chunk *newItem; - if ((newItem = Mix_LoadWAV(fpath))) { - soundpool[++items] = newItem; - logger.log("Sound::loadItem() success SOUND_SID = %d", items); + logger.log("Sound::fadeInMusic() Fading \"%s\" %i times (%i ms)", path, + loop, ms); + + music = Mix_LoadMUS(path); + if (music) { + Mix_FadeInMusic(music, loop, ms); + } + else { + logger.log("Sound::fadeInMusic() Warning: error loading file."); + } +} + +void Sound::fadeOutMusic(int ms) +{ + if (!installed) return; + + logger.log("Sound::fadeOutMusic() Fading-out (%i ms)", ms); + + if (music != NULL) { + Mix_FadeOutMusic(ms); + Mix_FreeMusic(music); + music = NULL; + } +} + +SOUND_ID Sound::loadSfx(const char *path) +{ + /* If sound system is not installed it can't load + * samples because doesn't know how to convert them */ + if (!installed) return 0; + + logger.log("Sound::loadSfx() pre-caching \"%s\"", path); + + ResourceManager *resman = ResourceManager::getInstance(); + SoundEffect *sample = resman->getSoundEffect(path); + if (sample) { + soundPool[++items] = sample; + logger.log("Sound::loadSfx() SOUND_ID = %d", items); return items; } return 0; } -void Sound::startItem(SOUND_SID id, int volume) +void Sound::playSfx(SOUND_ID id) { - if (soundpool[id]) { - logger.log("Sound::startItem() playing SOUND_SID = %d", id); - Mix_VolumeChunk(soundpool[id], volume); - Mix_PlayChannel(-1, soundpool[id], 0); + if (!installed) return; + + if (soundPool[id]) { + logger.log("Sound::playSfx() Playing SOUND_ID = %d", id); + soundPool[id]->play(0, sfxVolume); + } +} + +void Sound::playSfx(const char *path) +{ + if (!installed) return; + + ResourceManager *resman = ResourceManager::getInstance(); + SoundEffect *sample = resman->getSoundEffect(path); + if (sample) { + sample->play(0, 120); + logger.log("Sound::playSfx() Playing: %s", path); } } void Sound::clearCache() { - for (SOUND_SID i = 0; i == items; i++) { - Mix_FreeChunk(soundpool[i]); - soundpool[i] = NULL; + for (SOUND_ID i = 0; i == items; i++) { + soundPool[i]->unload(); + delete soundPool[i]; + soundPool[i] = NULL; } - soundpool.clear(); - logger.log("Sound::clearCache() wiped all items off the cache"); + soundPool.clear(); + logger.log("Sound::clearCache() Wiped all items off the cache"); } void Sound::close() { - isOk = -1; + installed = false; clearCache(); Mix_CloseAudio(); - logger.log("Sound::close() shutting down Sound"); -} - -bool Sound::isMaxVol(int vol) -{ - if (vol > 0 && vol < 128) return false; - else return true; + logger.log("Sound::close() Shutting down sound..."); } diff --git a/src/sound.h b/src/sound.h index 44499618..c0f2f3ba 100644 --- a/src/sound.h +++ b/src/sound.h @@ -24,13 +24,14 @@ #ifndef _TMW_SOUND_H #define _TMW_SOUND_H +#include <guichan.hpp> #include <SDL.h> #include <SDL_mixer.h> #include <map> -#include <string> -#include <fstream> -typedef short SOUND_SID; +#include "resources/resourcemanager.h" + +typedef short SOUND_ID; /** Sound engine * @@ -39,115 +40,103 @@ typedef short SOUND_SID; class Sound { public: /** - * \brief Install the sound engine - * - * \param voices Overall reserved voices - * \param mod_voices Voices dedicated for mod-playback - * - * Overall voices must not be less or equal to the specified amount of - * mod_voices! if mod-voices is too low some mods will not sound - * correctly since a couple of tracks are not going to be played along - * w/ the others. so missing ins- truments can be a result. 32/20 - * sounds realistic here. + * Installs the sound engine. */ - void init(int voices, int mod_voices); + void init(); + + /** + * Logs various info about sound device. + */ + void info(); /** - * \brief Deinstall all sound functionality - * - * Normally you won't need to call this since this is done by SDL when - * shutting itself down. but if you find a reason to delete the - * sound-engine from memory (e.g. garbage-collection) feel free to use - * it. :-P + * Removes all sound functionalities. */ void close(); /** - * \brief Start background music + * Starts background music. * * \param in Full path to file * \param loop The number of times the song is played (-1 = infinite) */ - void startBgm(char *in, int loop = -1); + void playMusic(const char *path, int loop = -1); /** - * \brief Stop all currently running background music tracks + * Stops currently running background music track. + */ + void stopMusic(); + + /** + * Fades in background music. * - * You need to stop all playback when you want to switch from mod to - * midi. playing a new track is usually simple as calling StartMIDI() - * or StartMOD() again. passing NULL to the playing functions only - * means to make playback stop. + * \param in Full path to file + * \param loop The number of times the song is played (-1 = infinite) + * \param ms Duration of fade-in effect (ms) */ - void stopBgm(); + void fadeInMusic(const char *path, int loop = -1, int ms = 2000); + + /** + * Fades out currently running background music track. + * + * \param ms Duration of fade-out effect (ms) + */ + void fadeOutMusic(int ms); /** - * \brief Set the volume value-range: 0-128 + * Sets music volume. * - * \param music Volume value - * - * All values may only be between 0-128 where 0 means muted. + * \param volume Volume value */ - void setVolume(int music); + void setMusicVolume(int volume); /** - * \brief Adjusts current volume - * \param amusic Volume difference + * Sets sfx volume. + * + * \param volume Volume value */ - void adjustVolume(int amusic); + void setSfxVolume(int volume); /** - * \brief Preloads a sound-item into buffer + * Preloads a sound-item into buffer. * - * \param fpath Full path to file - * - * Please make sure that the object is not loaded more than once since - * the function will not run any checks on its own! - * - * The return value should be kept as a reference to the object loaded. - * if not it is practicaly lost. + * \param path Full path to file */ - SOUND_SID loadItem(char *fpath); + SOUND_ID loadSfx(const char *path); /** - * \brief Plays an item in soundpool + * Plays an item in soundpool. * * \param id Id returned to the item in the soundpool - * \param volume Volume the sound should be played with (possible - * range: 0-128) */ - void startItem(SOUND_SID id, int volume); + void playSfx(SOUND_ID id); /** - * \brief Wipe all items off the cache + * Plays an item. + * + * \param path Full path to file + */ + void playSfx(const char *path); + + /** + * Wipe all items off the cache */ void clearCache(); - Sound() { isOk = -1; } + Sound() { installed = false; } - /** if allegro is shut down or object is deleted any BGM is - stopped and SFX run out */ - ~Sound() { stopBgm(); close(); } + ~Sound() { stopMusic(); close(); } private: - /** initial value is -1 which means error or noninitialzed. - you can only play sounds and bgm if this is 0. - that should be the case after calling Init() successfully */ - int isOk; + bool installed; - int pan; - int vol_music; + int musicVolume, sfxVolume; - Mix_Music *bgm; + Mix_Music *music; /** list of preloaded sound data / items */ - std::map<int, Mix_Chunk*> soundpool; - SOUND_SID items; - - /** - * \brief checks if value equals min-/maximum volume and returns - * <code>true</code> if that's the case. - */ - bool isMaxVol(int vol); + std::map<int, SoundEffect*> soundPool; + SOUND_ID items; }; #endif |