mirror of
https://github.com/edubart/otclient.git
synced 2025-10-20 06:23:26 +02:00
Implement async dispatcher #221
This commit is contained in:
@@ -31,11 +31,10 @@ SoundFile::SoundFile(const FileStreamPtr& fileStream)
|
||||
|
||||
SoundFilePtr SoundFile::loadSoundFile(const std::string& filename)
|
||||
{
|
||||
stdext::timer t;
|
||||
FileStreamPtr file = g_resources.openFile(filename);
|
||||
if(!file) {
|
||||
g_logger.traceError(stdext::format("unable to open %s", filename));
|
||||
return nullptr;
|
||||
}
|
||||
if(!file)
|
||||
stdext::throw_exception(stdext::format("unable to open %s", filename));
|
||||
|
||||
// cache file buffer to avoid lags from hard drive
|
||||
file->cache();
|
||||
@@ -50,7 +49,7 @@ SoundFilePtr SoundFile::loadSoundFile(const std::string& filename)
|
||||
if(oggSoundFile->prepareOgg())
|
||||
soundFile = oggSoundFile;
|
||||
} else
|
||||
g_logger.error(stdext::format("unknown sound file format %s", filename));
|
||||
stdext::throw_exception(stdext::format("unknown sound file format %s", filename));
|
||||
|
||||
return soundFile;
|
||||
}
|
||||
|
@@ -30,6 +30,8 @@
|
||||
#include <framework/core/clock.h>
|
||||
#include <framework/core/eventdispatcher.h>
|
||||
#include <framework/core/resourcemanager.h>
|
||||
#include <framework/core/asyncdispatcher.h>
|
||||
#include <thread>
|
||||
|
||||
SoundManager g_sounds;
|
||||
|
||||
@@ -57,9 +59,14 @@ void SoundManager::terminate()
|
||||
{
|
||||
ensureContext();
|
||||
|
||||
for(auto it = m_streamFiles.begin(); it != m_streamFiles.end();++it)
|
||||
it->second.wait();
|
||||
m_streamFiles.clear();
|
||||
|
||||
m_sources.clear();
|
||||
m_buffers.clear();
|
||||
m_channels.clear();
|
||||
|
||||
m_audioEnabled = false;
|
||||
|
||||
alcMakeContextCurrent(nullptr);
|
||||
@@ -86,6 +93,23 @@ void SoundManager::poll()
|
||||
lastUpdate = now;
|
||||
|
||||
ensureContext();
|
||||
|
||||
for(auto it = m_streamFiles.begin(); it != m_streamFiles.end();) {
|
||||
StreamSoundSourcePtr source = it->first;
|
||||
std::future<SoundFilePtr>& future = it->second;
|
||||
|
||||
if(std::is_ready(future)) {
|
||||
SoundFilePtr sound = future.get();
|
||||
if(sound)
|
||||
source->setSoundFile(sound);
|
||||
else
|
||||
source->stop();
|
||||
it = m_streamFiles.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
for(auto it = m_sources.begin(); it != m_sources.end();) {
|
||||
SoundSourcePtr source = *it;
|
||||
|
||||
@@ -161,9 +185,8 @@ SoundSourcePtr SoundManager::play(std::string filename, float fadetime, float ga
|
||||
soundSource->setRelative(true);
|
||||
soundSource->setGain(gain);
|
||||
|
||||
if(fadetime > 0) {
|
||||
if(fadetime > 0)
|
||||
soundSource->setFading(StreamSoundSource::FadingOn, fadetime);
|
||||
}
|
||||
|
||||
soundSource->play();
|
||||
|
||||
@@ -202,45 +225,55 @@ SoundSourcePtr SoundManager::createSoundSource(const std::string& filename)
|
||||
source = SoundSourcePtr(new SoundSource);
|
||||
source->setBuffer(it->second);
|
||||
} else {
|
||||
SoundFilePtr soundFile = SoundFile::loadSoundFile(filename);
|
||||
if(!soundFile)
|
||||
return nullptr;
|
||||
#if defined __linux && !defined OPENGL_ES
|
||||
// due to OpenAL implementation bug, stereo buffers are always downmixed to mono on linux systems
|
||||
// this is hack to work around the issue
|
||||
// solution taken from http://opensource.creative.com/pipermail/openal/2007-April/010355.html
|
||||
CombinedSoundSourcePtr combinedSource(new CombinedSoundSource);
|
||||
StreamSoundSourcePtr streamSource;
|
||||
|
||||
if(soundFile->getSize() <= MAX_CACHE_SIZE) {
|
||||
source = SoundSourcePtr(new SoundSource);
|
||||
SoundBufferPtr buffer = SoundBufferPtr(new SoundBuffer);
|
||||
buffer->fillBuffer(soundFile);
|
||||
source->setBuffer(buffer);
|
||||
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;
|
||||
|
||||
#if defined __linux && !defined OPENGL_ES
|
||||
// due to OpenAL implementation bug, stereo buffers are always downmixed to mono on linux systems
|
||||
// this is hack to work around the issue
|
||||
// solution taken from http://opensource.creative.com/pipermail/openal/2007-April/010355.html
|
||||
if(soundFile->getSampleFormat() == AL_FORMAT_STEREO16) {
|
||||
CombinedSoundSourcePtr combinedSource(new CombinedSoundSource);
|
||||
|
||||
streamSource->downMix(StreamSoundSource::DownMixLeft);
|
||||
streamSource->setRelative(true);
|
||||
streamSource->setPosition(Point(-128, 0));
|
||||
combinedSource->addSource(streamSource);
|
||||
|
||||
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;
|
||||
streamSource = StreamSoundSourcePtr(new StreamSoundSource);
|
||||
streamSource->downMix(StreamSoundSource::DownMixLeft);
|
||||
streamSource->setRelative(true);
|
||||
streamSource->setPosition(Point(-128, 0));
|
||||
combinedSource->addSource(streamSource);
|
||||
m_streamFiles[streamSource] = g_asyncDispatcher.schedule([=]() -> SoundFilePtr {
|
||||
stdext::timer a;
|
||||
try {
|
||||
return SoundFile::loadSoundFile(filename);
|
||||
} catch(std::exception& e) {
|
||||
g_logger.error(e.what());
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
});
|
||||
|
||||
streamSource = StreamSoundSourcePtr(new StreamSoundSource);
|
||||
streamSource->downMix(StreamSoundSource::DownMixRight);
|
||||
streamSource->setRelative(true);
|
||||
streamSource->setPosition(Point(128,0));
|
||||
combinedSource->addSource(streamSource);
|
||||
m_streamFiles[streamSource] = g_asyncDispatcher.schedule([=]() -> SoundFilePtr {
|
||||
try {
|
||||
return SoundFile::loadSoundFile(filename);
|
||||
} catch(std::exception& e) {
|
||||
g_logger.error(e.what());
|
||||
return nullptr;
|
||||
}
|
||||
});
|
||||
|
||||
source = combinedSource;
|
||||
#else
|
||||
StreamSoundSourcePtr streamSource(new StreamSoundSource);
|
||||
m_streamFiles[streamSource] = m_loadJobs [=]() -> SoundFilePtr {
|
||||
try {
|
||||
return SoundFile::loadSoundFile(filename);
|
||||
} catch(std::exception& e) {
|
||||
g_logger.error(e.what());
|
||||
return nullptr;
|
||||
}
|
||||
});
|
||||
source = streamSource;
|
||||
#endif
|
||||
}
|
||||
} catch(std::exception& e) {
|
||||
g_logger.error(stdext::format("failed to load sound source: '%s'", e.what()));
|
||||
|
@@ -57,6 +57,7 @@ private:
|
||||
ALCdevice *m_device;
|
||||
ALCcontext *m_context;
|
||||
|
||||
std::map<StreamSoundSourcePtr, std::future<SoundFilePtr>> m_streamFiles;
|
||||
std::unordered_map<std::string, SoundBufferPtr> m_buffers;
|
||||
std::vector<SoundSourcePtr> m_sources;
|
||||
stdext::boolean<true> m_audioEnabled;
|
||||
|
@@ -25,6 +25,7 @@
|
||||
#include "soundfile.h"
|
||||
|
||||
#include <framework/util/databuffer.h>
|
||||
#include <boost/concept_check.hpp>
|
||||
|
||||
StreamSoundSource::StreamSoundSource()
|
||||
{
|
||||
@@ -41,22 +42,26 @@ StreamSoundSource::~StreamSoundSource()
|
||||
void StreamSoundSource::setSoundFile(const SoundFilePtr& soundFile)
|
||||
{
|
||||
m_soundFile = soundFile;
|
||||
if(m_waitingFile) {
|
||||
m_waitingFile = false;
|
||||
play();
|
||||
}
|
||||
}
|
||||
|
||||
void StreamSoundSource::play()
|
||||
{
|
||||
m_playing = true;
|
||||
|
||||
if(!m_soundFile) {
|
||||
m_waitingFile = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if(m_eof) {
|
||||
m_soundFile->reset();
|
||||
m_eof = false;
|
||||
}
|
||||
|
||||
if(!m_soundFile) {
|
||||
g_logger.error("there is not sound file to play the stream");
|
||||
return;
|
||||
}
|
||||
|
||||
queueBuffers();
|
||||
|
||||
SoundSource::play();
|
||||
@@ -64,9 +69,13 @@ void StreamSoundSource::play()
|
||||
|
||||
void StreamSoundSource::stop()
|
||||
{
|
||||
m_playing = false;
|
||||
|
||||
if(m_waitingFile)
|
||||
return;
|
||||
|
||||
SoundSource::stop();
|
||||
unqueueBuffers();
|
||||
m_playing = false;
|
||||
}
|
||||
|
||||
void StreamSoundSource::queueBuffers()
|
||||
@@ -91,6 +100,9 @@ void StreamSoundSource::unqueueBuffers()
|
||||
|
||||
void StreamSoundSource::update()
|
||||
{
|
||||
if(m_waitingFile)
|
||||
return;
|
||||
|
||||
SoundSource::update();
|
||||
|
||||
int processed = 0;
|
||||
@@ -118,6 +130,9 @@ void StreamSoundSource::update()
|
||||
|
||||
bool StreamSoundSource::fillBufferAndQueue(uint buffer)
|
||||
{
|
||||
if(m_waitingFile)
|
||||
return false;
|
||||
|
||||
// fill buffer
|
||||
static DataBuffer<char> bufferData(2*STREAM_FRAGMENT_SIZE);
|
||||
ALenum format = m_soundFile->getSampleFormat();
|
||||
@@ -170,15 +185,5 @@ bool StreamSoundSource::fillBufferAndQueue(uint buffer)
|
||||
|
||||
void StreamSoundSource::downMix(StreamSoundSource::DownMix downMix)
|
||||
{
|
||||
if(!m_soundFile) {
|
||||
g_logger.error("down mix must be set after setting a sound file");
|
||||
return;
|
||||
}
|
||||
|
||||
if(m_soundFile->getSampleFormat() != AL_FORMAT_STEREO16) {
|
||||
g_logger.error("can only downmix 16 bit stereo audio files");
|
||||
return;
|
||||
}
|
||||
|
||||
m_downMix = downMix;
|
||||
}
|
||||
|
@@ -61,6 +61,7 @@ private:
|
||||
stdext::boolean<false> m_looping;
|
||||
stdext::boolean<false> m_playing;
|
||||
stdext::boolean<false> m_eof;
|
||||
stdext::boolean<false> m_waitingFile;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user