Update sound engine with some sound fixes
* Refactor client module
This commit is contained in:
parent
52ede065fc
commit
62cd3d04e1
|
@ -1,30 +1,33 @@
|
||||||
Client = {}
|
local musicFilename = "startup"
|
||||||
|
local musicChannel = g_sounds.getChannel(1)
|
||||||
|
|
||||||
local musicFilename = "startup.ogg"
|
function setMusic(filename)
|
||||||
|
|
||||||
function Client.setMusic(filename)
|
|
||||||
musicFilename = filename
|
musicFilename = filename
|
||||||
g_sounds.stopMusic(0)
|
|
||||||
|
|
||||||
if not g_game.isOnline() then
|
if not g_game.isOnline() then
|
||||||
g_sounds.playMusic(musicFilename, 3)
|
musicChannel:stop()
|
||||||
|
musicChannel:enqueue(musicFilename, 3)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Client.reloadScripts()
|
function reloadScripts()
|
||||||
|
g_textures.clearTexturesCache()
|
||||||
g_modules.reloadModules()
|
g_modules.reloadModules()
|
||||||
dofile '/otclientrc'
|
dofile('/' .. g_app.getCompactName() .. 'rc')
|
||||||
local message = tr('All modules and scripts were reloaded.')
|
local message = tr('All modules and scripts were reloaded.')
|
||||||
|
|
||||||
modules.game_textmessage.displayGameMessage(message)
|
modules.game_textmessage.displayGameMessage(message)
|
||||||
print(message)
|
print(message)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Client.startup()
|
function startup()
|
||||||
-- Play startup music (The Silver Tree, by Mattias Westlund)
|
-- Play startup music (The Silver Tree, by Mattias Westlund)
|
||||||
g_sounds.playMusic(musicFilename, 3)
|
musicChannel:enqueue(musicFilename, 3)
|
||||||
connect(g_game, { onGameStart = function() g_sounds.stopMusic(3) end })
|
connect(g_game, { onGameStart = function() musicChannel:stop(3) end })
|
||||||
connect(g_game, { onGameEnd = function() g_sounds.playMusic(musicFilename, 3) end })
|
connect(g_game, { onGameEnd = function()
|
||||||
|
g_sounds.stopAll()
|
||||||
|
musicChannel:enqueue(musicFilename, 3)
|
||||||
|
end })
|
||||||
|
|
||||||
-- Check for startup errors
|
-- Check for startup errors
|
||||||
local errtitle = nil
|
local errtitle = nil
|
||||||
|
@ -44,7 +47,7 @@ function Client.startup()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Client.init()
|
function init()
|
||||||
g_window.setMinimumSize({ width = 600, height = 480 })
|
g_window.setMinimumSize({ width = 600, height = 480 })
|
||||||
g_sounds.preload(musicFilename)
|
g_sounds.preload(musicFilename)
|
||||||
|
|
||||||
|
@ -62,6 +65,8 @@ function Client.init()
|
||||||
local defaultPos = { x = (displaySize.width - size.width)/2,
|
local defaultPos = { x = (displaySize.width - size.width)/2,
|
||||||
y = (displaySize.height - size.height)/2 }
|
y = (displaySize.height - size.height)/2 }
|
||||||
local pos = g_settings.getPoint('window-pos', defaultPos)
|
local pos = g_settings.getPoint('window-pos', defaultPos)
|
||||||
|
pos.x = math.max(pos.x, 0)
|
||||||
|
pos.y = math.max(pos.y, 0)
|
||||||
g_window.move(pos)
|
g_window.move(pos)
|
||||||
|
|
||||||
-- window maximized?
|
-- window maximized?
|
||||||
|
@ -69,23 +74,25 @@ function Client.init()
|
||||||
if maximized then g_window.maximize() end
|
if maximized then g_window.maximize() end
|
||||||
end
|
end
|
||||||
|
|
||||||
g_window.setTitle('OTClient')
|
g_window.setTitle(g_app.getName())
|
||||||
g_window.setIcon(resolvepath('clienticon.png'))
|
g_window.setIcon(resolvepath('clienticon'))
|
||||||
g_keyboard.bindKeyDown('Ctrl+Shift+R', Client.reloadScripts)
|
|
||||||
|
|
||||||
connect(g_app, { onRun = Client.startup })
|
-- poll resize events
|
||||||
|
g_window.poll()
|
||||||
|
|
||||||
|
g_keyboard.bindKeyDown('Ctrl+Shift+R', reloadScripts)
|
||||||
|
|
||||||
|
connect(g_app, { onRun = startup })
|
||||||
end
|
end
|
||||||
|
|
||||||
function Client.terminate()
|
function terminate()
|
||||||
-- save window configs
|
-- save window configs
|
||||||
g_settings.set('window-size', g_window.getUnmaximizedSize())
|
g_settings.set('window-size', g_window.getUnmaximizedSize())
|
||||||
g_settings.set('window-pos', g_window.getUnmaximizedPos())
|
g_settings.set('window-pos', g_window.getUnmaximizedPos())
|
||||||
g_settings.set('window-maximized', g_window.isMaximized())
|
g_settings.set('window-maximized', g_window.isMaximized())
|
||||||
|
|
||||||
local protocolVersion = g_game.getProtocolVersion()
|
local clientVersion = g_game.getProtocolVersion()
|
||||||
if protocolVersion ~= 0 then
|
if clientVersion ~= 0 then
|
||||||
g_settings.set('protocol-version', protocolVersion)
|
g_settings.set('client-version', clientVersion)
|
||||||
end
|
end
|
||||||
|
|
||||||
Client = nil
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,6 +4,10 @@ Module
|
||||||
author: edubart
|
author: edubart
|
||||||
website: www.otclient.info
|
website: www.otclient.info
|
||||||
reloadable: false
|
reloadable: false
|
||||||
|
sandboxed: true
|
||||||
|
scripts: [ client ]
|
||||||
|
@onLoad: init()
|
||||||
|
@onUnload: terminate()
|
||||||
|
|
||||||
load-later:
|
load-later:
|
||||||
- client_skins
|
- client_skins
|
||||||
|
@ -18,9 +22,3 @@ Module
|
||||||
- client_exit
|
- client_exit
|
||||||
//- client_stats
|
//- client_stats
|
||||||
|
|
||||||
@onLoad: |
|
|
||||||
dofile 'client'
|
|
||||||
Client.init()
|
|
||||||
|
|
||||||
@onUnload: |
|
|
||||||
Client.terminate()
|
|
||||||
|
|
|
@ -184,7 +184,7 @@ function Options.setOption(key, value)
|
||||||
modules.game_interface.updateStretchShrink()
|
modules.game_interface.updateStretchShrink()
|
||||||
end)
|
end)
|
||||||
elseif key == 'enableMusic' then
|
elseif key == 'enableMusic' then
|
||||||
g_sounds.enableMusic(value)
|
g_sounds.enableAudio(value)
|
||||||
elseif key == 'showLeftPanel' then
|
elseif key == 'showLeftPanel' then
|
||||||
addEvent(function()
|
addEvent(function()
|
||||||
modules.game_interface.getLeftPanel():setOn(value)
|
modules.game_interface.getLeftPanel():setOn(value)
|
||||||
|
|
|
@ -426,6 +426,8 @@ if(FRAMEWORK_SOUND)
|
||||||
${CMAKE_CURRENT_LIST_DIR}/sound/oggsoundfile.h
|
${CMAKE_CURRENT_LIST_DIR}/sound/oggsoundfile.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/sound/soundbuffer.cpp
|
${CMAKE_CURRENT_LIST_DIR}/sound/soundbuffer.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/sound/soundbuffer.h
|
${CMAKE_CURRENT_LIST_DIR}/sound/soundbuffer.h
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/sound/soundchannel.cpp
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/sound/soundchannel.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/sound/soundfile.cpp
|
${CMAKE_CURRENT_LIST_DIR}/sound/soundfile.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/sound/soundfile.h
|
${CMAKE_CURRENT_LIST_DIR}/sound/soundfile.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/sound/soundmanager.cpp
|
${CMAKE_CURRENT_LIST_DIR}/sound/soundmanager.cpp
|
||||||
|
|
|
@ -34,6 +34,14 @@
|
||||||
#include <framework/stdext/net.h>
|
#include <framework/stdext/net.h>
|
||||||
#include <framework/platform/platform.h>
|
#include <framework/platform/platform.h>
|
||||||
|
|
||||||
|
#ifdef FW_SOUND
|
||||||
|
#include <framework/sound/soundmanager.h>
|
||||||
|
#include <framework/sound/soundsource.h>
|
||||||
|
#include <framework/sound/soundchannel.h>
|
||||||
|
#include <framework/sound/combinedsoundsource.h>
|
||||||
|
#include <framework/sound/streamsoundsource.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef FW_GRAPHICS
|
#ifdef FW_GRAPHICS
|
||||||
#include <framework/graphics/graphics.h>
|
#include <framework/graphics/graphics.h>
|
||||||
#include <framework/platform/platformwindow.h>
|
#include <framework/platform/platformwindow.h>
|
||||||
|
@ -759,15 +767,29 @@ void Application::registerLuaFunctions()
|
||||||
// SoundManager
|
// SoundManager
|
||||||
g_lua.registerSingletonClass("g_sounds");
|
g_lua.registerSingletonClass("g_sounds");
|
||||||
g_lua.bindSingletonFunction("g_sounds", "preload", &SoundManager::preload, &g_sounds);
|
g_lua.bindSingletonFunction("g_sounds", "preload", &SoundManager::preload, &g_sounds);
|
||||||
g_lua.bindSingletonFunction("g_sounds", "enableSound", &SoundManager::enableSound, &g_sounds);
|
|
||||||
g_lua.bindSingletonFunction("g_sounds", "play", &SoundManager::play, &g_sounds);
|
g_lua.bindSingletonFunction("g_sounds", "play", &SoundManager::play, &g_sounds);
|
||||||
g_lua.bindSingletonFunction("g_sounds", "enableMusic", &SoundManager::enableMusic, &g_sounds);
|
g_lua.bindSingletonFunction("g_sounds", "getChannel", &SoundManager::getChannel, &g_sounds);
|
||||||
g_lua.bindSingletonFunction("g_sounds", "playMusic", &SoundManager::playMusic, &g_sounds);
|
g_lua.bindSingletonFunction("g_sounds", "stopAll", &SoundManager::stopAll, &g_sounds);
|
||||||
g_lua.bindSingletonFunction("g_sounds", "stopMusic", &SoundManager::stopMusic, &g_sounds);
|
g_lua.bindSingletonFunction("g_sounds", "enableAudio", &SoundManager::enableAudio, &g_sounds);
|
||||||
g_lua.bindSingletonFunction("g_sounds", "isMusicEnabled", &SoundManager::isMusicEnabled, &g_sounds);
|
g_lua.bindSingletonFunction("g_sounds", "disableAudio", &SoundManager::disableAudio, &g_sounds);
|
||||||
g_lua.bindSingletonFunction("g_sounds", "isSoundEnabled", &SoundManager::isSoundEnabled, &g_sounds);
|
g_lua.bindSingletonFunction("g_sounds", "setAudioEnabled", &SoundManager::setAudioEnabled, &g_sounds);
|
||||||
g_lua.bindSingletonFunction("g_sounds", "isAudioEnabled", &SoundManager::isAudioEnabled, &g_sounds);
|
g_lua.bindSingletonFunction("g_sounds", "isAudioEnabled", &SoundManager::isAudioEnabled, &g_sounds);
|
||||||
g_lua.bindSingletonFunction("g_sounds", "getCurrentMusic", &SoundManager::getCurrentMusic, &g_sounds);
|
|
||||||
|
g_lua.registerClass<SoundSource>();
|
||||||
|
g_lua.registerClass<CombinedSoundSource, SoundSource>();
|
||||||
|
g_lua.registerClass<StreamSoundSource, SoundSource>();
|
||||||
|
|
||||||
|
g_lua.registerClass<SoundChannel>();
|
||||||
|
g_lua.bindClassMemberFunction<SoundChannel>("play", &SoundChannel::play);
|
||||||
|
g_lua.bindClassMemberFunction<SoundChannel>("stop", &SoundChannel::stop);
|
||||||
|
g_lua.bindClassMemberFunction<SoundChannel>("enqueue", &SoundChannel::enqueue);
|
||||||
|
g_lua.bindClassMemberFunction<SoundChannel>("enable", &SoundChannel::enable);
|
||||||
|
g_lua.bindClassMemberFunction<SoundChannel>("disable", &SoundChannel::disable);
|
||||||
|
g_lua.bindClassMemberFunction<SoundChannel>("setGain", &SoundChannel::setGain);
|
||||||
|
g_lua.bindClassMemberFunction<SoundChannel>("getGain", &SoundChannel::getGain);
|
||||||
|
g_lua.bindClassMemberFunction<SoundChannel>("setEnabled", &SoundChannel::setEnabled);
|
||||||
|
g_lua.bindClassMemberFunction<SoundChannel>("isEnabled", &SoundChannel::isEnabled);
|
||||||
|
g_lua.bindClassMemberFunction<SoundChannel>("getId", &SoundChannel::getId);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef FW_SQL
|
#ifdef FW_SQL
|
||||||
|
|
|
@ -34,6 +34,7 @@ class SoundManager;
|
||||||
class SoundSource;
|
class SoundSource;
|
||||||
class SoundBuffer;
|
class SoundBuffer;
|
||||||
class SoundFile;
|
class SoundFile;
|
||||||
|
class SoundChannel;
|
||||||
class StreamSoundSource;
|
class StreamSoundSource;
|
||||||
class CombinedSoundSource;
|
class CombinedSoundSource;
|
||||||
class OggSoundFile;
|
class OggSoundFile;
|
||||||
|
@ -41,6 +42,7 @@ class OggSoundFile;
|
||||||
typedef stdext::shared_object_ptr<SoundSource> SoundSourcePtr;
|
typedef stdext::shared_object_ptr<SoundSource> SoundSourcePtr;
|
||||||
typedef stdext::shared_object_ptr<SoundFile> SoundFilePtr;
|
typedef stdext::shared_object_ptr<SoundFile> SoundFilePtr;
|
||||||
typedef stdext::shared_object_ptr<SoundBuffer> SoundBufferPtr;
|
typedef stdext::shared_object_ptr<SoundBuffer> SoundBufferPtr;
|
||||||
|
typedef stdext::shared_object_ptr<SoundChannel> SoundChannelPtr;
|
||||||
typedef stdext::shared_object_ptr<StreamSoundSource> StreamSoundSourcePtr;
|
typedef stdext::shared_object_ptr<StreamSoundSource> StreamSoundSourcePtr;
|
||||||
typedef stdext::shared_object_ptr<CombinedSoundSource> CombinedSoundSourcePtr;
|
typedef stdext::shared_object_ptr<CombinedSoundSource> CombinedSoundSourcePtr;
|
||||||
typedef stdext::shared_object_ptr<OggSoundFile> OggSoundFilePtr;
|
typedef stdext::shared_object_ptr<OggSoundFile> OggSoundFilePtr;
|
||||||
|
|
|
@ -46,21 +46,21 @@ void SoundManager::init()
|
||||||
g_logger.error(stdext::format("unable to create audio context: %s", alcGetString(m_device, alcGetError(m_device))));
|
g_logger.error(stdext::format("unable to create audio context: %s", alcGetString(m_device, alcGetError(m_device))));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
alcMakeContextCurrent(m_context);
|
|
||||||
|
|
||||||
m_musicEnabled = true;
|
if(alcMakeContextCurrent(m_context) != ALC_TRUE) {
|
||||||
m_soundEnabled = true;
|
g_logger.error(stdext::format("unable to make context current: %s", alcGetString(m_device, alcGetError(m_device))));
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundManager::terminate()
|
void SoundManager::terminate()
|
||||||
{
|
{
|
||||||
|
ensureContext();
|
||||||
|
|
||||||
m_sources.clear();
|
m_sources.clear();
|
||||||
m_buffers.clear();
|
m_buffers.clear();
|
||||||
m_musicSource = nullptr;
|
m_channels.clear();
|
||||||
m_currentMusic = "";
|
m_audioEnabled = false;
|
||||||
|
|
||||||
m_musicEnabled = false;
|
|
||||||
m_soundEnabled = false;
|
|
||||||
|
|
||||||
alcMakeContextCurrent(nullptr);
|
alcMakeContextCurrent(nullptr);
|
||||||
|
|
||||||
|
@ -85,6 +85,7 @@ void SoundManager::poll()
|
||||||
|
|
||||||
lastUpdate = now;
|
lastUpdate = now;
|
||||||
|
|
||||||
|
ensureContext();
|
||||||
for(auto it = m_sources.begin(); it != m_sources.end();) {
|
for(auto it = m_sources.begin(); it != m_sources.end();) {
|
||||||
SoundSourcePtr source = *it;
|
SoundSourcePtr source = *it;
|
||||||
|
|
||||||
|
@ -96,10 +97,8 @@ void SoundManager::poll()
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_musicSource) {
|
for(auto it : m_channels) {
|
||||||
m_musicSource->update();
|
it.second->update();
|
||||||
if(!m_musicSource->isPlaying())
|
|
||||||
m_musicSource = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(m_context) {
|
if(m_context) {
|
||||||
|
@ -107,18 +106,33 @@ void SoundManager::poll()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SoundManager::setAudioEnabled(bool enable)
|
||||||
|
{
|
||||||
|
if(m_audioEnabled == enable)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_audioEnabled = enable;
|
||||||
|
if(!enable) {
|
||||||
|
ensureContext();
|
||||||
|
for(const SoundSourcePtr& source : m_sources) {
|
||||||
|
source->stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SoundManager::preload(std::string filename)
|
void SoundManager::preload(std::string filename)
|
||||||
{
|
{
|
||||||
filename = g_resources.resolvePath(filename);
|
filename = resolveSoundFile(filename);
|
||||||
|
|
||||||
auto it = m_buffers.find(filename);
|
auto it = m_buffers.find(filename);
|
||||||
if(it != m_buffers.end())
|
if(it != m_buffers.end())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
ensureContext();
|
||||||
SoundFilePtr soundFile = SoundFile::loadSoundFile(filename);
|
SoundFilePtr soundFile = SoundFile::loadSoundFile(filename);
|
||||||
|
|
||||||
// only keep small files
|
// only keep small files
|
||||||
if(soundFile->getSize() > MAX_CACHE_SIZE)
|
if(!soundFile || soundFile->getSize() > MAX_CACHE_SIZE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SoundBufferPtr buffer = SoundBufferPtr(new SoundBuffer);
|
SoundBufferPtr buffer = SoundBufferPtr(new SoundBuffer);
|
||||||
|
@ -126,85 +140,55 @@ void SoundManager::preload(std::string filename)
|
||||||
m_buffers[filename] = buffer;
|
m_buffers[filename] = buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundManager::enableSound(bool enable)
|
SoundSourcePtr SoundManager::play(std::string filename, float fadetime, float gain)
|
||||||
{
|
{
|
||||||
if(!isAudioEnabled())
|
if(!m_audioEnabled)
|
||||||
return;
|
return nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
void SoundManager::play(std::string filename)
|
ensureContext();
|
||||||
{
|
|
||||||
if(!m_soundEnabled || filename.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
filename = g_resources.resolvePath(filename);
|
if(gain == 0)
|
||||||
|
gain = 1.0f;
|
||||||
|
|
||||||
|
filename = resolveSoundFile(filename);
|
||||||
SoundSourcePtr soundSource = createSoundSource(filename);
|
SoundSourcePtr soundSource = createSoundSource(filename);
|
||||||
if(!soundSource) {
|
if(!soundSource) {
|
||||||
g_logger.error(stdext::format("unable to play '%s'", filename));
|
g_logger.error(stdext::format("unable to play '%s'", filename));
|
||||||
return;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
soundSource->setName(filename);
|
||||||
soundSource->setRelative(true);
|
soundSource->setRelative(true);
|
||||||
|
soundSource->setGain(gain);
|
||||||
|
|
||||||
|
if(fadetime > 0) {
|
||||||
|
soundSource->setFading(StreamSoundSource::FadingOn, fadetime);
|
||||||
|
}
|
||||||
|
|
||||||
soundSource->play();
|
soundSource->play();
|
||||||
|
|
||||||
m_sources.push_back(soundSource);
|
m_sources.push_back(soundSource);
|
||||||
|
|
||||||
|
return soundSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundManager::enableMusic(bool enable)
|
SoundChannelPtr SoundManager::getChannel(int channel)
|
||||||
{
|
{
|
||||||
if(!isAudioEnabled())
|
ensureContext();
|
||||||
return;
|
if(!m_channels[channel])
|
||||||
|
m_channels[channel] = SoundChannelPtr(new SoundChannel(channel));
|
||||||
m_musicEnabled = enable;
|
return m_channels[channel];
|
||||||
|
|
||||||
if(enable && !m_currentMusic.empty())
|
|
||||||
playMusic(m_currentMusic, 3.0f);
|
|
||||||
else
|
|
||||||
m_musicSource = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundManager::playMusic(std::string filename, float fadetime)
|
void SoundManager::stopAll()
|
||||||
{
|
{
|
||||||
if(filename.empty())
|
ensureContext();
|
||||||
return;
|
for(const SoundSourcePtr& source : m_sources) {
|
||||||
|
source->stop();
|
||||||
filename = g_resources.resolvePath(filename);
|
|
||||||
|
|
||||||
if(m_currentMusic == filename && m_musicSource)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(!m_musicEnabled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(filename.empty()) {
|
|
||||||
m_musicSource = nullptr;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_musicSource = createSoundSource(filename);
|
for(auto it : m_channels) {
|
||||||
if(!m_musicSource) {
|
it.second->stop();
|
||||||
g_logger.error(stdext::format("unable to play '%s'", filename));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_musicSource->setRelative(true);
|
|
||||||
|
|
||||||
if(fadetime > 0) {
|
|
||||||
m_musicSource->setGain(0);
|
|
||||||
m_musicSource->setFading(StreamSoundSource::FadingOn, fadetime);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_musicSource->play();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SoundManager::stopMusic(float fadetime)
|
|
||||||
{
|
|
||||||
if(m_musicSource) {
|
|
||||||
if(fadetime > 0)
|
|
||||||
m_musicSource->setFading(StreamSoundSource::FadingOff, 3.0f);
|
|
||||||
else
|
|
||||||
m_musicSource->stop();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,51 +196,69 @@ SoundSourcePtr SoundManager::createSoundSource(const std::string& filename)
|
||||||
{
|
{
|
||||||
SoundSourcePtr source;
|
SoundSourcePtr source;
|
||||||
|
|
||||||
auto it = m_buffers.find(filename);
|
try {
|
||||||
if(it != m_buffers.end()) {
|
auto it = m_buffers.find(filename);
|
||||||
source = SoundSourcePtr(new SoundSource);
|
if(it != m_buffers.end()) {
|
||||||
source->setBuffer(it->second);
|
|
||||||
} else {
|
|
||||||
SoundFilePtr soundFile = SoundFile::loadSoundFile(filename);
|
|
||||||
if(!soundFile)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
if(soundFile->getSize() <= MAX_CACHE_SIZE) {
|
|
||||||
source = SoundSourcePtr(new SoundSource);
|
source = SoundSourcePtr(new SoundSource);
|
||||||
SoundBufferPtr buffer = SoundBufferPtr(new SoundBuffer);
|
source->setBuffer(it->second);
|
||||||
buffer->fillBuffer(soundFile);
|
|
||||||
source->setBuffer(buffer);
|
|
||||||
m_buffers[filename] = buffer;
|
|
||||||
g_logger.warning(stdext::format("uncached sound '%s' requested to be played", filename));
|
|
||||||
} else {
|
} else {
|
||||||
StreamSoundSourcePtr streamSource(new StreamSoundSource);
|
SoundFilePtr soundFile = SoundFile::loadSoundFile(filename);
|
||||||
streamSource->setSoundFile(soundFile);
|
if(!soundFile)
|
||||||
source = streamSource;
|
return nullptr;
|
||||||
|
|
||||||
#if defined __linux && !defined OPENGL_ES
|
if(soundFile->getSize() <= MAX_CACHE_SIZE) {
|
||||||
// due to OpenAL implementation bug, stereo buffers are always downmixed to mono on linux systems
|
source = SoundSourcePtr(new SoundSource);
|
||||||
// this is hack to work around the issue
|
SoundBufferPtr buffer = SoundBufferPtr(new SoundBuffer);
|
||||||
// solution taken from http://opensource.creative.com/pipermail/openal/2007-April/010355.html
|
buffer->fillBuffer(soundFile);
|
||||||
if(soundFile->getSampleFormat() == AL_FORMAT_STEREO16) {
|
source->setBuffer(buffer);
|
||||||
CombinedSoundSourcePtr combinedSource(new CombinedSoundSource);
|
m_buffers[filename] = buffer;
|
||||||
|
g_logger.warning(stdext::format("uncached sound '%s' requested to be played", filename));
|
||||||
|
} else {
|
||||||
|
StreamSoundSourcePtr streamSource(new StreamSoundSource);
|
||||||
|
streamSource->setSoundFile(soundFile);
|
||||||
|
source = streamSource;
|
||||||
|
|
||||||
streamSource->downMix(StreamSoundSource::DownMixLeft);
|
#if defined __linux && !defined OPENGL_ES
|
||||||
streamSource->setRelative(true);
|
// due to OpenAL implementation bug, stereo buffers are always downmixed to mono on linux systems
|
||||||
streamSource->setPosition(Point(-128, 0));
|
// this is hack to work around the issue
|
||||||
combinedSource->addSource(streamSource);
|
// solution taken from http://opensource.creative.com/pipermail/openal/2007-April/010355.html
|
||||||
|
if(soundFile->getSampleFormat() == AL_FORMAT_STEREO16) {
|
||||||
|
CombinedSoundSourcePtr combinedSource(new CombinedSoundSource);
|
||||||
|
|
||||||
streamSource = StreamSoundSourcePtr(new StreamSoundSource);
|
streamSource->downMix(StreamSoundSource::DownMixLeft);
|
||||||
streamSource->setSoundFile(SoundFile::loadSoundFile(filename));
|
streamSource->setRelative(true);
|
||||||
streamSource->downMix(StreamSoundSource::DownMixRight);
|
streamSource->setPosition(Point(-128, 0));
|
||||||
streamSource->setRelative(true);
|
combinedSource->addSource(streamSource);
|
||||||
streamSource->setPosition(Point(128,0));
|
|
||||||
combinedSource->addSource(streamSource);
|
|
||||||
|
|
||||||
source = combinedSource;
|
streamSource = StreamSoundSourcePtr(new StreamSoundSource);
|
||||||
|
streamSource->setSoundFile(SoundFile::loadSoundFile(filename));
|
||||||
|
streamSource->downMix(StreamSoundSource::DownMixRight);
|
||||||
|
streamSource->setRelative(true);
|
||||||
|
streamSource->setPosition(Point(128,0));
|
||||||
|
combinedSource->addSource(streamSource);
|
||||||
|
|
||||||
|
source = combinedSource;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
} catch(std::exception& e) {
|
||||||
|
g_logger.error(stdext::format("failed to load sound source: '%s'", e.what()));
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string SoundManager::resolveSoundFile(std::string file)
|
||||||
|
{
|
||||||
|
file = g_resources.guessFileType(file, "ogg");
|
||||||
|
file = g_resources.resolvePath(file);
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SoundManager::ensureContext()
|
||||||
|
{
|
||||||
|
if(m_context)
|
||||||
|
alcMakeContextCurrent(m_context);
|
||||||
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#define SOUNDMANAGER_H
|
#define SOUNDMANAGER_H
|
||||||
|
|
||||||
#include "declarations.h"
|
#include "declarations.h"
|
||||||
|
#include "soundchannel.h"
|
||||||
|
|
||||||
//@bindsingleton g_sounds
|
//@bindsingleton g_sounds
|
||||||
class SoundManager
|
class SoundManager
|
||||||
|
@ -32,38 +33,34 @@ class SoundManager
|
||||||
MAX_CACHE_SIZE = 100000,
|
MAX_CACHE_SIZE = 100000,
|
||||||
POLL_DELAY = 100
|
POLL_DELAY = 100
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void init();
|
void init();
|
||||||
void terminate();
|
void terminate();
|
||||||
void poll();
|
void poll();
|
||||||
|
|
||||||
|
void setAudioEnabled(bool enable);
|
||||||
|
bool isAudioEnabled() { return m_device && m_context && m_audioEnabled ; }
|
||||||
|
void enableAudio() { setAudioEnabled(true); }
|
||||||
|
void disableAudio() { setAudioEnabled(true); }
|
||||||
|
void stopAll();
|
||||||
|
|
||||||
void preload(std::string filename);
|
void preload(std::string filename);
|
||||||
void enableSound(bool enable);
|
SoundSourcePtr play(std::string filename, float fadetime = 0, float gain = 0);
|
||||||
void play(std::string filename);
|
SoundChannelPtr getChannel(int channel);
|
||||||
|
|
||||||
void enableMusic(bool enable);
|
std::string resolveSoundFile(std::string file);
|
||||||
void playMusic(std::string filename, float fadetime);
|
void ensureContext();
|
||||||
void stopMusic(float fadetime = 0);
|
|
||||||
|
|
||||||
bool isMusicEnabled() { return m_musicEnabled; }
|
|
||||||
bool isSoundEnabled() { return m_soundEnabled; }
|
|
||||||
bool isAudioEnabled() { return m_device && m_context; }
|
|
||||||
std::string getCurrentMusic() { return m_currentMusic; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StreamSoundSourcePtr createStreamSoundSource(const std::string& filename);
|
|
||||||
SoundSourcePtr createSoundSource(const std::string& filename);
|
SoundSourcePtr createSoundSource(const std::string& filename);
|
||||||
uint loadFileIntoBuffer(const SoundFilePtr& soundFile);
|
|
||||||
|
ALCdevice *m_device;
|
||||||
|
ALCcontext *m_context;
|
||||||
|
|
||||||
std::unordered_map<std::string, SoundBufferPtr> m_buffers;
|
std::unordered_map<std::string, SoundBufferPtr> m_buffers;
|
||||||
std::vector<SoundSourcePtr> m_sources;
|
std::vector<SoundSourcePtr> m_sources;
|
||||||
SoundSourcePtr m_musicSource;
|
stdext::boolean<true> m_audioEnabled;
|
||||||
ALCdevice *m_device;
|
std::unordered_map<int, SoundChannelPtr> m_channels;
|
||||||
ALCcontext *m_context;
|
|
||||||
stdext::boolean<false> m_musicEnabled;
|
|
||||||
stdext::boolean<false> m_soundEnabled;
|
|
||||||
std::string m_currentMusic;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern SoundManager g_sounds;
|
extern SoundManager g_sounds;
|
||||||
|
|
|
@ -28,9 +28,12 @@
|
||||||
SoundSource::SoundSource()
|
SoundSource::SoundSource()
|
||||||
{
|
{
|
||||||
m_sourceId = 0;
|
m_sourceId = 0;
|
||||||
|
m_channel = 0;
|
||||||
m_fadeState = NoFading;
|
m_fadeState = NoFading;
|
||||||
m_fadeTime = 0;
|
m_fadeTime = 0;
|
||||||
m_fadeStartTime = 0;
|
m_fadeStartTime = 0;
|
||||||
|
m_fadeGain = 0;
|
||||||
|
m_gain = 1.0f;
|
||||||
|
|
||||||
alGenSources(1, &m_sourceId);
|
alGenSources(1, &m_sourceId);
|
||||||
assert(alGetError() == AL_NO_ERROR);
|
assert(alGetError() == AL_NO_ERROR);
|
||||||
|
@ -95,6 +98,7 @@ void SoundSource::setReferenceDistance(float distance)
|
||||||
void SoundSource::setGain(float gain)
|
void SoundSource::setGain(float gain)
|
||||||
{
|
{
|
||||||
alSourcef(m_sourceId, AL_GAIN, gain);
|
alSourcef(m_sourceId, AL_GAIN, gain);
|
||||||
|
m_gain = gain;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundSource::setPitch(float pitch)
|
void SoundSource::setPitch(float pitch)
|
||||||
|
@ -114,7 +118,7 @@ void SoundSource::setVelocity(const Point& velocity)
|
||||||
|
|
||||||
void SoundSource::setFading(FadeState state, float fadeTime)
|
void SoundSource::setFading(FadeState state, float fadeTime)
|
||||||
{
|
{
|
||||||
float now = g_clock.seconds();
|
float now = stdext::millis() / 1000.0f;
|
||||||
if(m_fadeState != NoFading) {
|
if(m_fadeState != NoFading) {
|
||||||
float elapsed = now - m_fadeStartTime;
|
float elapsed = now - m_fadeStartTime;
|
||||||
float add;
|
float add;
|
||||||
|
@ -128,26 +132,30 @@ void SoundSource::setFading(FadeState state, float fadeTime)
|
||||||
|
|
||||||
m_fadeState = state;
|
m_fadeState = state;
|
||||||
m_fadeTime = fadeTime;
|
m_fadeTime = fadeTime;
|
||||||
|
m_fadeGain = m_gain;
|
||||||
|
|
||||||
|
if(m_fadeState == FadingOn)
|
||||||
|
setGain(0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SoundSource::update()
|
void SoundSource::update()
|
||||||
{
|
{
|
||||||
float now = g_clock.seconds();
|
float now = stdext::millis() / 1000.0f;
|
||||||
if(m_fadeState == FadingOn) {
|
if(m_fadeState == FadingOn) {
|
||||||
float elapsed = now - m_fadeStartTime;
|
float elapsed = now - m_fadeStartTime;
|
||||||
if(elapsed >= m_fadeTime) {
|
if(elapsed >= m_fadeTime) {
|
||||||
setGain(1.0);
|
|
||||||
m_fadeState = NoFading;
|
m_fadeState = NoFading;
|
||||||
} else {
|
} else {
|
||||||
setGain(elapsed / m_fadeTime);
|
setGain((elapsed / m_fadeTime) * m_fadeGain);
|
||||||
}
|
}
|
||||||
} else if(m_fadeState == FadingOff) {
|
} else if(m_fadeState == FadingOff) {
|
||||||
float time = now - m_fadeStartTime;
|
float elapsed = now - m_fadeStartTime;
|
||||||
if(time >= m_fadeTime) {
|
if(elapsed >= m_fadeTime) {
|
||||||
|
setGain(m_fadeGain);
|
||||||
stop();
|
stop();
|
||||||
m_fadeState = NoFading;
|
m_fadeState = NoFading;
|
||||||
} else {
|
} else {
|
||||||
setGain((m_fadeTime - time) / m_fadeTime);
|
setGain(((m_fadeTime - elapsed) / m_fadeTime) * m_fadeGain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,8 +25,9 @@
|
||||||
|
|
||||||
#include "declarations.h"
|
#include "declarations.h"
|
||||||
#include "soundbuffer.h"
|
#include "soundbuffer.h"
|
||||||
|
#include <framework/luaengine/luaobject.h>
|
||||||
|
|
||||||
class SoundSource : public stdext::shared_object
|
class SoundSource : public LuaObject
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
SoundSource(uint sourceId) : m_sourceId(sourceId) { }
|
SoundSource(uint sourceId) : m_sourceId(sourceId) { }
|
||||||
|
@ -43,6 +44,7 @@ public:
|
||||||
virtual bool isBuffering();
|
virtual bool isBuffering();
|
||||||
virtual bool isPlaying() { return isBuffering(); }
|
virtual bool isPlaying() { return isBuffering(); }
|
||||||
|
|
||||||
|
void setName(const std::string& name) { m_name == name; }
|
||||||
virtual void setLooping(bool looping);
|
virtual void setLooping(bool looping);
|
||||||
virtual void setRelative(bool relative);
|
virtual void setRelative(bool relative);
|
||||||
virtual void setReferenceDistance(float distance);
|
virtual void setReferenceDistance(float distance);
|
||||||
|
@ -52,18 +54,27 @@ public:
|
||||||
virtual void setVelocity(const Point& velocity);
|
virtual void setVelocity(const Point& velocity);
|
||||||
virtual void setFading(FadeState state, float fadetime);
|
virtual void setFading(FadeState state, float fadetime);
|
||||||
|
|
||||||
|
std::string getName() { return m_name; }
|
||||||
|
uchar getChannel() { return m_channel; }
|
||||||
|
float getGain() { return m_gain; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void setBuffer(const SoundBufferPtr& buffer);
|
void setBuffer(const SoundBufferPtr& buffer);
|
||||||
|
void setChannel(uchar channel) { m_channel = channel; }
|
||||||
|
|
||||||
virtual void update();
|
virtual void update();
|
||||||
friend class SoundManager;
|
friend class SoundManager;
|
||||||
friend class CombinedSoundSource;
|
friend class CombinedSoundSource;
|
||||||
|
|
||||||
uint m_sourceId;
|
uint m_sourceId;
|
||||||
|
uchar m_channel;
|
||||||
|
std::string m_name;
|
||||||
SoundBufferPtr m_buffer;
|
SoundBufferPtr m_buffer;
|
||||||
FadeState m_fadeState;
|
FadeState m_fadeState;
|
||||||
float m_fadeStartTime;
|
float m_fadeStartTime;
|
||||||
float m_fadeTime;
|
float m_fadeTime;
|
||||||
|
float m_fadeGain;
|
||||||
|
float m_gain;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -28,8 +28,8 @@
|
||||||
class StreamSoundSource : public SoundSource
|
class StreamSoundSource : public SoundSource
|
||||||
{
|
{
|
||||||
enum {
|
enum {
|
||||||
STREAM_BUFFER_SIZE = 1024 * 200,
|
STREAM_BUFFER_SIZE = 1024 * 400,
|
||||||
STREAM_FRAGMENTS = 5,
|
STREAM_FRAGMENTS = 4,
|
||||||
STREAM_FRAGMENT_SIZE = STREAM_BUFFER_SIZE / STREAM_FRAGMENTS
|
STREAM_FRAGMENT_SIZE = STREAM_BUFFER_SIZE / STREAM_FRAGMENTS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue