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

View File

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