// NeL - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #include "stdsound.h" #include "nel/sound/music_channel_fader.h" // Project includes #include "nel/sound/driver/sound_driver.h" #include "nel/sound/driver/music_channel.h" #include "nel/sound/source_music_channel.h" using namespace std; using namespace NLMISC; namespace NLSOUND { CMusicChannelFader::CMusicChannelFader() : _SoundDriver(NULL), _ActiveMusicFader(0), _Gain(1.0f), _LastTime(0) { } CMusicChannelFader::~CMusicChannelFader() { } void CMusicChannelFader::init(ISoundDriver *soundDriver) { nlassert(!_SoundDriver); _SoundDriver = soundDriver; _ActiveMusicFader = 0; _Gain = 1.0f; _LastTime = CTime::getLocalTime(); for (uint i = 0; i < _MaxMusicFader; ++i) { nlassert(!_MusicFader[i].MusicChannel); _MusicFader[i].MusicChannel = _SoundDriver->createMusicChannel(); if (!_MusicFader[i].MusicChannel) { if (_SoundDriver->getOption(ISoundDriver::OptionHasBufferStreaming)) { _MusicFader[i].MusicChannel = new CSourceMusicChannel(); } else { release(); nlwarning("No music channel available!"); return; } } } } void CMusicChannelFader::release() { if (_SoundDriver) { for (uint i = 0; i < _MaxMusicFader; ++i) if (_MusicFader[i].MusicChannel) { delete _MusicFader[i].MusicChannel; _MusicFader[i].MusicChannel = NULL; } _SoundDriver = NULL; } } void CMusicChannelFader::reset() { for (uint i = 0; i < _MaxMusicFader; ++i) if (_MusicFader[i].MusicChannel) { if (_MusicFader[i].MusicChannel) _MusicFader[i].MusicChannel->reset(); } } void CMusicChannelFader::update() { TTime current_time = CTime::getLocalTime(); float delta_time = (float)(current_time - _LastTime) / 1000.0f; _LastTime = current_time; for (uint i = 0; i < _MaxMusicFader; ++i) { _CMusicFader &fader = _MusicFader[i]; if (fader.Playing) { if (fader.MusicChannel->isEnded()) { fader.MusicChannel->stop(); fader.Playing = false; fader.Fade = false; } else if (fader.Fade) { // wait with fading in until the song has started playing (at 0 volume) if (!fader.MusicChannel->isLoadingAsync()) { fader.XFadeVolume += fader.XFadeDVolume * delta_time; if (fader.XFadeVolume <= 0.f) { // fadeout complete fader.MusicChannel->stop(); fader.Fade = false; fader.Playing = false; } else if (fader.XFadeVolume >= 1.f) { // fadein complete fader.Fade = false; fader.XFadeVolume = 1.f; } } } } } updateVolume(); } void CMusicChannelFader::updateVolume() { for (uint i = 0; i < _MaxMusicFader; ++i) if (_MusicFader[i].Playing) _MusicFader[i].MusicChannel->setVolume(_MusicFader[i].XFadeVolume * _Gain); } /** Play some music (.ogg etc...) * NB: if an old music was played, it is first stop with stopMusic() * \param filepath file path, CPath::lookup is done here * \param async stream music from hard disk, preload in memory if false * \param loop must be true to play the music in loop. */ bool CMusicChannelFader::play(const std::string &filepath, uint xFadeTime, bool async, bool loop) { stop(xFadeTime); // Find the next best free music channel uint nextFader = _MaxMusicFader; for (uint i = 0; i < _MaxMusicFader; ++i) if (!_MusicFader[i].Playing) { nextFader = i; break; } if (nextFader == _MaxMusicFader) { nextFader = (_ActiveMusicFader + 1) % _MaxMusicFader; _MusicFader[nextFader].MusicChannel->stop(); _MusicFader[nextFader].Fade = false; _MusicFader[nextFader].Playing = false; } _ActiveMusicFader = nextFader; // Play a song in it :) _CMusicFader &fader = _MusicFader[_ActiveMusicFader]; if (xFadeTime) fader.fadeIn(xFadeTime); else fader.XFadeVolume = 1.0f; fader.Playing = true; updateVolume(); // make sure at ok volume to start :) fader.Playing = fader.MusicChannel->play(filepath, async, loop); return fader.Playing; } /// Stop the music previously loaded and played (the Memory is also freed) void CMusicChannelFader::stop(uint xFadeTime) { if (xFadeTime) { for (uint i = 0; i < _MaxMusicFader; ++i) if (_MusicFader[i].Playing) _MusicFader[i].fadeOut(xFadeTime); } else { for (uint i = 0; i < _MaxMusicFader; ++i) if (_MusicFader[i].Playing) { _MusicFader[i].MusicChannel->stop(); _MusicFader[i].Fade = false; _MusicFader[i].Playing = false; } } } /// Pause the music previously loaded and played (the Memory is not freed) void CMusicChannelFader::pause() { for (uint i = 0; i < _MaxMusicFader; ++i) if (_MusicFader[i].Playing) _MusicFader[i].MusicChannel->pause(); } /// Resume the music previously paused void CMusicChannelFader::resume() { for (uint i = 0; i < _MaxMusicFader; ++i) if (_MusicFader[i].Playing) _MusicFader[i].MusicChannel->resume(); } /// Return true if all songs are finished. bool CMusicChannelFader::isEnded() { for (uint i = 0; i < _MaxMusicFader; ++i) { if (_MusicFader[i].Playing) if (!_MusicFader[i].MusicChannel->isEnded()) return false; // at least one song still playing } return true; // no song found that is still playing } /// Return the total length (in second) of the music currently played float CMusicChannelFader::getLength() { return _MusicFader[_ActiveMusicFader].MusicChannel->getLength(); } /// Set the music volume (if any music played). (volume value inside [0 , 1]) (default: 1) /// NB: the volume of music is NOT affected by IListener::setGain() void CMusicChannelFader::setVolume(float gain) { _Gain = gain; updateVolume(); } } /* namespace NLSOUND */ /* end of file */