29template<
typename SampleType =
float>
39 : channels_(channel_ptrs)
50 if (start > num_samples_) start = num_samples_;
51 const auto available = num_samples_ - start;
52 if (length > available) length = available;
53 return BufferView(channels_, num_channels_, length, sample_offset_ + start);
58 std::span<SampleType>
channel(std::size_t index) {
59 return {channels_[index] + sample_offset_, num_samples_};
63 std::span<const SampleType>
channel(std::size_t index)
const {
64 return {channels_[index] + sample_offset_, num_samples_};
68 SampleType*
channel_ptr(std::size_t index) {
return channels_[index] + sample_offset_; }
70 const SampleType*
channel_ptr(std::size_t index)
const {
return channels_[index] + sample_offset_; }
75 if (num_channels_ != 0 && channels_ ==
nullptr)
78 if (channels_[
channel] ==
nullptr)
87 bool empty()
const {
return num_channels_ == 0 || num_samples_ == 0; }
91 for (std::size_t ch = 0; ch < num_channels_; ++ch) {
92 std::fill_n(channels_[ch] + sample_offset_, num_samples_, SampleType{0});
99 : channels_(channel_ptrs)
102 , sample_offset_(sample_offset)
105 SampleType*
const* channels_ =
nullptr;
106 std::size_t num_channels_ = 0;
107 std::size_t num_samples_ = 0;
108 std::size_t sample_offset_ = 0;
118template<
typename SampleType =
float>
133 , num_channels_(other.num_channels_)
134 , num_samples_(other.num_samples_) {
135 refresh_channel_pointers();
139 if (
this != &other) {
141 num_channels_ = other.num_channels_;
142 num_samples_ = other.num_samples_;
143 refresh_channel_pointers();
149 : data_(
std::move(other.data_))
150 , num_channels_(other.num_channels_)
151 , num_samples_(other.num_samples_) {
152 refresh_channel_pointers();
153 other.num_channels_ = 0;
154 other.num_samples_ = 0;
159 if (
this != &other) {
160 data_ = std::move(other.data_);
161 num_channels_ = other.num_channels_;
162 num_samples_ = other.num_samples_;
163 refresh_channel_pointers();
164 other.num_channels_ = 0;
165 other.num_samples_ = 0;
176 data_.resize(sample_count, SampleType{0});
177 refresh_channel_pointers();
183 return {ptrs_.data(), num_channels_, num_samples_};
191 return {ptrs_.data(), num_channels_, num_samples_};
195 std::span<SampleType>
channel(std::size_t index) {
196 return {ptrs_[index], num_samples_};
200 std::span<const SampleType>
channel(std::size_t index)
const {
201 return {ptrs_[index], num_samples_};
212 std::vector<SampleType>().swap(data_);
213 std::vector<SampleType*>().swap(ptrs_);
220 std::fill(data_.begin(), data_.end(), SampleType{0});
224 static std::size_t checked_sample_count(std::size_t
num_channels,
228#if defined(__cpp_exceptions) && __cpp_exceptions
229 throw std::length_error(
"audio buffer dimensions overflow");
239 void refresh_channel_pointers() {
240 ptrs_.resize(num_channels_);
241 for (std::size_t ch = 0; ch < num_channels_; ++ch) {
242 ptrs_[ch] = data_.data() + ch * num_samples_;
246 std::vector<SampleType> data_;
247 std::vector<SampleType*> ptrs_;
248 std::size_t num_channels_ = 0;
249 std::size_t num_samples_ = 0;
Non-owning view over multi-channel audio sample data.
Definition buffer.hpp:30
std::span< const SampleType > channel(std::size_t index) const
Get a span over all samples in one channel.
Definition buffer.hpp:63
bool empty() const
True if the buffer has zero channels or zero samples.
Definition buffer.hpp:87
std::size_t num_samples() const
Definition buffer.hpp:84
std::size_t num_channels() const
Definition buffer.hpp:83
BufferView slice(std::size_t start, std::size_t length) const
Create a non-owning slice over this view.
Definition buffer.hpp:49
BufferView(SampleType *const *channel_ptrs, std::size_t num_channels, std::size_t num_samples)
Construct from an array of per-channel pointers.
Definition buffer.hpp:38
std::span< SampleType > channel(std::size_t index)
Get a span over all samples in one channel.
Definition buffer.hpp:58
const SampleType * channel_ptr(std::size_t index) const
Raw pointer to one channel's sample data.
Definition buffer.hpp:70
void clear()
Zero-fill all channels.
Definition buffer.hpp:90
SampleType * channel_ptr(std::size_t index)
Raw pointer to one channel's sample data.
Definition buffer.hpp:68
bool has_valid_channels() const noexcept
Check channel storage before a caller dereferences a borrowed host view.
Definition buffer.hpp:74
Buffer & operator=(Buffer &&other)
Definition buffer.hpp:158
Buffer & operator=(const Buffer &other)
Definition buffer.hpp:138
Buffer(const Buffer &other)
Definition buffer.hpp:131
BufferView< const SampleType > view() const
Create a non-owning BufferView over this buffer's data.
Definition buffer.hpp:190
void resize(std::size_t num_channels, std::size_t num_samples)
Resize the buffer, reallocating if necessary. New samples are zero-filled.
Definition buffer.hpp:172
std::size_t num_channels() const
Definition buffer.hpp:204
std::span< SampleType > channel(std::size_t index)
Get a span over all samples in one channel.
Definition buffer.hpp:195
void release() noexcept
Release all owned sample and channel-pointer storage.
Definition buffer.hpp:211
std::size_t allocated_sample_capacity() const noexcept
Number of sample elements retained by the backing allocation.
Definition buffer.hpp:208
std::span< const SampleType > channel(std::size_t index) const
Get a span over all samples in one channel.
Definition buffer.hpp:200
BufferView< SampleType > view()
Create a non-owning BufferView over this buffer's data.
Definition buffer.hpp:182
std::size_t num_samples() const
Definition buffer.hpp:205
Buffer(std::size_t num_channels, std::size_t num_samples)
Allocate a buffer with the given dimensions, zero-filled.
Definition buffer.hpp:126
Buffer(Buffer &&other)
Definition buffer.hpp:148
void clear()
Zero-fill all channels.
Definition buffer.hpp:219
Definition analyzer_provider.hpp:12