Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'extern/audaspace/src/fx/DynamicMusic.cpp')
-rw-r--r--extern/audaspace/src/fx/DynamicMusic.cpp346
1 files changed, 346 insertions, 0 deletions
diff --git a/extern/audaspace/src/fx/DynamicMusic.cpp b/extern/audaspace/src/fx/DynamicMusic.cpp
new file mode 100644
index 00000000000..b77cd749576
--- /dev/null
+++ b/extern/audaspace/src/fx/DynamicMusic.cpp
@@ -0,0 +1,346 @@
+/*******************************************************************************
+* Copyright 2015-2016 Juan Francisco Crespo Galán
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+******************************************************************************/
+
+#include "fx/DynamicMusic.h"
+#include "generator/Silence.h"
+#include "fx/Fader.h"
+#include "fx/Limiter.h"
+
+#include <mutex>
+#include <condition_variable>
+
+AUD_NAMESPACE_BEGIN
+
+DynamicMusic::DynamicMusic(std::shared_ptr<IDevice> device) :
+m_device(device), m_fadeTime(1.0f)
+{
+ m_id = 0;
+ m_transitioning = false;
+ m_stopThread = false;
+ m_volume = m_device->getVolume();
+ m_scenes.push_back(std::vector<std::shared_ptr<ISound>>(1, nullptr));
+}
+
+DynamicMusic::~DynamicMusic()
+{
+ stop();
+}
+
+int DynamicMusic::addScene(std::shared_ptr<ISound> sound)
+{
+ std::vector<std::shared_ptr<ISound>> v;
+ m_scenes.push_back(v);
+ for(int i = 0; i < m_scenes.size()-1; i++)
+ m_scenes.back().push_back(nullptr);
+ for(int i = 0; i < m_scenes.size()-1; i++)
+ m_scenes[i].push_back(nullptr);
+ m_scenes.back().push_back(sound);
+
+ return m_scenes.size() - 1;
+}
+
+bool DynamicMusic::changeScene(int id)
+{
+ if(id >= m_scenes.size() || m_transitioning)
+ return false;
+ else
+ {
+ if(m_fadeThread.joinable())
+ m_fadeThread.join();
+ m_device->lock();
+ if(id == m_id)
+ {
+ m_currentHandle->setVolume(m_volume);
+ m_currentHandle->setLoopCount(-1);
+ }
+ else
+ {
+ m_soundTarget = id;
+ if(m_scenes[m_id][id] == nullptr)
+ {
+ m_stopThread = false;
+ if((m_scenes[m_id][m_id] != nullptr && m_currentHandle->getStatus() != STATUS_INVALID) || m_scenes[m_soundTarget][m_soundTarget] != nullptr)
+ {
+ m_transitioning = true;
+ if(m_scenes[m_id][m_id] == nullptr || m_currentHandle->getStatus() == STATUS_INVALID)
+ {
+ m_device->lock();
+ m_currentHandle = m_device->play(m_scenes[m_soundTarget][m_soundTarget]);
+ m_currentHandle->setVolume(0.0f);
+ m_currentHandle->setLoopCount(-1);
+ m_device->unlock();
+ m_fadeThread = std::thread(&DynamicMusic::fadeInThread, this);
+ }
+ else
+ {
+ if(m_scenes[m_soundTarget][m_soundTarget] != nullptr)
+ {
+ m_device->lock();
+ m_transitionHandle = m_currentHandle;
+ m_currentHandle = m_device->play(m_scenes[m_soundTarget][m_soundTarget]);
+ m_currentHandle->setVolume(0.0f);
+ m_currentHandle->setLoopCount(-1);
+ m_device->unlock();
+ m_fadeThread = std::thread(&DynamicMusic::crossfadeThread, this);
+ }
+ else
+ {
+ m_transitionHandle = m_currentHandle;
+ m_currentHandle = nullptr;
+ m_fadeThread = std::thread(&DynamicMusic::fadeOutThread, this);
+ }
+ }
+ }
+ }
+ else
+ {
+ if(m_scenes[m_id][m_id] == nullptr || m_currentHandle->getStatus() == STATUS_INVALID)
+ transitionCallback(this);
+ else
+ {
+ m_currentHandle->setLoopCount(0);
+ m_currentHandle->setStopCallback(transitionCallback, this);
+ }
+ }
+ }
+ m_device->unlock();
+ return true;
+ }
+}
+
+int DynamicMusic::getScene()
+{
+ return m_id;
+}
+
+bool DynamicMusic::addTransition(int init, int end, std::shared_ptr<ISound> sound)
+{
+ if(init != end && init < m_scenes.size() && end < m_scenes.size() && init >= 0 && end >= 0)
+ {
+ m_scenes[init][end] = sound;
+ return true;
+ }
+ return false;
+}
+
+void DynamicMusic::setFadeTime(float seconds)
+{
+ m_device->lock();
+ m_fadeTime = seconds;
+ m_device->unlock();
+}
+
+float DynamicMusic::getFadeTime()
+{
+ return m_fadeTime;
+}
+
+bool DynamicMusic::resume()
+{
+ bool result = false, resultTrans = false;
+
+ if(m_currentHandle != nullptr)
+ result = m_currentHandle->resume();
+ if(m_transitionHandle != nullptr)
+ resultTrans = m_transitionHandle->resume();
+
+ return result || resultTrans;
+}
+
+bool DynamicMusic::pause()
+{
+ bool result = false, resultTrans = false;
+
+ if(m_currentHandle != nullptr)
+ result = m_currentHandle->pause();
+ if(m_transitionHandle != nullptr)
+ resultTrans = m_transitionHandle->pause();
+
+ return result || resultTrans;
+}
+
+bool DynamicMusic::seek(float position)
+{
+ bool result;
+
+ if(m_currentHandle != nullptr)
+ {
+ result = m_currentHandle->seek(position);
+ if(m_transitionHandle != nullptr && result == true)
+ m_transitionHandle->stop();
+ }
+
+ return result;
+}
+
+float DynamicMusic::getPosition()
+{
+ float result = 0.0f;
+
+ if(m_currentHandle != nullptr)
+ result = m_currentHandle->getPosition();
+
+ return result;
+}
+
+float DynamicMusic::getVolume()
+{
+ return m_volume;
+}
+
+bool DynamicMusic::setVolume(float volume)
+{
+ m_volume = volume;
+ bool result = false, resultTrans = false;
+
+ if(m_currentHandle != nullptr)
+ result = m_currentHandle->setVolume(volume);
+ if(m_transitionHandle != nullptr)
+ {
+ m_device->lock();
+ if(volume<m_transitionHandle->getVolume())
+ resultTrans = m_transitionHandle->setVolume(0.0f);
+ m_device->unlock();
+ }
+ if(m_currentHandle == nullptr && m_transitionHandle == nullptr)
+ result = true;
+
+ return result || resultTrans;
+}
+
+Status DynamicMusic::getStatus()
+{
+ if(m_currentHandle != nullptr)
+ {
+ Status result = m_currentHandle->getStatus();
+ return result;
+ }
+ else
+ return STATUS_INVALID;
+}
+
+bool DynamicMusic::stop()
+{
+ m_stopThread = true;
+ bool result = false, resultTrans = false;
+
+ if(m_currentHandle != nullptr)
+ result = m_currentHandle->stop();
+ if(m_transitionHandle != nullptr)
+
+ resultTrans = m_transitionHandle->stop();
+
+ if(m_fadeThread.joinable())
+ m_fadeThread.join();
+ m_id = 0;
+
+ return result || resultTrans;
+}
+
+void DynamicMusic::transitionCallback(void* player)
+{
+ auto dat = reinterpret_cast<DynamicMusic*>(player);
+ dat->m_transitioning = true;
+ dat->m_device->lock();
+ dat->m_currentHandle = dat->m_device->play(dat->m_scenes[dat->m_id][dat->m_soundTarget]);
+ dat->m_currentHandle->setVolume(dat->m_volume);
+ if(dat->m_scenes[dat->m_soundTarget][dat->m_soundTarget] != nullptr)
+ dat->m_currentHandle->setStopCallback(sceneCallback, player);
+ dat->m_device->unlock();
+}
+
+void DynamicMusic::sceneCallback(void* player)
+{
+ auto dat = reinterpret_cast<DynamicMusic*>(player);
+ dat->m_device->lock();
+ dat->m_currentHandle = dat->m_device->play(dat->m_scenes[dat->m_soundTarget][dat->m_soundTarget]);
+ dat->m_currentHandle->setVolume(dat->m_volume);
+ dat->m_currentHandle->setLoopCount(-1);
+ dat->m_device->unlock();
+ dat->m_id = int(dat->m_soundTarget);
+ dat->m_soundTarget = -1;
+ dat->m_transitioning = false;
+}
+
+void DynamicMusic::crossfadeThread()
+{
+ float currentVol = m_transitionHandle->getVolume();
+ float nextVol = m_currentHandle->getVolume();
+ float increment;
+
+ while(nextVol < m_volume && !m_stopThread)
+ {
+ increment = (m_volume / (m_fadeTime * 1000)) * 20;
+ currentVol -= increment;
+ nextVol += increment;
+ if(currentVol < 0)
+ currentVol = 0;
+ if(nextVol > m_volume)
+ nextVol = m_volume;
+ m_transitionHandle->setVolume(currentVol);
+ m_currentHandle->setVolume(nextVol);
+ std::this_thread::sleep_for(std::chrono::milliseconds(20));
+ }
+ if(m_stopThread)
+ m_transitionHandle->setVolume(m_volume);
+
+ m_transitionHandle->stop();
+
+ m_id = int(m_soundTarget);
+ m_transitioning = false;
+}
+
+void DynamicMusic::fadeInThread()
+{
+ float nextVol = m_currentHandle->getVolume();
+ float increment;
+
+ while(nextVol < m_volume && !m_stopThread)
+ {
+ increment = (m_volume / (m_fadeTime * 1000)) * 20;
+ nextVol += increment;
+ if(nextVol > m_volume)
+ nextVol = m_volume;
+ m_currentHandle->setVolume(nextVol);
+ std::this_thread::sleep_for(std::chrono::milliseconds(20));
+ }
+ if(m_stopThread)
+ m_currentHandle->setVolume(m_volume);
+
+ m_id = int(m_soundTarget);
+ m_transitioning = false;
+}
+
+void DynamicMusic::fadeOutThread()
+{
+ float currentVol = m_transitionHandle->getVolume();
+ float increment;
+
+ while(currentVol > 0.0f && !m_stopThread)
+ {
+ increment = (m_volume / (m_fadeTime * 1000)) * 20;
+ currentVol -= increment;
+ if(currentVol < 0)
+ currentVol = 0;
+ m_transitionHandle->setVolume(currentVol);
+ std::this_thread::sleep_for(std::chrono::milliseconds(20));
+ }
+
+ m_transitionHandle->stop();
+ m_id = int(m_soundTarget);
+ m_transitioning = false;
+}
+AUD_NAMESPACE_END