This commit is contained in:
paulfd 2019-08-23 15:46:02 +02:00
parent 0e89a0b2c6
commit 5d57a5ad24
4 changed files with 388 additions and 246 deletions

View file

@ -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

View file

@ -1,18 +1,18 @@
#pragma once
#include "Buffer.h"
#include "Helpers.h"
#include "Globals.h"
#include "Helpers.h"
#include "SIMDHelpers.h"
#include <array>
#include <iostream>
#include <type_traits>
#include "SIMDHelpers.h"
enum class Channel {left, right};
enum class Channel { left,
right };
template<class Type, unsigned int Alignment = SIMDConfig::defaultAlignment>
class StereoBuffer
{
template <class Type, unsigned int Alignment = SIMDConfig::defaultAlignment>
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<size_t>(numFrames)) && rightBuffer.resize(static_cast<size_t>(numFrames)))
{
if (leftBuffer.resize(static_cast<size_t>(numFrames)) && rightBuffer.resize(static_cast<size_t>(numFrames))) {
this->numFrames = numFrames;
return true;
}
@ -36,13 +35,14 @@ public:
absl::Span<const Type> 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<Type*, Type*> 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<Type*, Type*> 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<Type*, Type*> alignedEnds() { return { leftBuffer.alignedEnd(), rightBuffer.alignedEnd() }; }

View file

@ -1,19 +1,17 @@
#pragma once
#include "FilePool.h"
#include "Parser.h"
#include "Region.h"
#include "SfzHelpers.h"
#include "FilePool.h"
#include <vector>
#include <set>
#include <optional>
#include <random>
#include <set>
#include <string_view>
#include <vector>
namespace sfz
{
namespace sfz {
class Synth: public Parser
{
class Synth : public Parser {
public:
Synth()
{
@ -38,8 +36,7 @@ public:
void renderBlock(StereoBuffer<float>& 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<Opcode> 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<float> 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<float> randomDistribution { 0, 1 };
float getUniform()
{
return randomDistribution(randomGenerator);

View file

@ -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);