summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhenrik.lundin@webrtc.org <henrik.lundin@webrtc.org>2014-10-14 10:49:58 +0000
committerhenrik.lundin@webrtc.org <henrik.lundin@webrtc.org>2014-10-14 10:49:58 +0000
commit4dd7210b1a0ab6e85a16cf5abb0b439d300b7744 (patch)
treed53bfd79eb8fb6c401db171c78ee6f6a8b07ab4e
parent6368255205b7849b9ead613754cb5c31c8b0294b (diff)
downloadwebrtc-4dd7210b1a0ab6e85a16cf5abb0b439d300b7744.tar.gz
New ACM test to trigger audio glitch when switching output sample rate
This CL implements a new unit test. The test is designed to trigger a problem in ACM where switching the desired output frequency creates a short discontinuity in the output audio. The problem itself is not solved in this CL, but the failing test is disabled for now. BUG=3919 R=kwiberg@webrtc.org Review URL: https://webrtc-codereview.appspot.com/23019004 git-svn-id: http://webrtc.googlecode.com/svn/trunk/webrtc@7443 4adac7df-926f-26a2-2b94-8c16560cd09d
-rw-r--r--modules/audio_coding/main/acm2/acm_receive_test_oldapi.cc27
-rw-r--r--modules/audio_coding/main/acm2/acm_receive_test_oldapi.h29
-rw-r--r--modules/audio_coding/main/acm2/audio_coding_module_unittest_oldapi.cc102
-rw-r--r--modules/audio_coding/neteq/neteq.gypi2
-rw-r--r--modules/audio_coding/neteq/tools/constant_pcm_packet_source.cc71
-rw-r--r--modules/audio_coding/neteq/tools/constant_pcm_packet_source.h57
6 files changed, 286 insertions, 2 deletions
diff --git a/modules/audio_coding/main/acm2/acm_receive_test_oldapi.cc b/modules/audio_coding/main/acm2/acm_receive_test_oldapi.cc
index b0c9af13..391e99b0 100644
--- a/modules/audio_coding/main/acm2/acm_receive_test_oldapi.cc
+++ b/modules/audio_coding/main/acm2/acm_receive_test_oldapi.cc
@@ -164,6 +164,7 @@ void AcmReceiveTestOldApi::Run() {
}
ASSERT_TRUE(audio_sink_->WriteAudioFrame(output_frame));
clock_.AdvanceTimeMilliseconds(10);
+ AfterGetAudio();
}
// Insert packet after converting from RTPHeader to WebRtcRTPHeader.
@@ -183,5 +184,31 @@ void AcmReceiveTestOldApi::Run() {
}
}
+AcmReceiveTestToggleOutputFreqOldApi::AcmReceiveTestToggleOutputFreqOldApi(
+ PacketSource* packet_source,
+ AudioSink* audio_sink,
+ int output_freq_hz_1,
+ int output_freq_hz_2,
+ int toggle_period_ms,
+ NumOutputChannels exptected_output_channels)
+ : AcmReceiveTestOldApi(packet_source,
+ audio_sink,
+ output_freq_hz_1,
+ exptected_output_channels),
+ output_freq_hz_1_(output_freq_hz_1),
+ output_freq_hz_2_(output_freq_hz_2),
+ toggle_period_ms_(toggle_period_ms),
+ last_toggle_time_ms_(clock_.TimeInMilliseconds()) {
+}
+
+void AcmReceiveTestToggleOutputFreqOldApi::AfterGetAudio() {
+ if (clock_.TimeInMilliseconds() >= last_toggle_time_ms_ + toggle_period_ms_) {
+ output_freq_hz_ = (output_freq_hz_ == output_freq_hz_1_)
+ ? output_freq_hz_2_
+ : output_freq_hz_1_;
+ last_toggle_time_ms_ = clock_.TimeInMilliseconds();
+ }
+}
+
} // namespace test
} // namespace webrtc
diff --git a/modules/audio_coding/main/acm2/acm_receive_test_oldapi.h b/modules/audio_coding/main/acm2/acm_receive_test_oldapi.h
index 795893c2..e913fcf3 100644
--- a/modules/audio_coding/main/acm2/acm_receive_test_oldapi.h
+++ b/modules/audio_coding/main/acm2/acm_receive_test_oldapi.h
@@ -47,17 +47,42 @@ class AcmReceiveTestOldApi {
// Runs the test and returns true if successful.
void Run();
- private:
+ protected:
+ // Method is called after each block of output audio is received from ACM.
+ virtual void AfterGetAudio() {}
+
SimulatedClock clock_;
scoped_ptr<AudioCodingModule> acm_;
PacketSource* packet_source_;
AudioSink* audio_sink_;
- const int output_freq_hz_;
+ int output_freq_hz_;
NumOutputChannels exptected_output_channels_;
DISALLOW_COPY_AND_ASSIGN(AcmReceiveTestOldApi);
};
+// This test toggles the output frequency every |toggle_period_ms|. The test
+// starts with |output_freq_hz_1|. Except for the toggling, it does the same
+// thing as AcmReceiveTestOldApi.
+class AcmReceiveTestToggleOutputFreqOldApi : public AcmReceiveTestOldApi {
+ public:
+ AcmReceiveTestToggleOutputFreqOldApi(
+ PacketSource* packet_source,
+ AudioSink* audio_sink,
+ int output_freq_hz_1,
+ int output_freq_hz_2,
+ int toggle_period_ms,
+ NumOutputChannels exptected_output_channels);
+
+ protected:
+ void AfterGetAudio() OVERRIDE;
+
+ const int output_freq_hz_1_;
+ const int output_freq_hz_2_;
+ const int toggle_period_ms_;
+ int64_t last_toggle_time_ms_;
+};
+
} // namespace test
} // namespace webrtc
#endif // WEBRTC_MODULES_AUDIO_CODING_MAIN_ACM2_ACM_RECEIVE_TEST_H_
diff --git a/modules/audio_coding/main/acm2/audio_coding_module_unittest_oldapi.cc b/modules/audio_coding/main/acm2/audio_coding_module_unittest_oldapi.cc
index 0e9d2736..33c364a1 100644
--- a/modules/audio_coding/main/acm2/audio_coding_module_unittest_oldapi.cc
+++ b/modules/audio_coding/main/acm2/audio_coding_module_unittest_oldapi.cc
@@ -20,6 +20,7 @@
#include "webrtc/modules/audio_coding/main/interface/audio_coding_module_typedefs.h"
#include "webrtc/modules/audio_coding/neteq/tools/audio_checksum.h"
#include "webrtc/modules/audio_coding/neteq/tools/audio_loop.h"
+#include "webrtc/modules/audio_coding/neteq/tools/constant_pcm_packet_source.h"
#include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h"
#include "webrtc/modules/audio_coding/neteq/tools/output_audio_file.h"
#include "webrtc/modules/audio_coding/neteq/tools/packet.h"
@@ -935,4 +936,105 @@ TEST_F(AcmSenderBitExactnessOldApi, Opus_stereo_20ms) {
test::AcmReceiveTestOldApi::kStereoOutput);
}
+// This test fixture is implemented to run ACM and change the desired output
+// frequency during the call. The input packets are simply PCM16b-wb encoded
+// payloads with a constant value of |kSampleValue|. The test fixture itself
+// acts as PacketSource in between the receive test class and the constant-
+// payload packet source class. The output is both written to file, and analyzed
+// in this test fixture.
+class AcmSwitchingOutputFrequencyOldApi : public ::testing::Test,
+ public test::PacketSource,
+ public test::AudioSink {
+ protected:
+ static const size_t kTestNumPackets = 100;
+ static const int kEncodedSampleRateHz = 16000;
+ static const size_t kPayloadLenSamples = 30 * kEncodedSampleRateHz / 1000;
+ static const int kPayloadType = 108; // Default payload type for PCM16b-wb.
+
+ AcmSwitchingOutputFrequencyOldApi()
+ : first_output_(true),
+ num_packets_(0),
+ packet_source_(kPayloadLenSamples,
+ kSampleValue,
+ kEncodedSampleRateHz,
+ kPayloadType),
+ high_output_freq_(0),
+ has_toggled_(false) {}
+
+ void Run(int low_output_freq, int high_output_freq, int toggle_period_ms) {
+ // Set up the receiver used to decode the packets and verify the decoded
+ // output.
+ const std::string output_file_name =
+ webrtc::test::OutputPath() +
+ ::testing::UnitTest::GetInstance()
+ ->current_test_info()
+ ->test_case_name() +
+ "_" + ::testing::UnitTest::GetInstance()->current_test_info()->name() +
+ "_output.pcm";
+ test::OutputAudioFile output_file(output_file_name);
+ // Have the output audio sent both to file and to the WriteArray method in
+ // this class.
+ test::AudioSinkFork output(this, &output_file);
+ test::AcmReceiveTestToggleOutputFreqOldApi receive_test(
+ this,
+ &output,
+ low_output_freq,
+ high_output_freq,
+ toggle_period_ms,
+ test::AcmReceiveTestOldApi::kMonoOutput);
+ ASSERT_NO_FATAL_FAILURE(receive_test.RegisterDefaultCodecs());
+ high_output_freq_ = high_output_freq;
+
+ // This is where the actual test is executed.
+ receive_test.Run();
+ }
+
+ // Inherited from test::PacketSource.
+ test::Packet* NextPacket() OVERRIDE {
+ // Check if it is time to terminate the test. The packet source is of type
+ // ConstantPcmPacketSource, which is infinite, so we must end the test
+ // "manually".
+ if (num_packets_++ > kTestNumPackets) {
+ EXPECT_TRUE(has_toggled_);
+ return NULL; // Test ended.
+ }
+
+ // Get the next packet from the source.
+ return packet_source_.NextPacket();
+ }
+
+ // Inherited from test::AudioSink.
+ bool WriteArray(const int16_t* audio, size_t num_samples) {
+ // Skip checking the first output frame, since it has a number of zeros
+ // due to how NetEq is initialized.
+ if (first_output_) {
+ first_output_ = false;
+ return true;
+ }
+ for (size_t i = 0; i < num_samples; ++i) {
+ EXPECT_EQ(kSampleValue, audio[i]);
+ }
+ if (num_samples ==
+ static_cast<size_t>(high_output_freq_ / 100)) // Size of 10 ms frame.
+ has_toggled_ = true;
+ // The return value does not say if the values match the expectation, just
+ // that the method could process the samples.
+ return true;
+ }
+
+ const int16_t kSampleValue = 1000;
+ bool first_output_;
+ size_t num_packets_;
+ test::ConstantPcmPacketSource packet_source_;
+ int high_output_freq_;
+ bool has_toggled_;
+};
+
+TEST_F(AcmSwitchingOutputFrequencyOldApi, TestWithoutToggling) {
+ Run(16000, 16000, 1000);
+}
+
+TEST_F(AcmSwitchingOutputFrequencyOldApi, DISABLED_TestWithToggling) {
+ Run(16000, 32000, 1000);
+}
} // namespace webrtc
diff --git a/modules/audio_coding/neteq/neteq.gypi b/modules/audio_coding/neteq/neteq.gypi
index 34d64a1f..0901615a 100644
--- a/modules/audio_coding/neteq/neteq.gypi
+++ b/modules/audio_coding/neteq/neteq.gypi
@@ -185,6 +185,8 @@
'tools/audio_loop.cc',
'tools/audio_loop.h',
'tools/audio_sink.h',
+ 'tools/constant_pcm_packet_source.cc',
+ 'tools/constant_pcm_packet_source.h',
'tools/input_audio_file.cc',
'tools/input_audio_file.h',
'tools/output_audio_file.h',
diff --git a/modules/audio_coding/neteq/tools/constant_pcm_packet_source.cc b/modules/audio_coding/neteq/tools/constant_pcm_packet_source.cc
new file mode 100644
index 00000000..a92f4125
--- /dev/null
+++ b/modules/audio_coding/neteq/tools/constant_pcm_packet_source.cc
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "webrtc/modules/audio_coding/neteq/tools/constant_pcm_packet_source.h"
+
+#include <algorithm>
+
+#include "webrtc/base/checks.h"
+#include "webrtc/modules/audio_coding/codecs/pcm16b/include/pcm16b.h"
+#include "webrtc/modules/audio_coding/neteq/tools/packet.h"
+
+namespace webrtc {
+namespace test {
+
+ConstantPcmPacketSource::ConstantPcmPacketSource(size_t payload_len_samples,
+ int16_t sample_value,
+ int sample_rate_hz,
+ int payload_type)
+ : payload_len_samples_(payload_len_samples),
+ packet_len_bytes_(2 * payload_len_samples_ + kHeaderLenBytes),
+ samples_per_ms_(sample_rate_hz / 1000),
+ next_arrival_time_ms_(0.0),
+ payload_type_(payload_type),
+ seq_number_(0),
+ timestamp_(0),
+ payload_ssrc_(0xABCD1234) {
+ int encoded_len = WebRtcPcm16b_EncodeW16(&sample_value, 1, &encoded_sample_);
+ CHECK_EQ(encoded_len, 2);
+}
+
+Packet* ConstantPcmPacketSource::NextPacket() {
+ CHECK_GT(packet_len_bytes_, kHeaderLenBytes);
+ uint8_t* packet_memory = new uint8_t[packet_len_bytes_];
+ // Fill the payload part of the packet memory with the pre-encoded value.
+ std::fill_n(reinterpret_cast<int16_t*>(packet_memory + kHeaderLenBytes),
+ payload_len_samples_,
+ encoded_sample_);
+ WriteHeader(packet_memory);
+ // |packet| assumes ownership of |packet_memory|.
+ Packet* packet =
+ new Packet(packet_memory, packet_len_bytes_, next_arrival_time_ms_);
+ next_arrival_time_ms_ += payload_len_samples_ / samples_per_ms_;
+ return packet;
+}
+
+void ConstantPcmPacketSource::WriteHeader(uint8_t* packet_memory) {
+ packet_memory[0] = 0x80;
+ packet_memory[1] = payload_type_ & 0xFF;
+ packet_memory[2] = (seq_number_ >> 8) & 0xFF;
+ packet_memory[3] = seq_number_ & 0xFF;
+ packet_memory[4] = (timestamp_ >> 24) & 0xFF;
+ packet_memory[5] = (timestamp_ >> 16) & 0xFF;
+ packet_memory[6] = (timestamp_ >> 8) & 0xFF;
+ packet_memory[7] = timestamp_ & 0xFF;
+ packet_memory[8] = (payload_ssrc_ >> 24) & 0xFF;
+ packet_memory[9] = (payload_ssrc_ >> 16) & 0xFF;
+ packet_memory[10] = (payload_ssrc_ >> 8) & 0xFF;
+ packet_memory[11] = payload_ssrc_ & 0xFF;
+ ++seq_number_;
+ timestamp_ += static_cast<uint32_t>(payload_len_samples_);
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/modules/audio_coding/neteq/tools/constant_pcm_packet_source.h b/modules/audio_coding/neteq/tools/constant_pcm_packet_source.h
new file mode 100644
index 00000000..8a4bbf17
--- /dev/null
+++ b/modules/audio_coding/neteq/tools/constant_pcm_packet_source.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_CONSTANT_PCM_PACKET_SOURCE_H_
+#define WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_CONSTANT_PCM_PACKET_SOURCE_H_
+
+#include <stdio.h>
+#include <string>
+
+#include "webrtc/base/constructormagic.h"
+#include "webrtc/common_types.h"
+#include "webrtc/modules/audio_coding/neteq/tools/packet_source.h"
+
+namespace webrtc {
+namespace test {
+
+// This class implements a packet source that delivers PCM16b encoded packets
+// with a constant sample value. The payload length, constant sample value,
+// sample rate, and payload type are all set in the constructor.
+class ConstantPcmPacketSource : public PacketSource {
+ public:
+ ConstantPcmPacketSource(size_t payload_len_samples,
+ int16_t sample_value,
+ int sample_rate_hz,
+ int payload_type);
+
+ // Returns a pointer to the next packet. Will never return NULL. That is,
+ // the source is infinite.
+ Packet* NextPacket() OVERRIDE;
+
+ private:
+ void WriteHeader(uint8_t* packet_memory);
+
+ const size_t kHeaderLenBytes = 12;
+ const size_t payload_len_samples_;
+ const size_t packet_len_bytes_;
+ int16_t encoded_sample_;
+ const int samples_per_ms_;
+ double next_arrival_time_ms_;
+ const int payload_type_;
+ uint16_t seq_number_;
+ uint32_t timestamp_;
+ const uint32_t payload_ssrc_;
+
+ DISALLOW_COPY_AND_ASSIGN(ConstantPcmPacketSource);
+};
+
+} // namespace test
+} // namespace webrtc
+#endif // WEBRTC_MODULES_AUDIO_CODING_NETEQ_TOOLS_CONSTANT_PCM_PACKET_SOURCE_H_