@@ -105,6 +105,10 @@ class AudioEngineDevice : public AudioDeviceModule, public AudioSessionObserver
105
105
public:
106
106
enum RenderMode { Device = 0 , Manual = 1 };
107
107
enum MuteMode { VoiceProcessing = 0 , RestartEngine = 1 };
108
+ enum SpeechActivityEvent {
109
+ kStarted = 0 ,
110
+ kEnded ,
111
+ };
108
112
109
113
// Represents the state of the audio engine, including input/output status,
110
114
// rendering mode, and various configuration flags.
@@ -189,6 +193,129 @@ class AudioEngineDevice : public AudioDeviceModule, public AudioSessionObserver
189
193
bool IsInputDefaultDevice () const { return input_device_id == 0 ; }
190
194
};
191
195
196
+ struct EngineStateTransition {
197
+ EngineState prev;
198
+ EngineState next;
199
+
200
+ bool HasNoChanges () const { return prev == next; }
201
+
202
+ bool DidEnableOutput () const { return !prev.IsOutputEnabled () && next.IsOutputEnabled (); }
203
+
204
+ bool DidEnableInput () const { return !prev.IsInputEnabled () && next.IsInputEnabled (); }
205
+
206
+ bool DidDisableOutput () const { return prev.IsOutputEnabled () && !next.IsOutputEnabled (); }
207
+
208
+ bool DidDisableInput () const { return prev.IsInputEnabled () && !next.IsInputEnabled (); }
209
+
210
+ bool DidAnyEnable () const { return DidEnableOutput () || DidEnableInput (); }
211
+
212
+ bool DidAnyDisable () const { return DidDisableOutput () || DidDisableInput (); }
213
+
214
+ bool DidBeginInterruption () const { return !prev.is_interrupted && next.is_interrupted ; }
215
+
216
+ bool DidEndInterruption () const { return prev.is_interrupted && !next.is_interrupted ; }
217
+
218
+ bool DidUpdateAudioGraph () const {
219
+ return (prev.IsInputEnabled () != next.IsInputEnabled ()) ||
220
+ (prev.IsOutputEnabled () != next.IsOutputEnabled ());
221
+ }
222
+
223
+ bool DidUpdateVoiceProcessingEnabled () const {
224
+ return prev.voice_processing_enabled != next.voice_processing_enabled ;
225
+ }
226
+
227
+ bool DidUpdateOutputDevice () const { return prev.output_device_id != next.output_device_id ; }
228
+
229
+ bool DidUpdateInputDevice () const { return prev.input_device_id != next.input_device_id ; }
230
+
231
+ bool DidUpdateDefaultOutputDevice () const {
232
+ return prev.default_output_device_id != next.default_output_device_id ;
233
+ }
234
+
235
+ bool DidUpdateDefaultInputDevice () const {
236
+ return prev.default_input_device_id != next.default_input_device_id ;
237
+ }
238
+
239
+ bool DidUpdateMuteMode () const { return prev.mute_mode != next.mute_mode ; }
240
+
241
+ bool IsEngineRestartRequired () const {
242
+ return DidUpdateAudioGraph () || DidUpdateOutputDevice () || DidUpdateInputDevice () ||
243
+ // Voice processing enable state updates
244
+ DidUpdateVoiceProcessingEnabled () ||
245
+ // Handle default device updates
246
+ (DidUpdateDefaultOutputDevice () && next.IsOutputDefaultDevice ()) ||
247
+ (DidUpdateDefaultInputDevice () && next.IsInputDefaultDevice ());
248
+ }
249
+
250
+ // Special case to re-create engine when switching from Speaker & Mic ->
251
+ // Speaker only.
252
+ bool IsEngineRecreateRequired () const {
253
+ return (prev.IsOutputEnabled () && next.IsOutputEnabled ()) &&
254
+ (prev.IsInputEnabled () && !next.IsInputEnabled ());
255
+ }
256
+
257
+ bool DidEnableManualRenderingMode () const {
258
+ return prev.render_mode != RenderMode::Manual && next.render_mode == RenderMode::Manual;
259
+ }
260
+
261
+ bool DidEnableDeviceRenderingMode () const {
262
+ return prev.render_mode != RenderMode::Device && next.render_mode == RenderMode::Device;
263
+ }
264
+ };
265
+
266
+ class EngineObserver {
267
+ public:
268
+ virtual ~EngineObserver () = default ;
269
+
270
+ virtual void OnEngineDidReceiveMutedSpeechActivityEvent (SpeechActivityEvent event) {}
271
+
272
+ // AVAudioEngine lifecycle
273
+ virtual int32_t OnEngineDidCreate (AVAudioEngine* engine,
274
+ EngineStateTransition state_transition) {
275
+ return 0 ;
276
+ }
277
+
278
+ virtual int32_t OnEngineWillEnable (AVAudioEngine* engine,
279
+ EngineStateTransition state_transition) {
280
+ return 0 ;
281
+ }
282
+
283
+ virtual int32_t OnEngineWillStart (AVAudioEngine* engine,
284
+ EngineStateTransition state_transition) {
285
+ return 0 ;
286
+ }
287
+
288
+ virtual int32_t OnEngineDidStop (AVAudioEngine* engine, EngineStateTransition state_transition) {
289
+ return 0 ;
290
+ }
291
+
292
+ virtual int32_t OnEngineDidDisable (AVAudioEngine* engine,
293
+ EngineStateTransition state_transition) {
294
+ return 0 ;
295
+ }
296
+
297
+ virtual int32_t OnEngineWillRelease (AVAudioEngine* engine,
298
+ EngineStateTransition state_transition) {
299
+ return 0 ;
300
+ }
301
+
302
+ // Override the input node configuration with a custom implementation.
303
+ virtual int32_t OnEngineWillConnectInput (AVAudioEngine* engine, AVAudioNode* src,
304
+ AVAudioNode* dst, AVAudioFormat* format,
305
+ EngineStateTransition state_transition,
306
+ NSDictionary * context) {
307
+ return 0 ;
308
+ }
309
+
310
+ // Override the input node configuration with a custom implementation.
311
+ virtual int32_t OnEngineWillConnectOutput (AVAudioEngine* engine, AVAudioNode* src,
312
+ AVAudioNode* dst, AVAudioFormat* format,
313
+ EngineStateTransition state_transition,
314
+ NSDictionary * context) {
315
+ return 0 ;
316
+ }
317
+ };
318
+
192
319
explicit AudioEngineDevice (bool voice_processing_bypassed);
193
320
~AudioEngineDevice () override;
194
321
@@ -281,11 +408,13 @@ class AudioEngineDevice : public AudioDeviceModule, public AudioSessionObserver
281
408
282
409
bool IsEngineRunning ();
283
410
284
- int32_t SetEngineState (EngineState enable );
285
- int32_t GetEngineState (EngineState* enabled );
411
+ int32_t SetEngineState (EngineState new_state );
412
+ int32_t GetEngineState (EngineState* state );
286
413
287
414
int32_t SetObserver (AudioDeviceObserver* observer) override;
288
415
416
+ int32_t SetEngineObserver (EngineObserver* observer);
417
+
289
418
int32_t SetManualRenderingMode (bool enable);
290
419
int32_t ManualRenderingMode (bool * enabled);
291
420
@@ -313,85 +442,15 @@ class AudioEngineDevice : public AudioDeviceModule, public AudioSessionObserver
313
442
int32_t InitAndStartRecording ();
314
443
315
444
private:
316
- struct EngineStateUpdate {
317
- EngineState prev;
318
- EngineState next;
319
-
320
- bool HasNoChanges () const { return prev == next; }
321
-
322
- bool DidEnableOutput () const { return !prev.IsOutputEnabled () && next.IsOutputEnabled (); }
323
-
324
- bool DidEnableInput () const { return !prev.IsInputEnabled () && next.IsInputEnabled (); }
325
-
326
- bool DidDisableOutput () const { return prev.IsOutputEnabled () && !next.IsOutputEnabled (); }
327
-
328
- bool DidDisableInput () const { return prev.IsInputEnabled () && !next.IsInputEnabled (); }
329
-
330
- bool DidAnyEnable () const { return DidEnableOutput () || DidEnableInput (); }
331
-
332
- bool DidAnyDisable () const { return DidDisableOutput () || DidDisableInput (); }
333
-
334
- bool DidBeginInterruption () const { return !prev.is_interrupted && next.is_interrupted ; }
335
-
336
- bool DidEndInterruption () const { return prev.is_interrupted && !next.is_interrupted ; }
337
-
338
- bool DidUpdateAudioGraph () const {
339
- return (prev.IsInputEnabled () != next.IsInputEnabled ()) ||
340
- (prev.IsOutputEnabled () != next.IsOutputEnabled ());
341
- }
342
-
343
- bool DidUpdateVoiceProcessingEnabled () const {
344
- return prev.voice_processing_enabled != next.voice_processing_enabled ;
345
- }
346
-
347
- bool DidUpdateOutputDevice () const { return prev.output_device_id != next.output_device_id ; }
348
-
349
- bool DidUpdateInputDevice () const { return prev.input_device_id != next.input_device_id ; }
350
-
351
- bool DidUpdateDefaultOutputDevice () const {
352
- return prev.default_output_device_id != next.default_output_device_id ;
353
- }
354
-
355
- bool DidUpdateDefaultInputDevice () const {
356
- return prev.default_input_device_id != next.default_input_device_id ;
357
- }
358
-
359
- bool DidUpdateMuteMode () const { return prev.mute_mode != next.mute_mode ; }
360
-
361
- bool IsEngineRestartRequired () const {
362
- return DidUpdateAudioGraph () || DidUpdateOutputDevice () || DidUpdateInputDevice () ||
363
- // Voice processing enable state updates
364
- DidUpdateVoiceProcessingEnabled () ||
365
- // Handle default device updates
366
- (DidUpdateDefaultOutputDevice () && next.IsOutputDefaultDevice ()) ||
367
- (DidUpdateDefaultInputDevice () && next.IsInputDefaultDevice ());
368
- }
369
-
370
- // Special case to re-create engine when switching from Speaker & Mic ->
371
- // Speaker only.
372
- bool IsEngineRecreateRequired () const {
373
- return (prev.IsOutputEnabled () && next.IsOutputEnabled ()) &&
374
- (prev.IsInputEnabled () && !next.IsInputEnabled ());
375
- }
376
-
377
- bool DidEnableManualRenderingMode () const {
378
- return prev.render_mode != RenderMode::Manual && next.render_mode == RenderMode::Manual;
379
- }
380
-
381
- bool DidEnableDeviceRenderingMode () const {
382
- return prev.render_mode != RenderMode::Device && next.render_mode == RenderMode::Device;
383
- }
384
- };
385
-
386
445
EngineState engine_state_ RTC_GUARDED_BY (thread_);
387
446
388
447
AVAudioInputNode* InputNode ();
389
448
AVAudioOutputNode* OutputNode ();
390
449
391
450
bool IsMicrophonePermissionGranted ();
392
451
int32_t ModifyEngineState (std::function<EngineState (EngineState)> state_transform);
393
- int32_t ApplyDeviceEngineState (EngineStateUpdate state);
394
- int32_t ApplyManualEngineState (EngineStateUpdate state);
452
+ int32_t ApplyDeviceEngineState (EngineStateTransition state);
453
+ int32_t ApplyManualEngineState (EngineStateTransition state);
395
454
396
455
// AudioEngine observer methods. May be called from any thread.
397
456
void ReconfigureEngine (bool is_required);
@@ -430,6 +489,7 @@ class AudioEngineDevice : public AudioDeviceModule, public AudioSessionObserver
430
489
bool initialized_ RTC_GUARDED_BY (thread_);
431
490
432
491
AudioDeviceObserver* observer_ RTC_GUARDED_BY (thread_);
492
+ EngineObserver* engine_observer_ RTC_GUARDED_BY (thread_);
433
493
434
494
#if defined(WEBRTC_IOS)
435
495
// Audio interruption observer instance.
0 commit comments