summaryrefslogtreecommitdiff
path: root/src/audio/manager.hpp
blob: ec62fed6e3cb9b4a11548f1b755521f09c6c38a3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#pragma once
#ifdef WITH_VOICE
// clang-format off

#include <array>
#include <atomic>
#include <deque>
#include <gtkmm/treemodel.h>
#include <mutex>
#include <thread>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <miniaudio.h>
#include <opus.h>
#include <sigc++/sigc++.h>

#ifdef WITH_RNNOISE
#include <rnnoise.h>
#endif

#include "devices.hpp"
// clang-format on

class AudioManager {
public:
    AudioManager();
    ~AudioManager();

    void AddSSRC(uint32_t ssrc);
    void RemoveSSRC(uint32_t ssrc);
    void RemoveAllSSRCs();

    void SetOpusBuffer(uint8_t *ptr);
    void FeedMeOpus(uint32_t ssrc, const std::vector<uint8_t> &data);

    void StartCaptureDevice();
    void StopCaptureDevice();

    void SetPlaybackDevice(const Gtk::TreeModel::iterator &iter);
    void SetCaptureDevice(const Gtk::TreeModel::iterator &iter);

    void SetCapture(bool capture);
    void SetPlayback(bool playback);

    void SetCaptureGate(double gate);
    void SetCaptureGain(double gain);
    double GetCaptureGate() const noexcept;
    double GetCaptureGain() const noexcept;

    void SetMuteSSRC(uint32_t ssrc, bool mute);
    void SetVolumeSSRC(uint32_t ssrc, double volume);
    double GetVolumeSSRC(uint32_t ssrc) const;

    void SetEncodingApplication(int application);
    int GetEncodingApplication();
    void SetSignalHint(int signal);
    int GetSignalHint();
    void SetBitrate(int bitrate);
    int GetBitrate();

    void Enumerate();

    bool OK() const;

    double GetCaptureVolumeLevel() const noexcept;
    double GetSSRCVolumeLevel(uint32_t ssrc) const noexcept;

    AudioDevices &GetDevices();

    uint32_t GetRTPTimestamp() const noexcept;

    enum class VADMethod {
        Gate,
        RNNoise,
    };

    void SetVADMethod(VADMethod method);

private:
    void OnCapturedPCM(const int16_t *pcm, ma_uint32 frames);

    void UpdateReceiveVolume(uint32_t ssrc, const int16_t *pcm, int frames);
    void UpdateCaptureVolume(const int16_t *pcm, ma_uint32 frames);
    std::atomic<int> m_capture_peak_meter = 0;

    bool DecayVolumeMeters();

    bool CheckVADVoiceGate();

#ifdef WITH_RNNOISE
    bool CheckVADRNNoise(const int16_t *pcm);

    void RNNoiseInitialize();
    void RNNoiseUninitialize();
#endif

    friend void data_callback(ma_device *, void *, const void *, ma_uint32);
    friend void capture_data_callback(ma_device *, void *, const void *, ma_uint32);

    std::thread m_thread;

    bool m_ok;

    // playback
    ma_device m_playback_device;
    ma_device_config m_playback_config;
    ma_device_id m_playback_id;
    // capture
    ma_device m_capture_device;
    ma_device_config m_capture_config;
    ma_device_id m_capture_id;

    ma_context m_context;

    mutable std::mutex m_mutex;
    mutable std::mutex m_enc_mutex;

    std::unordered_map<uint32_t, std::pair<std::deque<int16_t>, OpusDecoder *>> m_sources;

    OpusEncoder *m_encoder;

    uint8_t *m_opus_buffer = nullptr;

    std::atomic<bool> m_should_capture = true;
    std::atomic<bool> m_should_playback = true;

    std::atomic<double> m_capture_gate = 0.0;
    std::atomic<double> m_capture_gain = 1.0;
    std::atomic<double> m_prob_threshold = 0.5;

    std::unordered_set<uint32_t> m_muted_ssrcs;
    std::unordered_map<uint32_t, double> m_volume_ssrc;

    mutable std::mutex m_vol_mtx;
    std::unordered_map<uint32_t, double> m_volumes;

    AudioDevices m_devices;

    VADMethod m_vad_method;
#ifdef WITH_RNNOISE
    DenoiseState *m_rnnoise;
#endif
    std::atomic<uint32_t> m_rtp_timestamp = 0;

public:
    using type_signal_opus_packet = sigc::signal<void(int payload_size)>;
    type_signal_opus_packet signal_opus_packet();

private:
    type_signal_opus_packet m_signal_opus_packet;
};
#endif