Add short-process loop for voices that make sample-level parameter changes

This commit is contained in:
Jack Andersen 2016-05-11 11:29:11 -10:00
parent b3e77c4384
commit 4a74a0ad7c
2 changed files with 139 additions and 30 deletions

View File

@ -16,18 +16,39 @@ AudioVoice::~AudioVoice()
soxr_delete(m_src);
}
void AudioVoice::setPitchRatio(double ratio)
void AudioVoice::_setPitchRatio(double ratio)
{
m_pitchRatio = ratio;
if (m_dynamicRate)
{
soxr_error_t err = soxr_set_io_ratio(m_src, ratio, m_parent.mixInfo().m_periodFrames);
if (err)
{
Log.report(logvisor::Fatal, "unable to set resampler rate: %s", soxr_strerror(err));
m_setPitchRatio = false;
return;
}
}
m_setPitchRatio = false;
}
void AudioVoice::_midUpdate()
{
if (m_resetSampleRate)
_resetSampleRate(m_deferredSampleRate);
if (m_setPitchRatio)
_setPitchRatio(m_pitchRatio);
}
void AudioVoice::setPitchRatio(double ratio)
{
m_setPitchRatio = true;
m_pitchRatio = ratio;
}
void AudioVoice::resetSampleRate(double sampleRate)
{
m_resetSampleRate = true;
m_deferredSampleRate = sampleRate;
}
void AudioVoice::start()
@ -53,10 +74,10 @@ AudioVoiceMono::AudioVoiceMono(BaseAudioVoiceEngine& root, IAudioMix& parent, IA
double sampleRate, bool dynamicRate)
: AudioVoice(root, parent, cb, dynamicRate)
{
resetSampleRate(sampleRate);
_resetSampleRate(sampleRate);
}
void AudioVoiceMono::resetSampleRate(double sampleRate)
void AudioVoiceMono::_resetSampleRate(double sampleRate)
{
soxr_delete(m_src);
@ -70,11 +91,13 @@ void AudioVoiceMono::resetSampleRate(double sampleRate)
if (err)
{
Log.report(logvisor::Fatal, "unable to create soxr resampler: %s", soxr_strerror(err));
m_resetSampleRate = false;
return;
}
soxr_set_input_fn(m_src, soxr_input_fn_t(SRCCallback), this, 0);
setPitchRatio(m_pitchRatio);
_setPitchRatio(m_pitchRatio);
m_resetSampleRate = false;
}
size_t AudioVoiceMono::SRCCallback(AudioVoiceMono* ctx, int16_t** data, size_t frames)
@ -93,10 +116,22 @@ size_t AudioVoiceMono::pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo,
if (scratch16.size() < frames)
scratch16.resize(frames);
size_t oDone = soxr_output(m_src, scratch16.data(), frames);
size_t oDone;
size_t totalDone = 0;
while (frames)
{
oDone = soxr_output(m_src, scratch16.data(), frames);
_midUpdate();
if (oDone)
{
m_matrix.mixMonoSampleData(mixInfo, scratch16.data(), buf, oDone);
totalDone += oDone;
frames -= oDone;
buf += oDone;
}
}
m_matrix.mixMonoSampleData(mixInfo, scratch16.data(), buf, oDone);
return oDone;
return totalDone;
}
size_t AudioVoiceMono::pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo,
@ -106,10 +141,22 @@ size_t AudioVoiceMono::pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo,
if (scratch32.size() < frames)
scratch32.resize(frames);
size_t oDone = soxr_output(m_src, scratch32.data(), frames);
size_t oDone;
size_t totalDone = 0;
while (frames)
{
oDone = soxr_output(m_src, scratch32.data(), frames);
_midUpdate();
if (oDone)
{
m_matrix.mixMonoSampleData(mixInfo, scratch32.data(), buf, oDone);
totalDone += oDone;
frames -= oDone;
buf += oDone;
}
}
m_matrix.mixMonoSampleData(mixInfo, scratch32.data(), buf, oDone);
return oDone;
return totalDone;
}
size_t AudioVoiceMono::pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo,
@ -119,10 +166,22 @@ size_t AudioVoiceMono::pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo,
if (scratchFlt.size() < frames)
scratchFlt.resize(frames);
size_t oDone = soxr_output(m_src, scratchFlt.data(), frames);
size_t oDone;
size_t totalDone = 0;
while (frames)
{
oDone = soxr_output(m_src, scratchFlt.data(), frames);
_midUpdate();
if (oDone)
{
m_matrix.mixMonoSampleData(mixInfo, scratchFlt.data(), buf, oDone);
totalDone += oDone;
frames -= oDone;
buf += oDone;
}
}
m_matrix.mixMonoSampleData(mixInfo, scratchFlt.data(), buf, oDone);
return oDone;
return totalDone;
}
void AudioVoiceMono::setDefaultMatrixCoefficients()
@ -155,10 +214,10 @@ AudioVoiceStereo::AudioVoiceStereo(BaseAudioVoiceEngine& root, IAudioMix& parent
double sampleRate, bool dynamicRate)
: AudioVoice(root, parent, cb, dynamicRate)
{
resetSampleRate(sampleRate);
_resetSampleRate(sampleRate);
}
void AudioVoiceStereo::resetSampleRate(double sampleRate)
void AudioVoiceStereo::_resetSampleRate(double sampleRate)
{
soxr_delete(m_src);
@ -172,11 +231,13 @@ void AudioVoiceStereo::resetSampleRate(double sampleRate)
if (!m_src)
{
Log.report(logvisor::Fatal, "unable to create soxr resampler: %s", soxr_strerror(err));
m_resetSampleRate = false;
return;
}
soxr_set_input_fn(m_src, soxr_input_fn_t(SRCCallback), this, 0);
setPitchRatio(m_pitchRatio);
_setPitchRatio(m_pitchRatio);
m_resetSampleRate = false;
}
size_t AudioVoiceStereo::SRCCallback(AudioVoiceStereo* ctx, int16_t** data, size_t frames)
@ -197,10 +258,22 @@ size_t AudioVoiceStereo::pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo,
if (scratch16.size() < samples)
scratch16.resize(samples);
size_t oDone = soxr_output(m_src, scratch16.data(), frames);
size_t oDone;
size_t totalDone = 0;
while (frames)
{
oDone = soxr_output(m_src, scratch16.data(), frames);
_midUpdate();
if (oDone)
{
m_matrix.mixStereoSampleData(mixInfo, scratch16.data(), buf, oDone);
totalDone += oDone;
frames -= oDone;
buf += oDone;
}
}
m_matrix.mixStereoSampleData(mixInfo, scratch16.data(), buf, oDone);
return oDone;
return totalDone;
}
size_t AudioVoiceStereo::pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo,
@ -211,10 +284,22 @@ size_t AudioVoiceStereo::pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo,
if (scratch32.size() < samples)
scratch32.resize(samples);
size_t oDone = soxr_output(m_src, scratch32.data(), frames);
size_t oDone;
size_t totalDone = 0;
while (frames)
{
oDone = soxr_output(m_src, scratch32.data(), frames);
_midUpdate();
if (oDone)
{
m_matrix.mixStereoSampleData(mixInfo, scratch32.data(), buf, oDone);
totalDone += oDone;
frames -= oDone;
buf += oDone;
}
}
m_matrix.mixStereoSampleData(mixInfo, scratch32.data(), buf, oDone);
return oDone;
return totalDone;
}
size_t AudioVoiceStereo::pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo,
@ -225,10 +310,22 @@ size_t AudioVoiceStereo::pumpAndMix(const AudioVoiceEngineMixInfo& mixInfo,
if (scratchFlt.size() < samples)
scratchFlt.resize(samples);
size_t oDone = soxr_output(m_src, scratchFlt.data(), frames);
size_t oDone;
size_t totalDone = 0;
while (frames)
{
oDone = soxr_output(m_src, scratchFlt.data(), frames);
_midUpdate();
if (oDone)
{
m_matrix.mixStereoSampleData(mixInfo, scratchFlt.data(), buf, oDone);
totalDone += oDone;
frames -= oDone;
buf += oDone;
}
}
m_matrix.mixStereoSampleData(mixInfo, scratchFlt.data(), buf, oDone);
return oDone;
return totalDone;
}
void AudioVoiceStereo::setDefaultMatrixCoefficients()

