/*************************************************************************** * * * 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. * * * ***************************************************************************/ #include #include #include #include #include "../global.h" #include "sound.h" #include "../basestrm.h" #include "../sgstream.h" #include "../music.h" #include "../sgstream.h" /** How long should this process sleep while waiting for a sound to play */ const int WAIT_SLEEP_MSEC = 50; SoundSystem* SoundSystem::instance = NULL; SoundSystem :: SoundSystem ( bool muteEffects, bool muteMusic, bool _off ) { musicState = uninitialized; currentPlaylist = NULL; musicBuf = NULL; this->effectsMuted = muteEffects; this->off = _off; for ( int i = 0; i < MIX_CHANNELS; i++ ) channel[i] = NULL; if ( instance ) fatalError ( "Only one instance of SoundSystem possible !"); instance = this; if( off ) return; if ( SDL_Init ( SDL_INIT_AUDIO ) < 0 ) { warning("Couldn't initialize SDL audio interface !"); off = true; sdl_initialized = false; return; } else sdl_initialized = true; int audio_rate = MIX_DEFAULT_FREQUENCY; Uint16 audio_format = MIX_DEFAULT_FORMAT; int audio_channels = 2; if ( Mix_OpenAudio ( audio_rate, audio_format, audio_channels, 2048 ) < 0 ) { mix_initialized = false; warning("Couldn't initialize SDL_mixer !"); off = true; return; } else { mix_initialized = true; if ( muteMusic ) musicState = init_paused; else musicState = init_ready; Mix_QuerySpec(&audio_rate, &audio_format, &audio_channels); displayLogMessage ( 5, "Opened audio at %d Hz %d bit %s\n", audio_rate, (audio_format&0xFF), (audio_channels > 1) ? "stereo" : "mono"); Mix_HookMusicFinished ( trackFinished ); } } void SoundSystem::setEffectsMute ( bool mute ) { if ( off ) return; if ( mute != this->effectsMuted ) { if ( mute ) { for ( int i = 0; i < MIX_CHANNELS; i++ ) if ( Mix_Playing(i) ) Mix_HaltChannel( i ); } this->effectsMuted = mute; } } void SoundSystem :: trackFinished( void ) { getInstance()->nextTrack(); } void SoundSystem :: nextTrack( void ) { if ( off || musicState==paused || musicState==init_paused) return; if ( musicBuf ) { Mix_FreeMusic( musicBuf ); musicBuf = NULL; } if ( currentPlaylist ) { ASCString filename = currentPlaylist->getNextTrack(); if ( !filename.empty() ) { musicState = playing; musicBuf = Mix_LoadMUS( filename.c_str() ); if ( !musicBuf ) { displayLogMessage ( 1, "Could not load music file " + filename + " ; SDL reports error " + SDL_GetError() + "\n" ); SDL_ClearError(); } else { int chan = Mix_PlayMusic ( musicBuf, 1 ); displayLogMessage ( 4, "Playing music on channel %d \n", chan ); } } } else displayLogMessage ( 1, "No play list available \n" ); } void SoundSystem :: playMusic ( MusicPlayList* playlist ) { currentPlaylist = playlist; nextTrack(); } void SoundSystem :: pauseMusic() { if ( off ) return; if ( musicState == playing ) { Mix_PauseMusic (); musicState = paused; } } void SoundSystem :: resumeMusic() { if ( off ) return; if ( musicState == init_ready || musicState == init_paused ) { if (musicState == init_paused) musicState = init_ready; nextTrack(); return; } if ( musicState == paused ) { Mix_ResumeMusic (); musicState = playing; } } void SoundSystem :: resumePauseMusic() { if ( musicState == playing ) pauseMusic(); else resumeMusic(); } void SoundSystem :: setMusicVolume( int volume ) { musicVolume = volume * 128 / 100; if ( off ) return; Mix_VolumeMusic ( musicVolume ); } void SoundSystem :: setEffectVolume( int volume ) { effectVolume = volume * 128 / 100; if ( off ) return; Mix_Volume ( -1, effectVolume ); } SoundSystem::~SoundSystem() { if ( !off ) { Mix_HaltMusic(); if ( musicBuf ) { Mix_FreeMusic( musicBuf ); musicBuf = NULL; } } if( mix_initialized ) Mix_CloseAudio(); if( sdl_initialized ) SDL_CloseAudio(); instance = NULL; } Mix_Chunk* SoundSystem::loadWave ( const ASCString& name ) { if ( off ) return NULL; if ( !exist ( name.c_str() )) { errorMessage ( " can't open sound file: " + name ); return NULL; } tnfilestream stream ( name, tnstream::reading ); Mix_Chunk* chunk = Mix_LoadWAV_RW( SDL_RWFromStream ( &stream ), 1); if ( chunk ) displayLogMessage ( 10, " SoundSystem::loadWave - sound " + name + " loaded successfully\n"); else displayLogMessage ( 10, " SoundSystem::loadWave - sound " + name + " loaded failed\n"); return chunk; } Sound::Sound( const ASCString& filename, int _fadeIn ) : name ( filename ), wave(NULL), fadeIn ( _fadeIn ) { if ( !SoundSystem::instance ) fatalError ( "Sound::Sound failed, because there is no SoundSystem initialized"); wave = SoundSystem::instance->loadWave( filename ); } void Sound::play(void) { if( SoundSystem::instance->areEffectsMuted() || !wave) return; int channel; if ( fadeIn ) channel = Mix_FadeInChannel ( -1, wave, 0, fadeIn ); else { channel = Mix_PlayChannel ( -1, wave, 0 ); Mix_Volume ( channel, SoundSystem::instance->getEffectVolume() ); } SoundSystem::instance->channel[ channel ] = this; } void Sound::playLoop() { if( SoundSystem::instance->areEffectsMuted() || !wave) return; int channel; if ( fadeIn ) channel = Mix_FadeInChannel ( -1, wave, -1, fadeIn ); else channel = Mix_PlayChannel ( -1, wave, -1 ); SoundSystem::instance->channel[ channel ] = this; } void Sound::stop() { for ( int i = 0; i < MIX_CHANNELS; i++ ) if ( SoundSystem::instance->channel[ i ] == this && Mix_Playing(i) ) Mix_HaltChannel( i ); } void Sound::playWait(void) { if( SoundSystem::instance->areEffectsMuted() || !wave) return; int channel = Mix_PlayChannel ( -1, wave, 0 ); SoundSystem::instance->channel[ channel ] = this; do { SDL_Delay(WAIT_SLEEP_MSEC); } while( SoundSystem::instance->channel[ channel ] == this && Mix_Playing(channel) ); } void Sound :: fadeOut ( int ms ) { for ( int i = 0; i < MIX_CHANNELS; i++ ) if ( SoundSystem::instance->channel[ i ] == this && Mix_Playing(i) ) Mix_FadeOutChannel( i, ms ); } Sound::~Sound(void) { stop(); if ( wave ) Mix_FreeChunk ( wave ); }