#pragma once #include #include #include #include #include #include struct AudioDevice { int fd; uint32_t channels; uint32_t sample_rate; uint32_t total_pins; uint32_t current_pin; }; class AudioServer { BAN_NON_MOVABLE(AudioServer); BAN_NON_COPYABLE(AudioServer); public: AudioServer(BAN::Vector&& audio_devices); BAN::ErrorOr on_new_client(int fd); void on_client_disconnect(int fd); bool on_client_packet(int fd, LibAudio::Packet); uint64_t update(); private: AudioDevice& device() { return m_audio_devices[m_current_audio_device]; } private: struct ClientInfo { LibAudio::AudioBuffer* buffer; size_t queued_head { 0 }; size_t sample_frames_queued() const { return ((buffer->capacity + queued_head - buffer->tail) % buffer->capacity) / buffer->channels; } size_t sample_frames_available() const { return ((buffer->capacity + buffer->head - queued_head) % buffer->capacity) / buffer->channels; } }; using sample_t = LibAudio::AudioBuffer::sample_t; private: enum class AddOrRemove { Add, Remove }; void reset_kernel_buffer(); void send_samples(); private: BAN::Vector m_audio_devices; size_t m_current_audio_device { 0 }; size_t m_samples_sent { 0 }; BAN::Array m_send_buffer; BAN::CircularQueue m_samples; BAN::HashMap m_audio_buffers; };