mirror of
https://github.com/AxioDL/boo.git
synced 2025-12-20 02:15:34 +00:00
Fix some submix issues
This commit is contained in:
@@ -2,16 +2,16 @@
|
||||
#include "AudioVoiceEngine.hpp"
|
||||
#include "AudioVoice.hpp"
|
||||
#include <string.h>
|
||||
#include <algorithm>
|
||||
|
||||
namespace boo
|
||||
{
|
||||
|
||||
static std::vector<int16_t> scratch16;
|
||||
static std::vector<int32_t> scratch32;
|
||||
static std::vector<float> scratchFlt;
|
||||
|
||||
AudioSubmix::AudioSubmix(IAudioHost& parent, IAudioSubmixCallback* cb)
|
||||
: m_parent(parent), m_cb(cb) {}
|
||||
AudioSubmix::AudioSubmix(BaseAudioVoiceEngine& root, IAudioMix& parent, IAudioSubmixCallback* cb)
|
||||
: m_root(root), m_parent(parent), m_cb(cb)
|
||||
{
|
||||
std::fill(std::begin(m_gains), std::end(m_gains), 1.f);
|
||||
}
|
||||
|
||||
AudioSubmix::~AudioSubmix()
|
||||
{
|
||||
@@ -22,90 +22,99 @@ void AudioSubmix::_pumpAndMixVoices(size_t frames, int16_t* dataOut)
|
||||
{
|
||||
const AudioVoiceEngineMixInfo& info = mixInfo();
|
||||
size_t sampleCount = frames * info.m_channelMap.m_channelCount;
|
||||
if (scratch16.size() < sampleCount)
|
||||
scratch16.resize(sampleCount);
|
||||
if (m_scratch16.size() < sampleCount)
|
||||
m_scratch16.resize(sampleCount);
|
||||
|
||||
/* Clear target buffer */
|
||||
memset(scratch16.data(), 0, sizeof(int16_t) * sampleCount);
|
||||
memset(m_scratch16.data(), 0, sizeof(int16_t) * sampleCount);
|
||||
|
||||
/* Pump child voices */
|
||||
for (AudioVoice* vox : m_activeVoices)
|
||||
if (vox->m_running)
|
||||
vox->pumpAndMix(m_parent.mixInfo(), frames, scratch16.data());
|
||||
vox->pumpAndMix(m_parent.mixInfo(), frames, m_scratch16.data());
|
||||
|
||||
/* Pump child submixes */
|
||||
for (AudioSubmix* smx : m_activeSubmixes)
|
||||
smx->_pumpAndMixVoices(frames, scratch16.data());
|
||||
smx->_pumpAndMixVoices(frames, m_scratch16.data());
|
||||
|
||||
/* Apply submix effect (if available) */
|
||||
if (m_cb && m_cb->canApplyEffect())
|
||||
m_cb->applyEffect(scratch16.data(), info.m_channelMap, info.m_sampleRate);
|
||||
m_cb->applyEffect(m_scratch16.data(), info.m_channelMap, info.m_sampleRate);
|
||||
|
||||
/* Merge into output mix */
|
||||
auto it = scratch16.begin();
|
||||
auto it = m_scratch16.begin();
|
||||
for (size_t f=0 ; f<frames ; ++f)
|
||||
for (size_t c=0 ; c<info.m_channelMap.m_channelCount ; ++c)
|
||||
*dataOut++ = Clamp16(*it++ * m_gains[c]);
|
||||
{
|
||||
*dataOut = Clamp16(*dataOut + *it++ * m_gains[c]);
|
||||
++dataOut;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioSubmix::_pumpAndMixVoices(size_t frames, int32_t* dataOut)
|
||||
{
|
||||
const AudioVoiceEngineMixInfo& info = mixInfo();
|
||||
size_t sampleCount = frames * info.m_channelMap.m_channelCount;
|
||||
if (scratch32.size() < sampleCount)
|
||||
scratch32.resize(sampleCount);
|
||||
if (m_scratch32.size() < sampleCount)
|
||||
m_scratch32.resize(sampleCount);
|
||||
|
||||
/* Clear target buffer */
|
||||
memset(scratch32.data(), 0, sizeof(int32_t) * sampleCount);
|
||||
memset(m_scratch32.data(), 0, sizeof(int32_t) * sampleCount);
|
||||
|
||||
/* Pump child voices */
|
||||
for (AudioVoice* vox : m_activeVoices)
|
||||
if (vox->m_running)
|
||||
vox->pumpAndMix(m_parent.mixInfo(), frames, scratch32.data());
|
||||
vox->pumpAndMix(m_parent.mixInfo(), frames, m_scratch32.data());
|
||||
|
||||
/* Pump child submixes */
|
||||
for (AudioSubmix* smx : m_activeSubmixes)
|
||||
smx->_pumpAndMixVoices(frames, scratch32.data());
|
||||
smx->_pumpAndMixVoices(frames, m_scratch32.data());
|
||||
|
||||
/* Apply submix effect (if available) */
|
||||
if (m_cb && m_cb->canApplyEffect())
|
||||
m_cb->applyEffect(scratch32.data(), info.m_channelMap, info.m_sampleRate);
|
||||
m_cb->applyEffect(m_scratch32.data(), info.m_channelMap, info.m_sampleRate);
|
||||
|
||||
/* Merge into output mix */
|
||||
auto it = scratch32.begin();
|
||||
auto it = m_scratch32.begin();
|
||||
for (size_t f=0 ; f<frames ; ++f)
|
||||
for (size_t c=0 ; c<info.m_channelMap.m_channelCount ; ++c)
|
||||
*dataOut++ = Clamp32(*it++ * m_gains[c]);
|
||||
{
|
||||
*dataOut = Clamp32(*dataOut + *it++ * m_gains[c]);
|
||||
++dataOut;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioSubmix::_pumpAndMixVoices(size_t frames, float* dataOut)
|
||||
{
|
||||
const AudioVoiceEngineMixInfo& info = mixInfo();
|
||||
size_t sampleCount = frames * info.m_channelMap.m_channelCount;
|
||||
if (scratchFlt.size() < sampleCount)
|
||||
scratchFlt.resize(sampleCount);
|
||||
if (m_scratchFlt.size() < sampleCount)
|
||||
m_scratchFlt.resize(sampleCount);
|
||||
|
||||
/* Clear target buffer */
|
||||
memset(scratchFlt.data(), 0, sizeof(float) * sampleCount);
|
||||
memset(m_scratchFlt.data(), 0, sizeof(float) * sampleCount);
|
||||
|
||||
/* Pump child voices */
|
||||
for (AudioVoice* vox : m_activeVoices)
|
||||
if (vox->m_running)
|
||||
vox->pumpAndMix(m_parent.mixInfo(), frames, scratchFlt.data());
|
||||
vox->pumpAndMix(m_parent.mixInfo(), frames, m_scratchFlt.data());
|
||||
|
||||
/* Pump child submixes */
|
||||
for (AudioSubmix* smx : m_activeSubmixes)
|
||||
smx->_pumpAndMixVoices(frames, scratchFlt.data());
|
||||
smx->_pumpAndMixVoices(frames, m_scratchFlt.data());
|
||||
|
||||
/* Apply submix effect (if available) */
|
||||
if (m_cb && m_cb->canApplyEffect())
|
||||
m_cb->applyEffect(scratchFlt.data(), info.m_channelMap, info.m_sampleRate);
|
||||
m_cb->applyEffect(m_scratchFlt.data(), info.m_channelMap, info.m_sampleRate);
|
||||
|
||||
/* Merge into output mix */
|
||||
auto it = scratchFlt.begin();
|
||||
auto it = m_scratchFlt.begin();
|
||||
for (size_t f=0 ; f<frames ; ++f)
|
||||
for (size_t c=0 ; c<info.m_channelMap.m_channelCount ; ++c)
|
||||
*dataOut++ = ClampFlt(*it++ * m_gains[c]);
|
||||
{
|
||||
*dataOut = ClampFlt(*dataOut + *it++ * m_gains[c]);
|
||||
++dataOut;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioSubmix::_unbindFrom(std::list<AudioVoice*>::iterator it)
|
||||
@@ -123,7 +132,7 @@ std::unique_ptr<IAudioVoice> AudioSubmix::allocateNewMonoVoice(double sampleRate
|
||||
bool dynamicPitch)
|
||||
{
|
||||
std::unique_ptr<IAudioVoice> ret =
|
||||
std::make_unique<AudioVoiceMono>(*this, cb, sampleRate, dynamicPitch);
|
||||
std::make_unique<AudioVoiceMono>(m_root, *this, cb, sampleRate, dynamicPitch);
|
||||
AudioVoiceMono* retMono = static_cast<AudioVoiceMono*>(ret.get());
|
||||
retMono->bindVoice(m_activeVoices.insert(m_activeVoices.end(), retMono));
|
||||
return ret;
|
||||
@@ -134,7 +143,7 @@ std::unique_ptr<IAudioVoice> AudioSubmix::allocateNewStereoVoice(double sampleRa
|
||||
bool dynamicPitch)
|
||||
{
|
||||
std::unique_ptr<IAudioVoice> ret =
|
||||
std::make_unique<AudioVoiceStereo>(*this, cb, sampleRate, dynamicPitch);
|
||||
std::make_unique<AudioVoiceStereo>(m_root, *this, cb, sampleRate, dynamicPitch);
|
||||
AudioVoiceStereo* retStereo = static_cast<AudioVoiceStereo*>(ret.get());
|
||||
retStereo->bindVoice(m_activeVoices.insert(m_activeVoices.end(), retStereo));
|
||||
return ret;
|
||||
@@ -143,12 +152,18 @@ std::unique_ptr<IAudioVoice> AudioSubmix::allocateNewStereoVoice(double sampleRa
|
||||
std::unique_ptr<IAudioSubmix> AudioSubmix::allocateNewSubmix(IAudioSubmixCallback* cb)
|
||||
{
|
||||
std::unique_ptr<IAudioSubmix> ret =
|
||||
std::make_unique<AudioSubmix>(*this, cb);
|
||||
std::make_unique<AudioSubmix>(m_root, *this, cb);
|
||||
AudioSubmix* retIntern = static_cast<AudioSubmix*>(ret.get());
|
||||
retIntern->bindSubmix(m_activeSubmixes.insert(m_activeSubmixes.end(), retIntern));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void AudioSubmix::setChannelGains(const float gains[8])
|
||||
{
|
||||
for (int i=0 ; i<8 ; ++i)
|
||||
m_gains[i] = gains[i];
|
||||
}
|
||||
|
||||
void AudioSubmix::unbindSubmix()
|
||||
{
|
||||
if (m_bound)
|
||||
|
||||
Reference in New Issue
Block a user