diff --git a/sources/Region.cpp b/sources/Region.cpp index 15f0d18a..3b4b4721 100644 --- a/sources/Region.cpp +++ b/sources/Region.cpp @@ -4,89 +4,125 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) { - switch (hash(opcode.opcode)) - { + switch (hash(opcode.opcode)) { // Sound source: sample playback - case hash("sample"): - sample = absl::StrReplaceAll(trim(opcode.value), {{"\\", "/"}}); - break; - case hash("delay"): setValueFromOpcode(opcode, delay, Default::delayRange); break; - case hash("delay_random"): setValueFromOpcode(opcode, delayRandom, Default::delayRange); break; - case hash("offset"): setValueFromOpcode(opcode, offset, Default::offsetRange); break; - case hash("offset_random"): setValueFromOpcode(opcode, offsetRandom, Default::offsetRange); break; - case hash("end"): setValueFromOpcode(opcode, sampleEnd, Default::sampleEndRange); break; - case hash("count"): setValueFromOpcode(opcode, sampleCount, Default::sampleCountRange); break; + case hash("sample"): + sample = absl::StrReplaceAll(trim(opcode.value), { { "\\", "/" } }); + break; + case hash("delay"): + setValueFromOpcode(opcode, delay, Default::delayRange); + break; + case hash("delay_random"): + setValueFromOpcode(opcode, delayRandom, Default::delayRange); + break; + case hash("offset"): + setValueFromOpcode(opcode, offset, Default::offsetRange); + break; + case hash("offset_random"): + setValueFromOpcode(opcode, offsetRandom, Default::offsetRange); + break; + case hash("end"): + setValueFromOpcode(opcode, sampleEnd, Default::sampleEndRange); + break; + case hash("count"): + setValueFromOpcode(opcode, sampleCount, Default::sampleCountRange); + break; case hash("loopmode"): case hash("loop_mode"): - switch(hash(opcode.value)) - { - case hash("no_loop"): - loopMode = SfzLoopMode::no_loop; - break; - case hash("one_shot"): - loopMode = SfzLoopMode::one_shot; - break; - case hash("loop_continuous"): - loopMode = SfzLoopMode::loop_continuous; - break; - case hash("loop_sustain"): - loopMode = SfzLoopMode::loop_sustain; - break; - default: - DBG("Unkown loop mode:" << std::string(opcode.value)); + switch (hash(opcode.value)) { + case hash("no_loop"): + loopMode = SfzLoopMode::no_loop; + break; + case hash("one_shot"): + loopMode = SfzLoopMode::one_shot; + break; + case hash("loop_continuous"): + loopMode = SfzLoopMode::loop_continuous; + break; + case hash("loop_sustain"): + loopMode = SfzLoopMode::loop_sustain; + break; + default: + DBG("Unkown loop mode:" << std::string(opcode.value)); } break; case hash("loopend"): - case hash("loop_end"): setRangeEndFromOpcode(opcode, loopRange, Default::loopRange); break; + case hash("loop_end"): + setRangeEndFromOpcode(opcode, loopRange, Default::loopRange); + break; case hash("loopstart"): - case hash("loop_start"): setRangeStartFromOpcode(opcode, loopRange, Default::loopRange); break; + case hash("loop_start"): + setRangeStartFromOpcode(opcode, loopRange, Default::loopRange); + break; // Instrument settings: voice lifecycle - case hash("group"): setValueFromOpcode(opcode, group, Default::groupRange); break; + case hash("group"): + setValueFromOpcode(opcode, group, Default::groupRange); + break; case hash("offby"): - case hash("off_by"): setValueFromOpcode(opcode, offBy, Default::groupRange); break; + case hash("off_by"): + setValueFromOpcode(opcode, offBy, Default::groupRange); + break; case hash("off_mode"): - switch(hash(opcode.value)) - { - case hash("fast"): - offMode = SfzOffMode::fast; - break; - case hash("normal"): - offMode = SfzOffMode::normal; - break; - default: - DBG("Unkown off mode:" << std::string(opcode.value)); + switch (hash(opcode.value)) { + case hash("fast"): + offMode = SfzOffMode::fast; + break; + case hash("normal"): + offMode = SfzOffMode::normal; + break; + default: + DBG("Unkown off mode:" << std::string(opcode.value)); } break; // Region logic: key mapping - case hash("lokey"): setRangeStartFromOpcode(opcode, keyRange, Default::keyRange); break; - case hash("hikey"): setRangeEndFromOpcode(opcode, keyRange, Default::keyRange); break; + case hash("lokey"): + setRangeStartFromOpcode(opcode, keyRange, Default::keyRange); + break; + case hash("hikey"): + setRangeEndFromOpcode(opcode, keyRange, Default::keyRange); + break; case hash("key"): setRangeStartFromOpcode(opcode, keyRange, Default::keyRange); setRangeEndFromOpcode(opcode, keyRange, Default::keyRange); setValueFromOpcode(opcode, pitchKeycenter, Default::keyRange); break; - case hash("lovel"): setRangeStartFromOpcode(opcode, velocityRange, Default::velocityRange); break; - case hash("hivel"): setRangeEndFromOpcode(opcode, velocityRange, Default::velocityRange); break; - + case hash("lovel"): + setRangeStartFromOpcode(opcode, velocityRange, Default::velocityRange); + break; + case hash("hivel"): + setRangeEndFromOpcode(opcode, velocityRange, Default::velocityRange); + break; + // Region logic: MIDI conditions - case hash("lochan"): setRangeStartFromOpcode(opcode, channelRange, Default::channelRange); break; - case hash("hichan"): setRangeEndFromOpcode(opcode, channelRange, Default::channelRange); break; - case hash("lobend"): setRangeStartFromOpcode(opcode, bendRange, Default::bendRange); break; - case hash("hibend"): setRangeEndFromOpcode(opcode, bendRange, Default::bendRange); break; - case hash("locc"): - if (opcode.parameter) - { + case hash("lochan"): + setRangeStartFromOpcode(opcode, channelRange, Default::channelRange); + break; + case hash("hichan"): + setRangeEndFromOpcode(opcode, channelRange, Default::channelRange); + break; + case hash("lobend"): + setRangeStartFromOpcode(opcode, bendRange, Default::bendRange); + break; + case hash("hibend"): + setRangeEndFromOpcode(opcode, bendRange, Default::bendRange); + break; + case hash("locc"): + if (opcode.parameter) { setRangeStartFromOpcode(opcode, ccConditions[*opcode.parameter], Default::ccRange); } break; case hash("hicc"): - if (opcode.parameter) - setRangeEndFromOpcode(opcode, ccConditions[*opcode.parameter], Default::ccRange); + if (opcode.parameter) + setRangeEndFromOpcode(opcode, ccConditions[*opcode.parameter], Default::ccRange); break; - case hash("sw_lokey"): setRangeStartFromOpcode(opcode, keyswitchRange, Default::keyRange); break; - case hash("sw_hikey"): setRangeEndFromOpcode(opcode, keyswitchRange, Default::keyRange); break; - case hash("sw_last"): + case hash("sw_lokey"): + setRangeStartFromOpcode(opcode, keyswitchRange, Default::keyRange); + break; + case hash("sw_hikey"): + setRangeEndFromOpcode(opcode, keyswitchRange, Default::keyRange); + break; + case hash("sw_last"): setValueFromOpcode(opcode, keyswitch, Default::keyRange); keySwitched = false; break; @@ -94,105 +130,159 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) setValueFromOpcode(opcode, keyswitchDown, Default::keyRange); keySwitched = false; break; - case hash("sw_up"): setValueFromOpcode(opcode, keyswitchUp, Default::keyRange); break; + case hash("sw_up"): + setValueFromOpcode(opcode, keyswitchUp, Default::keyRange); + break; case hash("sw_previous"): setValueFromOpcode(opcode, previousNote, Default::keyRange); previousKeySwitched = false; break; case hash("sw_vel"): - switch(hash(opcode.value)) - { - case hash("current"): - velocityOverride = SfzVelocityOverride::current; - break; - case hash("previous"): - velocityOverride = SfzVelocityOverride::previous; - break; - default: - DBG("Unknown velocity mode: " << std::string(opcode.value)); + switch (hash(opcode.value)) { + case hash("current"): + velocityOverride = SfzVelocityOverride::current; + break; + case hash("previous"): + velocityOverride = SfzVelocityOverride::previous; + break; + default: + DBG("Unknown velocity mode: " << std::string(opcode.value)); } break; // Region logic: internal conditions - case hash("lochanaft"): setRangeStartFromOpcode(opcode, aftertouchRange, Default::aftertouchRange); break; - case hash("hichanaft"): setRangeEndFromOpcode(opcode, aftertouchRange, Default::aftertouchRange); break; - case hash("lobpm"): setRangeStartFromOpcode(opcode, bpmRange, Default::bpmRange); break; - case hash("hibpm"): setRangeEndFromOpcode(opcode, bpmRange, Default::bpmRange); break; - case hash("lorand"): setRangeStartFromOpcode(opcode, randRange, Default::randRange); break; - case hash("hirand"): setRangeEndFromOpcode(opcode, randRange, Default::randRange); break; - case hash("seq_length"): setValueFromOpcode(opcode, sequenceLength, Default::sequenceRange); break; + case hash("lochanaft"): + setRangeStartFromOpcode(opcode, aftertouchRange, Default::aftertouchRange); + break; + case hash("hichanaft"): + setRangeEndFromOpcode(opcode, aftertouchRange, Default::aftertouchRange); + break; + case hash("lobpm"): + setRangeStartFromOpcode(opcode, bpmRange, Default::bpmRange); + break; + case hash("hibpm"): + setRangeEndFromOpcode(opcode, bpmRange, Default::bpmRange); + break; + case hash("lorand"): + setRangeStartFromOpcode(opcode, randRange, Default::randRange); + break; + case hash("hirand"): + setRangeEndFromOpcode(opcode, randRange, Default::randRange); + break; + case hash("seq_length"): + setValueFromOpcode(opcode, sequenceLength, Default::sequenceRange); + break; case hash("seq_position"): setValueFromOpcode(opcode, sequencePosition, Default::sequenceRange); sequenceSwitched = (opcode.value == "1"); break; // Region logic: triggers case hash("trigger"): - switch(hash(opcode.value)) - { - case hash("attack"): - trigger = SfzTrigger::attack; - break; - case hash("first"): - trigger = SfzTrigger::first; - break; - case hash("legato"): - trigger = SfzTrigger::legato; - break; - case hash("release"): - trigger = SfzTrigger::release; - break; - case hash("release_key"): - trigger = SfzTrigger::release_key; - break; - default: - DBG("Unknown trigger mode: " << std::string(opcode.value)); + switch (hash(opcode.value)) { + case hash("attack"): + trigger = SfzTrigger::attack; + break; + case hash("first"): + trigger = SfzTrigger::first; + break; + case hash("legato"): + trigger = SfzTrigger::legato; + break; + case hash("release"): + trigger = SfzTrigger::release; + break; + case hash("release_key"): + trigger = SfzTrigger::release_key; + break; + default: + DBG("Unknown trigger mode: " << std::string(opcode.value)); } break; - case hash("on_locc"): - if (opcode.parameter) - setRangeStartFromOpcode(opcode, ccTriggers[*opcode.parameter], Default::ccRange); + case hash("on_locc"): + if (opcode.parameter) + setRangeStartFromOpcode(opcode, ccTriggers[*opcode.parameter], Default::ccRange); break; case hash("on_hicc"): - if (opcode.parameter) - setRangeEndFromOpcode(opcode, ccTriggers[*opcode.parameter], Default::ccRange); + if (opcode.parameter) + setRangeEndFromOpcode(opcode, ccTriggers[*opcode.parameter], Default::ccRange); break; // Performance parameters: amplifier - case hash("volume"): setValueFromOpcode(opcode, volume, Default::volumeRange); break; - // case hash("volume_oncc"): - // if (opcode.parameter) - // setValueFromOpcode(opcode, volumeCCTriggers[*opcode.parameter], Default::volumeCCRange); + case hash("volume"): + setValueFromOpcode(opcode, volume, Default::volumeRange); + break; + // case hash("volume_oncc"): + // if (opcode.parameter) + // setValueFromOpcode(opcode, volumeCCTriggers[*opcode.parameter], Default::volumeCCRange); // break; - case hash("amplitude"): setValueFromOpcode(opcode, amplitude, Default::amplitudeRange); break; + case hash("amplitude"): + setValueFromOpcode(opcode, amplitude, Default::amplitudeRange); + break; case hash("amplitude_cc"): - case hash("amplitude_oncc"): setCCPairFromOpcode(opcode, amplitudeCC, Default::amplitudeRange); break; - case hash("pan"): setValueFromOpcode(opcode, pan, Default::panRange); break; - case hash("pan_oncc"): setCCPairFromOpcode(opcode, panCC, Default::panCCRange); break; - case hash("position"): setValueFromOpcode(opcode, position, Default::positionRange); break; - case hash("position_oncc"): setCCPairFromOpcode(opcode, positionCC, Default::positionCCRange); break; - case hash("width"): setValueFromOpcode(opcode, width, Default::widthRange); break; - case hash("width_oncc"): setCCPairFromOpcode(opcode, widthCC, Default::widthCCRange); break; - case hash("amp_keycenter"): setValueFromOpcode(opcode, ampKeycenter, Default::keyRange); break; - case hash("amp_keytrack"): setValueFromOpcode(opcode, ampKeytrack, Default::ampKeytrackRange); break; - case hash("amp_veltrack"): setValueFromOpcode(opcode, ampVeltrack, Default::ampVeltrackRange); break; - case hash("amp_random"): setValueFromOpcode(opcode, ampRandom, Default::ampRandomRange); break; + case hash("amplitude_oncc"): + setCCPairFromOpcode(opcode, amplitudeCC, Default::amplitudeRange); + break; + case hash("pan"): + setValueFromOpcode(opcode, pan, Default::panRange); + break; + case hash("pan_oncc"): + setCCPairFromOpcode(opcode, panCC, Default::panCCRange); + break; + case hash("position"): + setValueFromOpcode(opcode, position, Default::positionRange); + break; + case hash("position_oncc"): + setCCPairFromOpcode(opcode, positionCC, Default::positionCCRange); + break; + case hash("width"): + setValueFromOpcode(opcode, width, Default::widthRange); + break; + case hash("width_oncc"): + setCCPairFromOpcode(opcode, widthCC, Default::widthCCRange); + break; + case hash("amp_keycenter"): + setValueFromOpcode(opcode, ampKeycenter, Default::keyRange); + break; + case hash("amp_keytrack"): + setValueFromOpcode(opcode, ampKeytrack, Default::ampKeytrackRange); + break; + case hash("amp_veltrack"): + setValueFromOpcode(opcode, ampVeltrack, Default::ampVeltrackRange); + break; + case hash("amp_random"): + setValueFromOpcode(opcode, ampRandom, Default::ampRandomRange); + break; case hash("amp_velcurve_"): - if (opcode.parameter && Default::ccRange.containsWithEnd(*opcode.parameter)) - { + if (opcode.parameter && Default::ccRange.containsWithEnd(*opcode.parameter)) { if (auto value = readOpcode(opcode.value, Default::ampVelcurveRange); value) velocityPoints.emplace_back(*opcode.parameter, *value); } break; - case hash("xfin_lokey"): setRangeStartFromOpcode(opcode, crossfadeKeyInRange, Default::keyRange); break; - case hash("xfin_hikey"): setRangeEndFromOpcode(opcode, crossfadeKeyInRange, Default::keyRange); break; - case hash("xfout_lokey"): setRangeStartFromOpcode(opcode, crossfadeKeyOutRange, Default::keyRange); break; - case hash("xfout_hikey"): setRangeEndFromOpcode(opcode, crossfadeKeyOutRange, Default::keyRange); break; - case hash("xfin_lovel"): setRangeStartFromOpcode(opcode, crossfadeVelInRange, Default::velocityRange); break; - case hash("xfin_hivel"): setRangeEndFromOpcode(opcode, crossfadeVelInRange, Default::velocityRange); break; - case hash("xfout_lovel"): setRangeStartFromOpcode(opcode, crossfadeVelOutRange, Default::velocityRange); break; - case hash("xfout_hivel"): setRangeEndFromOpcode(opcode, crossfadeVelOutRange, Default::velocityRange); break; + case hash("xfin_lokey"): + setRangeStartFromOpcode(opcode, crossfadeKeyInRange, Default::keyRange); + break; + case hash("xfin_hikey"): + setRangeEndFromOpcode(opcode, crossfadeKeyInRange, Default::keyRange); + break; + case hash("xfout_lokey"): + setRangeStartFromOpcode(opcode, crossfadeKeyOutRange, Default::keyRange); + break; + case hash("xfout_hikey"): + setRangeEndFromOpcode(opcode, crossfadeKeyOutRange, Default::keyRange); + break; + case hash("xfin_lovel"): + setRangeStartFromOpcode(opcode, crossfadeVelInRange, Default::velocityRange); + break; + case hash("xfin_hivel"): + setRangeEndFromOpcode(opcode, crossfadeVelInRange, Default::velocityRange); + break; + case hash("xfout_lovel"): + setRangeStartFromOpcode(opcode, crossfadeVelOutRange, Default::velocityRange); + break; + case hash("xfout_hivel"): + setRangeEndFromOpcode(opcode, crossfadeVelOutRange, Default::velocityRange); + break; case hash("xf_keycurve"): - switch (hash(opcode.value)) - { + switch (hash(opcode.value)) { case hash("power"): crossfadeKeyCurve = SfzCrossfadeCurve::power; break; @@ -204,8 +294,7 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) } break; case hash("xf_velcurve"): - switch (hash(opcode.value)) - { + switch (hash(opcode.value)) { case hash("power"): crossfadeVelCurve = SfzCrossfadeCurve::power; break; @@ -218,34 +307,86 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) break; // Performance parameters: pitch - case hash("pitch_keycenter"): setValueFromOpcode(opcode, pitchKeycenter, Default::keyRange); break; - case hash("pitch_keytrack"): setValueFromOpcode(opcode, pitchKeytrack, Default::pitchKeytrackRange); break; - case hash("pitch_veltrack"): setValueFromOpcode(opcode, pitchVeltrack, Default::pitchVeltrackRange); break; - case hash("pitch_random"): setValueFromOpcode(opcode, pitchRandom, Default::pitchRandomRange); break; - case hash("transpose"): setValueFromOpcode(opcode, transpose, Default::transposeRange); break; - case hash("tune"): setValueFromOpcode(opcode, tune, Default::tuneRange); break; + case hash("pitch_keycenter"): + setValueFromOpcode(opcode, pitchKeycenter, Default::keyRange); + break; + case hash("pitch_keytrack"): + setValueFromOpcode(opcode, pitchKeytrack, Default::pitchKeytrackRange); + break; + case hash("pitch_veltrack"): + setValueFromOpcode(opcode, pitchVeltrack, Default::pitchVeltrackRange); + break; + case hash("pitch_random"): + setValueFromOpcode(opcode, pitchRandom, Default::pitchRandomRange); + break; + case hash("transpose"): + setValueFromOpcode(opcode, transpose, Default::transposeRange); + break; + case hash("tune"): + setValueFromOpcode(opcode, tune, Default::tuneRange); + break; // Amplitude Envelope - case hash("ampeg_attack"): setValueFromOpcode(opcode, amplitudeEG.attack, Default::egTimeRange); break; - case hash("ampeg_decay"): setValueFromOpcode(opcode, amplitudeEG.decay, Default::egTimeRange); break; - case hash("ampeg_delay"): setValueFromOpcode(opcode, amplitudeEG.delay, Default::egTimeRange); break; - case hash("ampeg_hold"): setValueFromOpcode(opcode, amplitudeEG.hold, Default::egTimeRange); break; - case hash("ampeg_release"): setValueFromOpcode(opcode, amplitudeEG.release, Default::egTimeRange); break; - case hash("ampeg_start"): setValueFromOpcode(opcode, amplitudeEG.start, Default::egPercentRange); break; - case hash("ampeg_sustain"): setValueFromOpcode(opcode, amplitudeEG.sustain, Default::egPercentRange); break; - case hash("ampeg_vel2attack"): setValueFromOpcode(opcode, amplitudeEG.vel2attack, Default::egOnCCTimeRange); break; - case hash("ampeg_vel2decay"): setValueFromOpcode(opcode, amplitudeEG.vel2decay, Default::egOnCCTimeRange); break; - case hash("ampeg_vel2delay"): setValueFromOpcode(opcode, amplitudeEG.vel2delay, Default::egOnCCTimeRange); break; - case hash("ampeg_vel2hold"): setValueFromOpcode(opcode, amplitudeEG.vel2hold, Default::egOnCCTimeRange); break; - case hash("ampeg_vel2release"): setValueFromOpcode(opcode, amplitudeEG.vel2release, Default::egOnCCTimeRange); break; - case hash("ampeg_vel2sustain"): setValueFromOpcode(opcode, amplitudeEG.vel2sustain, Default::egOnCCPercentRange); break; - case hash("ampeg_attack_oncc"): setCCPairFromOpcode(opcode, amplitudeEG.ccAttack, Default::egOnCCTimeRange); break; - case hash("ampeg_decay_oncc"): setCCPairFromOpcode(opcode, amplitudeEG.ccDecay, Default::egOnCCTimeRange); break; - case hash("ampeg_delay_oncc"): setCCPairFromOpcode(opcode, amplitudeEG.ccDelay, Default::egOnCCTimeRange); break; - case hash("ampeg_hold_oncc"): setCCPairFromOpcode(opcode, amplitudeEG.ccHold, Default::egOnCCTimeRange); break; - case hash("ampeg_release_oncc"): setCCPairFromOpcode(opcode, amplitudeEG.ccRelease, Default::egOnCCTimeRange); break; - case hash("ampeg_start_oncc"): setCCPairFromOpcode(opcode, amplitudeEG.ccStart, Default::egOnCCPercentRange); break; - case hash("ampeg_sustain_oncc"): setCCPairFromOpcode(opcode, amplitudeEG.ccSustain, Default::egOnCCPercentRange); break; + case hash("ampeg_attack"): + setValueFromOpcode(opcode, amplitudeEG.attack, Default::egTimeRange); + break; + case hash("ampeg_decay"): + setValueFromOpcode(opcode, amplitudeEG.decay, Default::egTimeRange); + break; + case hash("ampeg_delay"): + setValueFromOpcode(opcode, amplitudeEG.delay, Default::egTimeRange); + break; + case hash("ampeg_hold"): + setValueFromOpcode(opcode, amplitudeEG.hold, Default::egTimeRange); + break; + case hash("ampeg_release"): + setValueFromOpcode(opcode, amplitudeEG.release, Default::egTimeRange); + break; + case hash("ampeg_start"): + setValueFromOpcode(opcode, amplitudeEG.start, Default::egPercentRange); + break; + case hash("ampeg_sustain"): + setValueFromOpcode(opcode, amplitudeEG.sustain, Default::egPercentRange); + break; + case hash("ampeg_vel2attack"): + setValueFromOpcode(opcode, amplitudeEG.vel2attack, Default::egOnCCTimeRange); + break; + case hash("ampeg_vel2decay"): + setValueFromOpcode(opcode, amplitudeEG.vel2decay, Default::egOnCCTimeRange); + break; + case hash("ampeg_vel2delay"): + setValueFromOpcode(opcode, amplitudeEG.vel2delay, Default::egOnCCTimeRange); + break; + case hash("ampeg_vel2hold"): + setValueFromOpcode(opcode, amplitudeEG.vel2hold, Default::egOnCCTimeRange); + break; + case hash("ampeg_vel2release"): + setValueFromOpcode(opcode, amplitudeEG.vel2release, Default::egOnCCTimeRange); + break; + case hash("ampeg_vel2sustain"): + setValueFromOpcode(opcode, amplitudeEG.vel2sustain, Default::egOnCCPercentRange); + break; + case hash("ampeg_attack_oncc"): + setCCPairFromOpcode(opcode, amplitudeEG.ccAttack, Default::egOnCCTimeRange); + break; + case hash("ampeg_decay_oncc"): + setCCPairFromOpcode(opcode, amplitudeEG.ccDecay, Default::egOnCCTimeRange); + break; + case hash("ampeg_delay_oncc"): + setCCPairFromOpcode(opcode, amplitudeEG.ccDelay, Default::egOnCCTimeRange); + break; + case hash("ampeg_hold_oncc"): + setCCPairFromOpcode(opcode, amplitudeEG.ccHold, Default::egOnCCTimeRange); + break; + case hash("ampeg_release_oncc"): + setCCPairFromOpcode(opcode, amplitudeEG.ccRelease, Default::egOnCCTimeRange); + break; + case hash("ampeg_start_oncc"): + setCCPairFromOpcode(opcode, amplitudeEG.ccStart, Default::egOnCCPercentRange); + break; + case hash("ampeg_sustain_oncc"): + setCCPairFromOpcode(opcode, amplitudeEG.ccSustain, Default::egOnCCPercentRange); + break; // Ignored opcodes case hash("ampeg_depth"): case hash("ampeg_vel2depth"): @@ -259,13 +400,7 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) bool sfz::Region::isSwitchedOn() const noexcept { - return keySwitched && - previousKeySwitched && - sequenceSwitched && - pitchSwitched && - bpmSwitched && - aftertouchSwitched && - allCCSwitched; + return keySwitched && previousKeySwitched && sequenceSwitched && pitchSwitched && bpmSwitched && aftertouchSwitched && allCCSwitched; } bool sfz::Region::registerNoteOn(int channel, int noteNumber, uint8_t velocity, float randValue) @@ -274,10 +409,8 @@ bool sfz::Region::registerNoteOn(int channel, int noteNumber, uint8_t velocity, if (!chanOk) return false; - if (keyswitchRange.containsWithEnd(noteNumber)) - { - if (keyswitch) - { + if (keyswitchRange.containsWithEnd(noteNumber)) { + if (keyswitch) { if (*keyswitch == noteNumber) keySwitched = true; else @@ -292,8 +425,7 @@ bool sfz::Region::registerNoteOn(int channel, int noteNumber, uint8_t velocity, } const bool keyOk = keyRange.containsWithEnd(noteNumber); - if (keyOk) - { + if (keyOk) { // Update the number of notes playing for the region activeNotesInRange++; @@ -308,9 +440,8 @@ bool sfz::Region::registerNoteOn(int channel, int noteNumber, uint8_t velocity, if (trigger == SfzTrigger::release_key || velocityOverride == SfzVelocityOverride::previous) lastNoteVelocities[noteNumber] = velocity; - if (previousNote) - { - if ( *previousNote == noteNumber) + if (previousNote) { + if (*previousNote == noteNumber) previousKeySwitched = true; else previousKeySwitched = false; @@ -328,7 +459,7 @@ bool sfz::Region::registerNoteOn(int channel, int noteNumber, uint8_t velocity, const bool firstLegatoNote = (trigger == SfzTrigger::first && activeNotesInRange == 0); const bool attackTrigger = (trigger == SfzTrigger::attack); const bool notFirstLegatoNote = (trigger == SfzTrigger::legato && activeNotesInRange > 0); - + return keyOk && velOk && chanOk && randOk && (attackTrigger || firstLegatoNote || notFirstLegatoNote); } @@ -338,8 +469,7 @@ bool sfz::Region::registerNoteOff(int channel, int noteNumber, uint8_t velocity if (!chanOk) return false; - if (keyswitchRange.containsWithEnd(noteNumber)) - { + if (keyswitchRange.containsWithEnd(noteNumber)) { if (keyswitchDown && *keyswitchDown == noteNumber) keySwitched = false; @@ -355,7 +485,7 @@ bool sfz::Region::registerNoteOff(int channel, int noteNumber, uint8_t velocity if (!isSwitchedOn()) return false; - + const bool randOk = randRange.contains(randValue); const bool releaseTrigger = (trigger == SfzTrigger::release || trigger == SfzTrigger::release_key); return keyOk && chanOk && randOk && releaseTrigger; @@ -370,7 +500,7 @@ bool sfz::Region::registerCC(int channel, int ccNumber, uint8_t ccValue) ccSwitched.set(ccNumber, true); else ccSwitched.set(ccNumber, false); - + if (ccSwitched.all()) allCCSwitched = true; else @@ -386,7 +516,7 @@ void sfz::Region::registerPitchWheel(int channel, int pitch) { if (!channelRange.containsWithEnd(channel)) return; - + if (bendRange.containsWithEnd(pitch)) pitchSwitched = true; else @@ -397,7 +527,7 @@ void sfz::Region::registerAftertouch(int channel, uint8_t aftertouch) { if (!channelRange.containsWithEnd(channel)) return; - + if (aftertouchRange.containsWithEnd(aftertouch)) aftertouchSwitched = true; else diff --git a/sources/StereoBuffer.h b/sources/StereoBuffer.h index 1d6c51dc..145c7503 100644 --- a/sources/StereoBuffer.h +++ b/sources/StereoBuffer.h @@ -1,18 +1,18 @@ #pragma once #include "Buffer.h" -#include "Helpers.h" #include "Globals.h" +#include "Helpers.h" +#include "SIMDHelpers.h" #include #include #include -#include "SIMDHelpers.h" -enum class Channel {left, right}; +enum class Channel { left, + right }; -template -class StereoBuffer -{ +template +class StereoBuffer { public: static constexpr int numChannels { 2 }; StereoBuffer() = default; @@ -20,13 +20,12 @@ public: { resize(numFrames); } - - bool resize(int numFrames) + + bool resize(int numFrames) { // should have a positive number of frames... ASSERT(numFrames >= 0); - if (leftBuffer.resize(static_cast(numFrames)) && rightBuffer.resize(static_cast(numFrames))) - { + if (leftBuffer.resize(static_cast(numFrames)) && rightBuffer.resize(static_cast(numFrames))) { this->numFrames = numFrames; return true; } @@ -36,13 +35,14 @@ public: absl::Span getSpan(Channel channel) const { - switch(channel) - { - case Channel::left: return leftBuffer; - case Channel::right: return rightBuffer; + switch (channel) { + case Channel::left: + return leftBuffer; + case Channel::right: + return rightBuffer; // Should not be here by construction... - default: - ASSERTFALSE; + default: + ASSERTFALSE; return {}; } } @@ -50,13 +50,14 @@ public: Type& getSample(Channel channel, int sampleIndex) noexcept { ASSERT(sampleIndex >= 0); - switch(channel) - { - case Channel::left: return leftBuffer[sampleIndex]; - case Channel::right: return rightBuffer[sampleIndex]; + switch (channel) { + case Channel::left: + return leftBuffer[sampleIndex]; + case Channel::right: + return rightBuffer[sampleIndex]; // Should not be here by construction... - default: - ASSERTFALSE; + default: + ASSERTFALSE; return trash; } } @@ -87,21 +88,25 @@ public: Type* getChannel(Channel channel) noexcept { - switch(channel) - { - case Channel::left: return leftBuffer.data(); - case Channel::right: return rightBuffer.data(); - default: return {}; + switch (channel) { + case Channel::left: + return leftBuffer.data(); + case Channel::right: + return rightBuffer.data(); + default: + return {}; } } Type* begin(Channel channel) noexcept { - switch(channel) - { - case Channel::left: return leftBuffer.data(); - case Channel::right: return rightBuffer.data(); - default: return {}; + switch (channel) { + case Channel::left: + return leftBuffer.data(); + case Channel::right: + return rightBuffer.data(); + default: + return {}; } } std::pair getChannels() noexcept { return { leftBuffer.data(), rightBuffer.data() }; } @@ -109,22 +114,26 @@ public: Type* end(Channel channel) noexcept { - switch(channel) - { - case Channel::left: return leftBuffer.end(); - case Channel::right: return rightBuffer.end(); - default: return {}; + switch (channel) { + case Channel::left: + return leftBuffer.end(); + case Channel::right: + return rightBuffer.end(); + default: + return {}; } } std::pair ends() { return { leftBuffer.end(), rightBuffer.end() }; } Type* alignedEnd(Channel channel) noexcept { - switch(channel) - { - case Channel::left: return leftBuffer.alignedEnd(); - case Channel::right: return rightBuffer.alignedEnd(); - default: return {}; + switch (channel) { + case Channel::left: + return leftBuffer.alignedEnd(); + case Channel::right: + return rightBuffer.alignedEnd(); + default: + return {}; } } std::pair alignedEnds() { return { leftBuffer.alignedEnd(), rightBuffer.alignedEnd() }; } diff --git a/sources/Synth.h b/sources/Synth.h index 59540ca3..97a17b82 100644 --- a/sources/Synth.h +++ b/sources/Synth.h @@ -1,19 +1,17 @@ #pragma once +#include "FilePool.h" #include "Parser.h" #include "Region.h" #include "SfzHelpers.h" -#include "FilePool.h" -#include -#include #include #include +#include #include +#include -namespace sfz -{ +namespace sfz { -class Synth: public Parser -{ +class Synth : public Parser { public: Synth() { @@ -38,8 +36,7 @@ public: void renderBlock(StereoBuffer& buffer) { - for (auto& voice: voices) - { + for (auto& voice : voices) { voice->renderBlock(tempBuffer); buffer.add(tempBuffer); } @@ -48,14 +45,15 @@ public: void noteOn(int delay, int channel, int noteNumber, uint8_t velocity) { auto randValue = getUniform(); - for (auto& region: regions) - { - if (region->registerNoteOn(channel, noteNumber, velocity, randValue)) - { + for (auto& voice : voices) + voice->registerNoteOn(delay, channel, noteNumber, velocity); + + for (auto& region : regions) { + if (region->registerNoteOn(channel, noteNumber, velocity, randValue)) { auto voice = findFreeVoice(); if (voice == nullptr) continue; - + voice->startVoice(region.get(), channel, noteNumber, velocity, Voice::TriggerType::NoteOn); } } @@ -64,15 +62,18 @@ public: void noteOff(int delay, int channel, int noteNumber, uint8_t velocity) { auto randValue = getUniform(); - for (auto& region: regions) - { - if (region->registerNoteOff(channel, noteNumber, velocity, randValue)) - { + for (auto& voice : voices) { + if (voice->registerNoteOff(delay, channel, noteNumber, velocity)) { + // do something + } + } + + for (auto& region : regions) { + if (region->registerNoteOff(channel, noteNumber, velocity, randValue)) { auto voice = findFreeVoice(); if (voice == nullptr) continue; - - voice->startVoice(region.get(), channel, noteNumber, velocity, Voice::TriggerType::NoteOff); + voice->startVoice(region.get(), channel, noteNumber, velocity, Voice::TriggerType::NoteOff); } } @@ -84,17 +85,18 @@ public: protected: void callback(std::string_view header, std::vector members) final; + private: Voice* findFreeVoice() { auto freeVoice = absl::c_find_if(voices, [](const auto& voice) { return voice->isFree(); }); - if (freeVoice == voices.end()) - { + if (freeVoice == voices.end()) { DBG("Voices are overloaded, can't start a new note"); return {}; } return freeVoice->get(); } + bool hasGlobal { false }; bool hasControl { false }; int numGroups { 0 }; @@ -122,9 +124,10 @@ private: StereoBuffer tempBuffer { config::defaultSamplesPerBlock }; int samplesPerBlock { config::defaultSamplesPerBlock }; float sampleRate { config::defaultSampleRate }; - std::random_device rd { }; + std::random_device rd {}; std::mt19937 randomGenerator { rd() }; std::uniform_real_distribution randomDistribution { 0, 1 }; + float getUniform() { return randomDistribution(randomGenerator); diff --git a/sources/Voice.h b/sources/Voice.h index eb7b8b55..b173ac08 100644 --- a/sources/Voice.h +++ b/sources/Voice.h @@ -32,8 +32,8 @@ public: return (region == nullptr); } - bool registerNoteOn(int delay, int channel, int noteNumber, uint8_t velocity); - void registerNoteOff(int delay, int channel, int noteNumber, uint8_t velocity); + void registerNoteOn(int delay, int channel, int noteNumber, uint8_t velocity); + bool registerNoteOff(int delay, int channel, int noteNumber, uint8_t velocity); bool registerCC(int delay, int channel, int ccNumber, uint8_t ccValue); void registerPitchWheel(int delay, int channel, int pitch); void registerAftertouch(int delay, int channel, uint8_t aftertouch);