mirror of
https://github.com/RGBCube/serenity
synced 2025-05-18 13:55:08 +00:00

The file is now renamed to Queue.h, and the Resampler APIs with LegacyBuffer are also removed. These changes look large because nobody actually needs Buffer.h (or Queue.h). It was mostly transitive dependencies on the massive list of includes in that header, which are now almost all gone. Instead, we include common things like Sample.h directly, which should give faster compile times as very few files actually need Queue.h.
87 lines
2.2 KiB
C++
87 lines
2.2 KiB
C++
/*
|
|
* Copyright (c) 2022, kleines Filmröllchen <filmroellchen@serenityos.org>.
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/Concepts.h>
|
|
#include <AK/Types.h>
|
|
#include <AK/Vector.h>
|
|
|
|
namespace Audio {
|
|
|
|
// 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(u32 source, u32 target)
|
|
: m_source(source)
|
|
, m_target(target)
|
|
{
|
|
VERIFY(source > 0);
|
|
VERIFY(target > 0);
|
|
}
|
|
|
|
// 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)
|
|
{
|
|
m_last_sample_l = sample_l;
|
|
m_last_sample_r = sample_r;
|
|
m_current_ratio += m_target;
|
|
}
|
|
|
|
// 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)
|
|
{
|
|
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;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
template<ArrayLike<SampleType> Samples>
|
|
Vector<SampleType> resample(Samples&& to_resample)
|
|
{
|
|
Vector<SampleType> resampled;
|
|
resampled.ensure_capacity(to_resample.size() * ceil_div(m_source, m_target));
|
|
for (auto sample : to_resample) {
|
|
process_sample(sample, sample);
|
|
|
|
while (read_sample(sample, sample))
|
|
resampled.unchecked_append(sample);
|
|
}
|
|
|
|
return resampled;
|
|
}
|
|
|
|
void reset()
|
|
{
|
|
m_current_ratio = 0;
|
|
m_last_sample_l = {};
|
|
m_last_sample_r = {};
|
|
}
|
|
|
|
u32 source() const { return m_source; }
|
|
u32 target() const { return m_target; }
|
|
|
|
private:
|
|
const u32 m_source;
|
|
const u32 m_target;
|
|
u32 m_current_ratio { 0 };
|
|
SampleType m_last_sample_l {};
|
|
SampleType m_last_sample_r {};
|
|
};
|
|
|
|
}
|