Home | History | Annotate | Download | only in codec
      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