tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

cng_unittest.cc (8398B)


      1 /*
      2 *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
      3 *
      4 *  Use of this source code is governed by a BSD-style license
      5 *  that can be found in the LICENSE file in the root of the source
      6 *  tree. An additional intellectual property rights grant can be found
      7 *  in the file PATENTS.  All contributing project authors may
      8 *  be found in the AUTHORS file in the root of the source tree.
      9 */
     10 #include <cstddef>
     11 #include <cstdint>
     12 #include <cstdio>
     13 #include <string>
     14 
     15 #include "api/array_view.h"
     16 #include "modules/audio_coding/codecs/cng/webrtc_cng.h"
     17 #include "rtc_base/buffer.h"
     18 #include "rtc_base/checks.h"
     19 #include "test/gtest.h"
     20 #include "test/testsupport/file_utils.h"
     21 
     22 namespace webrtc {
     23 
     24 enum {
     25  kSidShortIntervalUpdate = 1,
     26  kSidNormalIntervalUpdate = 100,
     27  kSidLongIntervalUpdate = 10000
     28 };
     29 
     30 enum : size_t {
     31  kCNGNumParamsLow = 0,
     32  kCNGNumParamsNormal = 8,
     33  kCNGNumParamsHigh = WEBRTC_CNG_MAX_LPC_ORDER,
     34  kCNGNumParamsTooHigh = WEBRTC_CNG_MAX_LPC_ORDER + 1
     35 };
     36 
     37 enum { kNoSid, kForceSid };
     38 
     39 class CngTest : public ::testing::Test {
     40 protected:
     41  void SetUp() override;
     42 
     43  void TestCngEncode(int sample_rate_hz, int quality);
     44 
     45  int16_t speech_data_[640];  // Max size of CNG internal buffers.
     46 };
     47 
     48 class CngDeathTest : public CngTest {};
     49 
     50 void CngTest::SetUp() {
     51  FILE* input_file;
     52  const std::string file_name =
     53      test::ResourcePath("audio_coding/testfile32kHz", "pcm");
     54  input_file = fopen(file_name.c_str(), "rb");
     55  ASSERT_TRUE(input_file != nullptr);
     56  ASSERT_EQ(640, static_cast<int32_t>(
     57                     fread(speech_data_, sizeof(int16_t), 640, input_file)));
     58  fclose(input_file);
     59  input_file = nullptr;
     60 }
     61 
     62 void CngTest::TestCngEncode(int sample_rate_hz, int quality) {
     63  const size_t num_samples_10ms = CheckedDivExact(sample_rate_hz, 100);
     64  Buffer sid_data;
     65 
     66  ComfortNoiseEncoder cng_encoder(sample_rate_hz, kSidNormalIntervalUpdate,
     67                                  quality);
     68  EXPECT_EQ(0U, cng_encoder.Encode(
     69                    ArrayView<const int16_t>(speech_data_, num_samples_10ms),
     70                    kNoSid, &sid_data));
     71  EXPECT_EQ(static_cast<size_t>(quality + 1),
     72            cng_encoder.Encode(
     73                ArrayView<const int16_t>(speech_data_, num_samples_10ms),
     74                kForceSid, &sid_data));
     75 }
     76 
     77 #if GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
     78 // Create CNG encoder, init with faulty values, free CNG encoder.
     79 TEST_F(CngDeathTest, CngInitFail) {
     80  // Call with too few parameters.
     81  EXPECT_DEATH(
     82      {
     83        ComfortNoiseEncoder(8000, kSidNormalIntervalUpdate, kCNGNumParamsLow);
     84      },
     85      "");
     86  // Call with too many parameters.
     87  EXPECT_DEATH(
     88      {
     89        ComfortNoiseEncoder(8000, kSidNormalIntervalUpdate,
     90                            kCNGNumParamsTooHigh);
     91      },
     92      "");
     93 }
     94 
     95 // Encode Cng with too long input vector.
     96 TEST_F(CngDeathTest, CngEncodeTooLong) {
     97  Buffer sid_data;
     98 
     99  // Create encoder.
    100  ComfortNoiseEncoder cng_encoder(8000, kSidNormalIntervalUpdate,
    101                                  kCNGNumParamsNormal);
    102  // Run encoder with too much data.
    103  EXPECT_DEATH(cng_encoder.Encode(ArrayView<const int16_t>(speech_data_, 641),
    104                                  kNoSid, &sid_data),
    105               "");
    106 }
    107 #endif  // GTEST_HAS_DEATH_TEST && !defined(WEBRTC_ANDROID)
    108 
    109 TEST_F(CngTest, CngEncode8000) {
    110  TestCngEncode(8000, kCNGNumParamsNormal);
    111 }
    112 
    113 TEST_F(CngTest, CngEncode16000) {
    114  TestCngEncode(16000, kCNGNumParamsNormal);
    115 }
    116 
    117 TEST_F(CngTest, CngEncode32000) {
    118  TestCngEncode(32000, kCNGNumParamsHigh);
    119 }
    120 
    121 TEST_F(CngTest, CngEncode48000) {
    122  TestCngEncode(48000, kCNGNumParamsNormal);
    123 }
    124 
    125 TEST_F(CngTest, CngEncode64000) {
    126  TestCngEncode(64000, kCNGNumParamsNormal);
    127 }
    128 
    129 // Update SID parameters, for both 9 and 16 parameters.
    130 TEST_F(CngTest, CngUpdateSid) {
    131  Buffer sid_data;
    132 
    133  // Create and initialize encoder and decoder.
    134  ComfortNoiseEncoder cng_encoder(16000, kSidNormalIntervalUpdate,
    135                                  kCNGNumParamsNormal);
    136  ComfortNoiseDecoder cng_decoder;
    137 
    138  // Run normal Encode and UpdateSid.
    139  EXPECT_EQ(kCNGNumParamsNormal + 1,
    140            cng_encoder.Encode(ArrayView<const int16_t>(speech_data_, 160),
    141                               kForceSid, &sid_data));
    142  cng_decoder.UpdateSid(sid_data);
    143 
    144  // Reinit with new length.
    145  cng_encoder.Reset(16000, kSidNormalIntervalUpdate, kCNGNumParamsHigh);
    146  cng_decoder.Reset();
    147 
    148  // Expect 0 because of unstable parameters after switching length.
    149  EXPECT_EQ(0U, cng_encoder.Encode(ArrayView<const int16_t>(speech_data_, 160),
    150                                   kForceSid, &sid_data));
    151  EXPECT_EQ(
    152      kCNGNumParamsHigh + 1,
    153      cng_encoder.Encode(ArrayView<const int16_t>(speech_data_ + 160, 160),
    154                         kForceSid, &sid_data));
    155  cng_decoder.UpdateSid(
    156      ArrayView<const uint8_t>(sid_data.data(), kCNGNumParamsNormal + 1));
    157 }
    158 
    159 // Update SID parameters, with wrong parameters or without calling decode.
    160 TEST_F(CngTest, CngUpdateSidErroneous) {
    161  Buffer sid_data;
    162 
    163  // Encode.
    164  ComfortNoiseEncoder cng_encoder(16000, kSidNormalIntervalUpdate,
    165                                  kCNGNumParamsNormal);
    166  ComfortNoiseDecoder cng_decoder;
    167  EXPECT_EQ(kCNGNumParamsNormal + 1,
    168            cng_encoder.Encode(ArrayView<const int16_t>(speech_data_, 160),
    169                               kForceSid, &sid_data));
    170 
    171  // First run with valid parameters, then with too many CNG parameters.
    172  // The function will operate correctly by only reading the maximum number of
    173  // parameters, skipping the extra.
    174  EXPECT_EQ(kCNGNumParamsNormal + 1, sid_data.size());
    175  cng_decoder.UpdateSid(sid_data);
    176 
    177  // Make sure the input buffer is large enough. Since Encode() appends data, we
    178  // need to set the size manually only afterwards, or the buffer will be bigger
    179  // than anticipated.
    180  sid_data.SetSize(kCNGNumParamsTooHigh + 1);
    181  cng_decoder.UpdateSid(sid_data);
    182 }
    183 
    184 // Test to generate cng data, by forcing SID. Both normal and faulty condition.
    185 TEST_F(CngTest, CngGenerate) {
    186  Buffer sid_data;
    187  int16_t out_data[640];
    188 
    189  // Create and initialize encoder and decoder.
    190  ComfortNoiseEncoder cng_encoder(16000, kSidNormalIntervalUpdate,
    191                                  kCNGNumParamsNormal);
    192  ComfortNoiseDecoder cng_decoder;
    193 
    194  // Normal Encode.
    195  EXPECT_EQ(kCNGNumParamsNormal + 1,
    196            cng_encoder.Encode(ArrayView<const int16_t>(speech_data_, 160),
    197                               kForceSid, &sid_data));
    198 
    199  // Normal UpdateSid.
    200  cng_decoder.UpdateSid(sid_data);
    201 
    202  // Two normal Generate, one with new_period.
    203  EXPECT_TRUE(cng_decoder.Generate(ArrayView<int16_t>(out_data, 640), 1));
    204  EXPECT_TRUE(cng_decoder.Generate(ArrayView<int16_t>(out_data, 640), 0));
    205 
    206  // Call Genereate with too much data.
    207  EXPECT_FALSE(cng_decoder.Generate(ArrayView<int16_t>(out_data, 641), 0));
    208 }
    209 
    210 // Test automatic SID.
    211 TEST_F(CngTest, CngAutoSid) {
    212  Buffer sid_data;
    213 
    214  // Create and initialize encoder and decoder.
    215  ComfortNoiseEncoder cng_encoder(16000, kSidNormalIntervalUpdate,
    216                                  kCNGNumParamsNormal);
    217  ComfortNoiseDecoder cng_decoder;
    218 
    219  // Normal Encode, 100 msec, where no SID data should be generated.
    220  for (int i = 0; i < 10; i++) {
    221    EXPECT_EQ(0U,
    222              cng_encoder.Encode(ArrayView<const int16_t>(speech_data_, 160),
    223                                 kNoSid, &sid_data));
    224  }
    225 
    226  // We have reached 100 msec, and SID data should be generated.
    227  EXPECT_EQ(kCNGNumParamsNormal + 1,
    228            cng_encoder.Encode(ArrayView<const int16_t>(speech_data_, 160),
    229                               kNoSid, &sid_data));
    230 }
    231 
    232 // Test automatic SID, with very short interval.
    233 TEST_F(CngTest, CngAutoSidShort) {
    234  Buffer sid_data;
    235 
    236  // Create and initialize encoder and decoder.
    237  ComfortNoiseEncoder cng_encoder(16000, kSidShortIntervalUpdate,
    238                                  kCNGNumParamsNormal);
    239  ComfortNoiseDecoder cng_decoder;
    240 
    241  // First call will never generate SID, unless forced to.
    242  EXPECT_EQ(0U, cng_encoder.Encode(ArrayView<const int16_t>(speech_data_, 160),
    243                                   kNoSid, &sid_data));
    244 
    245  // Normal Encode, 100 msec, SID data should be generated all the time.
    246  for (int i = 0; i < 10; i++) {
    247    EXPECT_EQ(kCNGNumParamsNormal + 1,
    248              cng_encoder.Encode(ArrayView<const int16_t>(speech_data_, 160),
    249                                 kNoSid, &sid_data));
    250  }
    251 }
    252 
    253 }  // namespace webrtc