Ensure that an RTP audio level of 127 represents digital silence.

To quote rfc6464:
  The audio level for digital silence -- for a muted audio source, for
  example -- MUST be represented as 127 (-127 dBov), regardless of the
  dynamic range of the encoded audio format.

The behavior in webrtc is correct that digital silence is represented
with 127, but it is also possible to get a value of 127 for not quite
digitally silent audio buffer (as in, not strictly 0s).

Bug: webrtc:14029
Change-Id: I7ff8698a7e4d5c0960c667fd1cc961838e269456
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/261244
Commit-Queue: Tomas Gunnarsson <tommi@webrtc.org>
Reviewed-by: Per Åhgren <peah@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#36793}
This commit is contained in:
Tommi 2022-05-06 08:58:38 +02:00 committed by WebRTC LUCI CQ
parent 3b0481389f
commit 7f969c0eff
3 changed files with 25 additions and 3 deletions

View file

@ -101,8 +101,18 @@ void RmsLevel::AnalyzeMuted(size_t length) {
}
int RmsLevel::Average() {
int rms = (sample_count_ == 0) ? RmsLevel::kMinLevelDb
: ComputeRms(sum_square_ / sample_count_);
const bool have_samples = (sample_count_ != 0);
int rms = have_samples ? ComputeRms(sum_square_ / sample_count_)
: RmsLevel::kMinLevelDb;
// To ensure that kMinLevelDb represents digital silence (muted audio
// sources) we'll check here if the sum_square is actually 0. If it's not
// we'll bump up the return value to `kInaudibleButNotMuted`.
// https://datatracker.ietf.org/doc/html/rfc6464
if (have_samples && rms == RmsLevel::kMinLevelDb && sum_square_ != 0.0f) {
rms = kInaudibleButNotMuted;
}
Reset();
return rms;
}

View file

@ -34,7 +34,7 @@ class RmsLevel {
int peak;
};
enum : int { kMinLevelDb = 127 };
enum : int { kMinLevelDb = 127, kInaudibleButNotMuted = 126 };
RmsLevel();
~RmsLevel();

View file

@ -151,6 +151,18 @@ TEST(RmsLevelTest, ProcessMuted) {
EXPECT_EQ(6, level->Average()); // Average RMS halved due to the silence.
}
// Digital silence must yield 127 and anything else should yield 126 or lower.
TEST(RmsLevelTest, OnlyDigitalSilenceIs127) {
std::vector<int16_t> test_buffer(kSampleRateHz, 0);
auto level = RunTest(test_buffer);
EXPECT_EQ(127, level->Average());
// Change one sample to something other than 0 to make the buffer not strictly
// represent digital silence.
test_buffer[0] = 1;
level = RunTest(test_buffer);
EXPECT_LT(level->Average(), 127);
}
// Inserts 1 second of half-scale sinusoid, follwed by 10 ms of full-scale, and
// finally 1 second of half-scale again. Expect the average to be -9 dBFS due
// to the vast majority of the signal being half-scale, and the peak to be