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