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_point
concept. -
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_iterator
is a model of thestd::random_access_iterator
concept. Thevalue_type
of theindex_iterator
is simply astd::size_t
. -
multi_buffer<T>
is a model ofIndexableContainer
withbuffer_view
elements: an iterator-range containing pointers to the sample type (T*
). -
multi_buffer<T>
has member variablesframes
andchannels
that 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. |
|