diff options
Diffstat (limited to 'dom/media/gtest/TestAudioPacketizer.cpp')
-rw-r--r-- | dom/media/gtest/TestAudioPacketizer.cpp | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/dom/media/gtest/TestAudioPacketizer.cpp b/dom/media/gtest/TestAudioPacketizer.cpp new file mode 100644 index 000000000..86615eb10 --- /dev/null +++ b/dom/media/gtest/TestAudioPacketizer.cpp @@ -0,0 +1,167 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include <stdint.h> +#include <math.h> +#include "../AudioPacketizer.h" +#include "gtest/gtest.h" + +using namespace mozilla; + +template<typename T> +class AutoBuffer +{ +public: + explicit AutoBuffer(size_t aLength) + { + mStorage = new T[aLength]; + } + ~AutoBuffer() { + delete [] mStorage; + } + T* Get() { + return mStorage; + } +private: + T* mStorage; +}; + +int16_t Sequence(int16_t* aBuffer, uint32_t aSize, uint32_t aStart = 0) +{ + uint32_t i; + for (i = 0; i < aSize; i++) { + aBuffer[i] = aStart + i; + } + return aStart + i; +} + +void IsSequence(int16_t* aBuffer, uint32_t aSize, uint32_t aStart = 0) +{ + for (uint32_t i = 0; i < aSize; i++) { + ASSERT_TRUE(aBuffer[i] == static_cast<int64_t>(aStart + i)) << + "Buffer is not a sequence at offset " << i << std::endl; + } + // Buffer is a sequence. +} + +void Zero(int16_t* aBuffer, uint32_t aSize) +{ + for (uint32_t i = 0; i < aSize; i++) { + ASSERT_TRUE(aBuffer[i] == 0) << + "Buffer is not null at offset " << i << std::endl; + } +} + +double sine(uint32_t aPhase) { + return sin(aPhase * 2 * M_PI * 440 / 44100); +} + +TEST(AudioPacketizer, Test) +{ + for (int16_t channels = 1; channels < 2; channels++) { + // Test that the packetizer returns zero on underrun + { + AudioPacketizer<int16_t, int16_t> ap(441, channels); + for (int16_t i = 0; i < 10; i++) { + int16_t* out = ap.Output(); + Zero(out, 441); + delete[] out; + } + } + // Simple test, with input/output buffer size aligned on the packet size, + // alternating Input and Output calls. + { + AudioPacketizer<int16_t, int16_t> ap(441, channels); + int16_t seqEnd = 0; + for (int16_t i = 0; i < 10; i++) { + AutoBuffer<int16_t> b(441 * channels); + int16_t prevEnd = seqEnd; + seqEnd = Sequence(b.Get(), channels * 441, prevEnd); + ap.Input(b.Get(), 441); + int16_t* out = ap.Output(); + IsSequence(out, 441 * channels, prevEnd); + delete[] out; + } + } + // Simple test, with input/output buffer size aligned on the packet size, + // alternating two Input and Output calls. + { + AudioPacketizer<int16_t, int16_t> ap(441, channels); + int16_t seqEnd = 0; + for (int16_t i = 0; i < 10; i++) { + AutoBuffer<int16_t> b(441 * channels); + AutoBuffer<int16_t> b1(441 * channels); + int16_t prevEnd0 = seqEnd; + seqEnd = Sequence(b.Get(), 441 * channels, prevEnd0); + int16_t prevEnd1 = seqEnd; + seqEnd = Sequence(b1.Get(), 441 * channels, seqEnd); + ap.Input(b.Get(), 441); + ap.Input(b1.Get(), 441); + int16_t* out = ap.Output(); + int16_t* out2 = ap.Output(); + IsSequence(out, 441 * channels, prevEnd0); + IsSequence(out2, 441 * channels, prevEnd1); + delete[] out; + delete[] out2; + } + } + // Input/output buffer size not aligned on the packet size, + // alternating two Input and Output calls. + { + AudioPacketizer<int16_t, int16_t> ap(441, channels); + int16_t prevEnd = 0; + int16_t prevSeq = 0; + for (int16_t i = 0; i < 10; i++) { + AutoBuffer<int16_t> b(480 * channels); + AutoBuffer<int16_t> b1(480 * channels); + prevSeq = Sequence(b.Get(), 480 * channels, prevSeq); + prevSeq = Sequence(b1.Get(), 480 * channels, prevSeq); + ap.Input(b.Get(), 480); + ap.Input(b1.Get(), 480); + int16_t* out = ap.Output(); + int16_t* out2 = ap.Output(); + IsSequence(out, 441 * channels, prevEnd); + prevEnd += 441 * channels; + IsSequence(out2, 441 * channels, prevEnd); + prevEnd += 441 * channels; + delete[] out; + delete[] out2; + } + printf("Available: %d\n", ap.PacketsAvailable()); + } + + // "Real-life" test case: streaming a sine wave through a packetizer, and + // checking that we have the right output. + // 128 is, for example, the size of a Web Audio API block, and 441 is the + // size of a webrtc.org packet when the sample rate is 44100 (10ms) + { + AudioPacketizer<int16_t, int16_t> ap(441, channels); + AutoBuffer<int16_t> b(128 * channels); + uint32_t phase = 0; + uint32_t outPhase = 0; + for (int16_t i = 0; i < 1000; i++) { + for (int32_t j = 0; j < 128; j++) { + for (int32_t c = 0; c < channels; c++) { + // int16_t sinewave at 440Hz/44100Hz sample rate + b.Get()[j * channels + c] = (2 << 14) * sine(phase); + } + phase++; + } + ap.Input(b.Get(), 128); + while (ap.PacketsAvailable()) { + int16_t* packet = ap.Output(); + for (uint32_t k = 0; k < ap.PacketSize(); k++) { + for (int32_t c = 0; c < channels; c++) { + ASSERT_TRUE(packet[k * channels + c] == + static_cast<int16_t>(((2 << 14) * sine(outPhase)))); + } + outPhase++; + } + delete [] packet; + } + } + } + } +} |