OLD | NEW |
(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 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 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 |
OLD | NEW |