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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
|
#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>
#ifndef USE_PORTAUDIO
#include <miniaudio.h>
#else
#include <portaudio.h>
#endif
#include <opus.h>
#include <sigc++/sigc++.h>
#include <spdlog/spdlog.h>
#ifdef WITH_RNNOISE
#include <rnnoise.h>
#endif
#include "devices.hpp"
// clang-format on
class AudioManager {
public:
AudioManager(const Glib::ustring &backends_string);
~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(const std::string &method);
void SetVADMethod(VADMethod method);
VADMethod GetVADMethod() const;
#ifndef USE_PORTAUDIO
static std::vector<ma_backend> ParseBackendsList(const Glib::ustring &list);
#endif /* USE_PORTAUDIO */
#ifdef WITH_RNNOISE
float GetCurrentVADProbability() const;
double GetRNNProbThreshold() const;
void SetRNNProbThreshold(double value);
void SetSuppressNoise(bool value);
bool GetSuppressNoise() const;
#endif
void SetMixMono(bool value);
bool GetMixMono() const;
private:
#ifndef USE_PORTAUDIO
void OnCapturedPCM(const int16_t *pcm, ma_uint32 frames);
#else /* USE_PORTAUDIO */
void OnCapturedPCM(const int16_t *pcm, uint32_t frames);
#endif /* USE_PORTAUDIO */
void UpdateReceiveVolume(uint32_t ssrc, const int16_t *pcm, int frames);
#ifndef USE_PORTAUDIO
void UpdateCaptureVolume(const int16_t *pcm, ma_uint32 frames);
#else
void UpdateCaptureVolume(const int16_t *pcm, uint32_t frames);
#endif /* USE_PORTAUDIO */
std::atomic<int> m_capture_peak_meter = 0;
bool DecayVolumeMeters();
bool CheckVADVoiceGate();
#ifdef WITH_RNNOISE
bool CheckVADRNNoise(const int16_t *pcm, float *denoised_left, float *denoised_right);
void RNNoiseInitialize();
void RNNoiseUninitialize();
#endif
#ifndef USE_PORTAUDIO
friend void data_callback(ma_device *, void *, const void *, ma_uint32);
friend void capture_data_callback(ma_device *, void *, const void *, ma_uint32);
#else /* USE_PORTAUDIO */
friend int playCallback(const void *pInput, void *pOutput, unsigned long frameCount,
const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void *userData );
friend int recordCallback(const void *pInput, void *pOutput,
unsigned long frameCount,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags,
void *userData );
#endif /* USE_PORTAUDIO */
std::thread m_thread;
bool m_ok;
#ifndef USE_PORTAUDIO
// 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;
#else
// playback
PaStream* pa_playback_device;
PaStreamParameters m_playback_config;
// capture
PaStream* pa_capture_device;
PaStreamParameters m_capture_config;
#endif
mutable std::mutex m_mutex;
mutable std::mutex m_enc_mutex;
#ifdef WITH_RNNOISE
mutable std::mutex m_rnn_mutex;
#endif
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::atomic<float> m_vad_prob = 0.0;
std::atomic<bool> m_enable_noise_suppression = false;
std::atomic<bool> m_mix_mono = false;
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[2];
#endif
std::atomic<uint32_t> m_rtp_timestamp = 0;
#ifndef USE_PORTAUDIO
ma_log m_ma_log;
#endif
std::shared_ptr<spdlog::logger> m_log;
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
|