Merge pull request #127 from jpcima/wavetable-phase
Add support of oscillator_phase
This commit is contained in:
commit
99f0833a96
7 changed files with 47 additions and 0 deletions
|
|
@ -53,6 +53,10 @@ namespace Default
|
||||||
constexpr SfzLoopMode loopMode { SfzLoopMode::no_loop };
|
constexpr SfzLoopMode loopMode { SfzLoopMode::no_loop };
|
||||||
constexpr Range<uint32_t> loopRange { 0, std::numeric_limits<uint32_t>::max() };
|
constexpr Range<uint32_t> loopRange { 0, std::numeric_limits<uint32_t>::max() };
|
||||||
|
|
||||||
|
// Wavetable oscillator
|
||||||
|
constexpr float oscillatorPhase { 0.0 };
|
||||||
|
constexpr Range<float> oscillatorPhaseRange { -1.0, 360.0 };
|
||||||
|
|
||||||
// Instrument setting: voice lifecycle
|
// Instrument setting: voice lifecycle
|
||||||
constexpr uint32_t group { 0 };
|
constexpr uint32_t group { 0 };
|
||||||
constexpr Range<uint32_t> groupRange { 0, std::numeric_limits<uint32_t>::max() };
|
constexpr Range<uint32_t> groupRange { 0, std::numeric_limits<uint32_t>::max() };
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,11 @@ bool sfz::Region::parseOpcode(const Opcode& opcode)
|
||||||
setRangeStartFromOpcode(opcode, loopRange, Default::loopRange);
|
setRangeStartFromOpcode(opcode, loopRange, Default::loopRange);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Wavetable oscillator
|
||||||
|
case hash("oscillator_phase"):
|
||||||
|
setValueFromOpcode(opcode, oscillatorPhase, Default::oscillatorPhaseRange);
|
||||||
|
break;
|
||||||
|
|
||||||
// Instrument settings: voice lifecycle
|
// Instrument settings: voice lifecycle
|
||||||
case hash("group"): // fallthrough
|
case hash("group"): // fallthrough
|
||||||
case hash("polyphony_group"):
|
case hash("polyphony_group"):
|
||||||
|
|
|
||||||
|
|
@ -226,6 +226,9 @@ struct Region {
|
||||||
absl::optional<SfzLoopMode> loopMode {}; // loopmode
|
absl::optional<SfzLoopMode> loopMode {}; // loopmode
|
||||||
Range<uint32_t> loopRange { Default::loopRange }; //loopstart and loopend
|
Range<uint32_t> loopRange { Default::loopRange }; //loopstart and loopend
|
||||||
|
|
||||||
|
// Wavetable oscillator
|
||||||
|
float oscillatorPhase { Default::oscillatorPhase };
|
||||||
|
|
||||||
// Instrument settings: voice lifecycle
|
// Instrument settings: voice lifecycle
|
||||||
uint32_t group { Default::group }; // group
|
uint32_t group { Default::group }; // group
|
||||||
absl::optional<uint32_t> offBy {}; // off_by
|
absl::optional<uint32_t> offBy {}; // off_by
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,17 @@ void sfz::Voice::startVoice(Region* region, int delay, int number, uint8_t value
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
waveOscillator.setWavetable(wave);
|
waveOscillator.setWavetable(wave);
|
||||||
|
|
||||||
|
float phase;
|
||||||
|
const float phaseParam = region->oscillatorPhase;
|
||||||
|
if (phaseParam >= 0) {
|
||||||
|
phase = phaseParam * (1.0f / 360.0f);
|
||||||
|
phase -= static_cast<int>(phase);
|
||||||
|
} else {
|
||||||
|
std::uniform_real_distribution<float> phaseDist { 0.0001f, 0.9999f };
|
||||||
|
phase = phaseDist(Random::randomGenerator);
|
||||||
|
}
|
||||||
|
waveOscillator.setPhase(phase);
|
||||||
} else {
|
} else {
|
||||||
currentPromise = resources.filePool.getFilePromise(region->sample);
|
currentPromise = resources.filePool.getFilePromise(region->sample);
|
||||||
if (currentPromise == nullptr) {
|
if (currentPromise == nullptr) {
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,12 @@ void WavetableOscillator::setWavetable(const WavetableMulti* wave)
|
||||||
_multi = wave ? wave : &silenceMulti;
|
_multi = wave ? wave : &silenceMulti;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WavetableOscillator::setPhase(float phase)
|
||||||
|
{
|
||||||
|
ASSERT(phase >= 0.0f && phase <= 1.0f);
|
||||||
|
_phase = phase;
|
||||||
|
}
|
||||||
|
|
||||||
void WavetableOscillator::process(float frequency, float* output, unsigned nframes)
|
void WavetableOscillator::process(float frequency, float* output, unsigned nframes)
|
||||||
{
|
{
|
||||||
float phase = _phase;
|
float phase = _phase;
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,11 @@ public:
|
||||||
*/
|
*/
|
||||||
void setWavetable(const WavetableMulti* wave);
|
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.
|
Compute a cycle of the oscillator, with constant frequency.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -1392,6 +1392,19 @@ TEST_CASE("[Region] Parsing opcodes")
|
||||||
region.parseOpcode({ "effect3", "-50.65" });
|
region.parseOpcode({ "effect3", "-50.65" });
|
||||||
REQUIRE(region.gainToEffect[3] == 0.0f);
|
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
|
// Specific region bugs
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue