@@ -81,6 +81,11 @@ std::vector<std::string> AudioEngine::getInputDevices() {
8181 return devices;
8282}
8383
84+ void AudioEngine::setRxCallback (RxCallback callback) {
85+ std::lock_guard<AudioEngineMutex> lock (rx_callback_mutex_);
86+ rx_callback_ = std::move (callback);
87+ }
88+
8489bool AudioEngine::openOutput (const std::string& device) {
8590 if (!initialized_) {
8691 if (!initialize ()) return false ;
@@ -159,7 +164,7 @@ void AudioEngine::closeInput() {
159164}
160165
161166void AudioEngine::queueTxSamples (const std::vector<float >& samples) {
162- std::lock_guard<std::mutex > lock (tx_mutex_);
167+ std::lock_guard<AudioEngineMutex > lock (tx_mutex_);
163168 for (float s : samples) {
164169 tx_queue_.push (s);
165170 }
@@ -170,7 +175,7 @@ void AudioEngine::queueTxSamples(const std::vector<float>& samples) {
170175 std::vector<float > loopback_samples = samples;
171176 addChannelNoise (loopback_samples);
172177
173- std::lock_guard<std::mutex > rx_lock (rx_mutex_);
178+ std::lock_guard<AudioEngineMutex > rx_lock (rx_mutex_);
174179
175180 // Cap buffer size to prevent unbounded growth
176181 if (rx_buffer_.size () + loopback_samples.size () > MAX_RX_BUFFER_SAMPLES) {
@@ -191,23 +196,23 @@ void AudioEngine::queueTxSamples(const std::vector<float>& samples) {
191196}
192197
193198void AudioEngine::clearTxQueue () {
194- std::lock_guard<std::mutex > lock (tx_mutex_);
199+ std::lock_guard<AudioEngineMutex > lock (tx_mutex_);
195200 std::queue<float > empty;
196201 std::swap (tx_queue_, empty);
197202}
198203
199204bool AudioEngine::isTxQueueEmpty () const {
200- std::lock_guard<std::mutex > lock (tx_mutex_);
205+ std::lock_guard<AudioEngineMutex > lock (tx_mutex_);
201206 return tx_queue_.empty ();
202207}
203208
204209size_t AudioEngine::getTxQueueSize () const {
205- std::lock_guard<std::mutex > lock (tx_mutex_);
210+ std::lock_guard<AudioEngineMutex > lock (tx_mutex_);
206211 return tx_queue_.size ();
207212}
208213
209214std::vector<float > AudioEngine::getRxSamples (size_t max_samples) {
210- std::lock_guard<std::mutex > lock (rx_mutex_);
215+ std::lock_guard<AudioEngineMutex > lock (rx_mutex_);
211216
212217 size_t count = std::min (max_samples, rx_buffer_.size ());
213218 std::vector<float > samples (rx_buffer_.begin (), rx_buffer_.begin () + count);
@@ -217,7 +222,7 @@ std::vector<float> AudioEngine::getRxSamples(size_t max_samples) {
217222}
218223
219224size_t AudioEngine::getRxBufferSize () const {
220- std::lock_guard<std::mutex > lock (rx_mutex_);
225+ std::lock_guard<AudioEngineMutex > lock (rx_mutex_);
221226 return rx_buffer_.size ();
222227}
223228
@@ -250,7 +255,7 @@ void AudioEngine::stopCapture() {
250255}
251256
252257void AudioEngine::clearRxBuffer () {
253- std::lock_guard<std::mutex > lock (rx_mutex_);
258+ std::lock_guard<AudioEngineMutex > lock (rx_mutex_);
254259 rx_buffer_.clear ();
255260}
256261
@@ -267,7 +272,7 @@ void AudioEngine::outputCallback(void* userdata, Uint8* stream, int len) {
267272 float sum_sq = 0 .0f ;
268273 float gain = engine->output_gain_ .load ();
269274
270- std::lock_guard<std::mutex > lock (engine->tx_mutex_ );
275+ std::lock_guard<AudioEngineMutex > lock (engine->tx_mutex_ );
271276
272277 for (int i = 0 ; i < samples; ++i) {
273278 float out = 0 .0f ;
@@ -318,7 +323,7 @@ void AudioEngine::inputCallback(void* userdata, Uint8* stream, int len) {
318323 engine->input_level_ = rms;
319324
320325 {
321- std::lock_guard<std::mutex > lock (engine->rx_mutex_ );
326+ std::lock_guard<AudioEngineMutex > lock (engine->rx_mutex_ );
322327
323328 // Cap buffer size to prevent unbounded growth if main loop stalls
324329 if (engine->rx_buffer_ .size () + captured.size () > MAX_RX_BUFFER_SAMPLES) {
@@ -333,8 +338,13 @@ void AudioEngine::inputCallback(void* userdata, Uint8* stream, int len) {
333338 }
334339
335340 // Notify via callback (skip if muted during TX)
336- if (engine->rx_callback_ && !engine->rx_muted_ .load ()) {
337- engine->rx_callback_ (captured);
341+ AudioEngine::RxCallback rx_cb;
342+ {
343+ std::lock_guard<AudioEngineMutex> cb_lock (engine->rx_callback_mutex_ );
344+ rx_cb = engine->rx_callback_ ;
345+ }
346+ if (rx_cb && !engine->rx_muted_ .load ()) {
347+ rx_cb (captured);
338348 }
339349}
340350
0 commit comments