TeaSpeak-Client/native/serverconnection/src/connection/audio/AudioSender.h

81 lines
2.5 KiB
C++

#pragma once
#include <mutex>
#include <memory>
#include <optional>
#include "VoiceClient.h"
namespace tc {
namespace audio {
namespace codec {
class Converter;
class AudioEncoder;
}
class AudioReframer;
class AudioResampler;
class AudioOutputSource;
}
namespace connection {
class VoiceConnection;
class VoiceSender : public event::EventEntry {
template<typename _Tp, typename _Up>
friend inline std::shared_ptr<_Tp> std::static_pointer_cast(const std::shared_ptr<_Up>& __r) noexcept;
friend class VoiceConnection;
public:
explicit VoiceSender(VoiceConnection*);
virtual ~VoiceSender();
void finalize();
codec::value get_codec() { return this->current_codec_.value_or(this->target_codec_); }
void set_codec(codec::value value);
void send_data(const float* /* buffer */, size_t /* samples */, size_t /* sample rate */, size_t /* channels */);
void send_stop();
void set_voice_send_enabled(bool /* flag */);
private:
struct AudioFrame {
AudioFrame* next{nullptr};
float* buffer{nullptr};
size_t sample_count{0};
size_t sample_rate{0};
size_t channels{0};
std::chrono::system_clock::time_point timestamp{};
~AudioFrame() = default;
AudioFrame() = default;
};
std::weak_ptr<VoiceSender> _ref;
VoiceConnection* handle;
std::mutex raw_audio_buffer_mutex{};
AudioFrame* raw_audio_buffers_head{nullptr};
AudioFrame** raw_audio_buffers_tail{&this->raw_audio_buffers_head};
bool voice_send_enabled{false};
/* Codec specific values */
codec::value target_codec_{codec::OPUS_VOICE};
std::optional<codec::value> current_codec_{};
std::unique_ptr<audio::codec::AudioEncoder> codec_encoder{};
std::unique_ptr<audio::AudioResampler> codec_resampler{};
std::unique_ptr<audio::AudioReframer> codec_reframer{};
size_t audio_sequence_no{0};
/* Call these methods only when the execute lock has been accquired */
void encode_raw_frame(const AudioFrame*);
void handle_network_frame(const float* /* buffer */, size_t /* sample count */, bool /* flush */);
void flush_current_codec();
void event_execute(const std::chrono::system_clock::time_point &point) override;
};
}
}