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 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; 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 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) { 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 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, 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 LOG(ERROR) << "Decoded signal deviation: " << deviation; 124 EXPECT_LE(deviation, kMaxSignalDeviation); 125 } 126 127 void TestEncodeDecode(int packet_size, 128 double frequency_hz, 129 AudioPacket::SamplingRate rate) { 130 const int kTotalTestSamples = 24000; 131 132 encoder_.reset(new AudioEncoderOpus()); 133 decoder_.reset(new AudioDecoderOpus()); 134 135 std::vector<int16> received_data; 136 int pos = 0; 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()); 142 if (encoded.get()) { 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) { 146 const int16* data = 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)); 151 } 152 } 153 } 154 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); 159 160 ValidateReceivedData(packet_size, kDefaultSamplingRate, 161 frequency_hz, received_data); 162 } 163 164 protected: 165 scoped_ptr<AudioEncoderOpus> encoder_; 166 scoped_ptr<AudioDecoderOpus> decoder_; 167 }; 168 169 TEST_F(OpusAudioEncoderTest, CreateAndDestroy) { 170 } 171 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); 176 } 177 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); 182 } 183 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); 188 } 189 190 } // namespace remoting 191