diff options
author | kleines Filmröllchen <malu.bertsch@gmail.com> | 2021-06-25 13:37:38 +0200 |
---|---|---|
committer | Ali Mohammad Pur <Ali.mpfard@gmail.com> | 2021-06-25 20:48:14 +0430 |
commit | 184a9e7e67542faccd6a054b5c4d50f2916cd0d4 (patch) | |
tree | 585fd80bd90cb116849a12497bf6fc1e15c9249a /Userland/Libraries/LibAudio | |
parent | 2e0015527582c04dc0dd7b81d2af62923db90686 (diff) | |
download | serenity-184a9e7e67542faccd6a054b5c4d50f2916cd0d4.zip |
LibAudio: Make ResampleHelper templated for different sample types
Previously, ResampleHelper was fixed on handling double's, which makes
it unsuitable for the upcoming FLAC loader that needs to resample
integers. For this reason, ResampleHelper is templated to support
theoretically any type of sample, though only the necessary i32 and
double are templated right now.
The ResampleHelper implementations are moved from WavLoader.cpp to
Buffer.cpp.
This also improves some imports in the WavLoader files.
Diffstat (limited to 'Userland/Libraries/LibAudio')
-rw-r--r-- | Userland/Libraries/LibAudio/Buffer.cpp | 58 | ||||
-rw-r--r-- | Userland/Libraries/LibAudio/Buffer.h | 20 | ||||
-rw-r--r-- | Userland/Libraries/LibAudio/WavLoader.cpp | 32 | ||||
-rw-r--r-- | Userland/Libraries/LibAudio/WavLoader.h | 2 |
4 files changed, 73 insertions, 39 deletions
diff --git a/Userland/Libraries/LibAudio/Buffer.cpp b/Userland/Libraries/LibAudio/Buffer.cpp index 86a51aa7ac..efe6945a5f 100644 --- a/Userland/Libraries/LibAudio/Buffer.cpp +++ b/Userland/Libraries/LibAudio/Buffer.cpp @@ -5,10 +5,10 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include "Buffer.h" #include <AK/Atomic.h> #include <AK/Debug.h> #include <AK/String.h> -#include <LibAudio/Buffer.h> namespace Audio { @@ -44,7 +44,7 @@ i32 Buffer::allocate_id() } template<typename SampleReader> -static void read_samples_from_stream(InputMemoryStream& stream, SampleReader read_sample, Vector<Frame>& samples, ResampleHelper& resampler, int num_channels) +static void read_samples_from_stream(InputMemoryStream& stream, SampleReader read_sample, Vector<Frame>& samples, ResampleHelper<double>& resampler, int num_channels) { double norm_l = 0; double norm_r = 0; @@ -127,13 +127,13 @@ static double read_norm_sample_8(InputMemoryStream& stream) return double(sample) / NumericLimits<u8>::max(); } -RefPtr<Buffer> Buffer::from_pcm_data(ReadonlyBytes data, ResampleHelper& resampler, int num_channels, PcmSampleFormat sample_format) +RefPtr<Buffer> Buffer::from_pcm_data(ReadonlyBytes data, ResampleHelper<double>& resampler, int num_channels, PcmSampleFormat sample_format) { InputMemoryStream stream { data }; return from_pcm_stream(stream, resampler, num_channels, sample_format, data.size() / (pcm_bits_per_sample(sample_format) / 8)); } -RefPtr<Buffer> Buffer::from_pcm_stream(InputMemoryStream& stream, ResampleHelper& resampler, int num_channels, PcmSampleFormat sample_format, int num_samples) +RefPtr<Buffer> Buffer::from_pcm_stream(InputMemoryStream& stream, ResampleHelper<double>& resampler, int num_channels, PcmSampleFormat sample_format, int num_samples) { Vector<Frame> fdata; fdata.ensure_capacity(num_samples); @@ -166,4 +166,54 @@ RefPtr<Buffer> Buffer::from_pcm_stream(InputMemoryStream& stream, ResampleHelper return Buffer::create_with_samples(move(fdata)); } +template<typename SampleType> +ResampleHelper<SampleType>::ResampleHelper(double source, double target) + : m_ratio(source / target) +{ +} +template ResampleHelper<i32>::ResampleHelper(double, double); +template ResampleHelper<double>::ResampleHelper(double, double); + +template<typename SampleType> +Vector<SampleType> ResampleHelper<SampleType>::resample(Vector<SampleType> to_resample) +{ + Vector<SampleType> resampled; + resampled.ensure_capacity(to_resample.size() * m_ratio); + for (auto sample : to_resample) { + process_sample(sample, sample); + + while (read_sample(sample, sample)) + resampled.unchecked_append(sample); + } + + return resampled; +} +template Vector<i32> ResampleHelper<i32>::resample(Vector<i32>); +template Vector<double> ResampleHelper<double>::resample(Vector<double>); + +template<typename SampleType> +void ResampleHelper<SampleType>::process_sample(SampleType sample_l, SampleType sample_r) +{ + m_last_sample_l = sample_l; + m_last_sample_r = sample_r; + m_current_ratio += 1; +} +template void ResampleHelper<i32>::process_sample(i32, i32); +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; + next_l = m_last_sample_l; + next_r = m_last_sample_r; + return true; + } + + return false; +} +template bool ResampleHelper<i32>::read_sample(i32&, i32&); +template bool ResampleHelper<double>::read_sample(double&, double&); + } diff --git a/Userland/Libraries/LibAudio/Buffer.h b/Userland/Libraries/LibAudio/Buffer.h index 88d0fa0c56..3619111384 100644 --- a/Userland/Libraries/LibAudio/Buffer.h +++ b/Userland/Libraries/LibAudio/Buffer.h @@ -88,25 +88,33 @@ String sample_format_name(PcmSampleFormat format); // Small helper to resample from one playback rate to another // This isn't really "smart", in that we just insert (or drop) samples. // Should do better... +template<typename SampleType> class ResampleHelper { public: ResampleHelper(double source, double target); - void process_sample(double sample_l, double sample_r); - bool read_sample(double& next_l, double& next_r); + // To be used as follows: + // while the resampler doesn't need a new sample, read_sample(current) and store the resulting samples. + // as long as the resampler needs a new sample, process_sample(current) + + // Stores a new sample + void process_sample(SampleType sample_l, SampleType sample_r); + // Assigns the given sample to its correct value and returns false if there is a new sample required + bool read_sample(SampleType& next_l, SampleType& next_r); + Vector<SampleType> resample(Vector<SampleType> to_resample); private: const double m_ratio; double m_current_ratio { 0 }; - double m_last_sample_l { 0 }; - double m_last_sample_r { 0 }; + SampleType m_last_sample_l; + SampleType m_last_sample_r; }; // A buffer of audio samples, normalized to 44100hz. class Buffer : public RefCounted<Buffer> { public: - static RefPtr<Buffer> from_pcm_data(ReadonlyBytes data, ResampleHelper& resampler, int num_channels, PcmSampleFormat sample_format); - static RefPtr<Buffer> from_pcm_stream(InputMemoryStream& stream, ResampleHelper& resampler, int num_channels, PcmSampleFormat sample_format, int num_samples); + static RefPtr<Buffer> from_pcm_data(ReadonlyBytes data, ResampleHelper<double>& resampler, int num_channels, PcmSampleFormat sample_format); + static RefPtr<Buffer> from_pcm_stream(InputMemoryStream& stream, ResampleHelper<double>& resampler, int num_channels, PcmSampleFormat sample_format, int num_samples); static NonnullRefPtr<Buffer> create_with_samples(Vector<Frame>&& samples) { return adopt_ref(*new Buffer(move(samples))); diff --git a/Userland/Libraries/LibAudio/WavLoader.cpp b/Userland/Libraries/LibAudio/WavLoader.cpp index 3353549e20..2734ae4109 100644 --- a/Userland/Libraries/LibAudio/WavLoader.cpp +++ b/Userland/Libraries/LibAudio/WavLoader.cpp @@ -5,11 +5,11 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include "WavLoader.h" +#include "Buffer.h" #include <AK/Debug.h> #include <AK/NumericLimits.h> #include <AK/OwnPtr.h> -#include <LibAudio/Buffer.h> -#include <LibAudio/WavLoader.h> #include <LibCore/File.h> #include <LibCore/FileStream.h> @@ -30,7 +30,7 @@ WavLoaderPlugin::WavLoaderPlugin(const StringView& path) if (!valid) return; - m_resampler = make<ResampleHelper>(m_sample_rate, m_device_sample_rate); + m_resampler = make<ResampleHelper<double>>(m_sample_rate, m_device_sample_rate); } WavLoaderPlugin::WavLoaderPlugin(const ByteBuffer& buffer) @@ -46,7 +46,7 @@ WavLoaderPlugin::WavLoaderPlugin(const ByteBuffer& buffer) if (!valid) return; - m_resampler = make<ResampleHelper>(m_sample_rate, m_device_sample_rate); + m_resampler = make<ResampleHelper<double>>(m_sample_rate, m_device_sample_rate); } RefPtr<Buffer> WavLoaderPlugin::get_more_samples(size_t max_bytes_to_read_from_input) @@ -284,28 +284,4 @@ bool WavLoaderPlugin::parse_header() return true; } -ResampleHelper::ResampleHelper(double source, double target) - : m_ratio(source / target) -{ -} - -void ResampleHelper::process_sample(double sample_l, double sample_r) -{ - m_last_sample_l = sample_l; - m_last_sample_r = sample_r; - m_current_ratio += 1; -} - -bool ResampleHelper::read_sample(double& next_l, double& next_r) -{ - if (m_current_ratio > 0) { - m_current_ratio -= m_ratio; - next_l = m_last_sample_l; - next_r = m_last_sample_r; - return true; - } - - return false; -} - } diff --git a/Userland/Libraries/LibAudio/WavLoader.h b/Userland/Libraries/LibAudio/WavLoader.h index 4eaa4b9a4b..edef9ed1d3 100644 --- a/Userland/Libraries/LibAudio/WavLoader.h +++ b/Userland/Libraries/LibAudio/WavLoader.h @@ -71,7 +71,7 @@ private: // // It would avoid duplicate resampling code and would allow clients // to be agnostic of the destination audio device's sample rate. - OwnPtr<ResampleHelper> m_resampler; + OwnPtr<ResampleHelper<double>> m_resampler; u32 m_sample_rate { 0 }; u16 m_num_channels { 0 }; |