1 | /* |
2 | Copyright 2018 Google Inc. All Rights Reserved. |
3 | |
4 | Licensed under the Apache License, Version 2.0 (the "License"); |
5 | you may not use this file except in compliance with the License. |
6 | You may obtain a copy of the License at |
7 | |
8 | http://www.apache.org/licenses/LICENSE-2.0 |
9 | |
10 | Unless required by applicable law or agreed to in writing, software |
11 | distributed under the License is distributed on an "AS-IS" BASIS, |
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | See the License for the specific language governing permissions and |
14 | limitations under the License. |
15 | */ |
16 | |
17 | #ifndef RESONANCE_AUDIO_BASE_AUDIO_BUFFER_H_ |
18 | #define RESONANCE_AUDIO_BASE_AUDIO_BUFFER_H_ |
19 | |
20 | #include <algorithm> |
21 | #include <memory> |
22 | |
23 | #include "base/integral_types.h" |
24 | #include "base/aligned_allocator.h" |
25 | #include "base/channel_view.h" |
26 | #include "base/constants_and_types.h" |
27 | #include "base/logging.h" |
28 | #include "base/simd_utils.h" |
29 | |
30 | |
31 | namespace vraudio { |
32 | |
33 | // Audio buffer that manages multi-channel audio data in a planar data format. |
34 | // All channels are sequentially stored within a single consecutive chunk of |
35 | // memory. To access individual channel data, the array subscript operator can |
36 | // be used to obtain a |AudioBuffer::Channel|. Note that the user must guarantee |
37 | // that the AudioBuffer instance lives as long as its channel data is accessed |
38 | // via |AudioBuffer::Channel|s. Note that allocated buffers may *not* be |
39 | // initialized to zero. |
40 | // |
41 | // Examples: |
42 | // |
43 | // // Range-based for-loop over all channels and all samples. |
44 | // AudioBuffer audio_buffer(...) |
45 | // for (AudioBuffer::Channel& channel : audio_buffer) { |
46 | // for (float& sample : channel) { |
47 | // sample *= gain; |
48 | // } |
49 | // } |
50 | // |
51 | // // Range-based for-loop over all channels and array subscripts-based for-loop |
52 | // // to access samples. |
53 | // AudioBuffer audio_buffer(...) |
54 | // for (AudioBuffer::Channel& channel : audio_buffer) { |
55 | // for (size_t i = 0; i < channel.num_frames(); ++i) { |
56 | // channel[i] *= gain; |
57 | // } |
58 | // } |
59 | // |
60 | // // Array subscript-based for-loops over all channels samples. |
61 | // // AudioBuffer audio_buffer(...) |
62 | // for (size_t c=0; c < audio_buffer.num_channels(); ++c) { |
63 | // // First obtain a reference to AudioBuffer::Channel. |
64 | // AudioBuffer::Channel& channel = audio_buffer[c]; |
65 | // for (size_t i = 0; i < channel.num_frames(); ++i) { |
66 | // channel[i] *= gain; |
67 | // } |
68 | // } |
69 | // |
70 | // Note do *NOT* use double array subscripts to iterate over multiple samples |
71 | // since it performs a channel iterator lookup for every sample: |
72 | // for (size_t c=0; c < audio_buffer.num_channels(); ++c) { |
73 | // for (size_t i = 0; i < channel.size(); ++i) { |
74 | // audio_buffer[c][i] *= gain; // *BAD* |
75 | // } |
76 | // } |
77 | // |
78 | class AudioBuffer { |
79 | public: |
80 | // View on separate audio channel. |
81 | typedef ChannelView Channel; |
82 | |
83 | // Allocator class to allocate aligned floats. |
84 | typedef AlignedAllocator<float, kMemoryAlignmentBytes> FloatAllocator; |
85 | |
86 | // Allocator class to allocate aligned int16s. |
87 | typedef AlignedAllocator<int16, kMemoryAlignmentBytes> Int16Allocator; |
88 | |
89 | // AlignedFloatBuffer for storing audio data. |
90 | typedef std::vector<float, FloatAllocator> AlignedFloatVector; |
91 | |
92 | // AlignedInt16Buffer for storing audio data. |
93 | typedef std::vector<int16, Int16Allocator> AlignedInt16Vector; |
94 | |
95 | // Default constructor initializes an empty |AudioBuffer|. |
96 | AudioBuffer(); |
97 | |
98 | // Constructor. |
99 | // |
100 | // @param num_channels Number of channels. |
101 | // @param num_frames Number of frames. |
102 | AudioBuffer(size_t num_channels, size_t num_frames); |
103 | |
104 | // Move constructor. |
105 | AudioBuffer(AudioBuffer&& other); |
106 | |
107 | // Copy constructor is explicitly deleted to prevent accidental copies. |
108 | // Use copy assignment operator instead. |
109 | AudioBuffer(const AudioBuffer& other) = delete; |
110 | |
111 | // Copy assignment from AudioBuffer. |
112 | AudioBuffer& operator=(const AudioBuffer& other); |
113 | |
114 | // Returns the number of audio channels. |
115 | size_t num_channels() const { return channel_views_.size(); } |
116 | |
117 | // Returns the number of frames per buffer. |
118 | size_t num_frames() const { return num_frames_; } |
119 | |
120 | // Returns this buffer's source id. |
121 | SourceId source_id() const { return source_id_; } |
122 | |
123 | // Returns a reference to the selected ChannelView. |
124 | Channel& operator[](size_t channel) { |
125 | DCHECK_LT(channel, channel_views_.size()); |
126 | return channel_views_[channel]; |
127 | } |
128 | |
129 | // Returns a const reference to the selected ChannelView. |
130 | const Channel& operator[](size_t channel) const { |
131 | DCHECK_LT(channel, channel_views_.size()); |
132 | return channel_views_[channel]; |
133 | } |
134 | |
135 | // Copy assignment from std::vector<std::vector<float>>. |
136 | AudioBuffer& operator=(const std::vector<std::vector<float>>& other) { |
137 | DCHECK_EQ(other.size(), channel_views_.size()); |
138 | for (size_t channel = 0; channel < channel_views_.size(); ++channel) { |
139 | channel_views_[channel] = other[channel]; |
140 | } |
141 | return *this; |
142 | } |
143 | |
144 | // += operator |
145 | AudioBuffer& operator+=(const AudioBuffer& other) { |
146 | DCHECK_EQ(other.num_channels(), num_channels()); |
147 | DCHECK_EQ(other.num_frames(), num_frames()); |
148 | for (size_t i = 0; i < channel_views_.size(); ++i) |
149 | channel_views_[i] += other[i]; |
150 | |
151 | return *this; |
152 | } |
153 | |
154 | // -= operator |
155 | AudioBuffer& operator-=(const AudioBuffer& other) { |
156 | DCHECK_EQ(other.num_channels(), num_channels()); |
157 | DCHECK_EQ(other.num_frames(), num_frames()); |
158 | for (size_t i = 0; i < channel_views_.size(); ++i) |
159 | channel_views_[i] -= other[i]; |
160 | |
161 | return *this; |
162 | } |
163 | |
164 | // Returns an iterator to the ChannelView of the first channel. |
165 | std::vector<Channel>::iterator begin() { return channel_views_.begin(); } |
166 | |
167 | // Returns an iterator to the end of the ChannelView vector. |
168 | std::vector<Channel>::iterator end() { return channel_views_.end(); } |
169 | |
170 | // Returns a const_iterator to the ChannelView of the first channel. |
171 | std::vector<Channel>::const_iterator begin() const { |
172 | return channel_views_.begin(); |
173 | } |
174 | |
175 | // Returns an const_iterator to the end of the ChannelView vector. |
176 | std::vector<Channel>::const_iterator end() const { |
177 | return channel_views_.end(); |
178 | } |
179 | |
180 | // Fills all channels with zeros and reenables |Channel|s. |
181 | void Clear() { |
182 | for (Channel& channel : channel_views_) { |
183 | channel.SetEnabled(true); |
184 | channel.Clear(); |
185 | } |
186 | } |
187 | |
188 | // Returns the number of allocated frames per |Channel|. Note this may |
189 | // differ from the actual size of the |Channel| to ensure alignment of all |
190 | // |Channel|s. |
191 | size_t GetChannelStride() const { |
192 | return FindNextAlignedArrayIndex(length: num_frames_, type_size_bytes: sizeof(float), |
193 | memory_alignment_bytes: kMemoryAlignmentBytes); |
194 | } |
195 | |
196 | // Sets the source id of which the buffer belongs to. |
197 | void set_source_id(SourceId source_id) { source_id_ = source_id; } |
198 | |
199 | private: |
200 | // Allocates memory and initializes vector of |ChannelView|s. |
201 | void InitChannelViews(size_t num_channels); |
202 | |
203 | // Number of frames per buffer. |
204 | size_t num_frames_; |
205 | |
206 | // Audio buffer that sequentially stores multiple audio channels in a planar |
207 | // format. |
208 | AlignedFloatVector data_; |
209 | |
210 | // Size of audio buffer. |
211 | size_t data_size_; |
212 | |
213 | // Vector of |AudioBuffer::Channel|s. |
214 | std::vector<Channel> channel_views_; |
215 | |
216 | // Id of a source that this buffer belongs to. |
217 | SourceId source_id_; |
218 | }; |
219 | |
220 | } // namespace vraudio |
221 | |
222 | #endif // RESONANCE_AUDIO_BASE_AUDIO_BUFFER_H_ |
223 | |