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 }