Skip to content

PlanarView: Add channel stride and subView - #4

Merged
eyalamirmusic merged 1 commit into
mainfrom
feature/buffer-stride
Sep 25, 2026
Merged

eyalamirmusic merged 1 commit into
mainfrom
feature/buffer-stride

Conversation

@eyalamirmusic

Copy link
Copy Markdown
Owner

What changed

PlanarView gains a channel stride: channel c now starts c * channelStride elements after channel 0. The stride defaults to the channel length, so a view built with the existing constructors is still one contiguous block. A larger stride leaves gaps between channels, which is what a range of samples inside a larger planar block looks like.

Why

To represent sub-block ranges of a multi-channel planar buffer. A polyphonic synth base in ESeq needs to hand each voice a zero-based view of just the samples it renders (e.g. from a note-on partway through the block), without copying. Existing callers keep identical behaviour, because the default stride equals the sample count.

API added

  • PlanarView(T* data, SizeType numChannels, SizeType numSamples, SizeType channelStride), plus a matching deduction guide. Asserts channelStride >= numSamples when there is more than one channel.
  • int getChannelStride() const
  • bool isContiguous() const: true when empty, single-channel, or channelStride == numSamples.
  • PlanarView subView(SizeType offset, SizeType count = toEnd) const: samples [offset, offset + count) of every channel, keeping the stride. Offset and count are clamped to the channel length.
  • static constexpr int toEnd (forwarded from Span<T>::toEnd).

Behaviour changes inside the class

  • getChannel, operator[] and PlanarIterator offset by the stride, not the sample count.
  • The const-converting constructor carries the stride over.
  • fill now fills channel by channel, so it leaves the gaps between channels alone.
  • flat() asserts isContiguous().
  • getNumElements() still returns the logical count (channels × samples) and excludes the gaps.
  • sizeof(PlanarView) grows by one int.

Tests

  • Renamed PlanarView.is_a_pointer_and_two_ints to PlanarView.is_a_pointer_and_three_ints. Its static_assert now compares against a struct of a pointer and three ints, so it accounts for padding to the pointer's alignment.
  • New tests cover: the strided constructor, deduction with a stride, subView offsets, iterating a strided view, fill on a sub-view leaving the gaps alone, const conversion keeping the stride, isContiguous cases, subView clamping and empty results, flat() on an empty strided sub-view, and subView at compile time.

Test results

488/488 passing in this repo's own build.

A PlanarView can now carry a channel stride larger than its channel length,
so it can describe a range of samples inside a larger planar block. Added
a stride constructor, getChannelStride, isContiguous and subView(offset,
count). The default stride equals the sample count, so existing views
behave exactly as before.
@eyalamirmusic
eyalamirmusic merged commit 82b0904 into main Sep 25, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant