Audio library refactor: use spans for stream->read
This commit is contained in:
parent
7376109e96
commit
2209648999
22 changed files with 124 additions and 130 deletions
|
|
@ -20,7 +20,7 @@ namespace psemek::audio
|
||||||
float smoothness() const;
|
float smoothness() const;
|
||||||
float smoothness(float value);
|
float smoothness(float value);
|
||||||
|
|
||||||
void apply(float * data, std::size_t sample_count);
|
void apply(util::span<float> samples);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::atomic<float> gain_[2];
|
std::atomic<float> gain_[2];
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <psemek/util/span.hpp>
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
@ -14,7 +16,7 @@ namespace psemek::audio
|
||||||
|
|
||||||
// Return value less than sample count means end of stream
|
// Return value less than sample count means end of stream
|
||||||
// Must be called from mixing thread
|
// Must be called from mixing thread
|
||||||
virtual std::size_t read(float * data, std::size_t sample_count) = 0;
|
virtual std::size_t read(util::span<float> samples) = 0;
|
||||||
|
|
||||||
// The number of samples already played from this stream
|
// The number of samples already played from this stream
|
||||||
virtual std::size_t played() const = 0;
|
virtual std::size_t played() const = 0;
|
||||||
|
|
|
||||||
|
|
@ -26,17 +26,16 @@ namespace psemek::audio
|
||||||
return played_.load();
|
return played_.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t read(float * data, std::size_t sample_count) override
|
std::size_t read(util::span<float> samples) override
|
||||||
{
|
{
|
||||||
auto end = data + sample_count;
|
for (auto p = samples.begin(); p != samples.end();)
|
||||||
for (auto p = data; p != end;)
|
|
||||||
{
|
{
|
||||||
float v = func_();
|
float v = func_();
|
||||||
*p++ = v;
|
*p++ = v;
|
||||||
*p++ = v;
|
*p++ = v;
|
||||||
}
|
}
|
||||||
played_.fetch_add(sample_count);
|
played_.fetch_add(samples.size());
|
||||||
return sample_count;
|
return samples.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -26,18 +26,18 @@ namespace psemek::audio
|
||||||
return played_.load();
|
return played_.load();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t read(float * data, std::size_t sample_count) override
|
std::size_t read(util::span<float> samples) override
|
||||||
{
|
{
|
||||||
auto buffer = recorder_->buffer();
|
auto buffer = recorder_->buffer();
|
||||||
auto played = played_.load();
|
auto played = played_.load();
|
||||||
if (buffer.size() < played + sample_count)
|
if (buffer.size() < played + samples.size())
|
||||||
{
|
{
|
||||||
recorder_->request(sample_count);
|
recorder_->request(samples.size());
|
||||||
buffer = recorder_->buffer();
|
buffer = recorder_->buffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto count = std::min<std::size_t>(sample_count, buffer.size() - played);
|
auto count = std::min<std::size_t>(samples.size(), buffer.size() - played);
|
||||||
std::copy(buffer.data() + played, buffer.data() + played + count, data);
|
std::copy(buffer.data() + played, buffer.data() + played + count, samples.begin());
|
||||||
played_.fetch_add(count);
|
played_.fetch_add(count);
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,13 +27,13 @@ namespace psemek::audio
|
||||||
return stream_->length();
|
return stream_->length();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t read(float * data, std::size_t sample_count) override
|
std::size_t read(util::span<float> samples) override
|
||||||
{
|
{
|
||||||
auto result = stream_->read(data, sample_count);
|
auto count = stream_->read(samples);
|
||||||
|
|
||||||
for (std::size_t i = 0; i < result; i += 2)
|
for (std::size_t i = 0; i < count; i += 2)
|
||||||
{
|
{
|
||||||
float v = std::max(std::abs(data[i]), std::abs(data[i + 1]));
|
float v = std::max(std::abs(samples[i]), std::abs(samples[i + 1]));
|
||||||
|
|
||||||
float multiplier = (v > envelope_) ? envelope_attack_multiplier_ : envelope_release_multiplier_;
|
float multiplier = (v > envelope_) ? envelope_attack_multiplier_ : envelope_release_multiplier_;
|
||||||
|
|
||||||
|
|
@ -50,11 +50,11 @@ namespace psemek::audio
|
||||||
|
|
||||||
float gain = std::exp(log_gain);
|
float gain = std::exp(log_gain);
|
||||||
|
|
||||||
data[i + 0] *= gain;
|
samples[i + 0] *= gain;
|
||||||
data[i + 1] *= gain;
|
samples[i + 1] *= gain;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t played() const override
|
std::size_t played() const override
|
||||||
|
|
|
||||||
|
|
@ -32,14 +32,15 @@ namespace psemek::audio
|
||||||
return length_;
|
return length_;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t read(float * data, std::size_t sample_count) override
|
std::size_t read(util::span<float> samples) override
|
||||||
{
|
{
|
||||||
std::size_t count = 0;
|
std::size_t count = 0;
|
||||||
|
|
||||||
for (; index_ != streams_.size(); ++index_)
|
for (; index_ != streams_.size(); ++index_)
|
||||||
{
|
{
|
||||||
count += streams_[index_]->read(data + count, sample_count - count);
|
count += streams_[index_]->read(samples);
|
||||||
if (count == sample_count)
|
samples.consume(count);
|
||||||
|
if (samples.empty())
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,17 +32,17 @@ namespace psemek::audio
|
||||||
return stream_->length();
|
return stream_->length();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t read(float * data, std::size_t sample_count) override
|
std::size_t read(util::span<float> samples) override
|
||||||
{
|
{
|
||||||
auto result = stream_->read(data, sample_count);
|
auto count = stream_->read(samples);
|
||||||
float strength = strength_.load();
|
float strength = strength_.load();
|
||||||
|
|
||||||
for (std::size_t i = 0; i < result; ++i)
|
for (std::size_t i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
data[i] = std::tanh(strength * data[i]);
|
samples[i] = std::tanh(strength * samples[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t played() const override
|
std::size_t played() const override
|
||||||
|
|
|
||||||
|
|
@ -28,30 +28,30 @@ namespace psemek::audio
|
||||||
return stream_->played();
|
return stream_->played();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t read(float * data, std::size_t sample_count) override
|
std::size_t read(util::span<float> samples) override
|
||||||
{
|
{
|
||||||
auto const result = stream_->read(data, sample_count);
|
auto const count = stream_->read(samples);
|
||||||
std::fill(data, data + std::min<std::size_t>(result, start_.samples()), 0.f);
|
std::fill(samples.begin(), samples.begin() + std::min<std::size_t>(count, start_.samples()), 0.f);
|
||||||
|
|
||||||
if (result <= start_.samples())
|
if (count <= start_.samples())
|
||||||
{
|
{
|
||||||
start_ -= result;
|
start_ -= count;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (std::size_t i = start_.samples(); i < result; i += 2)
|
for (std::size_t i = start_.samples(); i < count; i += 2)
|
||||||
{
|
{
|
||||||
float m = static_cast<float>(std::min<std::size_t>(current_, length_.samples())) / length_.samples();
|
float m = static_cast<float>(std::min<std::size_t>(current_, length_.samples())) / length_.samples();
|
||||||
|
|
||||||
data[i + 0] *= m;
|
samples[i + 0] *= m;
|
||||||
data[i + 1] *= m;
|
samples[i + 1] *= m;
|
||||||
|
|
||||||
current_ += 2;
|
current_ += 2;
|
||||||
}
|
}
|
||||||
start_ = duration{};
|
start_ = duration{};
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -29,12 +29,12 @@ namespace psemek::audio
|
||||||
return stream_->played();
|
return stream_->played();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t read(float * data, std::size_t sample_count) override
|
std::size_t read(util::span<float> samples) override
|
||||||
{
|
{
|
||||||
if (current_ >= length_.samples())
|
if (current_ >= length_.samples())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
auto result = stream_->read(data, sample_count);
|
auto result = stream_->read(samples);
|
||||||
|
|
||||||
if (result <= start_.samples())
|
if (result <= start_.samples())
|
||||||
{
|
{
|
||||||
|
|
@ -46,8 +46,8 @@ namespace psemek::audio
|
||||||
{
|
{
|
||||||
float m = static_cast<float>(length_.samples() - std::min<std::size_t>(current_, length_.samples())) / length_.samples();
|
float m = static_cast<float>(length_.samples() - std::min<std::size_t>(current_, length_.samples())) / length_.samples();
|
||||||
|
|
||||||
data[i + 0] *= m;
|
samples[i + 0] *= m;
|
||||||
data[i + 1] *= m;
|
samples[i + 1] *= m;
|
||||||
|
|
||||||
current_ += 2;
|
current_ += 2;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,17 +20,17 @@ namespace psemek::audio
|
||||||
return stream_->length();
|
return stream_->length();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t read(float * data, std::size_t sample_count) override
|
std::size_t read(util::span<float> samples) override
|
||||||
{
|
{
|
||||||
std::size_t count = stream_->read(data, sample_count);
|
std::size_t count = stream_->read(samples);
|
||||||
|
|
||||||
for (std::size_t i = 0; i < count; i += 2)
|
for (std::size_t i = 0; i < count; i += 2)
|
||||||
{
|
{
|
||||||
std::swap(prev_[0], data[i + 0]);
|
std::swap(prev_[0], samples[i + 0]);
|
||||||
std::swap(prev_[1], data[i + 1]);
|
std::swap(prev_[1], samples[i + 1]);
|
||||||
|
|
||||||
data[i + 0] = prev_[0] * a0_ + data[i + 0] * a1_;
|
samples[i + 0] = prev_[0] * a0_ + samples[i + 0] * a1_;
|
||||||
data[i + 1] = prev_[1] * a0_ + data[i + 1] * a1_;
|
samples[i + 1] = prev_[1] * a0_ + samples[i + 1] * a1_;
|
||||||
}
|
}
|
||||||
|
|
||||||
return count;
|
return count;
|
||||||
|
|
|
||||||
|
|
@ -23,21 +23,21 @@ namespace psemek::audio
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t read(float * data, std::size_t sample_count) override
|
std::size_t read(util::span<float> samples) override
|
||||||
{
|
{
|
||||||
std::size_t result = 0;
|
std::size_t count = 0;
|
||||||
while (result < sample_count && (!count_ || repeated_ < *count_))
|
while (count < samples.size() && (!count_ || repeated_ < *count_))
|
||||||
{
|
{
|
||||||
auto need = sample_count - result;
|
auto need = samples.size() - count;
|
||||||
auto count = stream_->read(data + result, need);
|
auto scount = stream_->read({samples.begin() + count, need});
|
||||||
result += count;
|
count += scount;
|
||||||
if (count < need)
|
if (scount < need)
|
||||||
{
|
{
|
||||||
++repeated_;
|
++repeated_;
|
||||||
stream_ = dup_->stream();
|
stream_ = dup_->stream();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t played() const override
|
std::size_t played() const override
|
||||||
|
|
|
||||||
|
|
@ -34,42 +34,42 @@ namespace psemek::audio
|
||||||
return stream_->length();
|
return stream_->length();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t read(float * data, std::size_t sample_count) override
|
std::size_t read(util::span<float> samples) override
|
||||||
{
|
{
|
||||||
bool const paused = paused_.load();
|
bool const paused = paused_.load();
|
||||||
|
|
||||||
if (paused)
|
if (paused)
|
||||||
{
|
{
|
||||||
auto result = stream_->read(data, std::min(sample_count, level_));
|
auto count = stream_->read(samples.prefix(std::min(samples.size(), level_)));
|
||||||
|
|
||||||
for (std::size_t i = 0; i < result; i += 2)
|
for (std::size_t i = 0; i < count; i += 2)
|
||||||
{
|
{
|
||||||
float gain = static_cast<float>(level_) / length_.samples();
|
float gain = static_cast<float>(level_) / length_.samples();
|
||||||
data[i + 0] *= gain;
|
samples[i + 0] *= gain;
|
||||||
data[i + 1] *= gain;
|
samples[i + 1] *= gain;
|
||||||
level_ -= 2;
|
level_ -= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::fill(data + result, data + sample_count, 0.f);
|
std::fill(samples.begin() + count, samples.end(), 0.f);
|
||||||
return sample_count;
|
return samples.size();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto result = stream_->read(data, sample_count);
|
auto count = stream_->read(samples);
|
||||||
|
|
||||||
auto const max_level = static_cast<std::size_t>(length_.samples());
|
auto const max_level = static_cast<std::size_t>(length_.samples());
|
||||||
|
|
||||||
for (std::size_t i = 0; i < result; i += 2)
|
for (std::size_t i = 0; i < count; i += 2)
|
||||||
{
|
{
|
||||||
float gain = static_cast<float>(level_) / max_level;
|
float gain = static_cast<float>(level_) / max_level;
|
||||||
data[i + 0] *= gain;
|
samples[i + 0] *= gain;
|
||||||
data[i + 1] *= gain;
|
samples[i + 1] *= gain;
|
||||||
|
|
||||||
if (level_ < max_level)
|
if (level_ < max_level)
|
||||||
level_ += 2;
|
level_ += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,17 +46,17 @@ namespace psemek::audio
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t read(float * data, std::size_t sample_count) override
|
std::size_t read(util::span<float> samples) override
|
||||||
{
|
{
|
||||||
std::size_t result = 0;
|
std::size_t count = 0;
|
||||||
|
|
||||||
while (result < sample_count)
|
while (count < samples.size())
|
||||||
{
|
{
|
||||||
if (resampler_pos_ < resampler_.result().size())
|
if (resampler_pos_ < resampler_.result().size())
|
||||||
{
|
{
|
||||||
std::size_t size = std::min(sample_count - result, resampler_.result().size() - resampler_pos_);
|
std::size_t size = std::min(samples.size() - count, resampler_.result().size() - resampler_pos_);
|
||||||
std::copy(resampler_.result().data() + resampler_pos_, resampler_.result().data() + resampler_pos_ + size, data + result);
|
std::copy(resampler_.result().data() + resampler_pos_, resampler_.result().data() + resampler_pos_ + size, samples.begin() + count);
|
||||||
result += size;
|
count += size;
|
||||||
resampler_pos_ += size;
|
resampler_pos_ += size;
|
||||||
played_ += size;
|
played_ += size;
|
||||||
}
|
}
|
||||||
|
|
@ -64,18 +64,18 @@ namespace psemek::audio
|
||||||
{
|
{
|
||||||
resampler_pos_ = 0;
|
resampler_pos_ = 0;
|
||||||
|
|
||||||
std::size_t request_size = std::max<std::size_t>(sample_count, std::ceil(resampler_.ratio() * sample_count / 2.f) * 2);
|
std::size_t request_size = std::max<std::size_t>(samples.size(), std::ceil(resampler_.ratio() * samples.size() / 2.f) * 2);
|
||||||
source_buffer_.resize(request_size);
|
source_buffer_.resize(request_size);
|
||||||
auto count = stream_->read(source_buffer_.data(), request_size);
|
auto source_count = stream_->read({source_buffer_.data(), request_size});
|
||||||
|
|
||||||
if (count == 0)
|
if (source_count == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
resampler_.feed({source_buffer_.data(), source_buffer_.data() + count});
|
resampler_.feed({source_buffer_.data(), source_buffer_.data() + source_count});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t played() const override
|
std::size_t played() const override
|
||||||
|
|
|
||||||
|
|
@ -19,12 +19,11 @@ namespace psemek::audio
|
||||||
return length_.samples();
|
return length_.samples();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t read(float * data, std::size_t sample_count) override
|
std::size_t read(util::span<float> samples) override
|
||||||
{
|
{
|
||||||
auto played = stream_->played();
|
auto played = stream_->played();
|
||||||
auto result = std::min<std::size_t>(length_.samples() - played, sample_count);
|
auto max_count = std::min<std::size_t>(length_.samples() - played, samples.size());
|
||||||
result = stream_->read(data, result);
|
return stream_->read(samples.prefix(max_count));
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t played() const override
|
std::size_t played() const override
|
||||||
|
|
|
||||||
|
|
@ -31,11 +31,11 @@ namespace psemek::audio
|
||||||
return stream_->played();
|
return stream_->played();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t read(float * data, std::size_t sample_count) override
|
std::size_t read(util::span<float> samples) override
|
||||||
{
|
{
|
||||||
auto result = stream_->read(data, sample_count);
|
auto count = stream_->read(samples);
|
||||||
base_.apply(data, result);
|
base_.apply(samples.prefix(count));
|
||||||
return result;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -69,11 +69,11 @@ namespace psemek::audio
|
||||||
return stream_->played();
|
return stream_->played();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t read(float * data, std::size_t sample_count) override
|
std::size_t read(util::span<float> samples) override
|
||||||
{
|
{
|
||||||
auto result = stream_->read(data, sample_count);
|
auto count = stream_->read(samples);
|
||||||
base_.apply(data, result);
|
base_.apply(samples.prefix(count));
|
||||||
return result;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -26,13 +26,12 @@ namespace psemek::audio
|
||||||
return multiplier_to_smoothness(old);
|
return multiplier_to_smoothness(old);
|
||||||
}
|
}
|
||||||
|
|
||||||
void volume_base::apply(float * data, std::size_t sample_count)
|
void volume_base::apply(util::span<float> samples)
|
||||||
{
|
{
|
||||||
float gain[2] = {gain_[0].load(), gain_[1].load()};
|
float gain[2] = {gain_[0].load(), gain_[1].load()};
|
||||||
float smoothness_multiplier = smoothness_multiplier_.load();
|
float smoothness_multiplier = smoothness_multiplier_.load();
|
||||||
|
|
||||||
auto end = data + sample_count;
|
for (auto p = samples.begin(); p < samples.end();)
|
||||||
for (auto p = data; p < end;)
|
|
||||||
{
|
{
|
||||||
*p++ *= real_gain_[0];
|
*p++ *= real_gain_[0];
|
||||||
*p++ *= real_gain_[1];
|
*p++ *= real_gain_[1];
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ namespace psemek::audio
|
||||||
std::size_t const size = len / 2;
|
std::size_t const size = len / 2;
|
||||||
std::size_t read = 0;
|
std::size_t read = 0;
|
||||||
if (output)
|
if (output)
|
||||||
read = output->read(self->buffer.data(), size);
|
read = output->read({self->buffer.data(), size});
|
||||||
std::fill(self->buffer.data() + read, self->buffer.data() + size, 0.f);
|
std::fill(self->buffer.data() + read, self->buffer.data() + size, 0.f);
|
||||||
|
|
||||||
for (auto s : self->buffer)
|
for (auto s : self->buffer)
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ namespace psemek::audio
|
||||||
{
|
{
|
||||||
channel_ptr add(stream_ptr stream) override;
|
channel_ptr add(stream_ptr stream) override;
|
||||||
|
|
||||||
std::size_t read(float * data, std::size_t sample_count) override;
|
std::size_t read(util::span<float> samples) override;
|
||||||
|
|
||||||
std::optional<std::size_t> length() const override
|
std::optional<std::size_t> length() const override
|
||||||
{
|
{
|
||||||
|
|
@ -53,7 +53,7 @@ namespace psemek::audio
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t mixer_impl::read(float * data, std::size_t sample_count)
|
std::size_t mixer_impl::read(util::span<float> samples)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
std::vector<channel_ptr> new_channels;
|
std::vector<channel_ptr> new_channels;
|
||||||
|
|
@ -65,9 +65,9 @@ namespace psemek::audio
|
||||||
channels_.push_back(std::move(ch));
|
channels_.push_back(std::move(ch));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::fill(data, data + sample_count, 0.f);
|
std::fill(samples.begin(), samples.end(), 0.f);
|
||||||
|
|
||||||
buffer_.resize(sample_count);
|
buffer_.resize(samples.size());
|
||||||
|
|
||||||
for (auto & ch : channels_)
|
for (auto & ch : channels_)
|
||||||
{
|
{
|
||||||
|
|
@ -75,17 +75,11 @@ namespace psemek::audio
|
||||||
if (!stream)
|
if (!stream)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto read = stream->read(buffer_.data(), sample_count);
|
auto read = stream->read(buffer_);
|
||||||
|
|
||||||
{
|
std::copy(buffer_.data(), buffer_.data() + read, samples.begin());
|
||||||
auto begin = buffer_.data();
|
|
||||||
auto end = begin + read;
|
|
||||||
auto dst = data;
|
|
||||||
for (; begin < end; )
|
|
||||||
*dst++ += *begin++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (read < sample_count)
|
if (read < buffer_.size())
|
||||||
{
|
{
|
||||||
ch->stop();
|
ch->stop();
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -97,9 +91,9 @@ namespace psemek::audio
|
||||||
std::swap(channels_, alive_channels_);
|
std::swap(channels_, alive_channels_);
|
||||||
alive_channels_.clear();
|
alive_channels_.clear();
|
||||||
|
|
||||||
played_.fetch_add(sample_count);
|
played_.fetch_add(samples.size());
|
||||||
|
|
||||||
return sample_count;
|
return samples.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,9 +40,9 @@ namespace psemek::audio
|
||||||
samples_ = {storage_.data(), storage_.data() + samples_.size()};
|
samples_ = {storage_.data(), storage_.data() + samples_.size()};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto result = stream_->read(storage_.data() + samples_.size(), samples);
|
auto count = stream_->read({storage_.data() + samples_.size(), samples});
|
||||||
samples_ = {storage_.data(), storage_.data() + samples_.size() + result};
|
samples_ = {storage_.data(), storage_.data() + samples_.size() + count};
|
||||||
return result;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
util::span<float const> buffer() const override
|
util::span<float const> buffer() const override
|
||||||
|
|
|
||||||
|
|
@ -34,20 +34,20 @@ namespace psemek::audio
|
||||||
return std::min(left_->played(), right_->played());
|
return std::min(left_->played(), right_->played());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t read(float * data, std::size_t sample_count) override
|
std::size_t read(util::span<float> samples) override
|
||||||
{
|
{
|
||||||
if (buffer_.size() < sample_count)
|
if (buffer_.size() < samples.size())
|
||||||
buffer_.resize(sample_count);
|
buffer_.resize(samples.size());
|
||||||
|
|
||||||
auto right_result = right_->read(data, sample_count);
|
auto right_result = right_->read(samples);
|
||||||
auto left_result = left_->read(buffer_.data(), sample_count);
|
auto left_result = left_->read({buffer_.data(), samples.size()});
|
||||||
|
|
||||||
auto result = std::min(right_result, left_result);
|
auto result = std::min(right_result, left_result);
|
||||||
|
|
||||||
{
|
{
|
||||||
auto begin = buffer_.data();
|
auto begin = buffer_.data();
|
||||||
auto end = buffer_.data() + result;
|
auto end = buffer_.data() + result;
|
||||||
auto dst = data;
|
auto dst = samples.data();
|
||||||
for (; begin < end; begin += 2, dst += 2)
|
for (; begin < end; begin += 2, dst += 2)
|
||||||
*dst = *begin;
|
*dst = *begin;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,19 +43,19 @@ namespace psemek::audio
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t read(float * data, std::size_t sample_count) override
|
std::size_t read(util::span<float> samples) override
|
||||||
{
|
{
|
||||||
auto input = reinterpret_cast<std::uint8_t const *>(data_->data.data());
|
auto input = reinterpret_cast<std::uint8_t const *>(data_->data.data());
|
||||||
|
|
||||||
std::size_t result = 0;
|
std::size_t count = 0;
|
||||||
while (result < sample_count)
|
while (count < samples.size())
|
||||||
{
|
{
|
||||||
if (resampler_pos_ < resampler_.result().size())
|
if (resampler_pos_ < resampler_.result().size())
|
||||||
{
|
{
|
||||||
std::size_t size = std::min(resampler_.result().size() - resampler_pos_, sample_count - result);
|
std::size_t size = std::min(resampler_.result().size() - resampler_pos_, samples.size() - count);
|
||||||
std::copy(resampler_.result().data() + resampler_pos_, resampler_.result().data() + resampler_pos_ + size, data + result);
|
std::copy(resampler_.result().data() + resampler_pos_, resampler_.result().data() + resampler_pos_ + size, samples.begin() + count);
|
||||||
resampler_pos_ += size;
|
resampler_pos_ += size;
|
||||||
result += size;
|
count += size;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -84,9 +84,9 @@ namespace psemek::audio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
played_.fetch_add(result);
|
played_.fetch_add(count);
|
||||||
|
|
||||||
return result;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t played() const override
|
std::size_t played() const override
|
||||||
|
|
|
||||||
|
|
@ -25,23 +25,23 @@ namespace psemek::audio
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t read(float * data, std::size_t sample_count) override
|
std::size_t read(util::span<float> samples) override
|
||||||
{
|
{
|
||||||
std::size_t const size = buffer_.size();
|
std::size_t const size = buffer_.size();
|
||||||
|
|
||||||
for (std::size_t i = 0; i < sample_count; i += 2)
|
for (std::size_t i = 0; i < samples.size(); i += 2)
|
||||||
{
|
{
|
||||||
buffer_[buffer_pos_ + 0] = (buffer_[buffer_pos_ + 0] + buffer_[(buffer_pos_ + 2) % size + 0]) / 2.f;
|
buffer_[buffer_pos_ + 0] = (buffer_[buffer_pos_ + 0] + buffer_[(buffer_pos_ + 2) % size + 0]) / 2.f;
|
||||||
buffer_[buffer_pos_ + 1] = (buffer_[buffer_pos_ + 1] + buffer_[(buffer_pos_ + 2) % size + 1]) / 2.f;
|
buffer_[buffer_pos_ + 1] = (buffer_[buffer_pos_ + 1] + buffer_[(buffer_pos_ + 2) % size + 1]) / 2.f;
|
||||||
|
|
||||||
data[i + 0] = buffer_[buffer_pos_ + 0];
|
samples[i + 0] = buffer_[buffer_pos_ + 0];
|
||||||
data[i + 1] = buffer_[buffer_pos_ + 1];
|
samples[i + 1] = buffer_[buffer_pos_ + 1];
|
||||||
|
|
||||||
buffer_pos_ += 2;
|
buffer_pos_ += 2;
|
||||||
buffer_pos_ %= size;
|
buffer_pos_ %= size;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sample_count;
|
return samples.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t played() const override
|
std::size_t played() const override
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue