#include #include #include #include #include #include #include namespace psemek::audio { namespace { struct white_noise_impl : stream { std::optional length() const override { return std::nullopt; } std::size_t read(util::span samples) override { for (std::size_t i = 0; i < samples.size(); i += 2) { float value = d_(rng_); samples[i + 0] = value; samples[i + 1] = value; } played_.fetch_add(samples.size()); return samples.size(); } std::size_t played() const override { return played_.load(); } private: random::generator rng_{0x4b0a763ef6573bf2ull, 0}; random::uniform_distribution d_{-1.f, 1.f}; std::atomic played_; }; struct fixed_white_noise_impl : stream { fixed_white_noise_impl(float frequency) : buffer_(detail::white_noise(std::round(audio::frequency / frequency))) {} std::optional length() const override { return std::nullopt; } std::size_t read(util::span samples) override { std::size_t const size = buffer_.size(); for (std::size_t i = 0; i < samples.size(); i += 2) { samples[i + 0] = buffer_[buffer_pos_]; samples[i + 1] = buffer_[buffer_pos_]; buffer_pos_ += 1; buffer_pos_ %= size; } played_.fetch_add(samples.size()); return samples.size(); } std::size_t played() const override { return played_.load(); } private: std::vector buffer_; std::size_t buffer_pos_{0}; std::atomic played_; }; } stream_ptr white_noise() { return std::make_shared(); } stream_ptr white_noise(float frequency) { return std::make_shared(frequency); } }