dry-main, wet-submix audio routing

This commit is contained in:
Jack Andersen 2016-05-30 19:16:29 -10:00
parent 175aabbb0e
commit f1e07861ca
6 changed files with 115 additions and 33 deletions

View File

@ -68,6 +68,12 @@ struct IAudioVoice
/** Set channel-gains for stereo audio source (AudioChannel enum for array index) */
virtual void setStereoMatrixCoefficients(const float coefs[8][2], bool slew)=0;
/** Set submix-channel-gains for mono audio source (AudioChannel enum for array index) */
virtual void setMonoSubmixMatrixCoefficients(const float coefs[8], bool slew)=0;
/** Set submix-channel-gains for stereo audio source (AudioChannel enum for array index) */
virtual void setStereoSubmixMatrixCoefficients(const float coefs[8][2], bool slew)=0;
/** Called by client to dynamically adjust the pitch of voices with dynamic pitch enabled */
virtual void setPitchRatio(double ratio, bool slew)=0;

View File

@ -22,7 +22,7 @@ AudioSubmix::~AudioSubmix()
unbindSubmix();
}
void AudioSubmix::_pumpAndMixVoices(size_t frames, int16_t* dataOut)
void AudioSubmix::_pumpAndMixVoices(size_t frames, int16_t* dataOut, int16_t* mainOut)
{
const AudioVoiceEngineMixInfo& info = mixInfo();
size_t sampleCount = frames * info.m_channelMap.m_channelCount;
@ -35,11 +35,11 @@ void AudioSubmix::_pumpAndMixVoices(size_t frames, int16_t* dataOut)
/* Pump child voices */
for (AudioVoice* vox : m_activeVoices)
if (vox->m_running)
vox->pumpAndMix(m_parent.mixInfo(), frames, m_scratch16.data());
vox->pumpAndMix(m_parent.mixInfo(), frames, mainOut, m_scratch16.data());
/* Pump child submixes */
for (AudioSubmix* smx : m_activeSubmixes)
smx->_pumpAndMixVoices(frames, m_scratch16.data());
smx->_pumpAndMixVoices(frames, m_scratch16.data(), mainOut);
/* Apply submix effect (if available) */
if (m_cb && m_cb->canApplyEffect())
@ -55,7 +55,7 @@ void AudioSubmix::_pumpAndMixVoices(size_t frames, int16_t* dataOut)
}
}
void AudioSubmix::_pumpAndMixVoices(size_t frames, int32_t* dataOut)
void AudioSubmix::_pumpAndMixVoices(size_t frames, int32_t* dataOut, int32_t* mainOut)
{
const AudioVoiceEngineMixInfo& info = mixInfo();
size_t sampleCount = frames * info.m_channelMap.m_channelCount;
@ -68,11 +68,11 @@ void AudioSubmix::_pumpAndMixVoices(size_t frames, int32_t* dataOut)
/* Pump child voices */
for (AudioVoice* vox : m_activeVoices)
if (vox->m_running)
vox->pumpAndMix(m_parent.mixInfo(), frames, m_scratch32.data());
vox->pumpAndMix(m_parent.mixInfo(), frames, mainOut, m_scratch32.data());
/* Pump child submixes */
for (AudioSubmix* smx : m_activeSubmixes)
smx->_pumpAndMixVoices(frames, m_scratch32.data());
smx->_pumpAndMixVoices(frames, m_scratch32.data(), mainOut);
/* Apply submix effect (if available) */
if (m_cb && m_cb->canApplyEffect())
@ -88,7 +88,7 @@ void AudioSubmix::_pumpAndMixVoices(size_t frames, int32_t* dataOut)
}
}
void AudioSubmix::_pumpAndMixVoices(size_t frames, float* dataOut)
void AudioSubmix::_pumpAndMixVoices(size_t frames, float* dataOut, float* mainOut)
{
const AudioVoiceEngineMixInfo& info = mixInfo();
size_t sampleCount = frames * info.m_channelMap.m_channelCount;
@ -101,11 +101,11 @@ void AudioSubmix::_pumpAndMixVoices(size_t frames, float* dataOut)
/* Pump child voices */
for (AudioVoice* vox : m_activeVoices)
if (vox->m_running)
vox->pumpAndMix(m_parent.mixInfo(), frames, m_scratchFlt.data());
vox->pumpAndMix(m_parent.mixInfo(), frames, mainOut, m_scratchFlt.data());
/* Pump child submixes */
for (AudioSubmix* smx : m_activeSubmixes)
smx->_pumpAndMixVoices(frames, m_scratchFlt.data());
smx->_pumpAndMixVoices(frames, m_scratchFlt.data(), mainOut);
/* Apply submix effect (if available) */
if (m_cb && m_cb->canApplyEffect())

View File

@ -41,9 +41,9 @@ class AudioSubmix : public IAudioSubmix, public IAudioMix
std::vector<int32_t> m_scratch32;
std::vector<float> m_scratchFlt;
void _pumpAndMixVoices(size_t frames, int16_t* dataOut);
void _pumpAndMixVoices(size_t frames, int32_t* dataOut);
void _pumpAndMixVoices(size_t frames, float* dataOut);
void _pumpAndMixVoices(size_t frames, int16_t* dataOut, int16_t* mainOut);
void _pumpAndMixVoices(size_t frames, int32_t* dataOut, int32_t* mainOut);
void _pumpAndMixVoices(size_t frames, float* dataOut, float* mainOut);
void _unbindFrom(std::list<AudioVoice*>::iterator it);
void _unbindFrom(std::list<AudioSubmix*>::iterator it);

View File

@ -114,7 +114,7 @@ size_t AudioVoiceMono::SRCCallback(AudioVoiceMono* ctx, int16_t** data, size_t f
}
size_t AudioVoiceMono::pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo,
size_t frames, int16_t* buf)
size_t frames, int16_t* buf, int16_t* rbuf)
{
std::vector<int16_t>& scratch16 = m_root.m_scratch16;
if (scratch16.size() < frames)
@ -124,13 +124,17 @@ size_t AudioVoiceMono::pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo,
_midUpdate();
if (oDone)
{
m_matrix.mixMonoSampleData(mixInfo, scratch16.data(), buf, oDone);
if (rbuf)
m_subMatrix.mixMonoSampleData(mixInfo, scratch16.data(), rbuf, oDone);
}
return oDone;
}
size_t AudioVoiceMono::pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo,
size_t frames, int32_t* buf)
size_t frames, int32_t* buf, int32_t* rbuf)
{
std::vector<int32_t>& scratch32 = m_root.m_scratch32;
if (scratch32.size() < frames)
@ -140,13 +144,17 @@ size_t AudioVoiceMono::pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo,
_midUpdate();
if (oDone)
{
m_matrix.mixMonoSampleData(mixInfo, scratch32.data(), buf, oDone);
if (rbuf)
m_subMatrix.mixMonoSampleData(mixInfo, scratch32.data(), rbuf, oDone);
}
return oDone;
}
size_t AudioVoiceMono::pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo,
size_t frames, float* buf)
size_t frames, float* buf, float* rbuf)
{
std::vector<float>& scratchFlt = m_root.m_scratchFlt;
if (scratchFlt.size() < frames)
@ -156,7 +164,11 @@ size_t AudioVoiceMono::pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo,
_midUpdate();
if (oDone)
{
m_matrix.mixMonoSampleData(mixInfo, scratchFlt.data(), buf, oDone);
if (rbuf)
m_subMatrix.mixMonoSampleData(mixInfo, scratchFlt.data(), rbuf, oDone);
}
return oDone;
}
@ -164,6 +176,8 @@ size_t AudioVoiceMono::pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo,
void AudioVoiceMono::setDefaultMatrixCoefficients()
{
m_matrix.setDefaultMatrixCoefficients(m_parent.mixInfo().m_channels);
float zero[8] = {};
m_subMatrix.setMatrixCoefficients(zero);
}
void AudioVoiceMono::setMonoMatrixCoefficients(const float coefs[8], bool slew)
@ -187,6 +201,27 @@ void AudioVoiceMono::setStereoMatrixCoefficients(const float coefs[8][2], bool s
m_matrix.setMatrixCoefficients(newCoefs, slew ? m_root.m_5msFrames : 0);
}
void AudioVoiceMono::setMonoSubmixMatrixCoefficients(const float coefs[8], bool slew)
{
m_subMatrix.setMatrixCoefficients(coefs, slew ? m_root.m_5msFrames : 0);
}
void AudioVoiceMono::setStereoSubmixMatrixCoefficients(const float coefs[8][2], bool slew)
{
float newCoefs[8] =
{
coefs[0][0],
coefs[1][0],
coefs[2][0],
coefs[3][0],
coefs[4][0],
coefs[5][0],
coefs[6][0],
coefs[7][0]
};
m_subMatrix.setMatrixCoefficients(newCoefs, slew ? m_root.m_5msFrames : 0);
}
AudioVoiceStereo::AudioVoiceStereo(BaseAudioVoiceEngine& root, IAudioMix& parent, IAudioVoiceCallback* cb,
double sampleRate, bool dynamicRate)
: AudioVoice(root, parent, cb, dynamicRate)
@ -231,7 +266,7 @@ size_t AudioVoiceStereo::SRCCallback(AudioVoiceStereo* ctx, int16_t** data, size
}
size_t AudioVoiceStereo::pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo,
size_t frames, int16_t* buf)
size_t frames, int16_t* buf, int16_t* rbuf)
{
std::vector<int16_t>& scratch16 = m_root.m_scratch16;
size_t samples = frames * 2;
@ -242,13 +277,17 @@ size_t AudioVoiceStereo::pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo,
_midUpdate();
if (oDone)
{
m_matrix.mixStereoSampleData(mixInfo, scratch16.data(), buf, oDone);
if (rbuf)
m_subMatrix.mixStereoSampleData(mixInfo, scratch16.data(), rbuf, oDone);
}
return oDone;
}
size_t AudioVoiceStereo::pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo,
size_t frames, int32_t* buf)
size_t frames, int32_t* buf, int32_t* rbuf)
{
std::vector<int32_t>& scratch32 = m_root.m_scratch32;
size_t samples = frames * 2;
@ -259,13 +298,17 @@ size_t AudioVoiceStereo::pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo,
_midUpdate();
if (oDone)
{
m_matrix.mixStereoSampleData(mixInfo, scratch32.data(), buf, oDone);
if (rbuf)
m_subMatrix.mixStereoSampleData(mixInfo, scratch32.data(), rbuf, oDone);
}
return oDone;
}
size_t AudioVoiceStereo::pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo,
size_t frames, float* buf)
size_t frames, float* buf, float* rbuf)
{
std::vector<float>& scratchFlt = m_root.m_scratchFlt;
size_t samples = frames * 2;
@ -276,7 +319,11 @@ size_t AudioVoiceStereo::pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo,
_midUpdate();
if (oDone)
{
m_matrix.mixStereoSampleData(mixInfo, scratchFlt.data(), buf, oDone);
if (rbuf)
m_subMatrix.mixStereoSampleData(mixInfo, scratchFlt.data(), rbuf, oDone);
}
return oDone;
}
@ -284,6 +331,8 @@ size_t AudioVoiceStereo::pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo,
void AudioVoiceStereo::setDefaultMatrixCoefficients()
{
m_matrix.setDefaultMatrixCoefficients(m_parent.mixInfo().m_channels);
float zero[8][2] = {{}};
m_subMatrix.setMatrixCoefficients(zero);
}
void AudioVoiceStereo::setMonoMatrixCoefficients(const float coefs[8], bool slew)
@ -307,4 +356,25 @@ void AudioVoiceStereo::setStereoMatrixCoefficients(const float coefs[8][2], bool
m_matrix.setMatrixCoefficients(coefs, slew ? m_root.m_5msFrames : 0);
}
void AudioVoiceStereo::setMonoSubmixMatrixCoefficients(const float coefs[8], bool slew)
{
float newCoefs[8][2] =
{
{coefs[0], coefs[0]},
{coefs[1], coefs[1]},
{coefs[2], coefs[2]},
{coefs[3], coefs[3]},
{coefs[4], coefs[4]},
{coefs[5], coefs[5]},
{coefs[6], coefs[6]},
{coefs[7], coefs[7]}
};
m_subMatrix.setMatrixCoefficients(newCoefs, slew ? m_root.m_5msFrames : 0);
}
void AudioVoiceStereo::setStereoSubmixMatrixCoefficients(const float coefs[8][2], bool slew)
{
m_subMatrix.setMatrixCoefficients(coefs, slew ? m_root.m_5msFrames : 0);
}
}

