7fe70ed89b
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"
76 lines
2.3 KiB
C++
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
|