Change buffer level filter to store current level in number of samples.

The buffer level should not be converted back and forth between samples and packets in case of variable packet lengths.

Bug: webrtc:10736
Change-Id: Ia08dcfac3d8104dc79fbad0704a5f6f12a050a01
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/142178
Reviewed-by: Minyue Li <minyue@webrtc.org>
Commit-Queue: Jakob Ivarsson <jakobi@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28368}
diff --git a/modules/audio_coding/acm2/audio_coding_module_unittest.cc b/modules/audio_coding/acm2/audio_coding_module_unittest.cc
index c95091f..f9488a3 100644
--- a/modules/audio_coding/acm2/audio_coding_module_unittest.cc
+++ b/modules/audio_coding/acm2/audio_coding_module_unittest.cc
@@ -994,35 +994,35 @@
 #if (defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)) && \
     defined(WEBRTC_CODEC_ILBC)
 TEST_F(AcmReceiverBitExactnessOldApi, 8kHzOutput) {
-  Run(8000, PlatformChecksum("bcfbe2e89b4317b22e29557168edf187",
-                             "af15addb648cf7f032d6415672365fb3",
-                             "54a0008eb79537dee1d8fdaa5bc29f4b",
+  Run(8000, PlatformChecksum("bc5cc2391174c865f02d9b2ae568020a",
+                             "06621315b131e5ece54aff186ec7b9e4",
+                             "2d05bd35f4dd9798e4189d7da6e6ba10",
                              "4598140b5e4f7ee66c5adad609e65a3e",
-                             "3155d7f2593a3276986f36221a61783c"));
+                             "c0c14f9d8d4151510cafdaf78e2ebd20"));
 }
 
 TEST_F(AcmReceiverBitExactnessOldApi, 16kHzOutput) {
-  Run(16000, PlatformChecksum("1737deef193e6c90e139ce82b7361ae4",
-                              "9e2a9f7728c71d6559ce3a32d2b10a5d",
-                              "114958862099142ac78b12100c21cb8d",
+  Run(16000, PlatformChecksum("9e3893aeb5dda4f9cea6adec21d21ad8",
+                              "70d26c18385e05a35162460a2ef6a0e4",
+                              "b1ef73d7dde40033e30a76a1cc6a1ab6",
                               "f2aad418af974a3b1694d5ae5cc2c3c7",
-                              "af2889a5ca84fb40c9aa209b9318ee7a"));
+                              "25ae85ea1d2d629956cec7ea0b94f51c"));
 }
 
 TEST_F(AcmReceiverBitExactnessOldApi, 32kHzOutput) {
-  Run(32000, PlatformChecksum("1bf40ff024c6aa5b832d1d242c29cb3b",
-                              "3c9690cd136e9ecd1b26a22f70fe1d5c",
-                              "a1a3a01d8e25fcd11f1cedcd02e968b8",
+  Run(32000, PlatformChecksum("4be3e35ebfdce55157491945610ef663",
+                              "424fcd896d2050530648de083567aff7",
+                              "ab50b8546f56c359c8e4c7d74e49aae4",
                               "100869c8dcde51346c2073e52a272d98",
-                              "33695077e9ec6bca80819ce2ba263a78"));
+                              "87731746b160e4ae8313fa8af92bba12"));
 }
 
 TEST_F(AcmReceiverBitExactnessOldApi, 48kHzOutput) {
-  Run(48000, PlatformChecksum("bf92db1e502deff5adf6fd2e6ab9a2e5",
-                              "c37b110ab50d87620972daee5d1eaf31",
-                              "5d55b68be7bcf39b60fcc74519363fb4",
+  Run(48000, PlatformChecksum("1df82e2f5c1c96d94ad0edc55c723d01",
+                              "a623e44f7e41263245361e2b8c6cedd2",
+                              "22d0e9c2b62f367fb2d2052569c70e55",
                               "bd44bf97e7899186532f91235cef444d",
-                              "32eec738698ffe62b9777d6a349cd596"));
+                              "c3188d9fdaa8057a98815c9b7ecc48f1"));
 }
 
 TEST_F(AcmReceiverBitExactnessOldApi, 48kHzOutputExternalDecoder) {
@@ -1105,11 +1105,11 @@
   rtc::scoped_refptr<rtc::RefCountedObject<ADFactory>> factory(
       new rtc::RefCountedObject<ADFactory>);
   Run(48000,
-      PlatformChecksum("bf92db1e502deff5adf6fd2e6ab9a2e5",
-                       "c37b110ab50d87620972daee5d1eaf31",
-                       "5d55b68be7bcf39b60fcc74519363fb4",
+      PlatformChecksum("1df82e2f5c1c96d94ad0edc55c723d01",
+                       "a623e44f7e41263245361e2b8c6cedd2",
+                       "22d0e9c2b62f367fb2d2052569c70e55",
                        "bd44bf97e7899186532f91235cef444d",
-                       "32eec738698ffe62b9777d6a349cd596"),
+                       "c3188d9fdaa8057a98815c9b7ecc48f1"),
       factory, [](AudioCodingModule* acm) {
         acm->SetReceiveCodecs({{0, {"MockPCMu", 8000, 1}},
                                {103, {"ISAC", 16000, 1}},
@@ -1328,7 +1328,7 @@
   Run(AcmReceiverBitExactnessOldApi::PlatformChecksum(
           "2c9cb15d4ed55b5a0cadd04883bc73b0",
           "9336a9b993cbd8a751f0e8958e66c89c",
-          "bd4682225f7c4ad5f2049f6769713ac2",
+          "5c2eb46199994506236f68b2c8e51b0d",
           "343f1f42be0607c61e6516aece424609",
           "2c9cb15d4ed55b5a0cadd04883bc73b0"),
       AcmReceiverBitExactnessOldApi::PlatformChecksum(
@@ -1343,11 +1343,11 @@
 TEST_F(AcmSenderBitExactnessOldApi, IsacWb60ms) {
   ASSERT_NO_FATAL_FAILURE(SetUpTest("ISAC", 16000, 1, 103, 960, 960));
   Run(AcmReceiverBitExactnessOldApi::PlatformChecksum(
-          "1ad29139a04782a33daad8c2b9b35875",
-          "14d63c5f08127d280e722e3191b73bdd",
-          "edcf26694c289e3d9691faf79b74f09f",
+          "f59760fa000991ee5fa81f2e607db254",
+          "986aa16d7097a26e32e212e39ec58517",
+          "9a81e467eb1485f84aca796f8ea65011",
           "ef75e900e6f375e3061163c53fd09a63",
-          "1ad29139a04782a33daad8c2b9b35875"),
+          "f59760fa000991ee5fa81f2e607db254"),
       AcmReceiverBitExactnessOldApi::PlatformChecksum(
           "9e0a0ab743ad987b55b8e14802769c56",
           "ebe04a819d3a9d83a83a17f271e1139a",
diff --git a/modules/audio_coding/neteq/buffer_level_filter.cc b/modules/audio_coding/neteq/buffer_level_filter.cc
index 2f96618..675091d 100644
--- a/modules/audio_coding/neteq/buffer_level_filter.cc
+++ b/modules/audio_coding/neteq/buffer_level_filter.cc
@@ -22,52 +22,31 @@
 }
 
 void BufferLevelFilter::Reset() {
-  filtered_current_level_ = 0;
-  level_factor_ = 253;
+  filtered_current_level_ = 0.0;
+  level_factor_ = 0.988;
 }
 
-void BufferLevelFilter::Update(size_t buffer_size_packets,
-                               int time_stretched_samples,
-                               size_t packet_len_samples) {
-  // Filter:
-  // |filtered_current_level_| = |level_factor_| * |filtered_current_level_| +
-  //                            (1 - |level_factor_|) * |buffer_size_packets|
-  // |level_factor_| and |filtered_current_level_| are in Q8.
-  // |buffer_size_packets| is in Q0.
+void BufferLevelFilter::Update(size_t buffer_size_samples,
+                               int time_stretched_samples) {
+  filtered_current_level_ = level_factor_ * filtered_current_level_ +
+                            (1 - level_factor_) * buffer_size_samples;
+
+  // Account for time-scale operations (accelerate and pre-emptive expand) and
+  // make sure that the filtered value remains non-negative.
   filtered_current_level_ =
-      ((level_factor_ * filtered_current_level_) >> 8) +
-      ((256 - level_factor_) * rtc::dchecked_cast<int>(buffer_size_packets));
-
-  // Account for time-scale operations (accelerate and pre-emptive expand).
-  if (time_stretched_samples && packet_len_samples > 0) {
-    // Time-scaling has been performed since last filter update. Subtract the
-    // value of |time_stretched_samples| from |filtered_current_level_| after
-    // converting |time_stretched_samples| from samples to packets in Q8.
-    // Make sure that the filtered value remains non-negative.
-
-    int64_t time_stretched_packets =
-        (int64_t{time_stretched_samples} * (1 << 8)) /
-        rtc::dchecked_cast<int64_t>(packet_len_samples);
-
-    filtered_current_level_ = rtc::saturated_cast<int>(
-        std::max<int64_t>(0, filtered_current_level_ - time_stretched_packets));
-  }
+      std::max(0.0, filtered_current_level_ - time_stretched_samples);
 }
 
-void BufferLevelFilter::SetTargetBufferLevel(int target_buffer_level) {
-  if (target_buffer_level <= 1) {
-    level_factor_ = 251;
-  } else if (target_buffer_level <= 3) {
-    level_factor_ = 252;
-  } else if (target_buffer_level <= 7) {
-    level_factor_ = 253;
+void BufferLevelFilter::SetTargetBufferLevel(int target_buffer_level_packets) {
+  if (target_buffer_level_packets <= 1) {
+    level_factor_ = 0.980;
+  } else if (target_buffer_level_packets <= 3) {
+    level_factor_ = 0.984;
+  } else if (target_buffer_level_packets <= 7) {
+    level_factor_ = 0.988;
   } else {
-    level_factor_ = 254;
+    level_factor_ = 0.992;
   }
 }
 
-int BufferLevelFilter::filtered_current_level() const {
-  return filtered_current_level_;
-}
-
 }  // namespace webrtc
diff --git a/modules/audio_coding/neteq/buffer_level_filter.h b/modules/audio_coding/neteq/buffer_level_filter.h
index 83388fb..18b43a3 100644
--- a/modules/audio_coding/neteq/buffer_level_filter.h
+++ b/modules/audio_coding/neteq/buffer_level_filter.h
@@ -24,24 +24,24 @@
   virtual void Reset();
 
   // Updates the filter. Current buffer size is |buffer_size_packets| (Q0).
-  // If |time_stretched_samples| is non-zero, the value is converted to the
-  // corresponding number of packets, and is subtracted from the filtered
-  // value (thus bypassing the filter operation). |packet_len_samples| is the
-  // number of audio samples carried in each incoming packet.
-  virtual void Update(size_t buffer_size_packets,
-                      int time_stretched_samples,
-                      size_t packet_len_samples);
+  // |time_stretched_samples| is subtracted from the filtered value (thus
+  // bypassing the filter operation).
+  virtual void Update(size_t buffer_size_samples, int time_stretched_samples);
 
-  // Set the current target buffer level (obtained from
+  // Set the current target buffer level in number of packets (obtained from
   // DelayManager::base_target_level()). Used to select the appropriate
   // filter coefficient.
-  virtual void SetTargetBufferLevel(int target_buffer_level);
+  virtual void SetTargetBufferLevel(int target_buffer_level_packets);
 
-  virtual int filtered_current_level() const;
+  // Returns filtered current level in number of samples.
+  virtual int filtered_current_level() const {
+    // Round to nearest whole sample.
+    return static_cast<int>(filtered_current_level_ + 0.5);
+  }
 
  private:
-  int level_factor_;  // Filter factor for the buffer level filter in Q8.
-  int filtered_current_level_;  // Filtered current buffer level in Q8.
+  double level_factor_;  // Filter factor for the buffer level filter.
+  double filtered_current_level_;
 
   RTC_DISALLOW_COPY_AND_ASSIGN(BufferLevelFilter);
 };
diff --git a/modules/audio_coding/neteq/buffer_level_filter_unittest.cc b/modules/audio_coding/neteq/buffer_level_filter_unittest.cc
index 1f12e73..0d4a0f2 100644
--- a/modules/audio_coding/neteq/buffer_level_filter_unittest.cc
+++ b/modules/audio_coding/neteq/buffer_level_filter_unittest.cc
@@ -30,23 +30,22 @@
   for (int times = 10; times <= 50; times += 10) {
     for (int value = 100; value <= 200; value += 10) {
       filter.Reset();
-      filter.SetTargetBufferLevel(1);  // Makes filter coefficient 251/256.
+      filter.SetTargetBufferLevel(1);  // Makes filter coefficient 0.98.
       rtc::StringBuilder ss;
       ss << "times = " << times << ", value = " << value;
       SCOPED_TRACE(ss.str());  // Print out the parameter values on failure.
       for (int i = 0; i < times; ++i) {
-        filter.Update(value, 0 /* time_stretched_samples */,
-                      160 /* packet_len_samples */);
+        filter.Update(value, 0 /* time_stretched_samples */);
       }
       // Expect the filtered value to be (theoretically)
-      // (1 - (251/256) ^ |times|) * |value|.
-      double expected_value_double = (1 - pow(251.0 / 256.0, times)) * value;
+      // (1 - 0.980 ^ |times|) * |value|.
+      double expected_value_double = (1 - pow(0.98, times)) * value;
       int expected_value = static_cast<int>(expected_value_double);
       // filtered_current_level() returns the value in Q8.
       // The actual value may differ slightly from the expected value due to
       // intermediate-stage rounding errors in the filter implementation.
       // This is why we have to use EXPECT_NEAR with a tolerance of +/-1.
-      EXPECT_NEAR(expected_value, filter.filtered_current_level() >> 8, 1);
+      EXPECT_NEAR(expected_value, filter.filtered_current_level(), 1);
     }
   }
 }
@@ -58,104 +57,60 @@
   const int kTimes = 10;
   const int kValue = 100;
 
-  filter.SetTargetBufferLevel(3);  // Makes filter coefficient 252/256.
+  filter.SetTargetBufferLevel(3);  // Makes filter coefficient 0.984.
   for (int i = 0; i < kTimes; ++i) {
-    filter.Update(kValue, 0 /* time_stretched_samples */,
-                  160 /* packet_len_samples */);
+    filter.Update(kValue, 0 /* time_stretched_samples */);
   }
   // Expect the filtered value to be
-  // (1 - (252/256) ^ |kTimes|) * |kValue|.
-  int expected_value = 14;
-  // filtered_current_level() returns the value in Q8.
-  EXPECT_EQ(expected_value, filter.filtered_current_level() >> 8);
+  // (1 - 0.984 ^ |kTimes|) * |kValue|.
+  int expected_value = 15;
+  EXPECT_EQ(expected_value, filter.filtered_current_level());
 
   filter.Reset();
-  filter.SetTargetBufferLevel(7);  // Makes filter coefficient 253/256.
+  filter.SetTargetBufferLevel(7);  // Makes filter coefficient 0.988.
   for (int i = 0; i < kTimes; ++i) {
-    filter.Update(kValue, 0 /* time_stretched_samples */,
-                  160 /* packet_len_samples */);
+    filter.Update(kValue, 0 /* time_stretched_samples */);
   }
   // Expect the filtered value to be
-  // (1 - (253/256) ^ |kTimes|) * |kValue|.
+  // (1 - 0.988 ^ |kTimes|) * |kValue|.
   expected_value = 11;
-  // filtered_current_level() returns the value in Q8.
-  EXPECT_EQ(expected_value, filter.filtered_current_level() >> 8);
+  EXPECT_EQ(expected_value, filter.filtered_current_level());
 
   filter.Reset();
-  filter.SetTargetBufferLevel(8);  // Makes filter coefficient 254/256.
+  filter.SetTargetBufferLevel(8);  // Makes filter coefficient 0.992.
   for (int i = 0; i < kTimes; ++i) {
-    filter.Update(kValue, 0 /* time_stretched_samples */,
-                  160 /* packet_len_samples */);
+    filter.Update(kValue, 0 /* time_stretched_samples */);
   }
   // Expect the filtered value to be
-  // (1 - (254/256) ^ |kTimes|) * |kValue|.
-  expected_value = 7;
-  // filtered_current_level() returns the value in Q8.
-  EXPECT_EQ(expected_value, filter.filtered_current_level() >> 8);
+  // (1 - 0.992 ^ |kTimes|) * |kValue|.
+  expected_value = 8;
+  EXPECT_EQ(expected_value, filter.filtered_current_level());
 }
 
 TEST(BufferLevelFilter, TimeStretchedSamples) {
   BufferLevelFilter filter;
-  filter.SetTargetBufferLevel(1);  // Makes filter coefficient 251/256.
+  filter.SetTargetBufferLevel(1);  // Makes filter coefficient 0.98.
   // Update 10 times with value 100.
   const int kTimes = 10;
   const int kValue = 100;
-  const int kPacketSizeSamples = 160;
-  const int kNumPacketsStretched = 2;
-  const int kTimeStretchedSamples = kNumPacketsStretched * kPacketSizeSamples;
+  const int kTimeStretchedSamples = 3;
   for (int i = 0; i < kTimes; ++i) {
-    // Packet size set to 0. Do not expect the parameter
-    // |kTimeStretchedSamples| to have any effect.
-    filter.Update(kValue, kTimeStretchedSamples, 0 /* packet_len_samples */);
+    filter.Update(kValue, 0);
   }
   // Expect the filtered value to be
-  // (1 - (251/256) ^ |kTimes|) * |kValue|.
-  const int kExpectedValue = 17;
-  // filtered_current_level() returns the value in Q8.
-  EXPECT_EQ(kExpectedValue, filter.filtered_current_level() >> 8);
+  // (1 - 0.98 ^ |kTimes|) * |kValue|.
+  const int kExpectedValue = 18;
+  EXPECT_EQ(kExpectedValue, filter.filtered_current_level());
 
   // Update filter again, now with non-zero value for packet length.
   // Set the current filtered value to be the input, in order to isolate the
   // impact of |kTimeStretchedSamples|.
-  filter.Update(filter.filtered_current_level() >> 8, kTimeStretchedSamples,
-                kPacketSizeSamples);
-  EXPECT_EQ(kExpectedValue - kNumPacketsStretched,
-            filter.filtered_current_level() >> 8);
+  filter.Update(filter.filtered_current_level(), kTimeStretchedSamples);
+  EXPECT_EQ(kExpectedValue - kTimeStretchedSamples,
+            filter.filtered_current_level());
   // Try negative value and verify that we come back to the previous result.
-  filter.Update(filter.filtered_current_level() >> 8, -kTimeStretchedSamples,
-                kPacketSizeSamples);
-  EXPECT_EQ(kExpectedValue, filter.filtered_current_level() >> 8);
-}
-
-TEST(BufferLevelFilter, TimeStretchedSamplesNegativeUnevenFrames) {
-  BufferLevelFilter filter;
-  filter.SetTargetBufferLevel(1);  // Makes filter coefficient 251/256.
-  // Update 10 times with value 100.
-  const int kTimes = 10;
-  const int kValue = 100;
-  const int kPacketSizeSamples = 160;
-  const int kTimeStretchedSamples = -3.1415 * kPacketSizeSamples;
-  for (int i = 0; i < kTimes; ++i) {
-    // Packet size set to 0. Do not expect the parameter
-    // |kTimeStretchedSamples| to have any effect.
-    filter.Update(kValue, kTimeStretchedSamples, 0 /* packet_len_samples */);
-  }
-  // Expect the filtered value to be
-  // (1 - (251/256) ^ |kTimes|) * |kValue|.
-  const int kExpectedValue = 17;
-  // filtered_current_level() returns the value in Q8.
-  EXPECT_EQ(kExpectedValue, filter.filtered_current_level() >> 8);
-
-  // Update filter again, now with non-zero value for packet length.
-  // Set the current filtered value to be the input, in order to isolate the
-  // impact of |kTimeStretchedSamples|.
-  filter.Update(filter.filtered_current_level() >> 8, kTimeStretchedSamples,
-                kPacketSizeSamples);
-  EXPECT_EQ(21, filter.filtered_current_level() >> 8);
-  // Try negative value and verify that we come back to the previous result.
-  filter.Update(filter.filtered_current_level() >> 8, -kTimeStretchedSamples,
-                kPacketSizeSamples);
-  EXPECT_EQ(kExpectedValue, filter.filtered_current_level() >> 8);
+  filter.Update(filter.filtered_current_level(), -kTimeStretchedSamples);
+  EXPECT_EQ(kExpectedValue, filter.filtered_current_level());
 }
 
 }  // namespace webrtc
diff --git a/modules/audio_coding/neteq/decision_logic.cc b/modules/audio_coding/neteq/decision_logic.cc
index 40e421d..f9f420a 100644
--- a/modules/audio_coding/neteq/decision_logic.cc
+++ b/modules/audio_coding/neteq/decision_logic.cc
@@ -113,11 +113,9 @@
     cng_state_ = kCngInternalOn;
   }
 
-  const size_t samples_left =
-      sync_buffer.FutureLength() - expand.overlap_length();
   // TODO(jakobi): Use buffer span instead of num samples.
   const size_t cur_size_samples =
-      samples_left + packet_buffer_.NumSamplesInBuffer(decoder_frame_length);
+      packet_buffer_.NumSamplesInBuffer(decoder_frame_length);
 
   prev_time_scale_ =
       prev_time_scale_ && (prev_mode == kModeAccelerateSuccess ||
@@ -175,8 +173,7 @@
   // if the mute factor is low enough (otherwise the expansion was short enough
   // to not be noticable).
   // Note that the MuteFactor is in Q14, so a value of 16384 corresponds to 1.
-  size_t current_span =
-      samples_left + packet_buffer_.GetSpanSamples(decoder_frame_length);
+  size_t current_span = packet_buffer_.GetSpanSamples(decoder_frame_length);
   if ((prev_mode == kModeExpand || prev_mode == kModeCodecPlc) &&
       expand.MuteFactor(0) < 16384 / 2 &&
       current_span < static_cast<size_t>(delay_manager_->TargetLevel() *
@@ -193,9 +190,9 @@
     return ExpectedPacketAvailable(prev_mode, play_dtmf);
   } else if (!PacketBuffer::IsObsoleteTimestamp(
                  available_timestamp, target_timestamp, five_seconds_samples)) {
-    return FuturePacketAvailable(
-        sync_buffer, expand, decoder_frame_length, prev_mode, target_timestamp,
-        available_timestamp, play_dtmf, generated_noise_samples);
+    return FuturePacketAvailable(decoder_frame_length, prev_mode,
+                                 target_timestamp, available_timestamp,
+                                 play_dtmf, generated_noise_samples);
   } else {
     // This implies that available_timestamp < target_timestamp, which can
     // happen when a new stream or codec is received. Signal for a reset.
@@ -215,19 +212,13 @@
   buffer_level_filter_->SetTargetBufferLevel(
       delay_manager_->base_target_level());
 
-  size_t buffer_size_packets = 0;
-  if (packet_length_samples_ > 0) {
-    // Calculate size in packets.
-    buffer_size_packets = buffer_size_samples / packet_length_samples_;
-  }
   int sample_memory_local = 0;
   if (prev_time_scale_) {
     sample_memory_local = sample_memory_;
     timescale_countdown_ = tick_timer_->GetNewCountdown(kMinTimescaleInterval);
   }
 
-  buffer_level_filter_->Update(buffer_size_packets, sample_memory_local,
-                               packet_length_samples_);
+  buffer_level_filter_->Update(buffer_size_samples, sample_memory_local);
   prev_time_scale_ = false;
 }
 
@@ -283,15 +274,22 @@
 Operations DecisionLogic::ExpectedPacketAvailable(Modes prev_mode,
                                                   bool play_dtmf) {
   if (!disallow_time_stretching_ && prev_mode != kModeExpand && !play_dtmf) {
-    // Check criterion for time-stretching.
+    // Check criterion for time-stretching. The values are in number of packets
+    // in Q8.
     int low_limit, high_limit;
     delay_manager_->BufferLimits(&low_limit, &high_limit);
-    if (buffer_level_filter_->filtered_current_level() >= high_limit << 2)
+    int buffer_level_packets = 0;
+    if (packet_length_samples_ > 0) {
+      buffer_level_packets =
+          ((1 << 8) * buffer_level_filter_->filtered_current_level()) /
+          packet_length_samples_;
+    }
+    if (buffer_level_packets >= high_limit << 2)
       return kFastAccelerate;
     if (TimescaleAllowed()) {
-      if (buffer_level_filter_->filtered_current_level() >= high_limit)
+      if (buffer_level_packets >= high_limit)
         return kAccelerate;
-      if (buffer_level_filter_->filtered_current_level() < low_limit)
+      if (buffer_level_packets < low_limit)
         return kPreemptiveExpand;
     }
   }
@@ -299,8 +297,6 @@
 }
 
 Operations DecisionLogic::FuturePacketAvailable(
-    const SyncBuffer& sync_buffer,
-    const Expand& expand,
     size_t decoder_frame_length,
     Modes prev_mode,
     uint32_t target_timestamp,
@@ -327,10 +323,8 @@
     return kNormal;
   }
 
-  const size_t samples_left =
-      sync_buffer.FutureLength() - expand.overlap_length();
   const size_t cur_size_samples =
-      samples_left + packet_buffer_.NumPacketsInBuffer() * decoder_frame_length;
+      packet_buffer_.NumPacketsInBuffer() * decoder_frame_length;
 
   // If previous was comfort noise, then no merge is needed.
   if (prev_mode == kModeRfc3389Cng || prev_mode == kModeCodecInternalCng) {
@@ -365,8 +359,13 @@
 }
 
 bool DecisionLogic::UnderTargetLevel() const {
-  return buffer_level_filter_->filtered_current_level() <=
-         delay_manager_->TargetLevel();
+  int buffer_level_packets = 0;
+  if (packet_length_samples_ > 0) {
+    buffer_level_packets =
+        ((1 << 8) * buffer_level_filter_->filtered_current_level()) /
+        packet_length_samples_;
+  }
+  return buffer_level_packets <= delay_manager_->TargetLevel();
 }
 
 bool DecisionLogic::ReinitAfterExpands(uint32_t timestamp_leap) const {
diff --git a/modules/audio_coding/neteq/decision_logic.h b/modules/audio_coding/neteq/decision_logic.h
index 2414e8c..49020b0 100644
--- a/modules/audio_coding/neteq/decision_logic.h
+++ b/modules/audio_coding/neteq/decision_logic.h
@@ -134,9 +134,7 @@
 
   // Returns the operation to do given that the expected packet is not
   // available, but a packet further into the future is at hand.
-  Operations FuturePacketAvailable(const SyncBuffer& sync_buffer,
-                                   const Expand& expand,
-                                   size_t decoder_frame_length,
+  Operations FuturePacketAvailable(size_t decoder_frame_length,
                                    Modes prev_mode,
                                    uint32_t target_timestamp,
                                    uint32_t available_timestamp,
diff --git a/modules/audio_coding/neteq/mock/mock_buffer_level_filter.h b/modules/audio_coding/neteq/mock/mock_buffer_level_filter.h
index bf9fd59..031195c 100644
--- a/modules/audio_coding/neteq/mock/mock_buffer_level_filter.h
+++ b/modules/audio_coding/neteq/mock/mock_buffer_level_filter.h
@@ -22,10 +22,8 @@
   virtual ~MockBufferLevelFilter() { Die(); }
   MOCK_METHOD0(Die, void());
   MOCK_METHOD0(Reset, void());
-  MOCK_METHOD3(Update,
-               void(size_t buffer_size_packets,
-                    int time_stretched_samples,
-                    size_t packet_len_samples));
+  MOCK_METHOD2(Update,
+               void(size_t buffer_size_samples, int time_stretched_samples));
   MOCK_METHOD1(SetTargetBufferLevel, void(int target_buffer_level));
   MOCK_CONST_METHOD0(filtered_current_level, int());
 };
diff --git a/modules/audio_coding/neteq/neteq_impl.cc b/modules/audio_coding/neteq/neteq_impl.cc
index ad6becc..82ec18d 100644
--- a/modules/audio_coding/neteq/neteq_impl.cc
+++ b/modules/audio_coding/neteq/neteq_impl.cc
@@ -310,18 +310,12 @@
 
 int NetEqImpl::FilteredCurrentDelayMs() const {
   rtc::CritScope lock(&crit_sect_);
-  // Calculate the filtered packet buffer level in samples. The value from
-  // |buffer_level_filter_| is in number of packets, represented in Q8.
-  const size_t packet_buffer_samples =
-      (buffer_level_filter_->filtered_current_level() *
-       decoder_frame_length_) >>
-      8;
   // Sum up the filtered packet buffer level with the future length of the sync
-  // buffer, and divide the sum by the sample rate.
-  const size_t delay_samples =
-      packet_buffer_samples + sync_buffer_->FutureLength();
+  // buffer.
+  const int delay_samples = buffer_level_filter_->filtered_current_level() +
+                            sync_buffer_->FutureLength();
   // The division below will truncate. The return value is in ms.
-  return static_cast<int>(delay_samples) / rtc::CheckedDivExact(fs_hz_, 1000);
+  return delay_samples / rtc::CheckedDivExact(fs_hz_, 1000);
 }
 
 int NetEqImpl::NetworkStatistics(NetEqNetworkStatistics* stats) {
diff --git a/modules/audio_coding/neteq/neteq_unittest.cc b/modules/audio_coding/neteq/neteq_unittest.cc
index 6c67ca8..a864985 100644
--- a/modules/audio_coding/neteq/neteq_unittest.cc
+++ b/modules/audio_coding/neteq/neteq_unittest.cc
@@ -458,16 +458,16 @@
       webrtc::test::ResourcePath("audio_coding/neteq_universal_new", "rtp");
 
   const std::string output_checksum =
-      PlatformChecksum("9652cee1d6771a9cbfda821ae1bbdb41b0dd4dee",
-                       "54a7e32f163663c0af35bf70bf45cefc24ad62ef", "not used",
-                       "9652cee1d6771a9cbfda821ae1bbdb41b0dd4dee",
-                       "79496b0a1ef0a3824f3ee04789748a461bed643f");
+      PlatformChecksum("415cc2366810676aad27a92b7a9068e79b7e4093",
+                       "52411c46e946e1d50fa777bbfb4686e7161f9cc7", "not used",
+                       "415cc2366810676aad27a92b7a9068e79b7e4093",
+                       "3e02f268f3b4f3acfcc1c397214ea13d09c212fd");
 
   const std::string network_stats_checksum =
-      PlatformChecksum("c59b1f9f282b6d8733cdff975e3c150ca4a47d51",
-                       "bca95e565996a4ffd6e2ac15736e08843bdca93b", "not used",
-                       "c59b1f9f282b6d8733cdff975e3c150ca4a47d51",
-                       "c59b1f9f282b6d8733cdff975e3c150ca4a47d51");
+      PlatformChecksum("6c8726e8699cc61535e65ef9406d339954a05cf8",
+                       "b9f2c862328ddb8d3ec9e79f61cc1d937ee56df6", "not used",
+                       "6c8726e8699cc61535e65ef9406d339954a05cf8",
+                       "6c8726e8699cc61535e65ef9406d339954a05cf8");
 
   DecodeAndCompare(input_rtp_file, output_checksum, network_stats_checksum,
                    FLAG_gen_ref);
@@ -486,17 +486,17 @@
   // Checksum depends on libopus being compiled with or without SSE.
   const std::string maybe_sse =
       "14a63b3c7b925c82296be4bafc71bec85f2915c2|"
-      "2c05677daa968d6c68b92adf4affb7cd9bb4d363";
+      "8884ffe98700454875a88d1c3ea9b55e829a2016";
   const std::string output_checksum = PlatformChecksum(
-      maybe_sse, "b7b7ed802b0e18ee416973bf3b9ae98599b0181d",
-      "5876e52dda90d5ca433c3726555b907b97c86374", maybe_sse, maybe_sse);
+      maybe_sse, "1f76c884d16812704dec85f2b98db697108d2d9b",
+      "f888efef2d0710f202f19ba167ed509609146929", maybe_sse, maybe_sse);
 
   const std::string network_stats_checksum =
-      PlatformChecksum("adb3272498e436d1c019cbfd71610e9510c54497",
-                       "fa935a91abc7291db47428a2d7c5361b98713a92",
-                       "42106aa5267300f709f63737707ef07afd9dac61",
-                       "adb3272498e436d1c019cbfd71610e9510c54497",
-                       "adb3272498e436d1c019cbfd71610e9510c54497");
+      PlatformChecksum("bb8d91f71873df562224fe0dc5822b5dfb030090",
+                       "9f858290a675c4ceabf575feb6a59bef76d62eaf",
+                       "12963c965d9d102ebbc1f619508e2960a1f7dbee",
+                       "bb8d91f71873df562224fe0dc5822b5dfb030090",
+                       "bb8d91f71873df562224fe0dc5822b5dfb030090");
 
   DecodeAndCompare(input_rtp_file, output_checksum, network_stats_checksum,
                    FLAG_gen_ref);
@@ -796,7 +796,7 @@
   const double kDriftFactor = 1000.0 / (1000.0 + 25.0);
   const double kNetworkFreezeTimeMs = 5000.0;
   const bool kGetAudioDuringFreezeRecovery = false;
-  const int kDelayToleranceMs = 50;
+  const int kDelayToleranceMs = 60;
   const int kMaxTimeToSpeechMs = 200;
   LongCngWithClockDrift(kDriftFactor, kNetworkFreezeTimeMs,
                         kGetAudioDuringFreezeRecovery, kDelayToleranceMs,