160class ACompileTimeSoundResampler {
163 : mInputSampleRate(source->info().sampleRate)
164 , mConverter(aui::audio::platform::requested_sample_rate, std::move(source)) {}
166 template <ASampleFormat format>
167 inline void commitSample(
Transaction& transaction, aui::audio::impl::sample_type_t<format> sample) {
168 AUI_ASSERTX(transaction.destinationBufferIt <= transaction.destinationBufferEnd,
"buffer overrun");
170 int64_t newSample = int64_t(aui::audio::impl::sample_cast<sample_out, format>(sample));
171 if (transaction.volumeLevel) {
172 newSample = (*transaction.volumeLevel * newSample) / aui::audio::VolumeLevel::MAX;
174 newSample += int64_t(aui::audio::impl::extractSample<sample_out>(transaction.destinationBufferIt));
175 newSample = glm::clamp(newSample, MIN_VAL, MAX_VAL);
176 aui::audio::impl::pushSample<sample_out>(newSample, transaction.destinationBufferIt);
177 transaction.destinationBufferIt += aui::audio::impl::size_bytes<sample_out>();
180 constexpr size_t canReadSamples(
size_t canPushSamples) {
181 return (canPushSamples /
size_t(channels_out)) * size_t(channels_in);
184 inline void commitAllSamples(
Transaction& transaction) {
185 int deadbeef1 = 0xdeadbeef;
186 std::byte buf[BUFFER_SIZE];
187 int deadbeef2 = 0xdeadbeef;
188 while (
auto remSampleCount = transaction.remainingSampleCount<sample_out>()) {
189 size_t samplesToRead = canReadSamples(transaction.remainingSampleCount<sample_out>());
191 if (mInputSampleRate == aui::audio::platform::requested_sample_rate) {
192 std::span dst(buf, std::min(aui::audio::impl::size_bytes<sample_in>() * samplesToRead,
sizeof(buf)));
193 r = mConverter.source()->read(dst);
194 AUI_ASSERTX(r <= dst.size(),
"result larger than supplied buffer?");
195 AUI_ASSERTX(deadbeef1 == 0xdeadbeef,
"stack corruption");
196 AUI_ASSERTX(deadbeef2 == 0xdeadbeef,
"stack corruption");
197 iterateOverBuffer<sample_in>(transaction, buf, buf + r);
201 buf, std::min(aui::audio::impl::size_bytes<conv_sample_format>() * samplesToRead,
sizeof(buf)));
202 r = mConverter.convert(dst);
203 AUI_ASSERTX(r <= dst.size(),
"result larger than supplied buffer?");
204 iterateOverBuffer<conv_sample_format>(transaction, buf, buf + r);
205 AUI_ASSERTX(deadbeef1 == 0xdeadbeef,
"stack corruption");
206 AUI_ASSERTX(deadbeef2 == 0xdeadbeef,
"stack corruption");
215 template <ASampleFormat format>
216 void iterateOverBuffer(
Transaction& transaction, std::byte* begin, std::byte* end) {
217 static constexpr size_t stepSize =
static_cast<size_t>(channels_in) * aui::audio::impl::size_bytes<format>();
218 for (std::byte* it = begin; it + stepSize <= end; it += stepSize) {
219 if constexpr (channels_in == channels_out) {
220 for (
size_t i = 0; i < static_cast<size_t>(channels_in); i++) {
221 commitSample<format>(
223 aui::audio::impl::extractSample<format>(it + i * aui::audio::impl::size_bytes<format>()));
226 if constexpr (channels_in == AChannelFormat::MONO) {
228 auto sample = aui::audio::impl::extractSample<format>(it);
229 commitSample<format>(transaction, sample);
230 commitSample<format>(transaction, sample);
241 static constexpr int64_t MIN_VAL = std::numeric_limits<typename output_t::type>::min();
242 static constexpr int64_t MAX_VAL = std::numeric_limits<typename output_t::type>::max();
243 static constexpr size_t BUFFER_SIZE = 0x3000;
246 std::uint32_t mInputSampleRate;