mirror of https://github.com/AxioDL/boo.git
Add short-process loop for voices that make sample-level parameter changes
This commit is contained in:
parent
b3e77c4384
commit
4a74a0ad7c
|
@ -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()
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue