Multi Buffer
Overview
| Read Basic Concepts first for prerequisite information. |
Multi-buffer presents a multi-channel buffer arranged in a non-interleaved format where each channel has its own dedicated buffer, and the samples within each buffer are arranged sequentially in contiguous memory locations. The non-interleaved format is ideal for digital signal processing where it is necessary to perform operations on individual channels separately, often in parallel for maximum efficiency.
As an example, the figure below shows the memory layout of a 4-channel non-interleaved format.
Usage
A Multi-buffer can be conceptualized as a two-dimensional array. The first dimension in this representation corresponds to the samples (x-dimension), while the second dimension represents the channels (y-dimension). Essentially, you can access each individual sample using the two indices ch and i, where ch is the channel index and i is the sample index.
mb[ch][i]
Each dimension has a size which can be obtained this way:
mb.size() // The number of channels
mb[ch].size() // The number of frames per channel
That way, you can iterate through the channels and samples this way:
for (auto ch = 0; ch != mb.size() ++ch)
{
for (auto i = 0; i != mb[ch].size() ++i)
{
auto s = mb[ch][i];
// Do something with the sample `s`
}
}
Alternately, you can iterate through the channels and samples in a channel, using C++ range-based for loop syntax, as follows:
for (auto ch : mb.channels)
{
for (auto i : mb.frames)
{
auto s = mb[ch][i];
// Do something with the sample `s`
}
}
Take note that this syntax is unorthodox in the way it uses C++ range-based for loop syntax. Instead of accessing the channels and samples directly, mb.channels and mb.frames both return a range of indices (corresponding to 0..N, where N is number of channels, for mb.channels or samples, for mb.frames). The design rationale is to always allow random access to all channels and all samples for each channel.
For example, you might want to access both the left and right channels of a stereo (2-channel) multi-buffer and mix them:
auto left = mb[0];
auto right = mb[1];
for (auto i : mb.frames)
{
auto mono = right[i] + left[i]; // Add the left and right channels
// Do something with `mono`
}
mb[ch] returns a view of the channel. It does not copy the whole buffer. This "view" is lightweight and can be held and passed by value without worrying about performance.
|
The previous example can extend to an N channel mixer this way:
for (auto i : mb.frames)
{
auto sum = 0.0f;
for (auto ch : mb.channels)
sum += mb[ch][i];
// Do something with `sum`
}
If you simply need sequential access to the samples in a channel, you can do it this way:
for (auto ch : mb.channels)
{
for (auto s : mb[ch])
{
// Do something with the sample `s`
}
}
Declaration
template <std::floating_point T>
class multi_buffer
{
public:
using sample_type = T;
using buffer_view = iterator_range<T*>;
using frames_view = iterator_range<index_iterator>;
using channels_view = iterator_range<index_iterator>;
// Unspecified constructor
buffer_view operator[](std::size_t channel) const;
std::size_t size() const;
frames_view frames;
channels_view channels;
};
multi_buffer<T> is a template class that implements the multi-buffer.
-
The template paratemeter,
T, is the sample type which is a model of thestd::floating_pointconcept. -
iterator_range<I>is a template class that holds two random access iterators. It is a model ofIndexableContainer, andRandomAccessIteratable. The template parameter,I, is the iterator type. -
index_iteratoris a model of thestd::random_access_iteratorconcept. Thevalue_typeof theindex_iteratoris simply astd::size_t. -
multi_buffer<T>is a model ofIndexableContainerwithbuffer_viewelements: an iterator-range containing pointers to the sample type (T*). -
multi_buffer<T>has member variablesframesandchannelsthat are iterator-ranges containing index-iterators.
Expressions
Notation
T-
The sample type (typically
float). MB-
multi_buffer<T>type. mb-
Instance of
multi_buffer<T>. i-
Object of type
std::size_t, used for indexing.
Type Definitions
| Expression | Semantics | Type |
|---|---|---|
|
Get the sample type. |
`T |
|
Get the iterator type. |
|
|
Get the channel view type. |
|
|
Get the frames view type. |
|