aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/adlmidi_midiplay.cpp130
-rw-r--r--src/adlmidi_private.hpp109
2 files changed, 152 insertions, 87 deletions
diff --git a/src/adlmidi_midiplay.cpp b/src/adlmidi_midiplay.cpp
index 88c1b39..7c40fa0 100644
--- a/src/adlmidi_midiplay.cpp
+++ b/src/adlmidi_midiplay.cpp
@@ -2434,17 +2434,7 @@ uint64_t MIDIplay::ChooseDevice(const std::string &name)
size_t n = devices.size() * 16;
devices.insert(std::make_pair(name, n));
-
- size_t channelsBefore = Ch.size();
- size_t channels = n + 16;
- Ch.resize(channels);
-
- for(size_t ch = channelsBefore; ch < channels; ++ch) {
- for(unsigned i = 0; i < 128; ++i) {
- Ch[ch].activenotes[i].note = i;
- Ch[ch].activenotes[i].active = false;
- }
- }
+ Ch.resize(n + 16);
return n;
}
@@ -2708,3 +2698,121 @@ ADLMIDI_EXPORT bool AdlInstrumentTester::HandleInputChar(char ch)
}
#endif//ADLMIDI_DISABLE_CPP_EXTRAS
+
+// Implement the user map data structure.
+
+bool MIDIplay::AdlChannel::users_empty() const
+{
+ return !users_first;
+}
+
+MIDIplay::AdlChannel::LocationData *MIDIplay::AdlChannel::users_find(Location loc)
+{
+ LocationData *user = NULL;
+ for(LocationData *curr = users_first; !user && curr; curr = curr->next)
+ if(curr->loc == loc)
+ user = curr;
+ return user;
+}
+
+MIDIplay::AdlChannel::LocationData *MIDIplay::AdlChannel::users_allocate()
+{
+ // remove free cells front
+ LocationData *user = users_free_cells;
+ if(!user)
+ return NULL;
+ users_free_cells = user->next;
+ if(users_free_cells)
+ users_free_cells->prev = NULL;
+ // add to users front
+ if(users_first)
+ users_first->prev = user;
+ user->prev = NULL;
+ user->next = users_first;
+ users_first = user;
+ ++users_size;
+ return user;
+}
+
+MIDIplay::AdlChannel::LocationData *MIDIplay::AdlChannel::users_find_or_create(Location loc)
+{
+ LocationData *user = users_find(loc);
+ if(!user) {
+ user = users_allocate();
+ if(!user)
+ return NULL;
+ LocationData *prev = user->prev, *next = user->next;
+ *user = LocationData();
+ user->prev = prev; user->next = next;
+ user->loc = loc;
+ }
+ return user;
+}
+
+MIDIplay::AdlChannel::LocationData *MIDIplay::AdlChannel::users_insert(const LocationData &x)
+{
+ LocationData *user = users_find(x.loc);
+ if(!user)
+ {
+ user = users_allocate();
+ if(!user)
+ return NULL;
+ LocationData *prev = user->prev, *next = user->next;
+ *user = x;
+ user->prev = prev; user->next = next;
+ }
+ return user;
+}
+
+void MIDIplay::AdlChannel::users_erase(LocationData *user)
+{
+ if(user->prev)
+ user->prev->next = user->next;
+ if(user->next)
+ user->next->prev = user->prev;
+ if(user == users_first)
+ users_first = user->next;
+ user->prev = NULL;
+ user->next = users_free_cells;
+ users_free_cells = user;
+ --users_size;
+}
+
+void MIDIplay::AdlChannel::users_clear()
+{
+ users_first = NULL;
+ users_free_cells = users_cells;
+ users_size = 0;
+ for(size_t i = 0; i < users_max; ++i)
+ {
+ users_cells[i].prev = (i > 0) ? &users_cells[i - 1] : NULL;
+ users_cells[i].next = (i + 1 < users_max) ? &users_cells[i + 1] : NULL;
+ }
+}
+
+void MIDIplay::AdlChannel::users_assign(const LocationData *users, size_t count)
+{
+ assert(count <= users_max);
+ if(users == users_first && users) {
+ // self assignment
+ assert(users_size == count);
+ return;
+ }
+ users_clear();
+ const LocationData *src_cell = users;
+ // move to the last
+ if(src_cell) {
+ while(src_cell->next)
+ src_cell = src_cell->next;
+ }
+ // push cell copies in reverse order
+ while(src_cell) {
+ LocationData *dst_cell = users_allocate();
+ assert(dst_cell);
+ LocationData *prev = dst_cell->prev, *next = dst_cell->next;
+ *dst_cell = *src_cell;
+ dst_cell->prev = prev; dst_cell->next = next;
+ src_cell = src_cell->prev;
+ }
+ assert(users_size == count);
+}
diff --git a/src/adlmidi_private.hpp b/src/adlmidi_private.hpp
index adcf9cb..0fabf35 100644
--- a/src/adlmidi_private.hpp
+++ b/src/adlmidi_private.hpp
@@ -736,6 +736,7 @@ public:
activenoteiterator activenotes_find(uint8_t note)
{
+ assert(note < 128);
return activenoteiterator(
activenotes[note].active ? &activenotes[note] : 0);
}
@@ -749,6 +750,7 @@ public:
std::pair<activenoteiterator, bool> activenotes_insert(uint8_t note)
{
+ assert(note < 128);
NoteInfo &info = activenotes[note];
bool inserted = !info.active;
if(inserted) info.active = true;
@@ -766,6 +768,14 @@ public:
return !activenotes_begin();
}
+ void activenotes_clear()
+ {
+ for(unsigned i = 0; i < 128; ++i) {
+ activenotes[i].note = i;
+ activenotes[i].active = false;
+ }
+ }
+
void reset()
{
resetAllControllers();
@@ -794,8 +804,8 @@ public:
brightness = 127;
}
MIDIchannel()
- : activenotes()
{
+ activenotes_clear();
reset();
}
};
@@ -831,86 +841,33 @@ public:
LocationData users_cells[users_max];
unsigned users_size;
- bool users_empty() const
- { return !users_first; }
- LocationData *users_find(Location loc)
- {
- LocationData *user = NULL;
- for(LocationData *curr = users_first; !user && curr; curr = curr->next)
- if(curr->loc == loc)
- user = curr;
- return user;
- }
- LocationData *users_allocate()
- {
- // remove free cells front
- LocationData *user = users_free_cells;
- if(!user)
- return NULL;
- users_free_cells = user->next;
- if(users_free_cells)
- users_free_cells->prev = NULL;
- // add to users front
- if(users_first)
- users_first->prev = user;
- user->prev = NULL;
- user->next = users_first;
- users_first = user;
- ++users_size;
- return user;
- }
- LocationData *users_find_or_create(Location loc)
- {
- LocationData *user = users_find(loc);
- if(!user) {
- user = users_allocate();
- if(!user)
- return NULL;
- LocationData *prev = user->prev, *next = user->next;
- *user = LocationData();
- user->prev = prev; user->next = next;
- user->loc = loc;
- }
- return user;
- }
- LocationData *users_insert(const LocationData &x)
- {
- LocationData *user = users_find(x.loc);
- if(!user)
- {
- user = users_allocate();
- if(!user)
- return NULL;
- LocationData *prev = user->prev, *next = user->next;
- *user = x;
- user->prev = prev; user->next = next;
- }
- return user;
- }
- void users_erase(LocationData *user)
+ bool users_empty() const;
+ LocationData *users_find(Location loc);
+ LocationData *users_allocate();
+ LocationData *users_find_or_create(Location loc);
+ LocationData *users_insert(const LocationData &x);
+ void users_erase(LocationData *user);
+ void users_clear();
+ void users_assign(const LocationData *users, size_t count);
+
+ // For channel allocation:
+ AdlChannel(): koff_time_until_neglible(0)
{
- if(user->prev)
- user->prev->next = user->next;
- if(user->next)
- user->next->prev = user->prev;
- if(user == users_first)
- users_first = user->next;
- user->prev = NULL;
- user->next = users_free_cells;
- users_free_cells = user;
- --users_size;
+ users_clear();
}
- // For channel allocation:
- AdlChannel(): koff_time_until_neglible(0), users_first(NULL), users_size(0)
+ AdlChannel(const AdlChannel &oth): koff_time_until_neglible(oth.koff_time_until_neglible)
{
- users_free_cells = users_cells;
- for(size_t i = 0; i < users_max; ++i)
- {
- users_cells[i].prev = (i > 0) ? &users_cells[i - 1] : NULL;
- users_cells[i].next = (i + 1 < users_max) ? &users_cells[i + 1] : NULL;
- }
+ users_assign(oth.users_first, oth.users_size);
}
+
+ AdlChannel &operator=(const AdlChannel &oth)
+ {
+ koff_time_until_neglible = oth.koff_time_until_neglible;
+ users_assign(oth.users_first, oth.users_size);
+ return *this;
+ }
+
void AddAge(int64_t ms);
};