15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MSVC++ requires this to get M_PI. 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define _USE_MATH_DEFINES 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <math.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/codec/audio_encoder_opus.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/codec/audio_decoder_opus.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting { 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Maximum value that can be encoded in a 16-bit signed sample. 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMaxSampleValue = 32767; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kChannels = 2; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Phase shift between left and right channels. 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const double kChannelPhaseShift = 2 * M_PI / 3; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The sampling rate that OPUS uses internally and that we expect to get 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// from the decoder. 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const AudioPacket_SamplingRate kDefaultSamplingRate = 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioPacket::SAMPLING_RATE_48000; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Maximum latency expected from the encoder. 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMaxLatencyMs = 40; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// When verifying results ignore the first 1k samples. This is necessary because 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it takes some time for the codec to adjust for the input signal. 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kSkippedFirstSamples = 1000; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Maximum standard deviation of the difference between original and decoded 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// signals as a proportion of kMaxSampleValue. For two unrelated signals this 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// difference will be close to 1.0, even for signals that differ only slightly. 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The value is chosen such that all the tests pass normally, but fail with 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// small changes (e.g. one sample shift between signals). 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const double kMaxSignalDeviation = 0.1; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class OpusAudioEncoderTest : public testing::Test { 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Return test signal value at the specified position |pos|. |frequency_hz| 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // defines frequency of the signal. |channel| is used to calculate phase shift 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of the signal, so that different signals are generated for left and right 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // channels. 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int16 GetSampleValue( 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioPacket::SamplingRate rate, 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double frequency_hz, 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double pos, 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int channel) { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double angle = pos * 2 * M_PI * frequency_hz / rate + 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kChannelPhaseShift * channel; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<int>(sin(angle) * kMaxSampleValue + 0.5); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Creates audio packet filled with a test signal with the specified 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |frequency_hz|. 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<AudioPacket> CreatePacket( 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int samples, 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioPacket::SamplingRate rate, 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double frequency_hz, 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int pos) { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int16> data(samples * kChannels); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < samples; ++i) { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data[i * kChannels] = GetSampleValue(rate, frequency_hz, i + pos, 0); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data[i * kChannels + 1] = GetSampleValue(rate, frequency_hz, i + pos, 1); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<AudioPacket> packet(new AudioPacket()); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) packet->add_data(reinterpret_cast<char*>(&(data[0])), 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) samples * kChannels * sizeof(int16)); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) packet->set_encoding(AudioPacket::ENCODING_RAW); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) packet->set_sampling_rate(rate); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) packet->set_bytes_per_sample(AudioPacket::BYTES_PER_SAMPLE_2); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) packet->set_channels(AudioPacket::CHANNELS_STEREO); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return packet.Pass(); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Decoded data is normally shifted in phase relative to the original signal. 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This function returns the approximate shift in samples by finding the first 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // point when signal goes from negative to positive. 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double EstimateSignalShift(const std::vector<int16>& received_data) { 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = kSkippedFirstSamples; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i < received_data.size() / kChannels - 1; i++) { 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int16 this_sample = received_data[i * kChannels]; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int16 next_sample = received_data[(i + 1) * kChannels]; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (this_sample < 0 && next_sample > 0) { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i + static_cast<double>(-this_sample) / (next_sample - this_sample); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Compares decoded signal with the test signal that was encoded. It estimates 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // phase shift from the original signal, then calculates standard deviation of 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the difference between original and decoded signals. 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ValidateReceivedData(int samples, 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioPacket::SamplingRate rate, 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double frequency_hz, 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<int16>& received_data) { 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double shift = EstimateSignalShift(received_data); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double diff_sqare_sum = 0; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = kSkippedFirstSamples; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i < received_data.size() / kChannels; i++) { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double d = received_data[i * kChannels] - 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetSampleValue(rate, frequency_hz, i - shift, 0); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) diff_sqare_sum += d * d; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) d = received_data[i * kChannels + 1] - 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetSampleValue(rate, frequency_hz, i - shift, 1); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) diff_sqare_sum += d * d; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double deviation = sqrt(diff_sqare_sum / received_data.size()) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) / kMaxSampleValue; 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LOG(ERROR) << "Decoded signal deviation: " << deviation; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_LE(deviation, kMaxSignalDeviation); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void TestEncodeDecode(int packet_size, 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double frequency_hz, 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AudioPacket::SamplingRate rate) { 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kTotalTestSamples = 24000; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoder_.reset(new AudioEncoderOpus()); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) decoder_.reset(new AudioDecoderOpus()); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<int16> received_data; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int pos = 0; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (; pos < kTotalTestSamples; pos += packet_size) { 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<AudioPacket> source_packet = 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreatePacket(packet_size, rate, frequency_hz, pos); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<AudioPacket> encoded = 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) encoder_->Encode(source_packet.Pass()); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (encoded.get()) { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<AudioPacket> decoded = decoder_->Decode(encoded.Pass()); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(kDefaultSamplingRate, decoded->sampling_rate()); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < decoded->data_size(); ++i) { 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int16* data = 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const int16*>(decoded->data(i).data()); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) received_data.insert( 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) received_data.end(), data, 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data + decoded->data(i).size() / sizeof(int16)); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Verify that at most kMaxLatencyMs worth of samples is buffered inside 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |encoder_| and |decoder_|. 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_GE(static_cast<int>(received_data.size()) / kChannels, 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pos - rate * kMaxLatencyMs / 1000); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ValidateReceivedData(packet_size, kDefaultSamplingRate, 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frequency_hz, received_data); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<AudioEncoderOpus> encoder_; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<AudioDecoderOpus> decoder_; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(OpusAudioEncoderTest, CreateAndDestroy) { 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(OpusAudioEncoderTest, NoResampling) { 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestEncodeDecode(2000, 50, AudioPacket::SAMPLING_RATE_48000); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestEncodeDecode(2000, 3000, AudioPacket::SAMPLING_RATE_48000); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestEncodeDecode(2000, 10000, AudioPacket::SAMPLING_RATE_48000); 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(OpusAudioEncoderTest, Resampling) { 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestEncodeDecode(2000, 50, AudioPacket::SAMPLING_RATE_44100); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestEncodeDecode(2000, 3000, AudioPacket::SAMPLING_RATE_44100); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestEncodeDecode(2000, 10000, AudioPacket::SAMPLING_RATE_44100); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(OpusAudioEncoderTest, BufferSizeAndResampling) { 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestEncodeDecode(500, 3000, AudioPacket::SAMPLING_RATE_44100); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestEncodeDecode(1000, 3000, AudioPacket::SAMPLING_RATE_44100); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestEncodeDecode(5000, 3000, AudioPacket::SAMPLING_RATE_44100); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace remoting 191