Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(62)

Unified Diff: remoting/codec/audio_encoder_opus_unittest.cc

Issue 11189047: Add opus audio codec support in remoting (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: remoting/codec/audio_encoder_opus_unittest.cc
diff --git a/remoting/codec/audio_encoder_opus_unittest.cc b/remoting/codec/audio_encoder_opus_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..810a8b0c0c58b45378b25890499305aa30acdaa5
--- /dev/null
+++ b/remoting/codec/audio_encoder_opus_unittest.cc
@@ -0,0 +1,166 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// MSVC++ requires this to get M_PI.
+#define _USE_MATH_DEFINES
+#include <math.h>
+
+#include "remoting/codec/audio_encoder_opus.h"
+
+#include "base/logging.h"
+#include "remoting/codec/audio_decoder_opus.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace remoting {
+
+namespace {
+
+const int kChannels = 2;
+const double kChannelPhaseShift = 2 * M_PI / 3;
Wez 2012/10/22 22:50:21 nit: Add comments explaining what this is used for
Sergey Ulanov 2012/10/23 00:43:50 Done.
+const AudioPacket_SamplingRate kDefaultSamplingRate =
+ AudioPacket::SAMPLING_RATE_48000;
+const int kMaxLatencyMs = 40;
+
+// When verifying results ignore the first 1k samples. This is necessary because
+// it takes some time for the codec to adjust for the input signal.
+const int kSkippedFirstSamples = 1000;
+
+} // namespace
+
+class OpusAudioEncoderTest : public testing::Test {
+ public:
+
+ static int16 GetSampleValue(
+ AudioPacket::SamplingRate rate,
+ double frequency,
Wez 2012/10/22 22:50:21 nit: Specify units.
Sergey Ulanov 2012/10/23 00:43:50 Done.
+ double pos,
Wez 2012/10/22 22:50:21 nit: How can we have sub-sample position?
Sergey Ulanov 2012/10/23 00:43:50 That's used when comparing results - GetSignalShif
+ int channel) {
+ double angle = pos * 2 * M_PI * frequency / rate +
+ kChannelPhaseShift * channel;
+ return static_cast<int>(sin(angle) * 32767 + 0.5);
+ }
+
+ scoped_ptr<AudioPacket> CreatePacket(
+ int samples,
+ AudioPacket::SamplingRate rate,
+ double frequency,
+ int pos) {
+
+ std::vector<int16> data(samples * kChannels);
Wez 2012/10/22 22:50:21 nit: Add a comment to explain that we're filling t
Sergey Ulanov 2012/10/23 00:43:50 Done.
+ for (int i = 0; i < samples; ++i) {
+ data[i * kChannels] = GetSampleValue(rate, frequency, i + pos, 0);
+ data[i * kChannels + 1] = GetSampleValue(rate, frequency, i + pos, 1);
+ }
+
+ scoped_ptr<AudioPacket> packet(new AudioPacket());
+ packet->add_data(reinterpret_cast<char*>(&(data[0])),
+ samples * kChannels * sizeof(int16));
+ packet->set_encoding(AudioPacket::ENCODING_RAW);
+ packet->set_sampling_rate(rate);
+ packet->set_bytes_per_sample(AudioPacket::BYTES_PER_SAMPLE_2);
+ packet->set_channels(AudioPacket::CHANNELS_STEREO);
+ return packet.Pass();
+ }
+
+ // Decoded data is normally shifted in phase relative to the raw date. This
Wez 2012/10/22 22:50:21 typo: date -> data
Sergey Ulanov 2012/10/23 00:43:50 Done.
+ // function returns approximate the phase difference by finding the first
Wez 2012/10/22 22:50:21 typo: approximate the phase ... -> ... the approxi
Sergey Ulanov 2012/10/23 00:43:50 Done.
+ // point when signal goes from negative to positive.
+ double GetSignalShift(const std::vector<int16>& received_data) {
Wez 2012/10/22 22:50:21 nit: So this function is supposed to be getting th
Sergey Ulanov 2012/10/23 00:43:50 Renamed to EstimateSignalShift(). I don't think it
+ for (size_t i = kSkippedFirstSamples;
+ i < received_data.size() / kChannels - 1; i++) {
+ int16 this_sample = received_data[i * kChannels];
+ int16 next_sample = received_data[(i + 1) * kChannels];
+ if (this_sample < 0 && next_sample > 0) {
+ return i +
+ static_cast<double>(-this_sample) / (next_sample - this_sample);
+ }
+ }
+ return 0;
+ }
+
+ void ValidateReceivedData(int samples,
+ AudioPacket::SamplingRate rate,
+ double frequency,
+ const std::vector<int16>& received_data) {
Wez 2012/10/22 22:50:21 nit: Add a comment explaining that we validate the
Sergey Ulanov 2012/10/23 00:43:50 Done.
+ double shift = GetSignalShift(received_data);
+ double diff_sqare_sum = 0;
+ for (size_t i = kSkippedFirstSamples;
+ i < received_data.size() / kChannels; i++) {
+ double d = received_data[i * kChannels] -
+ GetSampleValue(rate, frequency, i - shift, 0);
+ diff_sqare_sum += d * d;
+ d = received_data[i * kChannels + 1] -
+ GetSampleValue(rate, frequency, i - shift, 1);
+ diff_sqare_sum += d * d;
+ }
+ double averate_difference = sqrt(diff_sqare_sum / received_data.size());
Wez 2012/10/22 22:50:21 typo: average_difference
Wez 2012/10/22 22:50:21 nit: Clarify the units you're using for the differ
Sergey Ulanov 2012/10/23 00:43:50 Done.
Sergey Ulanov 2012/10/23 00:43:50 Done.
+ EXPECT_LE(averate_difference, 5000);
Wez 2012/10/22 22:50:21 nit: Consider moving 5000 to a constant, above
Sergey Ulanov 2012/10/23 00:43:50 Done.
+ }
+
+ void ResetEncoder() {
Wez 2012/10/22 22:50:21 nit: ResetEncoder -> Reset or ResetEncoderAndDecod
Sergey Ulanov 2012/10/23 00:43:50 Removed this function.
+ encoder_.reset(new AudioEncoderOpus());
+ decoder_.reset(new AudioDecoderOpus());
+ }
+
+ void TestEncoderDecoder(int packet_size,
Wez 2012/10/22 22:50:21 typo: TestEncodeDecode
Sergey Ulanov 2012/10/23 00:43:50 Done.
+ double frequency,
+ AudioPacket::SamplingRate rate) {
+ const int kTotalTestSamples = 24000;
+ ResetEncoder();
+
+ std::vector<int16> received_data;
+ int pos = 0;
+ for (; pos < kTotalTestSamples; pos += packet_size) {
+ scoped_ptr<AudioPacket> source_packet =
+ CreatePacket(packet_size, rate, frequency, pos);
+ scoped_ptr<AudioPacket> encoded = encoder_->Encode(source_packet.Pass());
Wez 2012/10/22 22:50:21 Line too long?
Sergey Ulanov 2012/10/23 00:43:50 Done.
+ if (encoded.get()) {
Wez 2012/10/22 22:50:21 EXPECT(encoded.get())?
Sergey Ulanov 2012/10/23 00:43:50 Encoder is allowed to return NULL packet sometimes
+ scoped_ptr<AudioPacket> decoded = decoder_->Decode(encoded.Pass());
+ EXPECT_EQ(kDefaultSamplingRate, decoded->sampling_rate());
+ for (int i = 0; i < decoded->data_size(); ++i) {
+ const int16* data =
+ reinterpret_cast<const int16*>(decoded->data(i).data());
+ received_data.insert(
+ received_data.end(), data,
+ data + decoded->data(i).size() / sizeof(int16));
+ }
+ }
+ }
+
+ // Verify that at most kMaxLatencyMs worth of samples is buffered inside
+ // |encoder_| and |decoder_|.
+ EXPECT_GE(static_cast<int>(received_data.size()) / kChannels,
+ pos - rate * kMaxLatencyMs / 1000);
+
+ ValidateReceivedData(packet_size, kDefaultSamplingRate,
+ frequency, received_data);
+ }
+
+ protected:
+ scoped_ptr<AudioEncoderOpus> encoder_;
+ scoped_ptr<AudioDecoderOpus> decoder_;
+};
+
+TEST_F(OpusAudioEncoderTest, CreateAndDestroy) {
+}
+
+TEST_F(OpusAudioEncoderTest, NoResampling) {
+ TestEncoderDecoder(2000, 50, AudioPacket::SAMPLING_RATE_48000);
+ TestEncoderDecoder(2000, 3000, AudioPacket::SAMPLING_RATE_48000);
+ TestEncoderDecoder(2000, 10000, AudioPacket::SAMPLING_RATE_48000);
+}
+
+TEST_F(OpusAudioEncoderTest, Resampling) {
+ TestEncoderDecoder(2000, 50, AudioPacket::SAMPLING_RATE_44100);
+ TestEncoderDecoder(2000, 3000, AudioPacket::SAMPLING_RATE_44100);
+ TestEncoderDecoder(2000, 10000, AudioPacket::SAMPLING_RATE_44100);
+}
+
+TEST_F(OpusAudioEncoderTest, BufferSize) {
Wez 2012/10/22 22:50:21 nit: BufferingAndResampling / BufferSizeAndResampl
Sergey Ulanov 2012/10/23 00:43:50 Done.
+ TestEncoderDecoder(500, 3000, AudioPacket::SAMPLING_RATE_44100);
+ TestEncoderDecoder(1000, 3000, AudioPacket::SAMPLING_RATE_44100);
+ TestEncoderDecoder(5000, 3000, AudioPacket::SAMPLING_RATE_44100);
Wez 2012/10/22 22:50:21 How long to these tests take?
Sergey Ulanov 2012/10/23 00:43:50 About 0.6 seconds total for all tests in this file
+}
+
+} // namespace remoting

Powered by Google App Engine
This is Rietveld 408576698