#include "Region.h" #include "Helpers.h" #include "absl/strings/str_replace.h" bool sfz::Region::parseOpcode(const 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("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)); } break; case hash("loopend"): case hash("loop_end"): setRangeEndFromOpcode(opcode, loopRange, Default::loopRange); break; case hash("loopstart"): 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("offby"): 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)); } 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("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; // 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) setRangeStartFromOpcode(opcode, ccConditions[*opcode.parameter], Default::ccRange); break; case hash("hicc"): 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"): setValueFromOpcode(opcode, keyswitch, Default::keyRange); break; case hash("sw_down"): setValueFromOpcode(opcode, keyswitchDown, Default::keyRange); break; case hash("sw_up"): setValueFromOpcode(opcode, keyswitchUp, Default::keyRange); break; case hash("sw_previous"): setValueFromOpcode(opcode, previousNote, Default::keyRange); 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)); } 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("seq_position"): setValueFromOpcode(opcode, sequencePosition, Default::sequenceRange); 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)); } break; 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); 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); // 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("amp_velcurve_"): 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("xf_keycurve"): switch (hash(opcode.value)) { case hash("power"): crossfadeKeyCurve = SfzCrossfadeCurve::power; break; case hash("gain"): crossfadeKeyCurve = SfzCrossfadeCurve::gain; break; default: DBG("Unknown crossfade power curve: " << std::string(opcode.value)); } break; case hash("xf_velcurve"): switch (hash(opcode.value)) { case hash("power"): crossfadeVelCurve = SfzCrossfadeCurve::power; break; case hash("gain"): crossfadeVelCurve = SfzCrossfadeCurve::gain; break; default: DBG("Unknown crossfade power curve: " << std::string(opcode.value)); } 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; // 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; // Ignored opcodes case hash("ampeg_depth"): case hash("ampeg_vel2depth"): break; default: return false; } return true; } bool sfz::Region::isSwitchedOn() const noexcept { return false; } bool sfz::Region::registerNoteOn(int, int, uint8_t, float) { return false; } bool sfz::Region::registerNoteOff(int, int, uint8_t, float) { return false; } bool sfz::Region::registerCC(int, int, uint8_t) { return false; } void sfz::Region::registerPitchWheel(int, int) { } void sfz::Region::registerAftertouch(int, uint8_t) { } void sfz::Region::registerTempo(float) { }