diff --git a/src/sfizz/NumericId.h b/src/sfizz/NumericId.h index 1d975ec0..b2fed501 100644 --- a/src/sfizz/NumericId.h +++ b/src/sfizz/NumericId.h @@ -27,5 +27,15 @@ struct NumericId { return number != -1; } + constexpr bool operator==(NumericId other) const noexcept + { + return number == other.number; + } + + constexpr bool operator!=(NumericId other) const noexcept + { + return number != other.number; + } + const int number = -1; }; diff --git a/src/sfizz/Synth.cpp b/src/sfizz/Synth.cpp index c609d3c5..001dae48 100644 --- a/src/sfizz/Synth.cpp +++ b/src/sfizz/Synth.cpp @@ -1056,6 +1056,40 @@ const sfz::EffectBus* sfz::Synth::getEffectBusView(int idx) const noexcept return (size_t)idx < effectBuses.size() ? effectBuses[idx].get() : nullptr; } +const sfz::Region* sfz::Synth::getRegionById(NumericId id) const noexcept +{ + const size_t size = regions.size(); + + if (size == 0 || !id.valid()) + return nullptr; + + // search a sequence of ordered identifiers with potential gaps + size_t index = static_cast(id.number); + index = std::min(index, size - 1); + + while (index > 0 && regions[index]->getId().number > id.number) + --index; + + return (regions[index]->getId() == id) ? regions[index].get() : nullptr; +} + +const sfz::Voice* sfz::Synth::getVoiceById(NumericId id) const noexcept +{ + const size_t size = voices.size(); + + if (size == 0 || !id.valid()) + return nullptr; + + // search a sequence of ordered identifiers with potential gaps + size_t index = static_cast(id.number); + index = std::min(index, size - 1); + + while (index > 0 && voices[index]->getId().number > id.number) + --index; + + return (voices[index]->getId() == id) ? voices[index].get() : nullptr; +} + const sfz::Voice* sfz::Synth::getVoiceView(int idx) const noexcept { return (size_t)idx < voices.size() ? voices[idx].get() : nullptr; diff --git a/src/sfizz/Synth.h b/src/sfizz/Synth.h index d04a5c96..9c5420e9 100644 --- a/src/sfizz/Synth.h +++ b/src/sfizz/Synth.h @@ -178,6 +178,20 @@ public: * @brief Export a MIDI Name document describing the loaded instrument */ std::string exportMidnam(absl::string_view model = {}) const; + /** + * @brief Find the region which is associated with the given identifier. + * + * @param id + * @return const Region* + */ + const Region* getRegionById(NumericId id) const noexcept; + /** + * @brief Find the voice which is associated with the given identifier. + * + * @param id + * @return const Voice* + */ + const Voice* getVoiceById(NumericId id) const noexcept; /** * @brief Get a raw view into a specific region. This is mostly used * for testing.