| /* | |
| * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. | |
| * | |
| * Use of this source code is governed by a BSD-style license | |
| * that can be found in the LICENSE file in the root of the source | |
| * tree. An additional intellectual property rights grant can be found | |
| * in the file PATENTS. All contributing project authors may | |
| * be found in the AUTHORS file in the root of the source tree. | |
| */ | |
| #include "modules/audio_processing/agc2/rnn_vad/sequence_buffer.h" | |
| #include <algorithm> | |
| #include <array> | |
| #include <cstdint> | |
| #include "test/gtest.h" | |
| namespace webrtc { | |
| namespace rnn_vad { | |
| namespace { | |
| template <typename T, int S, int N> | |
| void TestSequenceBufferPushOp() { | |
| SCOPED_TRACE(S); | |
| SCOPED_TRACE(N); | |
| SequenceBuffer<T, S, N> seq_buf; | |
| auto seq_buf_view = seq_buf.GetBufferView(); | |
| std::array<T, N> chunk; | |
| // Check that a chunk is fully gone after ceil(S / N) push ops. | |
| chunk.fill(1); | |
| seq_buf.Push(chunk); | |
| chunk.fill(0); | |
| constexpr int required_push_ops = (S % N) ? S / N + 1 : S / N; | |
| for (int i = 0; i < required_push_ops - 1; ++i) { | |
| SCOPED_TRACE(i); | |
| seq_buf.Push(chunk); | |
| // Still in the buffer. | |
| auto m = std::max_element(seq_buf_view.begin(), seq_buf_view.end()); | |
| EXPECT_EQ(1, *m); | |
| } | |
| // Gone after another push. | |
| seq_buf.Push(chunk); | |
| auto m = std::max_element(seq_buf_view.begin(), seq_buf_view.end()); | |
| EXPECT_EQ(0, *m); | |
| // Check that the last item moves left by N positions after a push op. | |
| if (S > N) { | |
| // Fill in with non-zero values. | |
| for (int i = 0; i < N; ++i) | |
| chunk[i] = static_cast<T>(i + 1); | |
| seq_buf.Push(chunk); | |
| // With the next Push(), `last` will be moved left by N positions. | |
| const T last = chunk[N - 1]; | |
| for (int i = 0; i < N; ++i) | |
| chunk[i] = static_cast<T>(last + i + 1); | |
| seq_buf.Push(chunk); | |
| EXPECT_EQ(last, seq_buf_view[S - N - 1]); | |
| } | |
| } | |
| TEST(RnnVadTest, SequenceBufferGetters) { | |
| constexpr int buffer_size = 8; | |
| constexpr int chunk_size = 8; | |
| SequenceBuffer<int, buffer_size, chunk_size> seq_buf; | |
| EXPECT_EQ(buffer_size, seq_buf.size()); | |
| EXPECT_EQ(chunk_size, seq_buf.chunks_size()); | |
| // Test view. | |
| auto seq_buf_view = seq_buf.GetBufferView(); | |
| EXPECT_EQ(0, seq_buf_view[0]); | |
| EXPECT_EQ(0, seq_buf_view[seq_buf_view.size() - 1]); | |
| constexpr std::array<int, chunk_size> chunk = {10, 20, 30, 40, | |
| 50, 60, 70, 80}; | |
| seq_buf.Push(chunk); | |
| EXPECT_EQ(10, *seq_buf_view.begin()); | |
| EXPECT_EQ(80, *(seq_buf_view.end() - 1)); | |
| } | |
| TEST(RnnVadTest, SequenceBufferPushOpsUnsigned) { | |
| TestSequenceBufferPushOp<uint8_t, 32, 8>(); // Chunk size: 25%. | |
| TestSequenceBufferPushOp<uint8_t, 32, 16>(); // Chunk size: 50%. | |
| TestSequenceBufferPushOp<uint8_t, 32, 32>(); // Chunk size: 100%. | |
| TestSequenceBufferPushOp<uint8_t, 23, 7>(); // Non-integer ratio. | |
| } | |
| TEST(RnnVadTest, SequenceBufferPushOpsSigned) { | |
| TestSequenceBufferPushOp<int, 32, 8>(); // Chunk size: 25%. | |
| TestSequenceBufferPushOp<int, 32, 16>(); // Chunk size: 50%. | |
| TestSequenceBufferPushOp<int, 32, 32>(); // Chunk size: 100%. | |
| TestSequenceBufferPushOp<int, 23, 7>(); // Non-integer ratio. | |
| } | |
| TEST(RnnVadTest, SequenceBufferPushOpsFloating) { | |
| TestSequenceBufferPushOp<float, 32, 8>(); // Chunk size: 25%. | |
| TestSequenceBufferPushOp<float, 32, 16>(); // Chunk size: 50%. | |
| TestSequenceBufferPushOp<float, 32, 32>(); // Chunk size: 100%. | |
| TestSequenceBufferPushOp<float, 23, 7>(); // Non-integer ratio. | |
| } | |
| } // namespace | |
| } // namespace rnn_vad | |
| } // namespace webrtc |