calculateMos static method

double calculateMos({
  1. required double rtt,
  2. required double jitter,
  3. double packetLoss = 0.0,
})

Calculates the Mean Opinion Score (MOS) based on network metrics.

This implementation uses the ITU-T G.107 E-Model to estimate MOS. The formula is simplified for WebRTC audio calls.

@param rtt Round-trip time in seconds @param jitter Jitter in seconds @param packetLoss Packet loss ratio (0.0-1.0) @return Estimated MOS value between 1.0 and 4.5

Implementation

static double calculateMos({
  required double rtt,
  required double jitter,
  double packetLoss = 0.0,
}) {
  // Convert to milliseconds for calculation
  final rttMs = rtt * 1000;
  final jitterMs = jitter * 1000;

  // Clamp values to reasonable ranges
  final effectiveRtt = _clamp(rttMs, 0, 500);
  final effectiveJitter = _clamp(jitterMs, 0, 100);
  final effectivePacketLoss =
      _clamp(packetLoss, 0.0, 1.0) * 100; // Convert to percentage

  // Calculate R-factor based on ITU-T G.107 E-Model (simplified)
  // R = 93.2 - Id - Ie
  // where:
  // - Id is the delay impairment factor
  // - Ie is the equipment impairment factor (affected by packet loss and codec)

  // Delay impairment (Id)
  final delayImpairment = 0.024 * effectiveRtt +
      0.11 * (effectiveRtt - 177.3) * (effectiveRtt > 177.3 ? 1 : 0);

  // Equipment impairment (Ie)
  // For G.711 codec: Ie = 0 + 30 * packetLoss / (packetLoss + 10)
  // We add jitter impact as well
  final jitterImpairment = effectiveJitter * 0.05;
  final packetLossImpairment =
      30 * effectivePacketLoss / (effectivePacketLoss + 10);
  final equipmentImpairment = jitterImpairment + packetLossImpairment;

  // Calculate R-factor
  final rFactor = 93.2 - delayImpairment - equipmentImpairment;
  final clampedRFactor = _clamp(rFactor, 0, 100);

  // Convert R-factor to MOS using the standard formula
  // For R < 0: MOS = 1
  // For 0 <= R <= 100: MOS = 1 + 0.035*R + R*(R-60)*(100-R)*7*10^-6
  // For R > 100: MOS = 4.5

  double mos;
  if (clampedRFactor < 0) {
    mos = 1.0;
  } else if (clampedRFactor > 100) {
    mos = 4.5;
  } else {
    mos = 1 +
        0.035 * clampedRFactor +
        clampedRFactor *
            (clampedRFactor - 60) *
            (100 - clampedRFactor) *
            7 *
            1e-6;
  }

  // Ensure MOS is between 1.0 and 4.5
  return _clamp(mos, 1.0, 4.5);
}