MCC
Loading...
Searching...
No Matches
RhythmPattern.h
1#ifndef MCC_RHYTHM_RHYTHM_PATTERN_H
2#define MCC_RHYTHM_RHYTHM_PATTERN_H
3
4#include <stddef.h>
5#include <stdint.h>
6
7#include <MCC_BuildSettings.h>
8
9#include <Foundation/Containers/BitVector.h>
10
11namespace MCC {
12
54public:
56 static constexpr uint16_t MaximumSteps = 0xFFFFu;
57
59 static constexpr size_t BytesFor(uint32_t steps) noexcept {
60 return Foundation::Containers::BitVector::BytesFor(steps);
61 }
62
64 RhythmPattern() noexcept : _steps() {}
65
72 explicit RhythmPattern(int32_t steps) noexcept;
73
78 RhythmPattern(uint8_t* buffer, size_t bytes) noexcept : _steps(buffer, bytes) {}
79
80 // Copy, move and destruction follow Foundation::Containers::BitVector:
81 // a copy owns exactly its steps; copy assignment, and move assignment
82 // into an attached pattern, copy into the existing storage; a move
83 // otherwise takes the storage; owned storage is freed on destruction.
84
86 static RhythmPattern Invalid() noexcept { return RhythmPattern(); }
87
94 static RhythmPattern FromMask(uint32_t onsets, int32_t steps) noexcept;
95
97 static RhythmPattern FromString(const char* text) noexcept;
98
100 static RhythmPattern FromIntervals(const char* text) noexcept;
101
112 bool Attach(uint8_t* buffer, size_t bytes) noexcept { return _steps.Attach(buffer, bytes); }
113
118 void Release() noexcept { _steps.Release(); }
119
121 bool OwnsStorage() const noexcept { return _steps.OwnsStorage(); }
122
132 bool Parse(const char* text) noexcept;
133
143 bool ParseIntervals(const char* text) noexcept;
144
146 bool IsValid() const noexcept { return !_steps.IsEmpty(); }
147
149 uint16_t StepCount() const noexcept { return static_cast<uint16_t>(_steps.GetCount()); }
150
152 uint16_t Capacity() const noexcept;
153
155 uint16_t OnsetCount() const noexcept;
156
161 bool IsOnset(int32_t step) const noexcept;
162
167 int32_t OnsetStep(int32_t index) const noexcept;
168
175 int32_t InteronsetInterval(int32_t index) const noexcept;
176
183 bool SetOnset(int32_t step, bool onset = true) noexcept;
184
193 bool Resize(int32_t steps) noexcept;
194
200 bool Reserve(int32_t steps) noexcept;
201
207 bool Append(bool onset = false) noexcept;
208
214 bool Append(const RhythmPattern& other) noexcept;
215
221 bool ShrinkToFit() noexcept;
222
227 bool Rotate(int32_t steps) noexcept;
228
230 bool Invert() noexcept;
231
239 RhythmPattern Rotated(int32_t steps) const noexcept;
240
246 bool IsRotationOf(const RhythmPattern& other) const noexcept;
247
249 RhythmPattern Complement() const noexcept;
250
255 RhythmPattern Concatenated(const RhythmPattern& other) const noexcept;
256
258 friend bool operator==(const RhythmPattern& a, const RhythmPattern& b) noexcept {
259 return a._steps == b._steps;
260 }
261
263 friend bool operator!=(const RhythmPattern& a, const RhythmPattern& b) noexcept {
264 return a._steps != b._steps;
265 }
266
267private:
268 // Bit i is step i; bits past the step count are always zero.
269 Foundation::Containers::BitVector _steps;
270
271 bool Bit(uint16_t step) const noexcept { return _steps.Get(step); }
272 void ReverseSteps(uint16_t first, uint16_t last) noexcept;
273};
274
275} // namespace MCC
276
277#endif // MCC_RHYTHM_RHYTHM_PATTERN_H
uint16_t OnsetCount() const noexcept
Returns the number of onsets, or 0 for the invalid pattern.
bool SetOnset(int32_t step, bool onset=true) noexcept
Makes step step an onset or a rest.
uint16_t Capacity() const noexcept
Returns how many steps fit without reallocating.
bool Reserve(int32_t steps) noexcept
Ensures Capacity() is at least steps without changing the pattern; false when steps is outside [0,...
RhythmPattern(uint8_t *buffer, size_t bytes) noexcept
Creates an empty (invalid) pattern attached to buffer, or with owned storage when buffer is null; see...
Definition RhythmPattern.h:78
static RhythmPattern FromMask(uint32_t onsets, int32_t steps) noexcept
Creates up to 32 steps from a mask: bit i marks step i.
static constexpr uint16_t MaximumSteps
Largest step count.
Definition RhythmPattern.h:56
bool ShrinkToFit() noexcept
Asks owned storage to shrink to the bytes the steps need, as cpstd::vector::shrink_to_fit() does....
static constexpr size_t BytesFor(uint32_t steps) noexcept
Bytes needed to store steps steps; use it to size buffers.
Definition RhythmPattern.h:59
bool IsOnset(int32_t step) const noexcept
Returns true when step, reduced modulo StepCount(), is an onset; always false for the invalid pattern...
bool Invert() noexcept
Swaps onsets and rests in place; false for the invalid pattern.
RhythmPattern(int32_t steps) noexcept
Creates steps rests in owned storage.
RhythmPattern Rotated(int32_t steps) const noexcept
Returns the pattern started steps steps later (SPEC-RHY-12).
RhythmPattern Concatenated(const RhythmPattern &other) const noexcept
Returns this pattern followed by other; invalid when either is invalid or the result exceeds MaximumS...
bool Parse(const char *text) noexcept
Replaces the steps with box notation such as "x..x..x...x.x...".
bool Resize(int32_t steps) noexcept
Changes the step count, keeping existing steps and adding rests.
int32_t InteronsetInterval(int32_t index) const noexcept
Returns the steps from the index-th onset to the next one, wrapping around the cycle,...
bool Attach(uint8_t *buffer, size_t bytes) noexcept
Uses buffer (bytes long) as storage, without owning it.
Definition RhythmPattern.h:112
int32_t OnsetStep(int32_t index) const noexcept
Returns the step of the index-th onset (0-based), or -1 when index is outside [0, OnsetCount()).
RhythmPattern() noexcept
Creates the invalid pattern without storage (SPEC-ERR-2).
Definition RhythmPattern.h:64
static RhythmPattern Invalid() noexcept
Returns the invalid pattern.
Definition RhythmPattern.h:86
void Release() noexcept
Releases owned storage or detaches from the attached buffer, leaving the invalid pattern without stor...
Definition RhythmPattern.h:118
static RhythmPattern FromIntervals(const char *text) noexcept
Returns a new owned pattern parsed by ParseIntervals(), or invalid.
bool Append(bool onset=false) noexcept
Adds one step at the end. Owned storage grows geometrically when full; false and unchanged at Maximum...
bool ParseIntervals(const char *text) noexcept
Replaces the steps with interonset intervals such as "3-3-4-2-4".
uint16_t StepCount() const noexcept
Returns the number of steps, or 0 for the invalid pattern.
Definition RhythmPattern.h:149
bool Rotate(int32_t steps) noexcept
Starts the cycle steps steps later, in place and without allocating (SPEC-RHY-12)....
bool IsValid() const noexcept
Returns true unless this is the invalid pattern.
Definition RhythmPattern.h:146
static RhythmPattern FromString(const char *text) noexcept
Returns a new owned pattern parsed by Parse(), or invalid.
RhythmPattern Complement() const noexcept
Returns a copy with onsets and rests swapped. Invalid stays invalid.
bool IsRotationOf(const RhythmPattern &other) const noexcept
Returns true when both patterns are the same necklace: equal step counts and some rotation of other e...
friend bool operator!=(const RhythmPattern &a, const RhythmPattern &b) noexcept
Negation of operator==.
Definition RhythmPattern.h:263
bool OwnsStorage() const noexcept
Returns true when the storage is owned (heap) rather than attached.
Definition RhythmPattern.h:121
Music Composition Core public namespace.
Definition Version.h:4