43 lines
1.7 KiB
C++
43 lines
1.7 KiB
C++
#pragma once
|
|
|
|
#include "FluidSim/SimulationRingBuffer.hpp"
|
|
#include <SFML/Audio/SoundStream.hpp>
|
|
#include <array>
|
|
#include <atomic>
|
|
#include <cstdint>
|
|
|
|
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); }
|
|
void set_auto_gain(bool enabled) { auto_gain_enabled_.store(enabled, std::memory_order_relaxed); }
|
|
bool auto_gain() const { return auto_gain_enabled_.load(std::memory_order_relaxed); }
|
|
|
|
private:
|
|
static constexpr std::size_t block_size = 512;
|
|
SimulationRingBuffer& ring_;
|
|
std::array<float, block_size> temp_left_{}, temp_right_{};
|
|
std::array<std::int16_t, block_size * 2> output_{};
|
|
std::atomic<std::uint64_t> underrun_blocks_{};
|
|
std::atomic<double> speed_{1.0};
|
|
std::atomic<bool> auto_gain_enabled_{true};
|
|
float rms_power_{}, peak_envelope_{}, automatic_gain_{1.f};
|
|
float level_alpha_{}, peak_decay_{}, gain_rise_alpha_{}, gain_fall_alpha_{};
|
|
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
|