View File

@ -55,9 +55,9 @@ protected:
/* Mid-pump update */
void _midUpdate();
virtual size_t pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo, size_t frames, int16_t* buf)=0;
virtual size_t pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo, size_t frames, int32_t* buf)=0;
virtual size_t pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo, size_t frames, float* buf)=0;
virtual size_t pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo, size_t frames, int16_t* buf, int16_t* rbuf)=0;
virtual size_t pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo, size_t frames, int32_t* buf, int32_t* rbuf)=0;
virtual size_t pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo, size_t frames, float* buf, float* rbuf)=0;
AudioVoice(BaseAudioVoiceEngine& root, IAudioMix& parent, IAudioVoiceCallback* cb, bool dynamicRate);
public:
@ -72,14 +72,15 @@ public:
class AudioVoiceMono : public AudioVoice
{
AudioMatrixMono m_matrix;
AudioMatrixMono m_subMatrix;
void _resetSampleRate(double sampleRate);
static size_t SRCCallback(AudioVoiceMono* ctx,
int16_t** data, size_t requestedLen);
size_t pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo, size_t frames, int16_t* buf);
size_t pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo, size_t frames, int32_t* buf);
size_t pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo, size_t frames, float* buf);
size_t pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo, size_t frames, int16_t* buf, int16_t* rbuf);
size_t pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo, size_t frames, int32_t* buf, int32_t* rbuf);
size_t pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo, size_t frames, float* buf, float* rbuf);
public:
AudioVoiceMono(BaseAudioVoiceEngine& root, IAudioMix& parent, IAudioVoiceCallback* cb,
@ -87,19 +88,22 @@ public:
void setDefaultMatrixCoefficients();
void setMonoMatrixCoefficients(const float coefs[8], bool slew);
void setStereoMatrixCoefficients(const float coefs[8][2], bool slew);
void setMonoSubmixMatrixCoefficients(const float coefs[8], bool slew);
void setStereoSubmixMatrixCoefficients(const float coefs[8][2], bool slew);
};
class AudioVoiceStereo : public AudioVoice
{
AudioMatrixStereo m_matrix;
AudioMatrixStereo m_subMatrix;
void _resetSampleRate(double sampleRate);
static size_t SRCCallback(AudioVoiceStereo* ctx,
int16_t** data, size_t requestedLen);
size_t pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo, size_t frames, int16_t* buf);
size_t pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo, size_t frames, int32_t* buf);
size_t pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo, size_t frames, float* buf);
size_t pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo, size_t frames, int16_t* buf, int16_t* rbuf);
size_t pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo, size_t frames, int32_t* buf, int32_t* rbuf);
size_t pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo, size_t frames, float* buf, float* rbuf);
public:
AudioVoiceStereo(BaseAudioVoiceEngine& root, IAudioMix& parent, IAudioVoiceCallback* cb,
@ -107,6 +111,8 @@ public:
void setDefaultMatrixCoefficients();
void setMonoMatrixCoefficients(const float coefs[8], bool slew);
void setStereoMatrixCoefficients(const float coefs[8][2], bool slew);
void setMonoSubmixMatrixCoefficients(const float coefs[8], bool slew);
void setStereoSubmixMatrixCoefficients(const float coefs[8][2], bool slew);
};
}

