From 1ba7e6deb23c229b7a4510e87bf28e86de5e5ef6 Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Thu, 11 Jun 2020 22:22:47 +0200 Subject: [PATCH] Add stretch tuning API and implement --- src/sfizz.h | 9 +++++++++ src/sfizz.hpp | 8 ++++++++ src/sfizz/Resources.h | 2 ++ src/sfizz/Synth.cpp | 11 +++++++++++ src/sfizz/Synth.h | 6 ++++++ src/sfizz/Voice.cpp | 5 +++++ src/sfizz/sfizz.cpp | 5 +++++ src/sfizz/sfizz_wrapper.cpp | 6 ++++++ 8 files changed, 52 insertions(+) diff --git a/src/sfizz.h b/src/sfizz.h index e0a0c0a2..69bff64b 100644 --- a/src/sfizz.h +++ b/src/sfizz.h @@ -137,6 +137,15 @@ SFIZZ_EXPORTED_API void sfizz_set_tuning_frequency(sfizz_synth_t* synth, float f */ SFIZZ_EXPORTED_API float sfizz_get_tuning_frequency(sfizz_synth_t* synth); +/** + * @brief Configure stretch tuning using a predefined parametric Railsback curve. + * A ratio 1/2 is supposed to match the average piano; 0 disables (the default). + * + * @param synth The sfizz synth. + * @param ratio The parameter in domain 0-1. + */ +SFIZZ_EXPORTED_API void sfizz_load_stretch_tuning_by_ratio(sfizz_synth_t* synth, float ratio); + /** * @brief Return the number of regions in the currently loaded SFZ file. * diff --git a/src/sfizz.hpp b/src/sfizz.hpp index a57a5a4d..8dbffc36 100644 --- a/src/sfizz.hpp +++ b/src/sfizz.hpp @@ -119,6 +119,14 @@ public: */ float getTuningFrequency() const; + /** + * @brief Configure stretch tuning using a predefined parametric Railsback curve. + * A ratio 1/2 is supposed to match the average piano; 0 disables (the default). + * + * @param ratio The parameter in domain 0-1. + */ + void loadStretchTuningByRatio(float ratio); + /** * @brief Return the current number of regions loaded. */ diff --git a/src/sfizz/Resources.h b/src/sfizz/Resources.h index c998eb3c..933dde27 100644 --- a/src/sfizz/Resources.h +++ b/src/sfizz/Resources.h @@ -13,6 +13,7 @@ #include "Wavetables.h" #include "Curve.h" #include "Tuning.h" +#include "absl/types/optional.h" namespace sfz { @@ -29,6 +30,7 @@ struct Resources EQPool eqPool { midiState }; WavetablePool wavePool; Tuning tuning; + absl::optional stretch; void setSampleRate(float samplerate) { diff --git a/src/sfizz/Synth.cpp b/src/sfizz/Synth.cpp index 2718a1e1..50e9a569 100644 --- a/src/sfizz/Synth.cpp +++ b/src/sfizz/Synth.cpp @@ -516,6 +516,17 @@ float sfz::Synth::getTuningFrequency() const return resources.tuning.getTuningFrequency(); } +void sfz::Synth::loadStretchTuningByRatio(float ratio) +{ + CHECK(ratio >= 0.0f && ratio <= 1.0f); + ratio = clamp(ratio, 0.0f, 1.0f); + + if (ratio > 0.0f) + resources.stretch = StretchTuning::createRailsbackFromRatio(ratio); + else + resources.stretch.reset(); +} + sfz::Voice* sfz::Synth::findFreeVoice() noexcept { auto freeVoice = absl::c_find_if(voices, [](const std::unique_ptr& voice) { diff --git a/src/sfizz/Synth.h b/src/sfizz/Synth.h index 0819880e..84330734 100644 --- a/src/sfizz/Synth.h +++ b/src/sfizz/Synth.h @@ -150,6 +150,12 @@ public: * @return The frequency which indicates where standard tuning A4 is (default 440 Hz). */ float getTuningFrequency() const; + /** + * @brief Configure stretch tuning using a predefined parametric Railsback curve. + * + * @param ratio The parameter in domain 0-1. + */ + void loadStretchTuningByRatio(float ratio); /** * @brief Get the current number of regions loaded * diff --git a/src/sfizz/Voice.cpp b/src/sfizz/Voice.cpp index 6ae90db2..9f6df3a3 100644 --- a/src/sfizz/Voice.cpp +++ b/src/sfizz/Voice.cpp @@ -87,6 +87,11 @@ void sfz::Voice::startVoice(Region* region, int delay, int number, float value, const float numberRetuned = resources.tuning.getKeyFractional12TET(number); pitchRatio = region->getBasePitchVariation(numberRetuned, value); + + // apply stretch tuning if set + if (resources.stretch) + pitchRatio *= resources.stretch->getRatioForFractionalKey(numberRetuned); + baseVolumedB = region->getBaseVolumedB(number); baseGain = region->getBaseGain(); if (triggerType != TriggerType::CC) diff --git a/src/sfizz/sfizz.cpp b/src/sfizz/sfizz.cpp index 31047c77..b110b4e1 100644 --- a/src/sfizz/sfizz.cpp +++ b/src/sfizz/sfizz.cpp @@ -58,6 +58,11 @@ float sfz::Sfizz::getTuningFrequency() const return synth->getTuningFrequency(); } +void sfz::Sfizz::loadStretchTuningByRatio(float ratio) +{ + return synth->loadStretchTuningByRatio(ratio); +} + int sfz::Sfizz::getNumRegions() const noexcept { return synth->getNumRegions(); diff --git a/src/sfizz/sfizz_wrapper.cpp b/src/sfizz/sfizz_wrapper.cpp index 86ef1b67..15310942 100644 --- a/src/sfizz/sfizz_wrapper.cpp +++ b/src/sfizz/sfizz_wrapper.cpp @@ -67,6 +67,12 @@ float sfizz_get_tuning_frequency(sfizz_synth_t* synth) return self->getTuningFrequency(); } +void sfizz_load_stretch_tuning_by_ratio(sfizz_synth_t* synth, float ratio) +{ + auto self = reinterpret_cast(synth); + self->loadStretchTuningByRatio(ratio); +} + void sfizz_free(sfizz_synth_t* synth) { delete reinterpret_cast(synth);