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

Side by Side 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, 1 month 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « remoting/codec/audio_encoder_opus.cc ('k') | remoting/host/client_session.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // MSVC++ requires this to get M_PI.
6 #define _USE_MATH_DEFINES
7 #include <math.h>
8
9 #include "remoting/codec/audio_encoder_opus.h"
10
11 #include "base/logging.h"
12 #include "remoting/codec/audio_decoder_opus.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 namespace remoting {
16
17 namespace {
18
19 // Maximum value that can be encoded in a 16-bit signed sample.
20 const int kMaxSampleValue = 32767;
21
22 const int kChannels = 2;
23
24 // Phase shift between left and right channels.
25 const double kChannelPhaseShift = 2 * M_PI / 3;
26
27 // The sampling rate that OPUS uses internally and that we expect to get
28 // from the decoder.
29 const AudioPacket_SamplingRate kDefaultSamplingRate =
30 AudioPacket::SAMPLING_RATE_48000;
31
32 // Maximum latency expected from the encoder.
33 const int kMaxLatencyMs = 40;
34
35 // When verifying results ignore the first 1k samples. This is necessary because
36 // it takes some time for the codec to adjust for the input signal.
37 const int kSkippedFirstSamples = 1000;
38
39 // Maximum standard deviation of the difference between original and decoded
40 // signals as a proportion of kMaxSampleValue. For two unrelated signals this
41 // difference will be close to 1.0, even for signals that differ only slightly.
42 // The value is choose such that all the tests pass normally, but fail with
Wez 2012/10/23 05:10:10 typo: choose -> chosen
Sergey Ulanov 2012/10/23 17:36:31 Done.
43 // small small change (e.g. one sample shift between signals).
Wez 2012/10/23 05:10:10 typo: small small change -> small changes?
Sergey Ulanov 2012/10/23 17:36:31 Done.
44 const double kMaxSignalDeviation = 0.1;
45
46 } // namespace
47
48 class OpusAudioEncoderTest : public testing::Test {
49 public:
50 // Return test signal value at the specified position |pos|. |frequency_hz|
51 // defines frequency of the signal. |channel| is used to calculate phase shift
52 // of the signal, so that different signals are generated for left and right
53 // channels.
54 static int16 GetSampleValue(
55 AudioPacket::SamplingRate rate,
56 double frequency_hz,
57 double pos,
58 int channel) {
59 double angle = pos * 2 * M_PI * frequency_hz / rate +
60 kChannelPhaseShift * channel;
61 return static_cast<int>(sin(angle) * kMaxSampleValue + 0.5);
62 }
63
64 // Creates audio packet filled with a test signal with the specified
65 // |frequency_hz|.
66 scoped_ptr<AudioPacket> CreatePacket(
67 int samples,
68 AudioPacket::SamplingRate rate,
69 double frequency_hz,
70 int pos) {
71 std::vector<int16> data(samples * kChannels);
72 for (int i = 0; i < samples; ++i) {
73 data[i * kChannels] = GetSampleValue(rate, frequency_hz, i + pos, 0);
74 data[i * kChannels + 1] = GetSampleValue(rate, frequency_hz, i + pos, 1);
75 }
76
77 scoped_ptr<AudioPacket> packet(new AudioPacket());
78 packet->add_data(reinterpret_cast<char*>(&(data[0])),
79 samples * kChannels * sizeof(int16));
80 packet->set_encoding(AudioPacket::ENCODING_RAW);
81 packet->set_sampling_rate(rate);
82 packet->set_bytes_per_sample(AudioPacket::BYTES_PER_SAMPLE_2);
83 packet->set_channels(AudioPacket::CHANNELS_STEREO);
84 return packet.Pass();
85 }
86
87 // Decoded data is normally shifted in phase relative to the raw data. This
Wez 2012/10/23 05:10:10 nit: by raw data do you mean the original data?
Sergey Ulanov 2012/10/23 17:36:31 Done.
88 // function returns the approximate shift in samples by finding the first
89 // point when signal goes from negative to positive.
90 double EstimateSignalShift(const std::vector<int16>& received_data) {
91 for (size_t i = kSkippedFirstSamples;
92 i < received_data.size() / kChannels - 1; i++) {
93 int16 this_sample = received_data[i * kChannels];
94 int16 next_sample = received_data[(i + 1) * kChannels];
95 if (this_sample < 0 && next_sample > 0) {
96 return
97 i + static_cast<double>(-this_sample) / (next_sample - this_sample);
98 }
99 }
100 return 0;
101 }
102
103 // Compares decoded signal with the test signal that was decoded. It estimates
Wez 2012/10/23 05:10:10 typo: test signal that was encoded
Sergey Ulanov 2012/10/23 17:36:31 Done.
104 // phase shift from the original signal, then calculates standard deviation
105 // of the difference between original and decoded signal.
Wez 2012/10/23 05:10:10 typo: signal -> signals
Sergey Ulanov 2012/10/23 17:36:31 Done.
106 void ValidateReceivedData(int samples,
107 AudioPacket::SamplingRate rate,
108 double frequency_hz,
109 const std::vector<int16>& received_data) {
110 double shift = EstimateSignalShift(received_data);
111 double diff_sqare_sum = 0;
112 for (size_t i = kSkippedFirstSamples;
113 i < received_data.size() / kChannels; i++) {
114 double d = received_data[i * kChannels] -
115 GetSampleValue(rate, frequency_hz, i - shift, 0);
116 diff_sqare_sum += d * d;
117 d = received_data[i * kChannels + 1] -
118 GetSampleValue(rate, frequency_hz, i - shift, 1);
119 diff_sqare_sum += d * d;
120 }
121 double deviation = sqrt(diff_sqare_sum / received_data.size())
122 / kMaxSampleValue;
123 EXPECT_LE(deviation, kMaxSignalDeviation);
124 }
125
126 void TestEncodeDecode(int packet_size,
127 double frequency_hz,
128 AudioPacket::SamplingRate rate) {
129 const int kTotalTestSamples = 24000;
130
131 encoder_.reset(new AudioEncoderOpus());
132 decoder_.reset(new AudioDecoderOpus());
133
134 std::vector<int16> received_data;
135 int pos = 0;
136 for (; pos < kTotalTestSamples; pos += packet_size) {
137 scoped_ptr<AudioPacket> source_packet =
138 CreatePacket(packet_size, rate, frequency_hz, pos);
139 scoped_ptr<AudioPacket> encoded =
140 encoder_->Encode(source_packet.Pass());
141 if (encoded.get()) {
142 scoped_ptr<AudioPacket> decoded = decoder_->Decode(encoded.Pass());
143 EXPECT_EQ(kDefaultSamplingRate, decoded->sampling_rate());
144 for (int i = 0; i < decoded->data_size(); ++i) {
145 const int16* data =
146 reinterpret_cast<const int16*>(decoded->data(i).data());
147 received_data.insert(
148 received_data.end(), data,
149 data + decoded->data(i).size() / sizeof(int16));
150 }
151 }
152 }
153
154 // Verify that at most kMaxLatencyMs worth of samples is buffered inside
155 // |encoder_| and |decoder_|.
156 EXPECT_GE(static_cast<int>(received_data.size()) / kChannels,
157 pos - rate * kMaxLatencyMs / 1000);
158
159 ValidateReceivedData(packet_size, kDefaultSamplingRate,
160 frequency_hz, received_data);
161 }
162
163 protected:
164 scoped_ptr<AudioEncoderOpus> encoder_;
165 scoped_ptr<AudioDecoderOpus> decoder_;
166 };
167
168 TEST_F(OpusAudioEncoderTest, CreateAndDestroy) {
169 }
170
171 TEST_F(OpusAudioEncoderTest, NoResampling) {
172 TestEncodeDecode(2000, 50, AudioPacket::SAMPLING_RATE_48000);
173 TestEncodeDecode(2000, 3000, AudioPacket::SAMPLING_RATE_48000);
174 TestEncodeDecode(2000, 10000, AudioPacket::SAMPLING_RATE_48000);
175 }
176
177 TEST_F(OpusAudioEncoderTest, Resampling) {
178 TestEncodeDecode(2000, 50, AudioPacket::SAMPLING_RATE_44100);
179 TestEncodeDecode(2000, 3000, AudioPacket::SAMPLING_RATE_44100);
180 TestEncodeDecode(2000, 10000, AudioPacket::SAMPLING_RATE_44100);
181 }
182
183 TEST_F(OpusAudioEncoderTest, BufferSizeAndResampling) {
184 TestEncodeDecode(500, 3000, AudioPacket::SAMPLING_RATE_44100);
185 TestEncodeDecode(1000, 3000, AudioPacket::SAMPLING_RATE_44100);
186 TestEncodeDecode(5000, 3000, AudioPacket::SAMPLING_RATE_44100);
187 }
188
189 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/codec/audio_encoder_opus.cc ('k') | remoting/host/client_session.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698