View File

@ -35,9 +35,9 @@ void BaseAudioVoiceEngine::_pumpAndMixVoices(size_t frames, int16_t* dataOut)
for (AudioVoice* vox : m_activeVoices)
if (vox->m_running)
vox->pumpAndMix(m_mixInfo, thisFrames, dataOut);
vox->pumpAndMix(m_mixInfo, thisFrames, dataOut, nullptr);
for (AudioSubmix* smx : m_activeSubmixes)
smx->_pumpAndMixVoices(thisFrames, dataOut);
smx->_pumpAndMixVoices(thisFrames, dataOut, dataOut);
remFrames -= thisFrames;
dataOut += thisFrames * m_mixInfo.m_channelMap.m_channelCount;
}
@ -66,9 +66,9 @@ void BaseAudioVoiceEngine::_pumpAndMixVoices(size_t frames, int32_t* dataOut)
for (AudioVoice* vox : m_activeVoices)
if (vox->m_running)
vox->pumpAndMix(m_mixInfo, thisFrames, dataOut);
vox->pumpAndMix(m_mixInfo, thisFrames, dataOut, nullptr);
for (AudioSubmix* smx : m_activeSubmixes)
smx->_pumpAndMixVoices(thisFrames, dataOut);
smx->_pumpAndMixVoices(thisFrames, dataOut, dataOut);
remFrames -= thisFrames;
dataOut += thisFrames * m_mixInfo.m_channelMap.m_channelCount;
}
@ -97,9 +97,9 @@ void BaseAudioVoiceEngine::_pumpAndMixVoices(size_t frames, float* dataOut)
for (AudioVoice* vox : m_activeVoices)
if (vox->m_running)
vox->pumpAndMix(m_mixInfo, thisFrames, dataOut);
vox->pumpAndMix(m_mixInfo, thisFrames, dataOut, nullptr);
for (AudioSubmix* smx : m_activeSubmixes)
smx->_pumpAndMixVoices(thisFrames, dataOut);
smx->_pumpAndMixVoices(thisFrames, dataOut, dataOut);
remFrames -= thisFrames;
dataOut += thisFrames * m_mixInfo.m_channelMap.m_channelCount;
}