commit ed283ee50d74c91b3f2519b9ea5cf2600c05efac
parent d2b830813138a15a0298e2979645cc30293f832e
Author: Matt Demanett <matt@demanett.net>
Date: Mon, 11 Sep 2023 18:23:18 -0400
Fix crashes in ARP. #229
Diffstat:
2 files changed, 36 insertions(+), 12 deletions(-)
diff --git a/src/Arp.cpp b/src/Arp.cpp
@@ -1,5 +1,6 @@
#include "Arp.hpp"
+#include <unordered_set>
#define NOTES_IMMEDIATE_MODE "notes_immediate"
#define FIXED_GATE_MODE "fixed_gate"
@@ -134,28 +135,38 @@ void Arp::NoteSet::resetSequence() {
}
void Arp::NoteSet::addNote(int c, float pitch) {
- Note n;
- n.pitch = pitch;
- n.channel = c;
- int i = 0;
- while (n.pitch >= _notesByPitch[i].pitch && i < _noteCount) {
- if (n.pitch == _notesByPitch[i].pitch) {
+ for (int i = 0; i < _noteCount; ++i) {
+ if (_notesByPitch[i].pitch == pitch) {
return;
}
- ++i;
}
- assert(i <= _noteCount);
dropNote(c);
_noteOn[c] = true;
_notesDirty = true;
- shuffleUp(_notesByPitch, i);
+ Note n;
+ n.pitch = pitch;
+ n.channel = c;
+ int i = 0;
+ while (n.pitch >= _notesByPitch[i].pitch && i < _noteCount) {
+ ++i;
+ }
+ assert(i <= maxChannels);
+
+ if (i >= maxChannels) {
+ i = maxChannels - 1;
+ }
+ else {
+ shuffleUp(_notesByPitch, i);
+ }
_notesByPitch[i] = n;
_notesAsPlayed[_noteCount] = n;
++_noteCount;
assert(_noteCount <= maxChannels);
+ assert(uniqueChannelsCount(_notesAsPlayed) == _noteCount);
+ assert(uniqueChannelsCount(_notesByPitch) == _noteCount);
}
void Arp::NoteSet::dropNote(int c) {
@@ -165,13 +176,14 @@ void Arp::NoteSet::dropNote(int c) {
_noteOn[c] = false;
_notesDirty = true;
+ assert(_noteCount > 0);
int i = 0;
while (_notesAsPlayed[i].channel != c && i < _noteCount) {
++i;
}
assert(i < _noteCount);
shuffleDown(_notesAsPlayed, i);
- _notesAsPlayed[_noteCount].reset();
+ _notesAsPlayed[_noteCount - 1].reset();
i = 0;
while (_notesByPitch[i].channel != c && i < _noteCount) {
@@ -179,10 +191,12 @@ void Arp::NoteSet::dropNote(int c) {
}
assert(i < _noteCount);
shuffleDown(_notesByPitch, i);
- _notesByPitch[_noteCount].reset();
+ _notesByPitch[_noteCount - 1].reset();
--_noteCount;
assert(_noteCount >= 0);
+ assert(uniqueChannelsCount(_notesAsPlayed) == _noteCount);
+ assert(uniqueChannelsCount(_notesByPitch) == _noteCount);
}
void Arp::NoteSet::shuffleUp(Note* notes, int index) {
@@ -210,6 +224,16 @@ void Arp::NoteSet::sync() {
_syncTo->_notesDirty = false;
}
+int Arp::NoteSet::uniqueChannelsCount(Note* notes) {
+ std::unordered_set<int> channels;
+ for (int i = 0; i < maxChannels; ++i) {
+ if (notes[i].channel >= 0) {
+ channels.insert(notes[i].channel);
+ }
+ }
+ return channels.size();
+}
+
void Arp::reset() {
_clockTrigger.reset();
_resetTrigger.reset();
diff --git a/src/Arp.hpp b/src/Arp.hpp
@@ -61,7 +61,6 @@ struct Arp : BGModule {
void reset();
};
-
bool _noteOn[maxChannels] {};
int _noteCount = 0;
Note _notesAsPlayed[maxChannels];
@@ -84,6 +83,7 @@ struct Arp : BGModule {
void shuffleUp(Note* notes, int index);
void shuffleDown(Note* notes, int index);
void sync();
+ int uniqueChannelsCount(Note* notes);
};
struct GateLengthParamQuantity : ParamQuantity {