tor-browser

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

TestAudioPacketizer.cpp (6897B)


      1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include <math.h>
      8 #include <stdint.h>
      9 
     10 #include <memory>
     11 
     12 #include "../AudioPacketizer.h"
     13 #include "../TimedPacketizer.h"
     14 #include "gtest/gtest.h"
     15 
     16 using namespace mozilla;
     17 
     18 template <typename T>
     19 class AutoBuffer {
     20 public:
     21  explicit AutoBuffer(size_t aLength) { mStorage = new T[aLength]; }
     22  ~AutoBuffer() { delete[] mStorage; }
     23  T* Get() { return mStorage; }
     24 
     25 private:
     26  T* mStorage;
     27 };
     28 
     29 int16_t Sequence(int16_t* aBuffer, uint32_t aSize, uint32_t aStart = 0) {
     30  uint32_t i;
     31  for (i = 0; i < aSize; i++) {
     32    aBuffer[i] = (aStart + i) % INT16_MAX;
     33  }
     34  return aStart + i;
     35 }
     36 
     37 void IsSequence(int16_t* aBuffer, uint32_t aSize, uint32_t aStart = 0) {
     38  for (uint32_t i = 0; i < aSize; i++) {
     39    ASSERT_EQ(aBuffer[i], static_cast<int64_t>((aStart + i) % INT16_MAX))
     40        << "Buffer is not a sequence at offset " << i << '\n';
     41  }
     42  // Buffer is a sequence.
     43 }
     44 
     45 void Zero(std::unique_ptr<int16_t[]> aBuffer, uint32_t aSize) {
     46  for (uint32_t i = 0; i < aSize; i++) {
     47    ASSERT_TRUE(aBuffer[i] == 0)
     48    << "Buffer is not null at offset " << i << '\n';
     49  }
     50 }
     51 
     52 double sine(uint32_t aPhase) { return sin(aPhase * 2 * M_PI * 440 / 44100); }
     53 
     54 TEST(AudioPacketizer, Test)
     55 {
     56  for (int16_t channels = 1; channels < 2; channels++) {
     57    // Test that the packetizer returns zero on underrun
     58    {
     59      AudioPacketizer<int16_t, int16_t> ap(441, channels);
     60      for (int16_t i = 0; i < 10; i++) {
     61        std::unique_ptr<int16_t[]> out(ap.Output());
     62        Zero(std::move(out), 441);
     63      }
     64    }
     65    // Simple test, with input/output buffer size aligned on the packet size,
     66    // alternating Input and Output calls.
     67    {
     68      AudioPacketizer<int16_t, int16_t> ap(441, channels);
     69      int16_t seqEnd = 0;
     70      for (int16_t i = 0; i < 10; i++) {
     71        AutoBuffer<int16_t> b(441 * channels);
     72        int16_t prevEnd = seqEnd;
     73        seqEnd = Sequence(b.Get(), channels * 441, prevEnd);
     74        ap.Input(b.Get(), 441);
     75        std::unique_ptr<int16_t[]> out(ap.Output());
     76        IsSequence(out.get(), 441 * channels, prevEnd);
     77      }
     78    }
     79    // Simple test, with input/output buffer size aligned on the packet size,
     80    // alternating two Input and Output calls.
     81    {
     82      AudioPacketizer<int16_t, int16_t> ap(441, channels);
     83      int16_t seqEnd = 0;
     84      for (int16_t i = 0; i < 10; i++) {
     85        AutoBuffer<int16_t> b(441 * channels);
     86        AutoBuffer<int16_t> b1(441 * channels);
     87        int16_t prevEnd0 = seqEnd;
     88        seqEnd = Sequence(b.Get(), 441 * channels, prevEnd0);
     89        int16_t prevEnd1 = seqEnd;
     90        seqEnd = Sequence(b1.Get(), 441 * channels, seqEnd);
     91        ap.Input(b.Get(), 441);
     92        ap.Input(b1.Get(), 441);
     93        std::unique_ptr<int16_t[]> out(ap.Output());
     94        std::unique_ptr<int16_t[]> out2(ap.Output());
     95        IsSequence(out.get(), 441 * channels, prevEnd0);
     96        IsSequence(out2.get(), 441 * channels, prevEnd1);
     97      }
     98    }
     99    // Input/output buffer size not aligned on the packet size,
    100    // alternating two Input and Output calls.
    101    {
    102      AudioPacketizer<int16_t, int16_t> ap(441, channels);
    103      int16_t prevEnd = 0;
    104      int16_t prevSeq = 0;
    105      for (int16_t i = 0; i < 10; i++) {
    106        AutoBuffer<int16_t> b(480 * channels);
    107        AutoBuffer<int16_t> b1(480 * channels);
    108        prevSeq = Sequence(b.Get(), 480 * channels, prevSeq);
    109        prevSeq = Sequence(b1.Get(), 480 * channels, prevSeq);
    110        ap.Input(b.Get(), 480);
    111        ap.Input(b1.Get(), 480);
    112        std::unique_ptr<int16_t[]> out(ap.Output());
    113        std::unique_ptr<int16_t[]> out2(ap.Output());
    114        IsSequence(out.get(), 441 * channels, prevEnd);
    115        prevEnd += 441 * channels;
    116        IsSequence(out2.get(), 441 * channels, prevEnd);
    117        prevEnd += 441 * channels;
    118      }
    119      printf("Available: %d\n", ap.PacketsAvailable());
    120    }
    121 
    122    // "Real-life" test case: streaming a sine wave through a packetizer, and
    123    // checking that we have the right output.
    124    // 128 is, for example, the size of a Web Audio API block, and 441 is the
    125    // size of a webrtc.org packet when the sample rate is 44100 (10ms)
    126    {
    127      AudioPacketizer<int16_t, int16_t> ap(441, channels);
    128      AutoBuffer<int16_t> b(128 * channels);
    129      uint32_t phase = 0;
    130      uint32_t outPhase = 0;
    131      for (int16_t i = 0; i < 1000; i++) {
    132        for (int32_t j = 0; j < 128; j++) {
    133          for (int32_t c = 0; c < channels; c++) {
    134            // int16_t sinewave at 440Hz/44100Hz sample rate
    135            b.Get()[j * channels + c] = (2 << 14) * sine(phase);
    136          }
    137          phase++;
    138        }
    139        ap.Input(b.Get(), 128);
    140        while (ap.PacketsAvailable()) {
    141          std::unique_ptr<int16_t[]> packet(ap.Output());
    142          for (uint32_t k = 0; k < ap.mPacketSize; k++) {
    143            for (int32_t c = 0; c < channels; c++) {
    144              ASSERT_TRUE(packet[k * channels + c] ==
    145                          static_cast<int16_t>(((2 << 14) * sine(outPhase))));
    146            }
    147            outPhase++;
    148          }
    149        }
    150      }
    151    }
    152    // Test that clearing the packetizer empties it and starts returning zeros.
    153    {
    154      AudioPacketizer<int16_t, int16_t> ap(441, channels);
    155      AutoBuffer<int16_t> b(440 * channels);
    156      Sequence(b.Get(), 440 * channels);
    157      ap.Input(b.Get(), 440);
    158      EXPECT_EQ(ap.FramesAvailable(), 440U);
    159      ap.Clear();
    160      EXPECT_EQ(ap.FramesAvailable(), 0U);
    161      EXPECT_TRUE(ap.Empty());
    162      std::unique_ptr<int16_t[]> out(ap.Output());
    163      Zero(std::move(out), 441);
    164    }
    165  }
    166 }
    167 
    168 TEST(TimedPacketizer, Test)
    169 {
    170  const int channels = 2;
    171  const int64_t rate = 48000;
    172  const int64_t inputPacketSize = 240;
    173  const int64_t packetSize = 96;
    174  TimedPacketizer<int16_t, int16_t> tp(packetSize, channels, 0, rate);
    175  int16_t prevEnd = 0;
    176  int16_t prevSeq = 0;
    177  nsTArray<int16_t> packet;
    178  uint64_t tsCheck = 0;
    179  packet.SetLength(tp.PacketSize() * channels);
    180  for (int16_t i = 0; i < 10; i++) {
    181    AutoBuffer<int16_t> b(inputPacketSize * channels);
    182    prevSeq = Sequence(b.Get(), inputPacketSize * channels, prevSeq);
    183    tp.Input(b.Get(), inputPacketSize);
    184    while (tp.PacketsAvailable()) {
    185      media::TimeUnit ts = tp.Output(packet.Elements());
    186      IsSequence(packet.Elements(), packetSize * channels, prevEnd);
    187      EXPECT_EQ(ts, media::TimeUnit(tsCheck, rate));
    188      prevEnd += packetSize * channels;
    189      tsCheck += packetSize;
    190    }
    191  }
    192  EXPECT_TRUE(!tp.PacketsAvailable());
    193  uint32_t drained;
    194  media::TimeUnit ts = tp.Drain(packet.Elements(), drained);
    195  EXPECT_EQ(ts, media::TimeUnit(tsCheck, rate));
    196  EXPECT_LE(drained, packetSize);
    197 }