diff --git a/src/sfizz.h b/src/sfizz.h index 13432f5d..4e595bec 100644 --- a/src/sfizz.h +++ b/src/sfizz.h @@ -191,6 +191,19 @@ SFIZZ_EXPORTED_API void sfizz_send_note_off(sfizz_synth_t* synth, int delay, int */ SFIZZ_EXPORTED_API void sfizz_send_cc(sfizz_synth_t* synth, int delay, int cc_number, char cc_value); +/** + * @brief Send a high precision CC event to the synth. As with all MIDI + * events, this needs to happen before the call to + * sfizz_render_block in each block and should appear in order of + * the delays. + * + * @param synth The synth. + * @param delay The delay of the event in the block, in samples. + * @param cc_number The MIDI CC number. + * @param norm_value The normalized CC value, in domain 0 to 1. + */ +SFIZZ_EXPORTED_API void sfizz_send_hdcc(sfizz_synth_t* synth, int delay, int cc_number, float norm_value); + /** * @brief Send a pitch wheel event. As with all MIDI events, this needs * to happen before the call to sfizz_render_block in each block and diff --git a/src/sfizz.hpp b/src/sfizz.hpp index 63bd8173..1bd61935 100644 --- a/src/sfizz.hpp +++ b/src/sfizz.hpp @@ -163,6 +163,16 @@ public: */ void cc(int delay, int ccNumber, uint8_t ccValue) noexcept; + /** + * @brief Send a high precision CC event to the synth + * + * @param delay the delay at which the event occurs; this should be lower than the size of + * the block in the next call to renderBlock(). + * @param ccNumber the cc number. + * @param normValue the normalized cc value, in domain 0 to 1. + */ + void hdcc(int delay, int ccNumber, float normValue) noexcept; + /** * @brief Send a pitch bend event to the synth * diff --git a/src/sfizz/Synth.cpp b/src/sfizz/Synth.cpp index 5bc5c376..3df4f5f0 100644 --- a/src/sfizz/Synth.cpp +++ b/src/sfizz/Synth.cpp @@ -844,13 +844,18 @@ void sfz::Synth::noteOnDispatch(int delay, int noteNumber, float velocity) noexc } void sfz::Synth::cc(int delay, int ccNumber, uint8_t ccValue) noexcept +{ + const auto normalizedCC = normalizeCC(ccValue); + hdcc(delay, ccNumber, normalizedCC); +} + +void sfz::Synth::hdcc(int delay, int ccNumber, float normValue) noexcept { ASSERT(ccNumber < config::numCCs); ASSERT(ccNumber >= 0); - const auto normalizedCC = normalizeCC(ccValue); ScopedTiming logger { dispatchDuration, ScopedTiming::Operation::addToDuration }; - resources.midiState.ccEvent(delay, ccNumber, normalizedCC); + resources.midiState.ccEvent(delay, ccNumber, normValue); const std::unique_lock lock { callbackGuard, std::try_to_lock }; if (!lock.owns_lock()) @@ -862,15 +867,15 @@ void sfz::Synth::cc(int delay, int ccNumber, uint8_t ccValue) noexcept } for (auto& voice : voices) - voice->registerCC(delay, ccNumber, normalizedCC); + voice->registerCC(delay, ccNumber, normValue); for (auto& region : ccActivationLists[ccNumber]) { - if (region->registerCC(ccNumber, normalizedCC)) { + if (region->registerCC(ccNumber, normValue)) { auto voice = findFreeVoice(); if (voice == nullptr) continue; - voice->startVoice(region, delay, ccNumber, normalizedCC, Voice::TriggerType::CC); + voice->startVoice(region, delay, ccNumber, normValue, Voice::TriggerType::CC); } } } diff --git a/src/sfizz/Synth.h b/src/sfizz/Synth.h index 5cbeb455..1c711552 100644 --- a/src/sfizz/Synth.h +++ b/src/sfizz/Synth.h @@ -236,6 +236,15 @@ public: * @param ccValue the cc value */ void cc(int delay, int ccNumber, uint8_t ccValue) noexcept; + /** + * @brief Send a high precision CC event to the synth + * + * @param delay the delay at which the event occurs; this should be lower than the size of + * the block in the next call to renderBlock(). + * @param ccNumber the cc number + * @param normValue the normalized cc value, in domain 0 to 1 + */ + void hdcc(int delay, int ccNumber, float normValue) noexcept; /** * @brief Send a pitch bend event to the synth * diff --git a/src/sfizz/sfizz.cpp b/src/sfizz/sfizz.cpp index 6020dd11..7fdef570 100644 --- a/src/sfizz/sfizz.cpp +++ b/src/sfizz/sfizz.cpp @@ -93,6 +93,11 @@ void sfz::Sfizz::cc(int delay, int ccNumber, uint8_t ccValue) noexcept synth->cc(delay, ccNumber, ccValue); } +void sfz::Sfizz::hdcc(int delay, int ccNumber, float normValue) noexcept +{ + synth->hdcc(delay, ccNumber, normValue); +} + void sfz::Sfizz::pitchWheel(int delay, int pitch) noexcept { synth->pitchWheel(delay, pitch); diff --git a/src/sfizz/sfizz_wrapper.cpp b/src/sfizz/sfizz_wrapper.cpp index 28eb3fdd..9ec6eb6c 100644 --- a/src/sfizz/sfizz_wrapper.cpp +++ b/src/sfizz/sfizz_wrapper.cpp @@ -98,6 +98,11 @@ void sfizz_send_cc(sfizz_synth_t* synth, int delay, int cc_number, char cc_value auto self = reinterpret_cast(synth); self->cc(delay, cc_number, cc_value); } +void sfizz_send_hdcc(sfizz_synth_t* synth, int delay, int cc_number, float norm_value) +{ + auto self = reinterpret_cast(synth); + self->hdcc(delay, cc_number, norm_value); +} void sfizz_send_pitch_wheel(sfizz_synth_t* synth, int delay, int pitch) { auto self = reinterpret_cast(synth);