diff options
author | kleines Filmröllchen <malu.bertsch@gmail.com> | 2021-08-17 00:44:42 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-08-18 18:16:48 +0200 |
commit | d7ca60b998ebb0b1fb8aa418a3a6cd25609775f0 (patch) | |
tree | 1d40eda276d58ffcbe1ac67d06eb322bf48073be /Userland/Libraries | |
parent | 6c9343e262abe5a72f8b2f0d71590c627a7eb622 (diff) | |
download | serenity-d7ca60b998ebb0b1fb8aa418a3a6cd25609775f0.zip |
LibAudio: Resample with integer ratios instead of floats
Floating-point ratios are inherently imprecise, and can lead to
unpredictable or nondeterministic behavior when resampling and expecting
a certain number of resulting samples. Therefore, the resampler now uses
integer ratios, with almost identical but fully predictable behavior.
This also introduces the reset() function that the FLAC loader will use
in the future.
Diffstat (limited to 'Userland/Libraries')
-rw-r--r-- | Userland/Libraries/LibAudio/Buffer.cpp | 29 | ||||
-rw-r--r-- | Userland/Libraries/LibAudio/Buffer.h | 9 |
2 files changed, 27 insertions, 11 deletions
diff --git a/Userland/Libraries/LibAudio/Buffer.cpp b/Userland/Libraries/LibAudio/Buffer.cpp index efe6945a5f..1039f5bb3f 100644 --- a/Userland/Libraries/LibAudio/Buffer.cpp +++ b/Userland/Libraries/LibAudio/Buffer.cpp @@ -8,6 +8,7 @@ #include "Buffer.h" #include <AK/Atomic.h> #include <AK/Debug.h> +#include <AK/StdLibExtras.h> #include <AK/String.h> namespace Audio { @@ -167,18 +168,19 @@ RefPtr<Buffer> Buffer::from_pcm_stream(InputMemoryStream& stream, ResampleHelper } template<typename SampleType> -ResampleHelper<SampleType>::ResampleHelper(double source, double target) - : m_ratio(source / target) +ResampleHelper<SampleType>::ResampleHelper(u32 source, u32 target) + : m_source(source) + , m_target(target) { } -template ResampleHelper<i32>::ResampleHelper(double, double); -template ResampleHelper<double>::ResampleHelper(double, double); +template ResampleHelper<i32>::ResampleHelper(u32, u32); +template ResampleHelper<double>::ResampleHelper(u32, u32); template<typename SampleType> Vector<SampleType> ResampleHelper<SampleType>::resample(Vector<SampleType> to_resample) { Vector<SampleType> resampled; - resampled.ensure_capacity(to_resample.size() * m_ratio); + resampled.ensure_capacity(to_resample.size() * ceil_div(m_source, m_target)); for (auto sample : to_resample) { process_sample(sample, sample); @@ -196,7 +198,7 @@ void ResampleHelper<SampleType>::process_sample(SampleType sample_l, SampleType { m_last_sample_l = sample_l; m_last_sample_r = sample_r; - m_current_ratio += 1; + m_current_ratio += m_target; } template void ResampleHelper<i32>::process_sample(i32, i32); template void ResampleHelper<double>::process_sample(double, double); @@ -204,8 +206,8 @@ template void ResampleHelper<double>::process_sample(double, double); template<typename SampleType> bool ResampleHelper<SampleType>::read_sample(SampleType& next_l, SampleType& next_r) { - if (m_current_ratio > 0) { - m_current_ratio -= m_ratio; + if (m_current_ratio >= m_source) { + m_current_ratio -= m_source; next_l = m_last_sample_l; next_r = m_last_sample_r; return true; @@ -216,4 +218,15 @@ bool ResampleHelper<SampleType>::read_sample(SampleType& next_l, SampleType& nex template bool ResampleHelper<i32>::read_sample(i32&, i32&); template bool ResampleHelper<double>::read_sample(double&, double&); +template<typename SampleType> +void ResampleHelper<SampleType>::reset() +{ + m_current_ratio = 0; + m_last_sample_l = {}; + m_last_sample_r = {}; +} + +template void ResampleHelper<i32>::reset(); +template void ResampleHelper<double>::reset(); + } diff --git a/Userland/Libraries/LibAudio/Buffer.h b/Userland/Libraries/LibAudio/Buffer.h index 3619111384..6bf6377b96 100644 --- a/Userland/Libraries/LibAudio/Buffer.h +++ b/Userland/Libraries/LibAudio/Buffer.h @@ -91,7 +91,7 @@ String sample_format_name(PcmSampleFormat format); template<typename SampleType> class ResampleHelper { public: - ResampleHelper(double source, double target); + ResampleHelper(u32 source, u32 target); // To be used as follows: // while the resampler doesn't need a new sample, read_sample(current) and store the resulting samples. @@ -103,9 +103,12 @@ public: bool read_sample(SampleType& next_l, SampleType& next_r); Vector<SampleType> resample(Vector<SampleType> to_resample); + void reset(); + private: - const double m_ratio; - double m_current_ratio { 0 }; + const u32 m_source; + const u32 m_target; + u32 m_current_ratio { 0 }; SampleType m_last_sample_l; SampleType m_last_sample_r; }; |