summaryrefslogtreecommitdiff
path: root/src/events_ds.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/events_ds.h')
-rw-r--r--src/events_ds.h135
1 files changed, 135 insertions, 0 deletions
diff --git a/src/events_ds.h b/src/events_ds.h
new file mode 100644
index 0000000..4a31f47
--- /dev/null
+++ b/src/events_ds.h
@@ -0,0 +1,135 @@
+/* -*- Mode: c++ -*- */
+/***************************************************************************
+ * events_ds.h
+ *
+ * Sun Jan 12 00:17:31 CET 2020
+ * Copyright 2020 André Nusser
+ * andre.nusser@googlemail.com
+ ****************************************************************************/
+
+/*
+ * This file is part of DrumGizmo.
+ *
+ * DrumGizmo is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * DrumGizmo is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with DrumGizmo; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+#pragma once
+
+#include <config.h>
+
+#include <algorithm>
+#include <array>
+#include <vector>
+
+#include "events.h"
+#include "id.h"
+#include "memory_heap.h"
+#include "range.h"
+#include "instrument.h"
+
+// TODO: make it possible to choose sizes
+
+struct EventsDS
+{
+ //
+ // member functions
+ //
+ EventsDS() = default;
+
+ template <typename T, typename... Args>
+ T& emplace(int ch, Args&&... args);
+
+ void remove(EventID event_id);
+
+ std::size_t numberOfEvents(int ch) const;
+
+ template <typename T>
+ ContainerRange<std::vector<T>> iterateOver(int ch);
+
+ EventGroupIDs const& getSampleEventGroupIDsOf(InstrumentID instrument_id) const;
+ EventIDs const& getEventIDsOf(EventGroupID event_group_id) const;
+
+ void startAddingNewGroup(InstrumentID instrument_id = InstrumentID());
+
+private:
+ struct ChannelData {
+ std::vector<SampleEvent> sample_events;
+ };
+
+ using ChannelEventIndex = std::size_t;
+
+ struct EventInfo {
+ Event::Type type;
+ int ch;
+ ChannelEventIndex channel_event_index;
+
+ EventInfo(Event::Type type, int ch, ChannelEventIndex channel_event_index)
+ : type(type), ch(ch), channel_event_index(channel_event_index) {}
+ };
+ struct GroupData {
+ EventIDs event_ids;
+ Event::Type type;
+
+ // SampleEvent specific data
+ std::size_t instrument_index;
+ };
+
+ // general data
+ std::array<ChannelData, NUM_CHANNELS> channel_data_array;
+ MemoryHeap<EventInfo> id_to_info;
+ MemoryHeap<GroupData> id_to_group_data;
+
+ // SampleEvent specific data
+ // TODO: maybe use something that actually has the size of the number of instruments
+ // Also, can we guarantee that there are at most 128 instrument ids?
+ std::array<EventGroupIDs, 128> instruments_sample_event_group_ids;
+
+ EventGroupID current_group_id;
+ InstrumentID current_groups_instrument_id;
+
+ void removeGroup(EventGroupID group_id, InstrumentID instrument_id = InstrumentID());
+};
+
+template <typename T, typename... Args>
+T& EventsDS::emplace(int ch, Args&&... args)
+{
+ if (std::is_same<T, SampleEvent>::value)
+ {
+ auto& sample_events = channel_data_array[ch].sample_events;
+ auto channel_event_index = sample_events.size();
+ sample_events.emplace_back(std::forward<Args>(args)...);
+
+ auto event_id = id_to_info.emplace(Event::Type::SampleEvent, ch, channel_event_index);
+ id_to_group_data.get(current_group_id).event_ids.push_back(event_id);
+
+ auto& sample_event = sample_events.back();
+ sample_event.id = event_id;
+ sample_event.group_id = current_group_id;
+ assert(sample_event.instrument_id == current_groups_instrument_id);
+
+ return sample_event;
+ }
+
+ assert(false);
+}
+
+template <typename T>
+ContainerRange<std::vector<T>> EventsDS::iterateOver(int ch)
+{
+ if (std::is_same<T, SampleEvent>::value)
+ {
+ auto& sample_events = channel_data_array[ch].sample_events;
+ return ContainerRange<std::vector<T>>(sample_events.begin(), sample_events.end());
+ }
+}