120class ACompileTimeSoundResampler {
123 mInputSampleRate(source->info().sampleRate), mSource(source),
124 mConverter(aui::audio::platform::requested_sample_rate, std::move(source)) {
127 void setVolume(aui::audio::VolumeLevel volume) {
128 mVolumeLevel = volume;
131 template<ASampleFormat format>
132 inline void commitSample(aui::audio::impl::sample_type_t<format> sample) {
133 AUI_ASSERTX(mDestinationBufferIt <= mDestinationBufferEnd,
"buffer overrun");
135 int64_t newSample = int64_t(aui::audio::impl::sample_cast<sample_out, format>(sample));
137 newSample = (*mVolumeLevel * newSample) / aui::audio::VolumeLevel::MAX;
139 newSample += int64_t(aui::audio::impl::extractSample<sample_out>(mDestinationBufferIt));
140 newSample = glm::clamp(newSample, MIN_VAL, MAX_VAL);
141 aui::audio::impl::pushSample<sample_out>(newSample, mDestinationBufferIt);
142 mDestinationBufferIt += aui::audio::impl::size_bytes<sample_out>();
146 size_t remainingSampleCount()
const {
147 return (mDestinationBufferEnd - mDestinationBufferIt) / aui::audio::impl::size_bytes<sample_out>();
150 constexpr size_t canReadSamples(
size_t canPushSamples) {
151 return (canPushSamples /
size_t(channels_out)) * size_t(channels_in);
154 inline void commitAllSamples() {
155 std::byte buf[BUFFER_SIZE];
156 while (
auto remSampleCount = remainingSampleCount()) {
157 size_t samplesToRead = canReadSamples(remainingSampleCount());
159 if (mInputSampleRate == aui::audio::platform::requested_sample_rate) {
160 std::span dst(buf, std::min(aui::audio::impl::size_bytes<sample_in>() * samplesToRead,
sizeof(buf)));
161 r = mSource->read(dst);
162 iterateOverBuffer<sample_in>(buf, buf + r);
166 std::span dst(buf, std::min(aui::audio::impl::size_bytes<conv_sample_format>() * samplesToRead,
sizeof(buf)));
167 r = mConverter.convert(dst);
168 iterateOverBuffer<conv_sample_format>(buf, buf + r);
177 template <ASampleFormat format>
178 void iterateOverBuffer(std::byte* begin, std::byte* end) {
179 static constexpr size_t stepSize =
static_cast<size_t>(channels_in) * aui::audio::impl::size_bytes<format>();
180 for (std::byte *it = begin; it + stepSize <= end; it += stepSize) {
181 if constexpr (channels_in == channels_out) {
182 for (
size_t i = 0; i < static_cast<size_t>(channels_in); i++) {
183 commitSample<format>(aui::audio::impl::extractSample<format>(
184 it + i * aui::audio::impl::size_bytes<format>()));
187 if constexpr (channels_in == AChannelFormat::MONO) {
189 auto sample = aui::audio::impl::extractSample<format>(it);
190 commitSample<format>(sample);
191 commitSample<format>(sample);
199 void setDestination(std::span<std::byte> dst) {
200 mDestinationBufferBegin = dst.data();
201 mDestinationBufferEnd = dst.data() + dst.size();
202 mDestinationBufferIt = mDestinationBufferBegin;
206 bool isFull()
const {
207 return mDestinationBufferBegin != mDestinationBufferIt;
211 size_t writtenSize()
const {
212 return mDestinationBufferIt - mDestinationBufferBegin;
218 static constexpr int64_t MIN_VAL = std::numeric_limits<typename output_t::type>::min();
219 static constexpr int64_t MAX_VAL = std::numeric_limits<typename output_t::type>::max();
220 static constexpr size_t BUFFER_SIZE = 0x3000;
223 std::byte *mDestinationBufferBegin =
nullptr;
224 std::byte *mDestinationBufferEnd =
nullptr;
225 std::byte *mDestinationBufferIt =
nullptr;
226 std::uint32_t mInputSampleRate;