From 890d5ddb46d1a33f3a2141c1282f1c85f80c771b Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Mon, 16 Mar 2020 19:02:21 +0100 Subject: [PATCH 1/4] Add support of oscillator_phase --- src/sfizz/Defaults.h | 4 ++++ src/sfizz/Region.cpp | 5 +++++ src/sfizz/Region.h | 3 +++ src/sfizz/Voice.cpp | 11 +++++++++++ src/sfizz/Wavetables.cpp | 5 +++++ src/sfizz/Wavetables.h | 5 +++++ 6 files changed, 33 insertions(+) diff --git a/src/sfizz/Defaults.h b/src/sfizz/Defaults.h index 9e2684b7..f8f2d2d2 100644 --- a/src/sfizz/Defaults.h +++ b/src/sfizz/Defaults.h @@ -53,6 +53,10 @@ namespace Default constexpr SfzLoopMode loopMode { SfzLoopMode::no_loop }; constexpr Range loopRange { 0, std::numeric_limits::max() }; + // Wavetable oscillator + constexpr float oscillatorPhase { 0.0 }; + constexpr Range oscillatorPhaseRange { -1.0, 360.0 }; + // Instrument setting: voice lifecycle constexpr uint32_t group { 0 }; constexpr Range groupRange { 0, std::numeric_limits::max() }; diff --git a/src/sfizz/Region.cpp b/src/sfizz/Region.cpp index 10c5415a..8d8f14ee 100644 --- a/src/sfizz/Region.cpp +++ b/src/sfizz/Region.cpp @@ -95,6 +95,11 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) setRangeStartFromOpcode(opcode, loopRange, Default::loopRange); break; + // Wavetable oscillator + case hash("oscillator_phase"): + setValueFromOpcode(opcode, oscillatorPhase, Default::oscillatorPhaseRange); + break; + // Instrument settings: voice lifecycle case hash("group"): // fallthrough case hash("polyphony_group"): diff --git a/src/sfizz/Region.h b/src/sfizz/Region.h index fa5ea786..3ef284d0 100644 --- a/src/sfizz/Region.h +++ b/src/sfizz/Region.h @@ -226,6 +226,9 @@ struct Region { absl::optional loopMode {}; // loopmode Range loopRange { Default::loopRange }; //loopstart and loopend + // Wavetable oscillator + float oscillatorPhase { Default::oscillatorPhase }; + // Instrument settings: voice lifecycle uint32_t group { Default::group }; // group absl::optional offBy {}; // off_by diff --git a/src/sfizz/Voice.cpp b/src/sfizz/Voice.cpp index 423dda3a..b3c35a86 100644 --- a/src/sfizz/Voice.cpp +++ b/src/sfizz/Voice.cpp @@ -58,6 +58,17 @@ void sfz::Voice::startVoice(Region* region, int delay, int number, uint8_t value break; } waveOscillator.setWavetable(wave); + + float phase; + float phaseParam = region->oscillatorPhase; + if (phaseParam >= 0) { + phase = phaseParam * (1.0f / 360.0f); + phase -= static_cast(phase); + } else { + std::uniform_real_distribution phaseDist { 0.0001f, 0.9999f }; + phase = phaseDist(Random::randomGenerator); + } + waveOscillator.setPhase(phase); } else { currentPromise = resources.filePool.getFilePromise(region->sample); if (currentPromise == nullptr) { diff --git a/src/sfizz/Wavetables.cpp b/src/sfizz/Wavetables.cpp index 1e27853b..6073540f 100644 --- a/src/sfizz/Wavetables.cpp +++ b/src/sfizz/Wavetables.cpp @@ -30,6 +30,11 @@ void WavetableOscillator::setWavetable(const WavetableMulti* wave) _multi = wave ? wave : &silenceMulti; } +void WavetableOscillator::setPhase(float phase) +{ + _phase = phase; +} + void WavetableOscillator::process(float frequency, float* output, unsigned nframes) { float phase = _phase; diff --git a/src/sfizz/Wavetables.h b/src/sfizz/Wavetables.h index e6b8dff2..bdc715bc 100644 --- a/src/sfizz/Wavetables.h +++ b/src/sfizz/Wavetables.h @@ -37,6 +37,11 @@ public: */ void setWavetable(const WavetableMulti* wave); + /** + Set the current phase of this oscillator, between 0 and 1 excluded. + */ + void setPhase(float phase); + /** Compute a cycle of the oscillator, with constant frequency. */ From 281ee61146de70dff20b5f5172583b8e7ce6300e Mon Sep 17 00:00:00 2001 From: Paul Ferrand Date: Fri, 27 Mar 2020 18:05:30 +0100 Subject: [PATCH 2/4] local variable can be const --- src/sfizz/Voice.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sfizz/Voice.cpp b/src/sfizz/Voice.cpp index b3c35a86..719efdfc 100644 --- a/src/sfizz/Voice.cpp +++ b/src/sfizz/Voice.cpp @@ -60,7 +60,7 @@ void sfz::Voice::startVoice(Region* region, int delay, int number, uint8_t value waveOscillator.setWavetable(wave); float phase; - float phaseParam = region->oscillatorPhase; + const float phaseParam = region->oscillatorPhase; if (phaseParam >= 0) { phase = phaseParam * (1.0f / 360.0f); phase -= static_cast(phase); From 3f3cb7def8e3b5d93d0ddd564df75812e375cfb0 Mon Sep 17 00:00:00 2001 From: Paul Ferrand Date: Fri, 27 Mar 2020 18:05:40 +0100 Subject: [PATCH 3/4] Add an assertion --- src/sfizz/Wavetables.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sfizz/Wavetables.cpp b/src/sfizz/Wavetables.cpp index 6073540f..355b9fca 100644 --- a/src/sfizz/Wavetables.cpp +++ b/src/sfizz/Wavetables.cpp @@ -32,6 +32,7 @@ void WavetableOscillator::setWavetable(const WavetableMulti* wave) void WavetableOscillator::setPhase(float phase) { + ASSERT(phase >= 0.0f && phase <= 1.0f); _phase = phase; } From dcd688dbe56129cac55f268a5b2f08b7db9b4289 Mon Sep 17 00:00:00 2001 From: Paul Ferrand Date: Fri, 27 Mar 2020 18:17:15 +0100 Subject: [PATCH 4/4] Add oscillator phase tests --- tests/RegionT.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/RegionT.cpp b/tests/RegionT.cpp index 354cd06b..81af69bb 100644 --- a/tests/RegionT.cpp +++ b/tests/RegionT.cpp @@ -1392,6 +1392,19 @@ TEST_CASE("[Region] Parsing opcodes") region.parseOpcode({ "effect3", "-50.65" }); REQUIRE(region.gainToEffect[3] == 0.0f); } + + SECTION("Wavetable phase") + { + REQUIRE(region.oscillatorPhase == 0.0f); + region.parseOpcode({ "oscillator_phase", "45" }); + REQUIRE(region.oscillatorPhase == 45.0f); + region.parseOpcode({ "oscillator_phase", "45.32" }); + REQUIRE(region.oscillatorPhase == 45.32_a); + region.parseOpcode({ "oscillator_phase", "-1" }); + REQUIRE(region.oscillatorPhase == -1.0f); + region.parseOpcode({ "oscillator_phase", "361" }); + REQUIRE(region.oscillatorPhase == 360.0f); + } } // Specific region bugs