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 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
|
||||
constexpr uint32_t group { 0 };
|
||||
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);
|
||||
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"):
|
||||
|
|
|
|||
|
|
@ -226,6 +226,9 @@ struct Region {
|
|||
absl::optional<SfzLoopMode> loopMode {}; // loopmode
|
||||
Range<uint32_t> loopRange { Default::loopRange }; //loopstart and loopend
|
||||
|
||||
// Wavetable oscillator
|
||||
float oscillatorPhase { Default::oscillatorPhase };
|
||||
|
||||
// Instrument settings: voice lifecycle
|
||||
uint32_t group { Default::group }; // group
|
||||
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;
|
||||
}
|
||||
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 {
|
||||
currentPromise = resources.filePool.getFilePromise(region->sample);
|
||||
if (currentPromise == nullptr) {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,12 @@ void WavetableOscillator::setWavetable(const WavetableMulti* wave)
|
|||
_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)
|
||||
{
|
||||
float phase = _phase;
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue