paulxstretch/deps/clap-juce-extensions/clap-libs/clap-helpers/include/clap/helpers/note-end-queue.hh
essej 7fe70ed89b git subrepo clone (merge) https://github.com/free-audio/clap-helpers.git deps/clap-juce-extensions/clap-libs/clap-helpers
subrepo:
  subdir:   "deps/clap-juce-extensions/clap-libs/clap-helpers"
  merged:   "2bb43c187"
upstream:
  origin:   "https://github.com/free-audio/clap-helpers.git"
  branch:   "main"
  commit:   "2bb43c187"
git-subrepo:
  version:  "0.4.3"
  origin:   "https://github.com/ingydotnet/git-subrepo.git"
  commit:   "2f68596"
2022-06-14 21:35:21 -04:00

76 lines
2.3 KiB
C++

#include <cassert>
#include <cstddef>
#include <cstdint>
#include <unordered_set>
#include <clap/clap.h>
namespace clap { namespace helpers {
class NoteEndQueue {
public:
explicit NoteEndQueue(std::size_t initialBucketSize = 19)
: _voicesToKill(initialBucketSize) {}
void onNoteOn(int32_t noteId, int16_t port, int16_t channel, int16_t key) {
assert(checkValidEntry(noteId, port, channel, key));
_voicesToKill.erase(Entry(noteId, port, channel, key));
}
void onNoteEnd(int32_t noteId, int16_t port, int16_t channel, int16_t key) {
assert(checkValidEntry(noteId, port, channel, key));
_voicesToKill.insert(Entry(noteId, port, channel, key));
}
void flush(const clap_output_events *out) {
clap_event_note ev;
ev.velocity = 0;
ev.header.flags = 0;
ev.header.size = sizeof(ev);
ev.header.space_id = CLAP_CORE_EVENT_SPACE_ID;
ev.header.time = 0; // time is irrelevant here
ev.header.type = CLAP_EVENT_NOTE_END;
for (auto &e : _voicesToKill) {
ev.port_index = e._port;
ev.channel = e._channel;
ev.key = e._key;
ev.note_id = e._noteId;
out->try_push(out, &ev.header);
}
_voicesToKill.clear();
}
private:
bool checkValidEntry(int32_t noteId, int16_t port, int16_t channel, int16_t key) {
assert(noteId >= -1);
assert(port >= 0);
assert(channel >= 0 && channel < 16);
assert(key >= 0 && key < 127);
return true;
}
struct Entry {
constexpr Entry(int32_t noteId, int16_t port, int16_t channel, int16_t key)
: _noteId(noteId), _port(port), _channel(channel), _key(key) {}
constexpr bool operator==(const Entry &o) const noexcept {
return _port == o._port && _channel == o._channel && _key == o._key;
}
const int32_t _noteId;
const int16_t _port;
const int16_t _channel;
const int16_t _key;
};
struct EntryHash {
std::size_t operator()(const Entry &e) const noexcept {
return e._key ^ (e._channel << 8) ^ (e._port << 16) ^ (int64_t(e._noteId) << 32LL);
}
};
std::unordered_set<Entry, EntryHash> _voicesToKill;
};
}} // namespace clap::helpers