LMMS
Loading...
Searching...
No Matches
AudioBuffer.h
Go to the documentation of this file.
1/*
2 * AudioBuffer.h
3 *
4 * Copyright (c) 2026 Dalton Messmer <messmer.dalton/at/gmail.com>
5 *
6 * This file is part of LMMS - https://lmms.io
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this program (see COPYING); if not, write to the
20 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301 USA.
22 *
23 */
24
25#ifndef LMMS_AUDIO_BUFFER_H
26#define LMMS_AUDIO_BUFFER_H
27
28#include <bitset>
29#include <memory_resource>
30
31#include "AudioBufferView.h"
32#include "ArrayVector.h"
33#include "LmmsTypes.h"
34#include "lmms_constants.h"
35#include "lmms_export.h"
36
37namespace lmms
38{
39
78class LMMS_EXPORT AudioBuffer
79{
80public:
81 using ChannelFlags = std::bitset<MaxChannelsPerAudioBuffer>;
82
85 {
86 public:
87 ChannelGroup() = default;
92
93 auto buffers() const -> const float* const* { return m_buffers; }
94 auto buffers() -> float** { return m_buffers; }
95
96 auto buffer(ch_cnt_t channel) const -> const float*
97 {
98 assert(channel < m_channels);
99 return m_buffers[channel];
100 }
101
102 auto buffer(ch_cnt_t channel) -> float*
103 {
104 assert(channel < m_channels);
105 return m_buffers[channel];
106 }
107
108 auto channels() const -> ch_cnt_t { return m_channels; }
109
110 void setBuffers(float** newBuffers) { m_buffers = newBuffers; }
112
113 // TODO: Future additions: Group names, type (main/aux), speaker arrangements (for surround sound), ...
114
115 private:
120 float** m_buffers = nullptr;
121
124 };
125
126 AudioBuffer() = delete;
127
128 AudioBuffer(const AudioBuffer&) = delete;
130 auto operator=(const AudioBuffer&) -> AudioBuffer& = delete;
131 auto operator=(AudioBuffer&&) noexcept -> AudioBuffer& = default;
132
143 std::pmr::memory_resource* resource = std::pmr::get_default_resource());
144
156 template<class F>
158 std::pmr::memory_resource* resource, F&& groupVisitor)
159 : AudioBuffer{frames, channels, resource}
160 {
161 setGroups(groups, std::forward<F>(groupVisitor));
162 }
163
165 void allocateInterleavedBuffer();
166
167 auto hasInterleavedBuffer() const -> bool { return !m_interleavedBuffer.empty(); }
168
173 static auto allocationSize(f_cnt_t frames, ch_cnt_t channels,
174 bool withInterleavedBuffer = false) -> std::size_t;
175
177 auto groupCount() const -> group_cnt_t { return static_cast<group_cnt_t>(m_groups.size()); }
178
179 auto group(group_cnt_t index) const -> const ChannelGroup& { return m_groups[index]; }
180 auto group(group_cnt_t index) -> ChannelGroup& { return m_groups[index]; }
181
184 {
185 return {m_accessBuffer.data(), totalChannels(), m_frames};
186 }
187
190 {
191 return {m_accessBuffer.data(), totalChannels(), m_frames};
192 }
193
196 {
197 assert(index < groupCount());
198 const ChannelGroup& g = m_groups[index];
199 return {g.buffers(), g.channels(), m_frames};
200 }
201
204 {
205 assert(index < groupCount());
206 ChannelGroup& g = m_groups[index];
207 return {g.buffers(), g.channels(), m_frames};
208 }
209
211 auto buffer(ch_cnt_t channel) const -> std::span<const float>
212 {
213 return {m_accessBuffer[channel], m_frames};
214 }
215
217 auto buffer(ch_cnt_t channel) -> std::span<float>
218 {
219 return {m_accessBuffer[channel], m_frames};
220 }
221
223 auto totalChannels() const -> ch_cnt_t { return static_cast<ch_cnt_t>(m_accessBuffer.size()); }
224
226 auto frames() const -> f_cnt_t { return m_frames; }
227
230 {
232 return {m_interleavedBuffer.data(), m_frames};
233 }
234
241
252 auto addGroup(ch_cnt_t channels) -> ChannelGroup*;
253
263 template<class F>
264 void setGroups(group_cnt_t groups, F&& groupVisitor)
265 {
266 static_assert(std::is_invocable_r_v<ch_cnt_t, F, group_cnt_t, ChannelGroup&>,
267 "groupVisitor is passed the group index + group reference and must return the group's channel count");
268
269 m_groups.clear();
270 ch_cnt_t ch = 0;
271 for (group_cnt_t idx = 0; idx < groups; ++idx)
272 {
273 auto& group = m_groups.emplace_back();
274
275 const auto channels = groupVisitor(idx, group);
276 if (channels == 0) { throw std::runtime_error{"group cannot have zero channels"}; }
277
278 group.setBuffers(&m_accessBuffer[ch]);
279 group.setChannels(channels);
280
281 ch += channels;
282 if (ch > this->totalChannels())
283 {
284 throw std::runtime_error{"sum of group channel counts exceeds total channels"};
285 }
286 }
287 }
288
300
302 void assumeNonSilent(ch_cnt_t channel) { m_silenceFlags[channel] = false; }
303
315 void enableSilenceTracking(bool enabled);
317
319 void mixSilenceFlags(const AudioBuffer& other);
320
333 auto hasSignal(const ChannelFlags& channels) const -> bool;
334
336 auto hasAnySignal() const -> bool;
337
344 void sanitize(const ChannelFlags& channels, ch_cnt_t upperBound = MaxChannelsPerAudioBuffer);
345
347 void sanitizeAll();
348
356 auto updateSilenceFlags(const ChannelFlags& channels, ch_cnt_t upperBound = MaxChannelsPerAudioBuffer) -> bool;
357
359 auto updateAllSilenceFlags() -> bool;
360
367 void silenceChannels(const ChannelFlags& channels, ch_cnt_t upperBound = MaxChannelsPerAudioBuffer);
368
370 void silenceAllChannels();
371
373 auto absPeakValue(ch_cnt_t channel) const -> float;
374
375private:
381 std::pmr::vector<float> m_sourceBuffer;
382
388 std::pmr::vector<float*> m_accessBuffer;
389
395 std::pmr::vector<float> m_interleavedBuffer;
396
399
402
415
417};
418
419} // namespace lmms
420
421#endif // LMMS_AUDIO_BUFFER_H
#define noexcept
Definition DistrhoDefines.h:72
assert(0)
Definition ArrayVector.h:51
Non-owning collection of audio channels + metadata.
Definition AudioBuffer.h:85
auto buffer(ch_cnt_t channel) -> float *
Definition AudioBuffer.h:102
auto buffer(ch_cnt_t channel) const -> const float *
Definition AudioBuffer.h:96
ch_cnt_t m_channels
Number of channels in m_buffers - currently only 2 is used.
Definition AudioBuffer.h:123
void setBuffers(float **newBuffers)
Definition AudioBuffer.h:110
void setChannels(ch_cnt_t channels)
Definition AudioBuffer.h:111
float ** m_buffers
Definition AudioBuffer.h:120
ChannelGroup(float **buffers, ch_cnt_t channels)
Definition AudioBuffer.h:88
auto buffers() const -> const float *const *
Definition AudioBuffer.h:93
auto channels() const -> ch_cnt_t
Definition AudioBuffer.h:108
auto buffers() -> float **
Definition AudioBuffer.h:94
Definition AudioBuffer.h:79
ArrayVector< ChannelGroup, MaxGroupsPerAudioBuffer > m_groups
Divides channels into arbitrary groups.
Definition AudioBuffer.h:398
auto silenceTrackingEnabled() const -> bool
Definition AudioBuffer.h:316
auto allBuffers() const -> PlanarBufferView< const float >
Definition AudioBuffer.h:183
f_cnt_t m_frames
Frame count for every channel buffer.
Definition AudioBuffer.h:401
auto groupBuffers(group_cnt_t index) const -> PlanarBufferView< const float >
Definition AudioBuffer.h:195
std::pmr::vector< float > m_interleavedBuffer
Definition AudioBuffer.h:395
auto groupBuffers(group_cnt_t index) -> PlanarBufferView< float >
Definition AudioBuffer.h:203
auto group(group_cnt_t index) const -> const ChannelGroup &
Definition AudioBuffer.h:179
auto buffer(ch_cnt_t channel) const -> std::span< const float >
Definition AudioBuffer.h:211
auto allBuffers() -> PlanarBufferView< float >
Definition AudioBuffer.h:189
auto interleavedBuffer() const -> InterleavedBufferView< const float, 2 >
Definition AudioBuffer.h:229
auto hasInterleavedBuffer() const -> bool
Definition AudioBuffer.h:167
void assumeNonSilent(ch_cnt_t channel)
Forcibly pessimizes silence tracking for a specific channel.
Definition AudioBuffer.h:302
auto groupCount() const -> group_cnt_t
Definition AudioBuffer.h:177
auto group(group_cnt_t index) -> ChannelGroup &
Definition AudioBuffer.h:180
auto frames() const -> f_cnt_t
Definition AudioBuffer.h:226
bool m_silenceTrackingEnabled
Definition AudioBuffer.h:416
std::bitset< MaxChannelsPerAudioBuffer > ChannelFlags
Definition AudioBuffer.h:81
std::pmr::vector< float > m_sourceBuffer
Definition AudioBuffer.h:381
AudioBuffer(const AudioBuffer &)=delete
AudioBuffer(AudioBuffer &&) noexcept=default
ChannelFlags m_silenceFlags
Definition AudioBuffer.h:414
auto silenceFlags() const -> const ChannelFlags &
Definition AudioBuffer.h:299
void setGroups(group_cnt_t groups, F &&groupVisitor)
Changes the channel grouping without changing the channel count. Does not reallocate any buffers.
Definition AudioBuffer.h:264
auto interleavedBuffer() -> InterleavedBufferView< float, 2 >
Definition AudioBuffer.h:236
std::pmr::vector< float * > m_accessBuffer
Definition AudioBuffer.h:388
auto buffer(ch_cnt_t channel) -> std::span< float >
Definition AudioBuffer.h:217
AudioBuffer()=delete
auto totalChannels() const -> ch_cnt_t
Definition AudioBuffer.h:223
Definition AudioBufferView.h:291
Definition AudioBufferView.h:475
int g
Definition inflate.c:1573
Definition AudioAlsa.cpp:35
std::uint8_t group_cnt_t
Definition LmmsTypes.h:48
std::uint16_t ch_cnt_t
Definition LmmsTypes.h:44
constexpr auto DEFAULT_CHANNELS
Definition lmms_constants.h:38
constexpr auto MaxGroupsPerAudioBuffer
Definition lmms_constants.h:40
std::uint64_t f_cnt_t
Definition LmmsTypes.h:43
constexpr auto MaxChannelsPerAudioBuffer
Definition lmms_constants.h:39
Definition juce_Uuid.h:141
#define false
Definition ordinals.h:83
#define const
Definition zconf.h:137