2016-03-24 00:01:57 +00:00
|
|
|
#include "AudioVoiceEngine.hpp"
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
namespace boo
|
|
|
|
{
|
|
|
|
|
2016-05-16 22:14:07 +00:00
|
|
|
BaseAudioVoiceEngine::~BaseAudioVoiceEngine()
|
|
|
|
{
|
|
|
|
while (m_activeVoices.size())
|
|
|
|
m_activeVoices.front()->unbindVoice();
|
|
|
|
while (m_activeSubmixes.size())
|
|
|
|
m_activeSubmixes.front()->unbindSubmix();
|
|
|
|
}
|
|
|
|
|
2016-03-24 00:01:57 +00:00
|
|
|
void BaseAudioVoiceEngine::_pumpAndMixVoices(size_t frames, int16_t* dataOut)
|
|
|
|
{
|
|
|
|
memset(dataOut, 0, sizeof(int16_t) * frames * m_mixInfo.m_channelMap.m_channelCount);
|
2016-07-13 03:03:52 +00:00
|
|
|
m_mainSubmix.m_redirect16 = dataOut;
|
|
|
|
|
|
|
|
if (m_submixesDirty)
|
|
|
|
{
|
|
|
|
m_linearizedSubmixes = m_mainSubmix._linearizeC3();
|
|
|
|
m_submixesDirty = false;
|
|
|
|
}
|
2016-05-19 10:14:21 +00:00
|
|
|
|
|
|
|
size_t remFrames = frames;
|
|
|
|
while (remFrames)
|
|
|
|
{
|
|
|
|
size_t thisFrames;
|
|
|
|
if (remFrames < m_5msFrames)
|
|
|
|
{
|
|
|
|
thisFrames = remFrames;
|
|
|
|
if (m_5msCallback)
|
|
|
|
m_5msCallback(thisFrames / double(m_5msFrames) * 5.0 / 1000.0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
thisFrames = m_5msFrames;
|
|
|
|
if (m_5msCallback)
|
|
|
|
m_5msCallback(5.0 / 1000.0);
|
|
|
|
}
|
|
|
|
|
2016-07-13 03:03:52 +00:00
|
|
|
for (auto it = m_linearizedSubmixes.rbegin() ; it != m_linearizedSubmixes.rend() ; ++it)
|
|
|
|
(*it)->_zeroFill16();
|
|
|
|
|
2016-05-19 10:14:21 +00:00
|
|
|
for (AudioVoice* vox : m_activeVoices)
|
|
|
|
if (vox->m_running)
|
2016-07-13 03:03:52 +00:00
|
|
|
vox->pumpAndMix16(thisFrames);
|
|
|
|
|
|
|
|
for (auto it = m_linearizedSubmixes.rbegin() ; it != m_linearizedSubmixes.rend() ; ++it)
|
|
|
|
(*it)->_pumpAndMix16(thisFrames);
|
|
|
|
|
2016-07-14 06:16:40 +00:00
|
|
|
size_t sampleCount = thisFrames * m_mixInfo.m_channelMap.m_channelCount;
|
|
|
|
for (size_t i=0 ; i<sampleCount ; ++i)
|
|
|
|
dataOut[i] *= m_totalVol;
|
|
|
|
|
2016-05-19 10:14:21 +00:00
|
|
|
remFrames -= thisFrames;
|
2016-07-14 06:16:40 +00:00
|
|
|
dataOut += sampleCount;
|
2016-05-19 10:14:21 +00:00
|
|
|
}
|
2016-03-24 00:01:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void BaseAudioVoiceEngine::_pumpAndMixVoices(size_t frames, int32_t* dataOut)
|
|
|
|
{
|
|
|
|
memset(dataOut, 0, sizeof(int32_t) * frames * m_mixInfo.m_channelMap.m_channelCount);
|
2016-07-13 03:03:52 +00:00
|
|
|
m_mainSubmix.m_redirect32 = dataOut;
|
|
|
|
|
|
|
|
if (m_submixesDirty)
|
|
|
|
{
|
|
|
|
m_linearizedSubmixes = m_mainSubmix._linearizeC3();
|
|
|
|
m_submixesDirty = false;
|
|
|
|
}
|
2016-05-19 10:14:21 +00:00
|
|
|
|
|
|
|
size_t remFrames = frames;
|
|
|
|
while (remFrames)
|
|
|
|
{
|
|
|
|
size_t thisFrames;
|
|
|
|
if (remFrames < m_5msFrames)
|
|
|
|
{
|
|
|
|
thisFrames = remFrames;
|
|
|
|
if (m_5msCallback)
|
|
|
|
m_5msCallback(thisFrames / double(m_5msFrames) * 5.0 / 1000.0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
thisFrames = m_5msFrames;
|
|
|
|
if (m_5msCallback)
|
|
|
|
m_5msCallback(5.0 / 1000.0);
|
|
|
|
}
|
|
|
|
|
2016-07-13 03:03:52 +00:00
|
|
|
for (auto it = m_linearizedSubmixes.rbegin() ; it != m_linearizedSubmixes.rend() ; ++it)
|
|
|
|
(*it)->_zeroFill32();
|
|
|
|
|
2016-05-19 10:14:21 +00:00
|
|
|
for (AudioVoice* vox : m_activeVoices)
|
|
|
|
if (vox->m_running)
|
2016-07-13 03:03:52 +00:00
|
|
|
vox->pumpAndMix32(thisFrames);
|
|
|
|
|
|
|
|
for (auto it = m_linearizedSubmixes.rbegin() ; it != m_linearizedSubmixes.rend() ; ++it)
|
|
|
|
(*it)->_pumpAndMix32(thisFrames);
|
|
|
|
|
2016-07-14 06:16:40 +00:00
|
|
|
size_t sampleCount = thisFrames * m_mixInfo.m_channelMap.m_channelCount;
|
|
|
|
for (size_t i=0 ; i<sampleCount ; ++i)
|
|
|
|
dataOut[i] *= m_totalVol;
|
|
|
|
|
2016-05-19 10:14:21 +00:00
|
|
|
remFrames -= thisFrames;
|
2016-07-14 06:16:40 +00:00
|
|
|
dataOut += sampleCount;
|
2016-05-19 10:14:21 +00:00
|
|
|
}
|
2016-03-24 00:01:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void BaseAudioVoiceEngine::_pumpAndMixVoices(size_t frames, float* dataOut)
|
|
|
|
{
|
|
|
|
memset(dataOut, 0, sizeof(float) * frames * m_mixInfo.m_channelMap.m_channelCount);
|
2016-07-13 03:03:52 +00:00
|
|
|
m_mainSubmix.m_redirectFlt = dataOut;
|
|
|
|
|
|
|
|
if (m_submixesDirty)
|
|
|
|
{
|
|
|
|
m_linearizedSubmixes = m_mainSubmix._linearizeC3();
|
|
|
|
m_submixesDirty = false;
|
|
|
|
}
|
2016-05-19 10:14:21 +00:00
|
|
|
|
|
|
|
size_t remFrames = frames;
|
|
|
|
while (remFrames)
|
|
|
|
{
|
|
|
|
size_t thisFrames;
|
|
|
|
if (remFrames < m_5msFrames)
|
|
|
|
{
|
|
|
|
thisFrames = remFrames;
|
|
|
|
if (m_5msCallback)
|
|
|
|
m_5msCallback(thisFrames / double(m_5msFrames) * 5.0 / 1000.0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
thisFrames = m_5msFrames;
|
|
|
|
if (m_5msCallback)
|
|
|
|
m_5msCallback(5.0 / 1000.0);
|
|
|
|
}
|
|
|
|
|
2016-07-13 03:03:52 +00:00
|
|
|
for (auto it = m_linearizedSubmixes.rbegin() ; it != m_linearizedSubmixes.rend() ; ++it)
|
|
|
|
(*it)->_zeroFillFlt();
|
|
|
|
|
2016-05-19 10:14:21 +00:00
|
|
|
for (AudioVoice* vox : m_activeVoices)
|
|
|
|
if (vox->m_running)
|
2016-07-13 03:03:52 +00:00
|
|
|
vox->pumpAndMixFlt(thisFrames);
|
|
|
|
|
|
|
|
for (auto it = m_linearizedSubmixes.rbegin() ; it != m_linearizedSubmixes.rend() ; ++it)
|
|
|
|
(*it)->_pumpAndMixFlt(thisFrames);
|
|
|
|
|
2016-07-14 06:16:40 +00:00
|
|
|
size_t sampleCount = thisFrames * m_mixInfo.m_channelMap.m_channelCount;
|
|
|
|
for (size_t i=0 ; i<sampleCount ; ++i)
|
|
|
|
dataOut[i] *= m_totalVol;
|
|
|
|
|
2016-05-19 10:14:21 +00:00
|
|
|
remFrames -= thisFrames;
|
2016-07-14 06:16:40 +00:00
|
|
|
dataOut += sampleCount;
|
2016-05-19 10:14:21 +00:00
|
|
|
}
|
2016-05-07 04:28:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void BaseAudioVoiceEngine::_unbindFrom(std::list<AudioVoice*>::iterator it)
|
|
|
|
{
|
|
|
|
m_activeVoices.erase(it);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BaseAudioVoiceEngine::_unbindFrom(std::list<AudioSubmix*>::iterator it)
|
|
|
|
{
|
|
|
|
m_activeSubmixes.erase(it);
|
2017-01-22 01:39:15 +00:00
|
|
|
m_submixesDirty = true;
|
2016-03-24 00:01:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<IAudioVoice>
|
|
|
|
BaseAudioVoiceEngine::allocateNewMonoVoice(double sampleRate,
|
2016-05-07 04:28:32 +00:00
|
|
|
IAudioVoiceCallback* cb,
|
|
|
|
bool dynamicPitch)
|
2016-03-24 00:01:57 +00:00
|
|
|
{
|
|
|
|
std::unique_ptr<IAudioVoice> ret =
|
2016-07-13 03:03:52 +00:00
|
|
|
std::make_unique<AudioVoiceMono>(*this, cb, sampleRate, dynamicPitch);
|
2016-03-24 00:01:57 +00:00
|
|
|
AudioVoiceMono* retMono = static_cast<AudioVoiceMono*>(ret.get());
|
|
|
|
retMono->bindVoice(m_activeVoices.insert(m_activeVoices.end(), retMono));
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<IAudioVoice>
|
|
|
|
BaseAudioVoiceEngine::allocateNewStereoVoice(double sampleRate,
|
2016-05-07 04:28:32 +00:00
|
|
|
IAudioVoiceCallback* cb,
|
|
|
|
bool dynamicPitch)
|
2016-03-24 00:01:57 +00:00
|
|
|
{
|
|
|
|
std::unique_ptr<IAudioVoice> ret =
|
2016-07-13 03:03:52 +00:00
|
|
|
std::make_unique<AudioVoiceStereo>(*this, cb, sampleRate, dynamicPitch);
|
2016-03-24 00:01:57 +00:00
|
|
|
AudioVoiceStereo* retStereo = static_cast<AudioVoiceStereo*>(ret.get());
|
|
|
|
retStereo->bindVoice(m_activeVoices.insert(m_activeVoices.end(), retStereo));
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-05-07 04:28:32 +00:00
|
|
|
std::unique_ptr<IAudioSubmix>
|
2016-07-14 04:59:41 +00:00
|
|
|
BaseAudioVoiceEngine::allocateNewSubmix(bool mainOut, IAudioSubmixCallback* cb, int busId)
|
2016-05-07 04:28:32 +00:00
|
|
|
{
|
2016-07-14 04:59:41 +00:00
|
|
|
std::unique_ptr<IAudioSubmix> ret = std::make_unique<AudioSubmix>(*this, cb, busId, mainOut);
|
2016-05-07 04:28:32 +00:00
|
|
|
AudioSubmix* retIntern = static_cast<AudioSubmix*>(ret.get());
|
|
|
|
retIntern->bindSubmix(m_activeSubmixes.insert(m_activeSubmixes.end(), retIntern));
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2016-05-19 10:14:21 +00:00
|
|
|
void BaseAudioVoiceEngine::register5MsCallback(std::function<void(double dt)>&& callback)
|
|
|
|
{
|
|
|
|
m_5msCallback = std::move(callback);
|
|
|
|
}
|
|
|
|
|
2017-01-23 07:20:40 +00:00
|
|
|
void BaseAudioVoiceEngine::unregister5MsCallback()
|
|
|
|
{
|
|
|
|
m_5msCallback = {};
|
|
|
|
}
|
|
|
|
|
2016-07-14 06:16:40 +00:00
|
|
|
void BaseAudioVoiceEngine::setVolume(float vol)
|
|
|
|
{
|
|
|
|
m_totalVol = vol;
|
|
|
|
}
|
|
|
|
|
2016-05-07 04:28:32 +00:00
|
|
|
const AudioVoiceEngineMixInfo& BaseAudioVoiceEngine::mixInfo() const
|
|
|
|
{
|
|
|
|
return m_mixInfo;
|
|
|
|
}
|
|
|
|
|
2016-03-24 00:01:57 +00:00
|
|
|
}
|