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.
5 // MSVC++ requires this to get M_PI.
6 #define _USE_MATH_DEFINES
9 #include "remoting/codec/audio_encoder_opus.h"
11 #include "base/logging.h"
12 #include "remoting/codec/audio_decoder_opus.h"
13 #include "testing/gtest/include/gtest/gtest.h"
19 // Maximum value that can be encoded in a 16-bit signed sample.
20 const int kMaxSampleValue
= 32767;
22 const int kChannels
= 2;
24 // Phase shift between left and right channels.
25 const double kChannelPhaseShift
= 2 * M_PI
/ 3;
27 // The sampling rate that OPUS uses internally and that we expect to get
29 const AudioPacket_SamplingRate kDefaultSamplingRate
=
30 AudioPacket::SAMPLING_RATE_48000
;
32 // Maximum latency expected from the encoder.
33 const int kMaxLatencyMs
= 40;
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;
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 chosen such that all the tests pass normally, but fail with
43 // small changes (e.g. one sample shift between signals).
44 const double kMaxSignalDeviation
= 0.1;
48 class OpusAudioEncoderTest
: public testing::Test
{
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
54 static int16
GetSampleValue(
55 AudioPacket::SamplingRate rate
,
59 double angle
= pos
* 2 * M_PI
* frequency_hz
/ rate
+
60 kChannelPhaseShift
* channel
;
61 return static_cast<int>(sin(angle
) * kMaxSampleValue
+ 0.5);
64 // Creates audio packet filled with a test signal with the specified
66 scoped_ptr
<AudioPacket
> CreatePacket(
68 AudioPacket::SamplingRate rate
,
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);
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
);
87 // Decoded data is normally shifted in phase relative to the original signal.
88 // This 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) {
97 i
+ static_cast<double>(-this_sample
) / (next_sample
- this_sample
);
103 // Compares decoded signal with the test signal that was encoded. It estimates
104 // phase shift from the original signal, then calculates standard deviation of
105 // the difference between original and decoded signals.
106 void ValidateReceivedData(int samples
,
107 AudioPacket::SamplingRate rate
,
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
;
121 double deviation
= sqrt(diff_sqare_sum
/ received_data
.size())
123 LOG(ERROR
) << "Decoded signal deviation: " << deviation
;
124 EXPECT_LE(deviation
, kMaxSignalDeviation
);
127 void TestEncodeDecode(int packet_size
,
129 AudioPacket::SamplingRate rate
) {
130 const int kTotalTestSamples
= 24000;
132 encoder_
.reset(new AudioEncoderOpus());
133 decoder_
.reset(new AudioDecoderOpus());
135 std::vector
<int16
> received_data
;
137 for (; pos
< kTotalTestSamples
; pos
+= packet_size
) {
138 scoped_ptr
<AudioPacket
> source_packet
=
139 CreatePacket(packet_size
, rate
, frequency_hz
, pos
);
140 scoped_ptr
<AudioPacket
> encoded
=
141 encoder_
->Encode(source_packet
.Pass());
143 scoped_ptr
<AudioPacket
> decoded
= decoder_
->Decode(encoded
.Pass());
144 EXPECT_EQ(kDefaultSamplingRate
, decoded
->sampling_rate());
145 for (int i
= 0; i
< decoded
->data_size(); ++i
) {
147 reinterpret_cast<const int16
*>(decoded
->data(i
).data());
148 received_data
.insert(
149 received_data
.end(), data
,
150 data
+ decoded
->data(i
).size() / sizeof(int16
));
155 // Verify that at most kMaxLatencyMs worth of samples is buffered inside
156 // |encoder_| and |decoder_|.
157 EXPECT_GE(static_cast<int>(received_data
.size()) / kChannels
,
158 pos
- rate
* kMaxLatencyMs
/ 1000);
160 ValidateReceivedData(packet_size
, kDefaultSamplingRate
,
161 frequency_hz
, received_data
);
165 scoped_ptr
<AudioEncoderOpus
> encoder_
;
166 scoped_ptr
<AudioDecoderOpus
> decoder_
;
169 TEST_F(OpusAudioEncoderTest
, CreateAndDestroy
) {
172 TEST_F(OpusAudioEncoderTest
, NoResampling
) {
173 TestEncodeDecode(2000, 50, AudioPacket::SAMPLING_RATE_48000
);
174 TestEncodeDecode(2000, 3000, AudioPacket::SAMPLING_RATE_48000
);
175 TestEncodeDecode(2000, 10000, AudioPacket::SAMPLING_RATE_48000
);
178 TEST_F(OpusAudioEncoderTest
, Resampling
) {
179 TestEncodeDecode(2000, 50, AudioPacket::SAMPLING_RATE_44100
);
180 TestEncodeDecode(2000, 3000, AudioPacket::SAMPLING_RATE_44100
);
181 TestEncodeDecode(2000, 10000, AudioPacket::SAMPLING_RATE_44100
);
184 TEST_F(OpusAudioEncoderTest
, BufferSizeAndResampling
) {
185 TestEncodeDecode(500, 3000, AudioPacket::SAMPLING_RATE_44100
);
186 TestEncodeDecode(1000, 3000, AudioPacket::SAMPLING_RATE_44100
);
187 TestEncodeDecode(5000, 3000, AudioPacket::SAMPLING_RATE_44100
);
190 } // namespace remoting