applyVoiceProcessing method

Future<void> applyVoiceProcessing({
  1. bool? noiseSuppression,
  2. NoiseSuppressionLevel? noiseSuppressionLevel,
  3. bool? echoCancellation,
  4. bool? autoGainControl,
  5. bool? highPassFilter,
})

Applies the provided voice processing settings to the LocalMediaTracks.

Implementation

Future<void> applyVoiceProcessing({
  bool? noiseSuppression,
  NoiseSuppressionLevel? noiseSuppressionLevel,
  bool? echoCancellation,
  bool? autoGainControl,
  bool? highPassFilter,
}) async {
  Log.debug(
    'applyVoiceProcessing(noiseSuppression: $noiseSuppression, noiseSuppressionLevel: $noiseSuppressionLevel, echoCancellation: $echoCancellation, autoGainControl: $autoGainControl, highPassFilter: $highPassFilter)',
    '$runtimeType',
  );

  noiseSuppression ??= _noiseSuppression.value;
  noiseSuppressionLevel ??= _noiseSuppressionLevel.value;
  echoCancellation ??= _echoCancellation.value;
  autoGainControl ??= _autoGainControl.value;
  highPassFilter ??= _highPassFilter.value;

  if (noiseSuppression == _noiseSuppression.value &&
      noiseSuppressionLevel == _noiseSuppressionLevel.value &&
      echoCancellation == _echoCancellation.value &&
      autoGainControl == _autoGainControl.value &&
      highPassFilter == _highPassFilter.value) {
    // No-op, as these settings are already applied.
    return;
  }

  // TODO: Chromium agents don't support changing noise suppression settings
  //       on an active track, thus tracks should be recreated.
  if (WebUtils.isChrome) {
    _noiseSuppression.value = noiseSuppression ?? _noiseSuppression.value;
    _noiseSuppressionLevel.value =
        noiseSuppressionLevel ?? _noiseSuppressionLevel.value;
    _echoCancellation.value = echoCancellation ?? _echoCancellation.value;
    _autoGainControl.value = autoGainControl ?? _autoGainControl.value;
    _highPassFilter.value = highPassFilter ?? _highPassFilter.value;

    await _room?.disableAudio();

    members[_me]?.tracks.removeWhere((t) {
      if (t.kind == MediaKind.audio && t.source == MediaSourceKind.device) {
        t.stop();
        t.dispose();
        return true;
      }
      return false;
    });

    await _updateTracks(
      audio: audioState.value.isEnabled,
      video: videoState.value.isEnabled,
      screen: screenShareState.value.isEnabled,
    );

    await _room?.enableAudio();
    return;
  }

  for (var t in me.tracks.map((e) => e.track).whereType<LocalMediaTrack>()) {
    if (!t.isAudioProcessingAvailable()) {
      Log.debug(
        'applyVoiceProcessing() -> audio processing not available for track $t',
        '$runtimeType',
      );

      continue;
    }

    if (noiseSuppression != _noiseSuppression.value ||
        _noiseSuppressionLevel.value != noiseSuppressionLevel) {
      final bool? enabled = _noiseSuppression.value = noiseSuppression;
      final NoiseSuppressionLevel? level = _noiseSuppressionLevel.value =
          noiseSuppressionLevel;

      if (enabled != null) {
        try {
          await t.setNoiseSuppressionEnabled(enabled);

          if (enabled && level != null) {
            await t.setNoiseSuppressionLevel(level);
          }
        } catch (e, _) {
          Log.error(
            '💥 applyVoiceProcessing() -> Failed to invoke `setNoiseSuppressionEnabled($enabled)` for track $t due to: $e',
            '$runtimeType',
          );
        }
      }
    }

    if (echoCancellation != _echoCancellation.value) {
      final bool? enabled = _echoCancellation.value = echoCancellation;

      if (enabled != null) {
        try {
          await t.setEchoCancellationEnabled(enabled);
        } catch (e, _) {
          Log.error(
            '💥 applyVoiceProcessing() -> Failed to invoke `setEchoCancellationEnabled($enabled)` for track $t due to: $e',
            '$runtimeType',
          );
        }
      }
    }

    if (autoGainControl != _autoGainControl.value) {
      final bool? enabled = _autoGainControl.value = autoGainControl;

      if (enabled != null) {
        try {
          await t.setAutoGainControlEnabled(enabled);
        } catch (e, _) {
          Log.error(
            '💥 applyVoiceProcessing() -> Failed to invoke `setAutoGainControlEnabled($enabled)` for track $t due to: $e',
            '$runtimeType',
          );
        }
      }
    }

    if (highPassFilter != _highPassFilter.value) {
      final bool? enabled = _highPassFilter.value = highPassFilter;

      if (enabled != null) {
        try {
          await t.setHighPassFilterEnabled(enabled);
        } catch (e, _) {
          Log.error(
            '💥 applyVoiceProcessing() -> Failed to invoke `setHighPassFilterEnabled($enabled)` for track $t due to: $e',
            '$runtimeType',
          );
        }
      }
    }
  }
}