Skip to content

Commit

Permalink
fix(mixer): Improved dynamic sample rate conversion.
Browse files Browse the repository at this point in the history
Signed-off-by: Axel Nana <[email protected]>
  • Loading branch information
na2axl committed Aug 25, 2024
1 parent f7ef74c commit b125b81
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 7 deletions.
3 changes: 3 additions & 0 deletions include/SparkyStudios/Audio/Amplitude/DSP/AudioConverter.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ namespace SparkyStudios::Audio::Amplitude
ChannelConversionMode _channelConversionMode;

bool _needResampling;
bool _srcInitialized;

Settings _settings;
};
} // namespace SparkyStudios::Audio::Amplitude

Expand Down
25 changes: 22 additions & 3 deletions src/DSP/AudioConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ namespace SparkyStudios::Audio::Amplitude
AudioConverter::AudioConverter()
: _resampler(nullptr)
, _channelConversionMode(kChannelConversionModeDisabled)
, _needResampling(false)
, _srcInitialized(false)
{
_resampler = Resampler::Construct("default");
Reset();
Expand All @@ -42,8 +44,15 @@ namespace SparkyStudios::Audio::Amplitude
else
return false; // Unsupported channel conversion mode

_needResampling = settings.m_sourceChannelCount != settings.m_targetChannelCount;
_resampler->Initialize(settings.m_targetChannelCount, settings.m_sourceSampleRate, settings.m_targetSampleRate);
_needResampling = settings.m_sourceSampleRate != settings.m_targetSampleRate;

if (_needResampling)
{
_resampler->Initialize(settings.m_targetChannelCount, settings.m_sourceSampleRate, settings.m_targetSampleRate);
_srcInitialized = true;
}

_settings = settings;

return true;
}
Expand Down Expand Up @@ -78,7 +87,17 @@ namespace SparkyStudios::Audio::Amplitude
void AudioConverter::SetSampleRate(AmUInt64 sourceSampleRate, AmUInt64 targetSampleRate)
{
_needResampling = sourceSampleRate != targetSampleRate;
_resampler->SetSampleRate(sourceSampleRate, targetSampleRate);

_settings.m_sourceSampleRate = sourceSampleRate;
_settings.m_targetSampleRate = targetSampleRate;

if (!_needResampling)
return;

if (_srcInitialized)
_resampler->SetSampleRate(sourceSampleRate, targetSampleRate);
else
_resampler->Initialize(_settings.m_targetChannelCount, sourceSampleRate, targetSampleRate);
}

AmUInt64 AudioConverter::GetRequiredInputFrameCount(AmUInt64 outputFrameCount) const
Expand Down
11 changes: 7 additions & 4 deletions src/Mixer/Amplimix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#include <Core/Engine.h>
#include <Mixer/Amplimix.h>

#define AMPLIMIX_STORE(A, C) std::atomic_store_explicit(A, C, std::memory_order_release)
#define AMPLIMIX_STORE(A, C) std::atomic_store_explicit(A, (C), std::memory_order_release)
#define AMPLIMIX_LOAD(A) std::atomic_load_explicit(A, std::memory_order_acquire)
#define AMPLIMIX_CSWAP(A, E, C) std::atomic_compare_exchange_strong_explicit(A, E, C, std::memory_order_acq_rel, std::memory_order_acquire)

Expand Down Expand Up @@ -529,6 +529,10 @@ namespace SparkyStudios::Audio::Amplitude
AMPLIMIX_STORE(&lay->userPlaySpeed, speed);
// atomically set cursor to start position based on given argument
AMPLIMIX_STORE(&lay->cursor, lay->start);
// store the base sample rate ratio for this source
AMPLIMIX_STORE(
&lay->baseSampleRateRatio,
static_cast<AmReal32>(sound->format.GetSampleRate()) / static_cast<AmReal32>(_device.mRequestedOutputSampleRate));

// Initialize the converter
lay->dataConverter = ampoolnew(MemoryPoolKind::Amplimix, AudioConverter);
Expand Down Expand Up @@ -1064,9 +1068,8 @@ namespace SparkyStudios::Audio::Amplitude
{
currentSpeed = AM_Lerp(currentSpeed, 0.75f, playSpeed);

const AmReal32 basePitch =
static_cast<AmReal32>(layer->snd->format.GetSampleRate()) / static_cast<AmReal32>(_device.mRequestedOutputSampleRate);
const AmReal32 sampleRateRatio = basePitch * currentSpeed;
const AmReal32 baseSampleRateRatio = AMPLIMIX_LOAD(&layer->baseSampleRateRatio);
const AmReal32 sampleRateRatio = baseSampleRateRatio * currentSpeed;

AMPLIMIX_STORE(&layer->targetPlaySpeed, playSpeed);
AMPLIMIX_STORE(&layer->sampleRateRatio, sampleRateRatio);
Expand Down
1 change: 1 addition & 0 deletions src/Mixer/Amplimix.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ namespace SparkyStudios::Audio::Amplitude
_Atomic(AmReal32) playSpeed; // current sound playback speed
_Atomic(AmReal32) targetPlaySpeed; // computed (real) sound playback speed
_Atomic(AmReal32) sampleRateRatio; // sample rate ratio
_Atomic(AmReal32) baseSampleRateRatio; // base sample rate ratio

AudioConverter* dataConverter; // miniaudio resampler & channel converter

Expand Down

0 comments on commit b125b81

Please sign in to comment.