diff --git a/code/nel/include/nel/sound/audio_mixer_user.h b/code/nel/include/nel/sound/audio_mixer_user.h
index 977fe066b..1316fe34a 100644
--- a/code/nel/include/nel/sound/audio_mixer_user.h
+++ b/code/nel/include/nel/sound/audio_mixer_user.h
@@ -403,6 +403,7 @@ public:
/// Add a source for play as possible (for non discadable sound)
void addSourceWaitingForPlay(CSourceCommon *source);
+ void removeSourceWaitingForPlay(CSourceCommon *source);
/// Read all user controled var sheets
void initUserVar();
diff --git a/code/nel/include/nel/sound/simple_source.h b/code/nel/include/nel/sound/simple_source.h
index 9b21200c9..c330fd7fa 100644
--- a/code/nel/include/nel/sound/simple_source.h
+++ b/code/nel/include/nel/sound/simple_source.h
@@ -142,6 +142,8 @@ private:
/// True when the sound is played muted and until the mixer event notifying the end.
bool _PlayMuted;
+ bool _WaitingForPlay;
+
};
diff --git a/code/nel/include/nel/sound/sound.h b/code/nel/include/nel/sound/sound.h
index 7d7542fc9..e9d4f755c 100644
--- a/code/nel/include/nel/sound/sound.h
+++ b/code/nel/include/nel/sound/sound.h
@@ -61,8 +61,9 @@ public:
SOUND_COMPLEX,
SOUND_BACKGROUND,
SOUND_CONTEXT,
- SOUND_MUSIC,
- SOUND_STREAM
+ SOUND_MUSIC, // soon to be deprecated hopefully
+ SOUND_STREAM,
+ SOUND_STREAM_FILE
};
diff --git a/code/nel/include/nel/sound/source_common.h b/code/nel/include/nel/sound/source_common.h
index ca0a9a2b8..1180fd68e 100644
--- a/code/nel/include/nel/sound/source_common.h
+++ b/code/nel/include/nel/sound/source_common.h
@@ -37,7 +37,8 @@ public:
SOURCE_COMPLEX,
SOURCE_BACKGROUND,
SOURCE_MUSIC, // DEPRECATED
- SOURCE_STREAM
+ SOURCE_STREAM,
+ SOURCE_STREAM_FILE
};
/// When groupController is NULL it will use the groupcontroller specified in the TSoundId. You should manually specify the groupController if this source is a child of another source, so that the parent source controller of the user-specified .sound file is the one that will be used.
diff --git a/code/nel/include/nel/sound/stream_file_sound.h b/code/nel/include/nel/sound/stream_file_sound.h
new file mode 100644
index 000000000..2429c3382
--- /dev/null
+++ b/code/nel/include/nel/sound/stream_file_sound.h
@@ -0,0 +1,94 @@
+/**
+ * \file stream_file_sound.h
+ * \brief CStreamFileSound
+ * \date 2012-04-11 09:57GMT
+ * \author Jan Boon (Kaetemi)
+ * CStreamFileSound
+ */
+
+/*
+ * Copyright (C) 2012 by authors
+ *
+ * This file is part of RYZOM CORE.
+ * RYZOM CORE 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.
+ *
+ * RYZOM CORE 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 RYZOM CORE. If not, see
+ * .
+ */
+
+#ifndef NLSOUND_STREAM_FILE_SOUND_H
+#define NLSOUND_STREAM_FILE_SOUND_H
+#include
+
+// STL includes
+
+// NeL includes
+
+// Project includes
+#include
+
+namespace NLSOUND {
+ class CSourceMusicChannel;
+
+/**
+ * \brief CStreamFileSound
+ * \date 2012-04-11 09:57GMT
+ * \author Jan Boon (Kaetemi)
+ * CStreamFileSound
+ */
+class CStreamFileSound : public CStreamSound
+{
+public:
+ friend CSourceMusicChannel;
+
+public:
+ CStreamFileSound();
+ virtual ~CStreamFileSound();
+
+ /// Get the type of the sound.
+ virtual TSOUND_TYPE getSoundType() { return SOUND_STREAM_FILE; }
+
+ /// Load the sound parameters from georges' form
+ virtual void importForm(const std::string& filename, NLGEORGES::UFormElm& formRoot);
+
+ /// Used by the george sound plugin to check sound recursion (ie sound 'toto' use sound 'titi' witch also use sound 'toto' ...).
+ virtual void getSubSoundList(std::vector > &/* subsounds */) const { }
+
+ /// Serialize the sound data.
+ virtual void serial(NLMISC::IStream &s);
+
+ /// Return the length of the sound in ms
+ virtual uint32 getDuration() { return 0; }
+
+ inline bool getAsync() { return m_Async; }
+
+ inline const std::string &getFilePath() { return m_FilePath; }
+
+private:
+ /// Used by CSourceMusicChannel to set the filePath and default settings on other parameters.
+ void setMusicFilePath(const std::string &filePath, bool async = true, bool loop = false);
+
+private:
+ CStreamFileSound(const CStreamFileSound &);
+ CStreamFileSound &operator=(const CStreamFileSound &);
+
+private:
+ bool m_Async;
+ std::string m_FilePath;
+
+}; /* class CStreamFileSound */
+
+} /* namespace NLSOUND */
+
+#endif /* #ifndef NLSOUND_STREAM_FILE_SOUND_H */
+
+/* end of file */
diff --git a/code/nel/include/nel/sound/stream_file_source.h b/code/nel/include/nel/sound/stream_file_source.h
new file mode 100644
index 000000000..16153d406
--- /dev/null
+++ b/code/nel/include/nel/sound/stream_file_source.h
@@ -0,0 +1,105 @@
+/**
+ * \file stream_file_source.h
+ * \brief CStreamFileSource
+ * \date 2012-04-11 09:57GMT
+ * \author Jan Boon (Kaetemi)
+ * CStreamFileSource
+ */
+
+/*
+ * Copyright (C) 2012 by authors
+ *
+ * This file is part of RYZOM CORE.
+ * RYZOM CORE 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.
+ *
+ * RYZOM CORE 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 RYZOM CORE. If not, see
+ * .
+ */
+
+#ifndef NLSOUND_STREAM_FILE_SOURCE_H
+#define NLSOUND_STREAM_FILE_SOURCE_H
+#include
+
+// STL includes
+
+// NeL includes
+#include
+
+// Project includes
+#include
+#include
+
+namespace NLSOUND {
+ class IAudioDecoder;
+
+/**
+ * \brief CStreamFileSource
+ * \date 2012-04-11 09:57GMT
+ * \author Jan Boon (Kaetemi)
+ * CStreamFileSource
+ */
+class CStreamFileSource : public CStreamSource, private NLMISC::IRunnable
+{
+public:
+ CStreamFileSource(CStreamFileSound *streamFileSound = NULL, bool spawn = false, TSpawnEndCallback cb = 0, void *cbUserParam = 0, NL3D::CCluster *cluster = 0, CGroupController *groupController = NULL);
+ virtual ~CStreamFileSource();
+
+ /// Return the source type
+ TSOURCE_TYPE getType() const { return SOURCE_STREAM_FILE; }
+
+ /// \name Playback control
+ //@{
+ /// Play
+ virtual void play();
+ /// Stop playing
+ virtual void stop();
+ /// Get playing state. Return false even if the source has stopped on its own.
+ virtual bool isPlaying();
+ /// Pause (following legacy music channel implementation)
+ void pause();
+ /// Resume (following legacy music channel implementation)
+ void resume();
+ /// check if song ended (following legacy music channel implementation)
+ bool isEnded();
+ //@}
+
+ /// \name Decoding thread
+ //@{
+ virtual void getName (std::string &result) const { result = "CStreamFileSource"; }
+ virtual void run();
+ //@}
+
+ // TODO: getTime
+
+private:
+ void bufferMore(uint bytes);
+
+private:
+ CStreamFileSource(const CStreamFileSource &);
+ CStreamFileSource &operator=(const CStreamFileSource &);
+
+private:
+ inline CStreamFileSound *getStreamFileSound() { return static_cast(m_StreamSound); }
+
+ NLMISC::IThread *m_Thread;
+
+ IAudioDecoder *m_AudioDecoder;
+
+ bool m_Paused;
+
+}; /* class CStreamFileSource */
+
+} /* namespace NLSOUND */
+
+#endif /* #ifndef NLSOUND_STREAM_FILE_SOURCE_H */
+
+/* end of file */
diff --git a/code/nel/include/nel/sound/stream_source.h b/code/nel/include/nel/sound/stream_source.h
index 702a26006..d0a31cf38 100644
--- a/code/nel/include/nel/sound/stream_source.h
+++ b/code/nel/include/nel/sound/stream_source.h
@@ -114,7 +114,7 @@ private:
CStreamSource(const CStreamSource &);
CStreamSource &operator=(const CStreamSource &);
-private:
+protected:
/// Return the source type
TSOURCE_TYPE getType() const { return SOURCE_STREAM; }
@@ -162,7 +162,13 @@ private:
/// The bytes per second according to the buffer format
uint m_BytesPerSecond;
-
+
+ /// Waiting for play for high priority sources
+ bool m_WaitingForPlay;
+
+ /// Inverse pitch
+ float m_PitchInv;
+
}; /* class CStreamSource */
} /* namespace NLSOUND */
diff --git a/code/nel/src/sound/CMakeLists.txt b/code/nel/src/sound/CMakeLists.txt
index 80e545d25..fae6ca7a6 100644
--- a/code/nel/src/sound/CMakeLists.txt
+++ b/code/nel/src/sound/CMakeLists.txt
@@ -58,6 +58,8 @@ FILE(GLOB STREAM
FILE(GLOB STREAM_FILE
audio_decoder.cpp ../../include/nel/sound/audio_decoder.h
audio_decoder_vorbis.cpp ../../include/nel/sound/audio_decoder_vorbis.h
+ stream_file_sound.cpp ../../include/nel/sound/stream_file_sound.h
+ stream_file_source.cpp ../../include/nel/sound/stream_file_source.h
)
FILE(GLOB USER_CLASSES
diff --git a/code/nel/src/sound/audio_mixer_user.cpp b/code/nel/src/sound/audio_mixer_user.cpp
index e03b1ae00..5d938a036 100644
--- a/code/nel/src/sound/audio_mixer_user.cpp
+++ b/code/nel/src/sound/audio_mixer_user.cpp
@@ -45,6 +45,7 @@
#include "nel/sound/context_sound.h"
#include "nel/sound/music_source.h"
#include "nel/sound/stream_source.h"
+#include "nel/sound/stream_file_source.h"
#include "nel/sound/simple_sound.h"
#include "nel/sound/music_sound.h"
#include "nel/sound/stream_sound.h"
@@ -250,6 +251,16 @@ void CAudioMixerUser::addSourceWaitingForPlay(CSourceCommon *source)
_SourceWaitingForPlay.push_back(source);
}
+// ******************************************************************
+
+void CAudioMixerUser::removeSourceWaitingForPlay(CSourceCommon *source)
+{
+ std::list::iterator it = find(_SourceWaitingForPlay.begin(), _SourceWaitingForPlay.end(), source);
+ if (it != _SourceWaitingForPlay.end())
+ {
+ _SourceWaitingForPlay.erase(it);
+ }
+}
// ******************************************************************
@@ -1948,6 +1959,13 @@ retrySound:
ret = new CStreamSource(streamSound, spawn, cb, userParam, cluster, static_cast(groupController));
}
break;
+ case CSound::SOUND_STREAM_FILE:
+ {
+ CStreamFileSound *streamFileSound = static_cast(id);
+ // This is a stream file thingy.
+ ret = new CStreamFileSource(streamFileSound, spawn, cb, userParam, cluster, static_cast(groupController));
+ }
+ break;
case CSound::SOUND_COMPLEX:
{
CComplexSound *complexSound = static_cast(id);
diff --git a/code/nel/src/sound/simple_source.cpp b/code/nel/src/sound/simple_source.cpp
index 695619f91..7c76533e3 100644
--- a/code/nel/src/sound/simple_source.cpp
+++ b/code/nel/src/sound/simple_source.cpp
@@ -32,7 +32,8 @@ CSimpleSource::CSimpleSource(CSimpleSound *simpleSound, bool spawn, TSpawnEndCal
: CSourceCommon(simpleSound, spawn, cb, cbUserParam, cluster, groupController),
_SimpleSound(simpleSound),
_Track(NULL),
- _PlayMuted(false)
+ _PlayMuted(false),
+ _WaitingForPlay(false)
{
nlassert(_SimpleSound != 0);
@@ -183,6 +184,7 @@ void CSimpleSource::play()
{
// This sound is not discardable, add it in waiting playlist
mixer->addSourceWaitingForPlay(this);
+ _WaitingForPlay = true;
return;
}
// there is no available track, just do a 'muted' play
@@ -193,6 +195,7 @@ void CSimpleSource::play()
}
CSourceCommon::play();
+ _WaitingForPlay = false;
}
/// Mixer event call when doing muted play
@@ -219,6 +222,13 @@ void CSimpleSource::stop()
// nldebug("CSimpleSource %p : stop", (CAudioMixerUser::IMixerEvent*)this);
// nlassert(_Playing);
+ if (_WaitingForPlay)
+ {
+ nlassert(!_Playing); // cannot already be playing if waiting for play
+ CAudioMixerUser *mixer = CAudioMixerUser::instance();
+ mixer->removeSourceWaitingForPlay(this);
+ }
+
if (!_Playing)
return;
diff --git a/code/nel/src/sound/sound.cpp b/code/nel/src/sound/sound.cpp
index 07c10f8ef..4d753bb96 100644
--- a/code/nel/src/sound/sound.cpp
+++ b/code/nel/src/sound/sound.cpp
@@ -26,6 +26,7 @@
#include "nel/sound/context_sound.h"
#include "nel/sound/music_sound.h"
#include "nel/sound/stream_sound.h"
+#include "nel/sound/stream_file_sound.h"
#include "nel/sound/group_controller.h"
#include "nel/sound/group_controller_root.h"
@@ -84,6 +85,11 @@ CSound *CSound::createSound(const std::string &filename, NLGEORGES::UFormElm& fo
ret = new CStreamSound();
ret->importForm(filename, formRoot);
}
+ else if (dfnName == "stream_file_sound.dfn")
+ {
+ ret = new CStreamFileSound();
+ ret->importForm(filename, formRoot);
+ }
else
{
nlassertex(false, ("SoundType unsuported : %s", dfnName.c_str()));
diff --git a/code/nel/src/sound/sound_bank.cpp b/code/nel/src/sound/sound_bank.cpp
index b4031b571..dd2076a72 100644
--- a/code/nel/src/sound/sound_bank.cpp
+++ b/code/nel/src/sound/sound_bank.cpp
@@ -23,6 +23,7 @@
#include "nel/sound/background_sound.h"
#include "nel/sound/music_sound.h"
#include "nel/sound/stream_sound.h"
+#include "nel/sound/stream_file_sound.h"
#include "nel/georges/u_form_loader.h"
#include "nel/georges/u_form_elm.h"
@@ -194,6 +195,9 @@ public:
case CSound::SOUND_STREAM:
Sound = new CStreamSound();
break;
+ case CSound::SOUND_STREAM_FILE:
+ Sound = new CStreamFileSound();
+ break;
default:
Sound = 0;
}
diff --git a/code/nel/src/sound/stream_file_sound.cpp b/code/nel/src/sound/stream_file_sound.cpp
new file mode 100644
index 000000000..7640d7893
--- /dev/null
+++ b/code/nel/src/sound/stream_file_sound.cpp
@@ -0,0 +1,91 @@
+/**
+ * \file stream_file_sound.cpp
+ * \brief CStreamFileSound
+ * \date 2012-04-11 09:57GMT
+ * \author Jan Boon (Kaetemi)
+ * CStreamFileSound
+ */
+
+/*
+ * Copyright (C) 2012 by authors
+ *
+ * This file is part of RYZOM CORE.
+ * RYZOM CORE 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.
+ *
+ * RYZOM CORE 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 RYZOM CORE. If not, see
+ * .
+ */
+
+#include "stdsound.h"
+#include
+
+// STL includes
+
+// NeL includes
+// #include
+
+// Project includes
+
+using namespace std;
+// using namespace NLMISC;
+
+namespace NLSOUND {
+
+CStreamFileSound::CStreamFileSound()
+{
+
+}
+
+CStreamFileSound::~CStreamFileSound()
+{
+
+}
+
+void CStreamFileSound::importForm(const std::string &filename, NLGEORGES::UFormElm &root)
+{
+ // Call the base class
+ CStreamSound::importForm(filename, root);
+
+ // Async
+ root.getValueByName(m_Async, ".SoundType.Async");
+
+ // FilePath
+ root.getValueByName(m_FilePath, ".SoundType.FilePath");
+}
+
+void CStreamFileSound::serial(NLMISC::IStream &s)
+{
+ CStreamSound::serial(s);
+
+ s.serial(m_Async);
+ s.serial(m_FilePath);
+}
+
+void CStreamFileSound::setMusicFilePath(const std::string &filePath, bool async, bool loop)
+{
+ _ConeInnerAngle = NLMISC::Pi * 2;
+ _ConeOuterAngle = NLMISC::Pi * 2;
+ _Looping = loop;
+ _Gain = 1.0f;
+ _ConeOuterGain = 1.0f;
+ _Direction = NLMISC::CVector(0.f, 0.f, 0.f);
+ _Pitch = 1.0f;
+ _Priority = HighestPri;
+ _MaxDist = 9000.0f;
+ _MinDist = 1000.0f;
+ m_Async = async;
+ m_FilePath = filePath;
+}
+
+} /* namespace NLSOUND */
+
+/* end of file */
diff --git a/code/nel/src/sound/stream_file_source.cpp b/code/nel/src/sound/stream_file_source.cpp
new file mode 100644
index 000000000..4514bf4c5
--- /dev/null
+++ b/code/nel/src/sound/stream_file_source.cpp
@@ -0,0 +1,244 @@
+/**
+ * \file stream_file_source.cpp
+ * \brief CStreamFileSource
+ * \date 2012-04-11 09:57GMT
+ * \author Jan Boon (Kaetemi)
+ * CStreamFileSource
+ */
+
+/*
+ * Copyright (C) 2012 by authors
+ *
+ * This file is part of RYZOM CORE.
+ * RYZOM CORE 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.
+ *
+ * RYZOM CORE 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 RYZOM CORE. If not, see
+ * .
+ */
+
+#include "stdsound.h"
+#include
+
+// STL includes
+
+// NeL includes
+// #include
+
+// Project includes
+#include
+#include
+
+using namespace std;
+// using namespace NLMISC;
+
+namespace NLSOUND {
+
+CStreamFileSource::CStreamFileSource(CStreamFileSound *streamFileSound, bool spawn, TSpawnEndCallback cb, void *cbUserParam, NL3D::CCluster *cluster, CGroupController *groupController)
+: CStreamSource(streamFileSound, spawn, cb, cbUserParam, cluster, groupController), m_AudioDecoder(NULL), m_Paused(false)
+{
+ m_Thread = NLMISC::IThread::create(this);
+}
+
+CStreamFileSource::~CStreamFileSource()
+{
+ stop();
+ m_Thread->wait(); // thread must have stopped for delete!
+ delete m_Thread;
+ m_Thread = NULL;
+ delete m_AudioDecoder;
+ m_AudioDecoder = NULL;
+}
+
+void CStreamFileSource::play()
+{
+ // note: CStreamSource will assert crash if already physically playing!
+
+ nldebug("play");
+
+ if (m_Thread->isRunning() && m_WaitingForPlay)
+ {
+ if (m_NextBuffer || !m_FreeBuffers)
+ {
+ CStreamSource::play();
+ }
+ else
+ {
+ m_WaitingForPlay = true;
+ CAudioMixerUser *mixer = CAudioMixerUser::instance();
+ mixer->addSourceWaitingForPlay(this);
+ }
+ }
+ else if (!_Playing)
+ {
+ if (!m_WaitingForPlay)
+ {
+ // thread may be stopping from stop call
+ m_Thread->wait();
+ }
+ nlassert(!_Playing);
+ m_WaitingForPlay = true;
+ m_Thread->start();
+ m_Thread->setPriority(NLMISC::ThreadPriorityHighest);
+ CAudioMixerUser *mixer = CAudioMixerUser::instance();
+ mixer->addSourceWaitingForPlay(this);
+ }
+
+ /*if (!m_WaitingForPlay)
+ {
+ m_WaitingForPlay = true;
+
+ m_Thread->wait(); // thread must have stopped to restart it!
+
+ m_Thread->start();
+ m_Thread->setPriority(NLMISC::ThreadPriorityHighest);
+ }
+
+ CStreamSource::play();*/
+}
+
+void CStreamFileSource::stop()
+{
+ nldebug("stop");
+
+ CStreamSource::stop();
+
+ // thread will check _Playing to stop
+}
+
+bool CStreamFileSource::isPlaying()
+{
+ nldebug("isPlaying");
+
+ return m_Thread->isRunning();
+}
+
+void CStreamFileSource::pause()
+{
+ nldebug("pause");
+
+ if (!m_Paused)
+ {
+ // thread checks for this to not delete the audio decoder
+ m_Paused = true;
+
+ // stop the underlying system
+ CStreamSource::stop();
+
+ // thread will check _Playing to stop
+ }
+ else
+ {
+ nlwarning("Already paused");
+ }
+}
+
+void CStreamFileSource::resume()
+{
+ nldebug("resume");
+
+ if (m_Paused)
+ {
+ m_Thread->wait(); // thread must have stopped to restart it!
+
+ play();
+ }
+ else
+ {
+ nlwarning("Not paused");
+ }
+}
+
+bool CStreamFileSource::isEnded()
+{
+ return (!m_Thread->isRunning() && !_Playing && !m_WaitingForPlay && !m_Paused);
+}
+
+void CStreamFileSource::bufferMore(uint bytes) // buffer from bytes (minimum) to bytes * 2 (maximum)
+{
+ uint8 *buffer = this->lock(bytes * 2);
+ if (buffer)
+ {
+ uint32 result = m_AudioDecoder->getNextBytes(buffer, bytes, bytes * 2);
+ this->unlock(result);
+ }
+}
+
+void CStreamFileSource::run()
+{
+ nldebug("run");
+
+ bool looping = _Looping;
+ if (m_Paused)
+ {
+ // handle paused!
+ m_Paused = false;
+ }
+ else if (m_AudioDecoder) // audio decoder should normally not exist when not paused and starting the thread
+ {
+ nlwarning("CAudioDecoder already exists, possible thread race bug with pause");
+ delete m_AudioDecoder;
+ m_AudioDecoder = NULL;
+ }
+ if (!m_AudioDecoder)
+ {
+ // load the file
+ m_AudioDecoder = IAudioDecoder::createAudioDecoder(getStreamFileSound()->getFilePath(), getStreamFileSound()->getAsync(), getStreamFileSound()->getLooping());
+ if (!m_AudioDecoder)
+ {
+ nlwarning("Failed to create IAudioDecoder, likely invalid format");
+ return;
+ }
+ this->setFormat(m_AudioDecoder->getChannels(), m_AudioDecoder->getBitsPerSample(), (uint32)m_AudioDecoder->getSamplesPerSec());
+ }
+ uint samples, bytes;
+ this->getRecommendedBufferSize(samples, bytes);
+ bufferMore(bytes);
+ while (_Playing || m_WaitingForPlay)
+ {
+ if (!m_AudioDecoder->isMusicEnded())
+ {
+ bool newLooping = _Looping;
+ if (looping != newLooping)
+ {
+ m_AudioDecoder->setLooping(looping);
+ looping = newLooping;
+ }
+
+ bufferMore(bytes);
+ NLMISC::nlSleep(this->getRecommendedSleepTime());
+ }
+ else
+ {
+ // wait until done playing buffers
+ while (this->hasFilledBuffersAvailable())
+ NLMISC::nlSleep(40);
+ // stop the physical source
+ // if (hasPhysicalSource())
+ // getPhysicalSource()->stop();
+ // the audio mixer will call stop on the logical source
+ break;
+ }
+ }
+ if (m_Paused)
+ {
+ // don't delete anything
+ }
+ else
+ {
+ delete m_AudioDecoder;
+ m_AudioDecoder = NULL;
+ }
+}
+
+} /* namespace NLSOUND */
+
+/* end of file */
diff --git a/code/nel/src/sound/stream_sound.cpp b/code/nel/src/sound/stream_sound.cpp
index 7552e79e5..e16158d4d 100644
--- a/code/nel/src/sound/stream_sound.cpp
+++ b/code/nel/src/sound/stream_sound.cpp
@@ -35,14 +35,15 @@ CStreamSound::~CStreamSound()
void CStreamSound::importForm(const std::string &filename, NLGEORGES::UFormElm &root)
{
- NLGEORGES::UFormElm *psoundType;
+ // cannot do this debug check because used also by CStreamFileSound
+ /*NLGEORGES::UFormElm *psoundType;
std::string dfnName;
// some basic checking.
root.getNodeByName(&psoundType, ".SoundType");
nlassert(psoundType != NULL);
psoundType->getDfnName(dfnName);
- nlassert(dfnName == "stream_sound.dfn");
+ nlassert(dfnName == "stream_sound.dfn");*/
// Call the base class
CSound::importForm(filename, root);
diff --git a/code/nel/src/sound/stream_source.cpp b/code/nel/src/sound/stream_source.cpp
index 2c3188454..7f6b0c608 100644
--- a/code/nel/src/sound/stream_source.cpp
+++ b/code/nel/src/sound/stream_source.cpp
@@ -36,12 +36,15 @@ CStreamSource::CStreamSource(CStreamSound *streamSound, bool spawn, TSpawnEndCal
m_FreeBuffers(3),
m_NextBuffer(0),
m_LastSize(0),
- m_BytesPerSecond(0)
+ m_BytesPerSecond(0),
+ m_WaitingForPlay(false),
+ m_PitchInv(1.0f)
{
nlassert(m_StreamSound != 0);
// get a local copy of the stream sound parameter
m_Alpha = m_StreamSound->getAlpha();//m_Buffers
+ m_PitchInv = 1.0f / _Pitch;
// create the three buffer objects
CAudioMixerUser *mixer = CAudioMixerUser::instance();
@@ -107,6 +110,8 @@ bool CStreamSource::isPlaying()
/// Set looping on/off for future playbacks (default: off)
void CStreamSource::setLooping(bool l)
{
+ CSourceCommon::setLooping(l);
+
//CAutoMutex autoMutex(m_BufferMutex);
//
//CSourceCommon::setLooping(l);
@@ -166,7 +171,9 @@ void CStreamSource::play()
ISource *pSource = getPhysicalSource();
nlassert(pSource != NULL);
- for (uint i = 0; i < m_NextBuffer; ++i)
+ uint nbS = m_NextBuffer;
+ if (!m_NextBuffer && !m_FreeBuffers) nbS = 3;
+ for (uint i = 0; i < nbS; ++i)
pSource->submitStreamingBuffer(m_Buffers[i]);
// pSource->setPos( _Position, false);
@@ -184,6 +191,7 @@ void CStreamSource::play()
pSource->setAlpha(m_Alpha);
// and play the sound
+ nlassert(nbS); // must have buffered already!
play = pSource->play();
// nldebug("CStreamSource %p : REAL play done", (CAudioMixerUser::IMixerEvent*)this);
}
@@ -193,6 +201,7 @@ void CStreamSource::play()
{
// This sound is not discardable, add it in waiting playlist
mixer->addSourceWaitingForPlay(this);
+ m_WaitingForPlay = true;
return;
}
else
@@ -209,10 +218,15 @@ void CStreamSource::play()
}
if (play)
+ {
CSourceCommon::play();
+ m_WaitingForPlay = false;
+ }
}
+#ifdef NL_DEBUG
nlassert(play);
+#endif
}
/// Stop playing
@@ -222,6 +236,13 @@ void CStreamSource::stop()
// nldebug("CStreamSource %p : stop", (CAudioMixerUser::IMixerEvent*)this);
// nlassert(_Playing);
+
+ if (m_WaitingForPlay)
+ {
+ nlassert(!_Playing); // cannot already be playing if waiting for play
+ CAudioMixerUser *mixer = CAudioMixerUser::instance();
+ mixer->removeSourceWaitingForPlay(this);
+ }
if (!_Playing)
return;
@@ -305,7 +326,7 @@ void CStreamSource::updateFinalGain()
void CStreamSource::setPitch(float pitch)
{
CAutoMutex autoMutex(m_BufferMutex);
-
+ m_PitchInv = 1.0f / pitch;
CSourceCommon::setPitch(pitch);
if (hasPhysicalSource())
getPhysicalSource()->setPitch(pitch);
@@ -372,7 +393,9 @@ bool CStreamSource::unlock(uint size)
++m_NextBuffer; m_NextBuffer %= 3;
--m_FreeBuffers;
if (hasPhysicalSource())
+ {
getPhysicalSource()->submitStreamingBuffer(buffer);
+ }
m_LastSize = size;
}
@@ -396,7 +419,7 @@ void CStreamSource::getRecommendedBufferSize(uint &samples, uint &bytes) const
uint32 CStreamSource::getRecommendedSleepTime() const
{
if (m_FreeBuffers > 0) return 0;
- uint32 sleepTime = (uint32)((1000.0f * ((float)m_LastSize) / (float)m_BytesPerSecond) / _Pitch);
+ uint32 sleepTime = (uint32)((1000.0f * ((float)m_LastSize) / (float)m_BytesPerSecond) * m_PitchInv);
clamp(sleepTime, (uint32)0, (uint32)1000);
return sleepTime;
}