sfizz/sources/Region.cpp

275 lines
No EOL
14 KiB
C++

#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)
{
}