AME
ame_AudioBuffer.hpp
Go to the documentation of this file.
1
10#pragma once
11
12#include <algorithm>
13#include <array>
14#include <cassert>
15#include <cmath>
16#include <cstddef>
17#include <cstdint>
18#include <span>
19
20namespace ame
21{
30template <class ElementType, size_t Extent>
32{
33public:
40 AudioBlockView (std::span<ElementType, Extent> view, const uint_fast32_t numChannels) noexcept
41 : view (view),
42 numChannels (numChannels),
43 numSamplesPerChannel (view.size() / numChannels)
44 {
45 }
46 ~AudioBlockView() = default;
47
49 uint_fast32_t getNumChannels() const noexcept
50 {
51 return numChannels;
52 }
53
55 uint_fast32_t getNumSamplesPerChannel() const noexcept
56 {
57 return numSamplesPerChannel;
58 }
59
65 void setSample (const uint_fast32_t destChannel, const uint_fast32_t destSample, const ElementType newValue)
66 {
67 assert (destChannel < numChannels);
68 assert (destSample < numSamplesPerChannel);
69 view[destSample * numChannels + destChannel] = newValue;
70 }
71
77 void addSample (const uint_fast32_t destChannel, const uint_fast32_t destSample, const ElementType valueToAdd)
78 {
79 assert (destChannel < numChannels);
80 assert (destSample < numSamplesPerChannel);
81 view[destSample * numChannels + destChannel] += valueToAdd;
82 }
83
85 void clear()
86 {
87 std::fill (view.begin(), view.end(), ElementType (0.0));
88 }
89
91 void applyGain (const float gain)
92 {
93 for_each (view.begin(), view.end(), [&gain] (auto& x)
94 { x *= gain; });
95 }
96
101 float getPeak (const uint_fast32_t channel) const
102 {
103 float peak = 0.0f;
104
105 for (auto i = channel; i < view.size(); i += numChannels)
106 {
107 const auto v = std::abs (view[i]);
108 if (v > peak)
109 {
110 peak = v;
111 }
112 }
113 return peak;
114 }
115
120 float getRMSLevel (const uint_fast32_t channel) const
121 {
122 assert (channel < numChannels);
123 float sum = 0.0f;
124 for (auto i = channel; i < view.size(); i += numChannels)
125 {
126 const auto sample = view[i];
127 sum += sample * sample;
128 }
129
130 return std::sqrt (sum / numSamplesPerChannel);
131 }
132
141 auto subView (uint_fast32_t offset, uint_fast32_t size)
142 {
143 return AudioBlockView { view.subspan (offset, size), numChannels };
144 }
145
146 std::span<ElementType, Extent> view;
147
148private:
149 uint_fast32_t numChannels;
150 uint_fast32_t numSamplesPerChannel;
151};
152
159template <typename FloatType, size_t Size>
161{
162public:
163 explicit AudioBuffer (const uint_fast32_t numChannels) : numChannels (numChannels), numSamplesPerChannel (Size / numChannels)
164 {
165 }
166 ~AudioBuffer() = default;
167
172 void setNumChannels (const uint_fast32_t channels)
173 {
174 numChannels = channels;
175 numSamplesPerChannel = Size / numChannels;
176 }
177
179 uint_fast32_t getNumChannels() const noexcept
180 {
181 return numChannels;
182 }
183
185 uint_fast32_t getNumSamplesPerChannel() const noexcept
186 {
187 return numSamplesPerChannel;
188 }
189
191 void clear()
192 {
193 buffer.fill (0.0f);
194 }
195
197 void applyGain (const float gain)
198 {
199 std::for_each (buffer.begin(), buffer.end(), [&gain] (auto& e)
200 { e *= gain; });
201 }
202
211 auto makeAudioBlockView (uint_fast32_t offset = 0, uint_fast32_t size = Size)
212 {
213 std::span sp { buffer.data() + offset, size };
214 return ame::AudioBlockView { sp, numChannels };
215 }
216
218 template <size_t Extent>
219 void addFrom (const uint_fast32_t destChannel, const uint_fast32_t destStartSample, const AudioBlockView<FloatType, Extent>& source, const uint_fast32_t sourceChannel, const uint_fast32_t sourceStartSample, const uint_fast32_t numSamplesToAdd)
220 {
221 const auto& destOffset = destStartSample * numChannels;
222 const auto& sourceOffset = sourceStartSample * source.getNumChannels();
223 const auto& destEnd = destOffset + numSamplesToAdd * numChannels;
224 const auto& sourceEnd = sourceOffset + numSamplesToAdd * source.getNumChannels();
225
226 assert (destEnd <= Size);
227 assert (sourceEnd <= source.getSize());
228
229 for (uint_fast32_t i = 0; i < numSamplesToAdd; ++i)
230 {
231 buffer[destOffset + i * destChannel] += source.buffer[sourceOffset + i * source.getNumChannels];
232 }
233 }
234
239 FloatType getPeak (const uint_fast32_t channel) const
240 {
241 assert (channel < numChannels);
242 FloatType peak = 0.0;
243 for (auto i = channel; i < numSamplesPerChannel * numChannels; i += numChannels)
244 {
245 const auto v = std::abs (buffer[i]);
246 if (v > peak)
247 {
248 peak = v;
249 }
250 }
251 return peak;
252 }
253
258 FloatType getRMSLevel (const uint_fast32_t channel) const
259 {
260 assert (channel < numChannels);
261 FloatType sum = 0.0;
262 for (auto i = channel; i < numSamplesPerChannel * numChannels; i += numChannels)
263 {
264 const auto sample = buffer[i];
265 sum += sample * sample;
266 }
267
268 return static_cast<FloatType> (std::sqrt (sum / numSamplesPerChannel));
269 }
270
271 std::array<FloatType, Size> buffer = {};
272
273private:
274 uint_fast32_t numChannels;
275 uint_fast32_t numSamplesPerChannel;
276};
277} // namespace ame
A lightweight data structure that stores a pointer to an audio buffer.
Definition: ame_AudioBuffer.hpp:32
uint_fast32_t getNumChannels() const noexcept
Returns the number of channels.
Definition: ame_AudioBuffer.hpp:49
void setSample(const uint_fast32_t destChannel, const uint_fast32_t destSample, const ElementType newValue)
Set a sample in the buffer.
Definition: ame_AudioBuffer.hpp:65
AudioBlockView(std::span< ElementType, Extent > view, const uint_fast32_t numChannels) noexcept
Constructor.
Definition: ame_AudioBuffer.hpp:40
float getRMSLevel(const uint_fast32_t channel) const
Returns the root mean squared level for a region of a channel.
Definition: ame_AudioBuffer.hpp:120
float getPeak(const uint_fast32_t channel) const
Finds the highest absolute sample value within a region of a channel.
Definition: ame_AudioBuffer.hpp:101
void clear()
Set all samples to 0.
Definition: ame_AudioBuffer.hpp:85
void addSample(const uint_fast32_t destChannel, const uint_fast32_t destSample, const ElementType valueToAdd)
Add a value to a sample in the buffer.
Definition: ame_AudioBuffer.hpp:77
void applyGain(const float gain)
Applies a gain multiple to all the audio data.
Definition: ame_AudioBuffer.hpp:91
auto subView(uint_fast32_t offset, uint_fast32_t size)
Returns an AudioBlockView that references N elements from an arbitrary position.
Definition: ame_AudioBuffer.hpp:141
uint_fast32_t getNumSamplesPerChannel() const noexcept
Returns the number of samples per channel.
Definition: ame_AudioBuffer.hpp:55
An audio buffer that supports multiple channels whose size is determined at compile time.
Definition: ame_AudioBuffer.hpp:161
void setNumChannels(const uint_fast32_t channels)
Set the number of channels.
Definition: ame_AudioBuffer.hpp:172
FloatType getPeak(const uint_fast32_t channel) const
Finds the highest absolute sample value within a region of a channel.
Definition: ame_AudioBuffer.hpp:239
FloatType getRMSLevel(const uint_fast32_t channel) const
Returns the root mean squared level for a region of a channel.
Definition: ame_AudioBuffer.hpp:258
void applyGain(const float gain)
Applies a gain multiple to all the audio data.
Definition: ame_AudioBuffer.hpp:197
void clear()
Set all samples to 0.
Definition: ame_AudioBuffer.hpp:191
auto makeAudioBlockView(uint_fast32_t offset=0, uint_fast32_t size=Size)
Returns an AudioBlockView that references N elements from an arbitrary position.
Definition: ame_AudioBuffer.hpp:211
uint_fast32_t getNumSamplesPerChannel() const noexcept
Returns the number of samples per channel.
Definition: ame_AudioBuffer.hpp:185
void addFrom(const uint_fast32_t destChannel, const uint_fast32_t destStartSample, const AudioBlockView< FloatType, Extent > &source, const uint_fast32_t sourceChannel, const uint_fast32_t sourceStartSample, const uint_fast32_t numSamplesToAdd)
addBuffer
Definition: ame_AudioBuffer.hpp:219
uint_fast32_t getNumChannels() const noexcept
Returns the number of channels.
Definition: ame_AudioBuffer.hpp:179