View File

@ -34,12 +34,24 @@ protected:
/* Sample-rate converter */
soxr_t m_src = nullptr;
double m_pitchRatio = 1.0;
bool m_dynamicRate;
/* Running bool */
bool m_running = false;
/* Deferred sample-rate reset */
bool m_resetSampleRate = false;
double m_deferredSampleRate;
virtual void _resetSampleRate(double sampleRate)=0;
/* Deferred pitch ratio set */
bool m_setPitchRatio = false;
double m_pitchRatio = 1.0;
void _setPitchRatio(double ratio);
/* 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;
@ -47,7 +59,7 @@ protected:
public:
~AudioVoice();
void resetSampleRate(double sampleRate);
void setPitchRatio(double ratio);
void start();
void stop();
@ -57,7 +69,7 @@ public:
class AudioVoiceMono : public AudioVoice
{
AudioMatrixMono m_matrix;
void resetSampleRate(double sampleRate);
void _resetSampleRate(double sampleRate);
static size_t SRCCallback(AudioVoiceMono* ctx,
int16_t** data, size_t requestedLen);
@ -77,7 +89,7 @@ public:
class AudioVoiceStereo : public AudioVoice
{
AudioMatrixStereo m_matrix;
void resetSampleRate(double sampleRate);
void _resetSampleRate(double sampleRate);
static size_t SRCCallback(AudioVoiceStereo* ctx,
int16_t** data, size_t requestedLen);