blob: cbf7bb754de2dbc8e04e83f6629e4819617c504a [file] [log] [blame]
alexander3c798932021-03-26 21:42:19 +00001/*
2 * Copyright (c) 2021 Arm Limited. All rights reserved.
3 * SPDX-License-Identifier: Apache-2.0
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17#ifndef AUDIO_UTILS_HPP
18#define AUDIO_UTILS_HPP
19
20#include <cstddef>
21#include <cstdint>
22
23namespace arm {
24namespace app {
25namespace audio {
26
27 template<class T>
28 class SlidingWindow {
29 public:
30
31 /**
32 * @brief Creates the window slider through the given data.
33 *
34 * @param[in] data Pointer to the data to slide through.
35 * @param[in] dataSize Size in T type elements wise.
36 * @param[in] windowSize Sliding window size in T type wise elements.
37 * @param[in] stride Stride size in T type wise elements.
38 */
39 SlidingWindow(T *data, size_t dataSize,
40 size_t windowSize, size_t stride) {
41 m_start = data;
42 m_dataSize = dataSize;
43 m_size = windowSize;
44 m_stride = stride;
45 }
46
47 SlidingWindow() = default;
48
49 ~SlidingWindow() = default;
50
51 /**
52 * @brief Get the next data window.
53 * @return Pointer to the next window, if next window is not available nullptr is returned.
54 */
55 virtual T *Next() {
56 if (HasNext()) {
57 m_count++;
58 return m_start + Index() * m_stride;
59 } else {
60 return nullptr;
61 }
62 }
63
64 /**
65 * @brief Checks if the next data portion is available.
66 * @return true if next data portion is available.
67 */
68 virtual bool HasNext() {
69 return m_size + m_count * m_stride <= m_dataSize;
70 }
71
72 /**
73 * @brief Reset the slider to the initial position.
74 */
75 virtual void Reset() {
76 m_count = 0;
77 }
78
79 /**
80 * @brief Resets the slider to the start of the new data.
81 * New data size MUST be the same as the old one.
82 * @param[in] newStart Pointer to the new data to slide through.
83 */
84 virtual void Reset(T *newStart) {
85 m_start = newStart;
86 Reset();
87 }
88
89 /**
90 * @brief Gets current index of the sliding window.
91 * @return Current position of the sliding window in number of strides.
92 */
93 size_t Index() {
94 return m_count == 0? 0: m_count - 1;
95 }
96
97 /**
98 * @brief Gets the index from the start of the data where the next window will begin.
99 * While Index() returns the index of sliding window itself this function
100 * returns the index of the data element itself.
101 * @return Index from the start of the data where the next sliding window will begin.
102 */
103 virtual uint32_t NextWindowStartIndex() {
104 return m_count == 0? 0: ((m_count) * m_stride);
105 }
106
107 /**
108 * @brief Go to given sliding window index.
109 * @param[in] index New position of the sliding window. If index is invalid
110 * (greater than possible range of strides) then next call to Next() will return nullptr.
111 */
112 void FastForward(size_t index) {
113 m_count = index;
114 }
115
116 /**
117 * @brief Calculates whole number of times the window can stride through the given data.
118 * @return Maximum number of whole strides.
119 */
120 size_t TotalStrides() {
121 if (m_size > m_dataSize) {
122 return 0;
123 }
124 return ((m_dataSize - m_size)/m_stride);
125 }
126
alexander3c798932021-03-26 21:42:19 +0000127
128 protected:
129 T *m_start = nullptr;
130 size_t m_dataSize = 0;
131 size_t m_size = 0;
132 size_t m_stride = 0;
133 size_t m_count = 0;
134 };
135
136 /*
alexander80eecfb2021-07-06 19:47:59 +0100137 * Sliding window that will cover the whole length of the input, even if
alexander3c798932021-03-26 21:42:19 +0000138 * this means the last window is not a full window length.
139 */
140 template<class T>
alexander80eecfb2021-07-06 19:47:59 +0100141 class FractionalSlidingWindow : public SlidingWindow<T> {
alexander3c798932021-03-26 21:42:19 +0000142 public:
143 using SlidingWindow<T>::SlidingWindow;
144
145 /**
146 * @brief Checks if the next data portion is available.
147 * @return true if next data portion is available.
148 */
149 bool HasNext() {
150 return this->m_count < 1 + this->FractionalTotalStrides() && (this->NextWindowStartIndex() < this->m_dataSize);
151 }
alexander80eecfb2021-07-06 19:47:59 +0100152
153 /**
154 * @brief Calculates number of times the window can stride through the given data.
155 * May not be a whole number.
156 * @return Number of strides to cover all data.
157 */
158 float FractionalTotalStrides() {
159 if (this->m_dataSize < this->m_size) {
160 return 0;
161 } else {
162 return ((this->m_dataSize - this->m_size) / static_cast<float>(this->m_stride));
163 }
164 }
alexander3c798932021-03-26 21:42:19 +0000165 };
166
167
168} /* namespace audio */
169} /* namespace app */
170} /* namespace arm */
171
172#endif /* AUDIO_UTILS_HPP */