1 /* 2 * Copyright (c) 2018 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 11 #ifndef MODULES_AUDIO_PROCESSING_AGC2_RNN_VAD_SYMMETRIC_MATRIX_BUFFER_H_ 12 #define MODULES_AUDIO_PROCESSING_AGC2_RNN_VAD_SYMMETRIC_MATRIX_BUFFER_H_ 13 14 #include <algorithm> 15 #include <array> 16 #include <cstring> 17 #include <utility> 18 19 #include "api/array_view.h" 20 #include "rtc_base/checks.h" 21 22 namespace webrtc { 23 namespace rnn_vad { 24 25 // Data structure to buffer the results of pair-wise comparisons between items 26 // stored in a ring buffer. Every time that the oldest item is replaced in the 27 // ring buffer, the new one is compared to the remaining items in the ring 28 // buffer. The results of such comparisons need to be buffered and automatically 29 // removed when one of the two corresponding items that have been compared is 30 // removed from the ring buffer. It is assumed that the comparison is symmetric 31 // and that comparing an item with itself is not needed. 32 template <typename T, size_t S> 33 class SymmetricMatrixBuffer { 34 static_assert(S > 2, ""); 35 36 public: 37 SymmetricMatrixBuffer() = default; 38 SymmetricMatrixBuffer(const SymmetricMatrixBuffer&) = delete; 39 SymmetricMatrixBuffer& operator=(const SymmetricMatrixBuffer&) = delete; 40 ~SymmetricMatrixBuffer() = default; 41 // Sets the buffer values to zero. Reset()42 void Reset() { 43 static_assert(std::is_arithmetic<T>::value, 44 "Integral or floating point required."); 45 buf_.fill(0); 46 } 47 // Pushes the results from the comparison between the most recent item and 48 // those that are still in the ring buffer. The first element in |values| must 49 // correspond to the comparison between the most recent item and the second 50 // most recent one in the ring buffer, whereas the last element in |values| 51 // must correspond to the comparison between the most recent item and the 52 // oldest one in the ring buffer. Push(rtc::ArrayView<T,S-1> values)53 void Push(rtc::ArrayView<T, S - 1> values) { 54 // Move the lower-right sub-matrix of size (S-2) x (S-2) one row up and one 55 // column left. 56 std::memmove(buf_.data(), buf_.data() + S, (buf_.size() - S) * sizeof(T)); 57 // Copy new values in the last column in the right order. 58 for (size_t i = 0; i < values.size(); ++i) { 59 const size_t index = (S - 1 - i) * (S - 1) - 1; 60 RTC_DCHECK_LE(static_cast<size_t>(0), index); 61 RTC_DCHECK_LT(index, buf_.size()); 62 buf_[index] = values[i]; 63 } 64 } 65 // Reads the value that corresponds to comparison of two items in the ring 66 // buffer having delay |delay1| and |delay2|. The two arguments must not be 67 // equal and both must be in {0, ..., S - 1}. GetValue(size_t delay1,size_t delay2)68 T GetValue(size_t delay1, size_t delay2) const { 69 int row = S - 1 - static_cast<int>(delay1); 70 int col = S - 1 - static_cast<int>(delay2); 71 RTC_DCHECK_NE(row, col) << "The diagonal cannot be accessed."; 72 if (row > col) 73 std::swap(row, col); // Swap to access the upper-right triangular part. 74 RTC_DCHECK_LE(0, row); 75 RTC_DCHECK_LT(row, S - 1) << "Not enforcing row < col and row != col."; 76 RTC_DCHECK_LE(1, col) << "Not enforcing row < col and row != col."; 77 RTC_DCHECK_LT(col, S); 78 const int index = row * (S - 1) + (col - 1); 79 RTC_DCHECK_LE(0, index); 80 RTC_DCHECK_LT(index, buf_.size()); 81 return buf_[index]; 82 } 83 84 private: 85 // Encode an upper-right triangular matrix (excluding its diagonal) using a 86 // square matrix. This allows to move the data in Push() with one single 87 // operation. 88 std::array<T, (S - 1) * (S - 1)> buf_{}; 89 }; 90 91 } // namespace rnn_vad 92 } // namespace webrtc 93 94 #endif // MODULES_AUDIO_PROCESSING_AGC2_RNN_VAD_SYMMETRIC_MATRIX_BUFFER_H_ 95