#pragma once #include "FluidSim/SimulationRingBuffer.hpp" #include #include #include #include namespace fluidsim::port { class AudioOutputStream final : public sf::SoundStream { public: explicit AudioOutputStream(SimulationRingBuffer& ring, unsigned int sample_rate = 44100); void set_speed(double speed) { speed_.store(speed, std::memory_order_relaxed); } std::uint64_t underrun_blocks() const { return underrun_blocks_.load(std::memory_order_relaxed); } double speed() const { return speed_.load(std::memory_order_relaxed); } private: static constexpr std::size_t block_size = 512; SimulationRingBuffer& ring_; std::array temp_left_{}, temp_right_{}; std::array output_{}; std::atomic underrun_blocks_{}; std::atomic speed_{1.0}; float previous_input_left_{}, previous_output_left_{}; float previous_input_right_{}, previous_output_right_{}; static constexpr std::size_t transition_samples = 64; std::size_t transition_remaining_{}; float last_left_{}, last_right_{}, transition_left_{}, transition_right_{}; bool starving_{true}; bool onGetData(Chunk& data) override; void onSeek(sf::Time time_offset) override; }; } // namespace fluidsim::port