From 0e1e65135ee6aea4aaec3b3c64fd3511ec3e24b3 Mon Sep 17 00:00:00 2001 From: Paul Fd Date: Wed, 25 Mar 2020 23:25:32 +0100 Subject: [PATCH] Region and Synth use float velocities internally --- src/sfizz/Defaults.h | 6 +-- src/sfizz/Region.cpp | 87 ++++++++++++++++++++++++++++++++-------- src/sfizz/Region.h | 56 ++++++++++++++++++++++++-- src/sfizz/Synth.cpp | 94 ++++++++++++++++++++++---------------------- tests/FilesT.cpp | 14 ++++--- tests/RegionT.cpp | 52 ++++++++++++------------ 6 files changed, 206 insertions(+), 103 deletions(-) diff --git a/src/sfizz/Defaults.h b/src/sfizz/Defaults.h index e735e9d3..b8921d99 100644 --- a/src/sfizz/Defaults.h +++ b/src/sfizz/Defaults.h @@ -68,7 +68,7 @@ namespace Default // Region logic: key mapping constexpr Range keyRange { 0, 127 }; - constexpr Range velocityRange { 0, 127 }; + constexpr Range velocityRange { 0.0f, 1.0f }; // Region logic: MIDI conditions constexpr Range channelRange { 1, 16 }; @@ -121,8 +121,8 @@ namespace Default constexpr Range ampRandomRange { 0.0, 24.0 }; constexpr Range crossfadeKeyInRange { 0, 0 }; constexpr Range crossfadeKeyOutRange { 127, 127 }; - constexpr Range crossfadeVelInRange { 0, 0 }; - constexpr Range crossfadeVelOutRange { 127, 127 }; + constexpr Range crossfadeVelInRange { 0.0f, 0.0f }; + constexpr Range crossfadeVelOutRange { 1.0f, 1.0f }; constexpr Range crossfadeCCInRange { 0, 0 }; constexpr Range crossfadeCCOutRange { 127, 127 }; constexpr SfzCrossfadeCurve crossfadeKeyCurve { SfzCrossfadeCurve::power }; diff --git a/src/sfizz/Region.cpp b/src/sfizz/Region.cpp index 13df28d2..95151b47 100644 --- a/src/sfizz/Region.cpp +++ b/src/sfizz/Region.cpp @@ -14,6 +14,7 @@ #include "MidiState.h" #include "absl/strings/str_replace.h" #include "absl/strings/str_cat.h" +#include "absl/algorithm/container.h" #include template @@ -138,10 +139,12 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) setValueFromOpcode(opcode, pitchKeycenter, Default::keyRange); break; case hash("lovel"): - setRangeStartFromOpcode(opcode, velocityRange, Default::velocityRange); + if (auto value = readOpcode(opcode.value, Default::midi7Range)) + velocityRange.setStart(normalizeVelocity(*value)); break; case hash("hivel"): - setRangeEndFromOpcode(opcode, velocityRange, Default::velocityRange); + if (auto value = readOpcode(opcode.value, Default::midi7Range)) + velocityRange.setEnd(normalizeVelocity(*value)); break; // Region logic: MIDI conditions @@ -303,8 +306,11 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) case hash("amp_velcurve_&"): { auto value = readOpcode(opcode.value, Default::ampVelcurveRange); + if (opcode.parameters.back() > 127) + return false; + if (value) - velocityPoints.emplace_back(opcode.parameters.back(), *value); + velocityPoints.emplace_back(normalizeVelocity(opcode.parameters.back()), *value); } break; case hash("xfin_lokey"): @@ -320,16 +326,20 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) setRangeEndFromOpcode(opcode, crossfadeKeyOutRange, Default::keyRange); break; case hash("xfin_lovel"): - setRangeStartFromOpcode(opcode, crossfadeVelInRange, Default::velocityRange); + if (auto value = readOpcode(opcode.value, Default::midi7Range)) + crossfadeVelInRange.setStart(normalizeVelocity(*value)); break; case hash("xfin_hivel"): - setRangeEndFromOpcode(opcode, crossfadeVelInRange, Default::velocityRange); + if (auto value = readOpcode(opcode.value, Default::midi7Range)) + crossfadeVelInRange.setEnd(normalizeVelocity(*value)); break; case hash("xfout_lovel"): - setRangeStartFromOpcode(opcode, crossfadeVelOutRange, Default::velocityRange); + if (auto value = readOpcode(opcode.value, Default::midi7Range)) + crossfadeVelOutRange.setStart(normalizeVelocity(*value)); break; case hash("xfout_hivel"): - setRangeEndFromOpcode(opcode, crossfadeVelOutRange, Default::velocityRange); + if (auto value = readOpcode(opcode.value, Default::midi7Range)) + crossfadeVelOutRange.setEnd(normalizeVelocity(*value)); break; case hash("xf_keycurve"): switch (hash(opcode.value)) { @@ -773,6 +783,13 @@ bool sfz::Region::isSwitchedOn() const noexcept bool sfz::Region::registerNoteOn(int noteNumber, uint8_t velocity, float randValue) noexcept { + return registerNoteOnNormalized(noteNumber, normalizeVelocity(velocity), randValue); +} + +bool sfz::Region::registerNoteOnNormalized(int noteNumber, float velocity, float randValue) noexcept +{ + ASSERT(velocity >= 0.0f && velocity <= 1.0f); + if (keyswitchRange.containsWithEnd(noteNumber)) { if (keyswitch) { if (*keyswitch == noteNumber) @@ -825,6 +842,13 @@ bool sfz::Region::registerNoteOn(int noteNumber, uint8_t velocity, float randVal bool sfz::Region::registerNoteOff(int noteNumber, uint8_t velocity, float randValue) noexcept { + return registerNoteOffNormalized(noteNumber, normalizeVelocity(velocity), randValue); +} + +bool sfz::Region::registerNoteOffNormalized(int noteNumber, float velocity, float randValue) noexcept +{ + ASSERT(velocity >= 0.0f && velocity <= 1.0f); + if (keyswitchRange.containsWithEnd(noteNumber)) { if (keyswitchDown && *keyswitchDown == noteNumber) keySwitched = false; @@ -893,11 +917,18 @@ void sfz::Region::registerTempo(float secondsPerQuarter) noexcept float sfz::Region::getBasePitchVariation(int noteNumber, uint8_t velocity) const noexcept { + return getBasePitchVariationNormalized(noteNumber, normalizeVelocity(velocity)); +} + +float sfz::Region::getBasePitchVariationNormalized(int noteNumber, float velocity) const noexcept +{ + ASSERT(velocity >= 0.0f && velocity <= 1.0f); + std::uniform_int_distribution pitchDistribution { -pitchRandom, pitchRandom }; auto pitchVariationInCents = pitchKeytrack * (noteNumber - (int)pitchKeycenter); // note difference with pitch center pitchVariationInCents += tune; // sample tuning pitchVariationInCents += config::centPerSemitone * transpose; // sample transpose - pitchVariationInCents += velocity / 127 * pitchVeltrack; // track velocity + pitchVariationInCents += velocity * pitchVeltrack; // track velocity pitchVariationInCents += pitchDistribution(Random::randomGenerator); // random pitch changes return centsFactor(pitchVariationInCents); } @@ -961,8 +992,13 @@ float crossfadeIn(const sfz::Range& crossfadeRange, U value, SfzCrossfadeCurv { if (value < crossfadeRange.getStart()) return 0.0f; + + const auto length = static_cast(crossfadeRange.length()); + if (length == 0.0f) + return 1.0f; + else if (value < crossfadeRange.getEnd()) { - const auto crossfadePosition = static_cast(value - crossfadeRange.getStart()) / std::max(static_cast(crossfadeRange.length()), 1.0f); + const auto crossfadePosition = static_cast(value - crossfadeRange.getStart()) / length; if (curve == SfzCrossfadeCurve::power) return sqrt(crossfadePosition); if (curve == SfzCrossfadeCurve::gain) @@ -977,8 +1013,13 @@ float crossfadeOut(const sfz::Range& crossfadeRange, U value, SfzCrossfadeCur { if (value > crossfadeRange.getEnd()) return 0.0f; + + const auto length = static_cast(crossfadeRange.length()); + if (length == 0.0f) + return 1.0f; + else if (value > crossfadeRange.getStart()) { - const auto crossfadePosition = static_cast(value - crossfadeRange.getStart()) / std::max(static_cast(crossfadeRange.length()), 1.0f); + const auto crossfadePosition = static_cast(value - crossfadeRange.getStart()) / length; if (curve == SfzCrossfadeCurve::power) return std::sqrt(1 - crossfadePosition); if (curve == SfzCrossfadeCurve::gain) @@ -990,6 +1031,13 @@ float crossfadeOut(const sfz::Range& crossfadeRange, U value, SfzCrossfadeCur float sfz::Region::getNoteGain(int noteNumber, uint8_t velocity) const noexcept { + return getNoteGainNormalized(noteNumber, normalizeVelocity(velocity)); +} + +float sfz::Region::getNoteGainNormalized(int noteNumber, float velocity) const noexcept +{ + ASSERT(velocity >= 0.0f && velocity <= 1.0f); + float baseGain { 1.0f }; // Amplitude key tracking @@ -1000,7 +1048,7 @@ float sfz::Region::getNoteGain(int noteNumber, uint8_t velocity) const noexcept baseGain *= crossfadeOut(crossfadeKeyOutRange, noteNumber, crossfadeKeyCurve); // Amplitude velocity tracking - baseGain *= velocityCurve(velocity); + baseGain *= velocityCurveNormalized(velocity); // Crossfades related to velocity baseGain *= crossfadeIn(crossfadeVelInRange, velocity, crossfadeVelCurve); @@ -1031,25 +1079,30 @@ float sfz::Region::getCrossfadeGain() const noexcept float sfz::Region::velocityCurve(uint8_t velocity) const noexcept { - float gain { 1.0f }; + return velocityCurveNormalized(normalizeVelocity(velocity)); +} +float sfz::Region::velocityCurveNormalized(float velocity) const noexcept +{ + ASSERT(velocity >= 0.0f && velocity <= 1.0f); + + float gain { 1.0f }; if (velocityPoints.size() > 0) { // Custom velocity curve - auto after = std::find_if(velocityPoints.begin(), velocityPoints.end(), [velocity](const std::pair& val) { return val.first >= velocity; }); + auto after = absl::c_find_if(velocityPoints, [velocity](const std::pair& val) { return val.first >= velocity; }); auto before = after == velocityPoints.begin() ? velocityPoints.begin() : after - 1; // Linear interpolation float relativePositionInSegment { - static_cast(velocity - before->first) / static_cast(after->first - before->first) + (velocity - before->first) / (after->first - before->first) }; float segmentEndpoints { after->second - before->second }; gain *= relativePositionInSegment * segmentEndpoints; } else { // Standard velocity curve - const float floatVelocity { static_cast(velocity) / 127.0f }; // FIXME: Maybe there's a prettier way to check the boundaries? const float gaindB = [&]() { if (ampVeltrack >= 0) - return floatVelocity == 0.0f ? -90.0f : 40 * std::log(floatVelocity) / std::log(10.0f); + return velocity == 0.0f ? -90.0f : 40 * std::log(velocity) / std::log(10.0f); else - return floatVelocity == 1.0f ? -90.0f : 40 * std::log(1 - floatVelocity) / std::log(10.0f); + return velocity == 1.0f ? -90.0f : 40 * std::log(1 - velocity) / std::log(10.0f); }(); gain *= db2mag( gaindB * std::abs(ampVeltrack) / sfz::Default::ampVeltrackRange.getEnd()); } diff --git a/src/sfizz/Region.h b/src/sfizz/Region.h index 47a6dfe6..7466507c 100644 --- a/src/sfizz/Region.h +++ b/src/sfizz/Region.h @@ -98,6 +98,30 @@ struct Region { * @return false */ bool registerNoteOff(int noteNumber, uint8_t velocity, float randValue) noexcept; + /** + * @brief Register a new note on event. The region may be switched on or off using keys so + * this function updates the keyswitches state. + * + * @param noteNumber + * @param velocity + * @param randValue a random value between 0 and 1 used to randomize a bit the region activations + * and vary the samples + * @return true if the region should trigger on this event. + * @return false + */ + bool registerNoteOnNormalized(int noteNumber, float velocity, float randValue) noexcept; + /** + * @brief Register a new note off event. The region may be switched on or off using keys so + * this function updates the keyswitches state. + * + * @param noteNumber + * @param velocity + * @param randValue a random value between 0 and 1 used to randomize a bit the region activations + * and vary the samples + * @return true if the region should trigger on this event. + * @return false + */ + bool registerNoteOffNormalized(int noteNumber, float velocity, float randValue) noexcept; /** * @brief Register a new CC event. The region may be switched on or off using CCs so * this function checks if it indeeds need to activate or not. @@ -136,6 +160,15 @@ struct Region { * @return float */ float getBasePitchVariation(int noteNumber, uint8_t velocity) const noexcept; + /** + * @brief Get the base pitch of the region depending on which note has been + * pressed and at which velocity. + * + * @param noteNumber + * @param velocity + * @return float + */ + float getBasePitchVariationNormalized(int noteNumber, float velocity) const noexcept; /** * @brief Get the note-related gain of the region depending on which note has been * pressed and at which velocity. @@ -145,6 +178,15 @@ struct Region { * @return float */ float getNoteGain(int noteNumber, uint8_t velocity) const noexcept; + /** + * @brief Get the note-related gain of the region depending on which note has been + * pressed and at which velocity. + * + * @param noteNumber + * @param velocity + * @return float + */ + float getNoteGainNormalized(int noteNumber, float velocity) const noexcept; /** * @brief Get the additional crossfade gain of the region depending on the * CC values @@ -179,6 +221,12 @@ struct Region { * @return float */ float velocityCurve(uint8_t velocity) const noexcept; + /** + * @brief Computes the gain value related to the velocity of the note + * + * @return float + */ + float velocityCurveNormalized(float velocity) const noexcept; /** * @brief Get the region offset in samples * @@ -243,7 +291,7 @@ struct Region { // Region logic: key mapping Range keyRange { Default::keyRange }; //lokey, hikey and key - Range velocityRange { Default::velocityRange }; // hivel and lovel + Range velocityRange { Default::velocityRange }; // hivel and lovel // Region logic: MIDI conditions Range bendRange { Default::bendRange }; // hibend and lobend @@ -282,12 +330,12 @@ struct Region { uint8_t ampKeycenter { Default::ampKeycenter }; // amp_keycenter float ampKeytrack { Default::ampKeytrack }; // amp_keytrack float ampVeltrack { Default::ampVeltrack }; // amp_keytrack - std::vector> velocityPoints; // amp_velcurve_N + std::vector> velocityPoints; // amp_velcurve_N float ampRandom { Default::ampRandom }; // amp_random Range crossfadeKeyInRange { Default::crossfadeKeyInRange }; Range crossfadeKeyOutRange { Default::crossfadeKeyOutRange }; - Range crossfadeVelInRange { Default::crossfadeVelInRange }; - Range crossfadeVelOutRange { Default::crossfadeVelOutRange }; + Range crossfadeVelInRange { Default::crossfadeVelInRange }; + Range crossfadeVelOutRange { Default::crossfadeVelOutRange }; SfzCrossfadeCurve crossfadeKeyCurve { Default::crossfadeKeyCurve }; SfzCrossfadeCurve crossfadeVelCurve { Default::crossfadeVelCurve }; SfzCrossfadeCurve crossfadeCCCurve { Default::crossfadeCCCurve }; diff --git a/src/sfizz/Synth.cpp b/src/sfizz/Synth.cpp index fd36c0e0..e6d4f294 100644 --- a/src/sfizz/Synth.cpp +++ b/src/sfizz/Synth.cpp @@ -44,7 +44,7 @@ sfz::Synth::~Synth() std::this_thread::sleep_for(std::chrono::milliseconds(1)); } - for (auto& voice: voices) + for (auto& voice : voices) voice->reset(); resources.filePool.emptyFileLoadingQueues(); @@ -129,11 +129,11 @@ void sfz::Synth::clear() std::this_thread::sleep_for(std::chrono::milliseconds(1)); } - for (auto &voice: voices) + for (auto& voice : voices) voice->reset(); - for (auto& list: noteActivationLists) + for (auto& list : noteActivationLists) list.clear(); - for (auto& list: ccActivationLists) + for (auto& list : ccActivationLists) list.clear(); regions.clear(); effectBuses.clear(); @@ -275,17 +275,19 @@ void sfz::Synth::handleEffectOpcodes(const std::vector& members) void addEndpointsToVelocityCurve(sfz::Region& region) { if (region.velocityPoints.size() > 0) { - absl::c_sort(region.velocityPoints, [](const std::pair& lhs, const std::pair& rhs) { return lhs.first < rhs.first; }); + const auto velocityStart = sfz::Default::velocityRange.getStart(); + const auto velocityEnd = sfz::Default::velocityRange.getEnd(); + absl::c_sort(region.velocityPoints, [](const std::pair& lhs, const std::pair& rhs) { return lhs.first < rhs.first; }); if (region.ampVeltrack > 0) { - if (region.velocityPoints.back().first != sfz::Default::velocityRange.getEnd()) - region.velocityPoints.push_back(std::make_pair(127, 1.0f)); - if (region.velocityPoints.front().first != sfz::Default::velocityRange.getStart()) - region.velocityPoints.insert(region.velocityPoints.begin(), std::make_pair(0, 0.0f)); + if (region.velocityPoints.front().first != velocityStart) + region.velocityPoints.insert(region.velocityPoints.begin(), std::make_pair(velocityStart, velocityStart)); + if (region.velocityPoints.back().first != velocityEnd) + region.velocityPoints.push_back(std::make_pair(velocityEnd, velocityEnd)); } else { - if (region.velocityPoints.front().first != sfz::Default::velocityRange.getEnd()) - region.velocityPoints.insert(region.velocityPoints.begin(), std::make_pair(127, 0.0f)); - if (region.velocityPoints.back().first != sfz::Default::velocityRange.getStart()) - region.velocityPoints.push_back(std::make_pair(0, 1.0f)); + if (region.velocityPoints.front().first != velocityEnd) + region.velocityPoints.insert(region.velocityPoints.begin(), std::make_pair(velocityEnd, velocityStart)); + if (region.velocityPoints.back().first != velocityStart) + region.velocityPoints.push_back(std::make_pair(velocityStart, velocityEnd)); } } } @@ -341,8 +343,7 @@ bool sfz::Synth::loadSfzFile(const fs::path& file) if (region->loopRange.getEnd() == Default::loopRange.getEnd()) region->loopRange.setEnd(region->sampleEnd); - if (fileInformation->loopBegin != Default::loopRange.getStart() && - fileInformation->loopEnd != Default::loopRange.getEnd()) { + if (fileInformation->loopBegin != Default::loopRange.getStart() && fileInformation->loopEnd != Default::loopRange.getEnd()) { if (region->loopRange.getStart() == Default::loopRange.getStart()) region->loopRange.setStart(fileInformation->loopBegin); @@ -374,8 +375,7 @@ bool sfz::Synth::loadSfzFile(const fs::path& file) } for (auto note = 0; note < 128; note++) { - if (region->keyRange.containsWithEnd(note) || - (region->hasKeyswitches() && region->keyswitchRange.containsWithEnd(note))) + if (region->keyRange.containsWithEnd(note) || (region->hasKeyswitches() && region->keyswitchRange.containsWithEnd(note))) noteActivationLists[note].push_back(region); } @@ -396,16 +396,13 @@ bool sfz::Synth::loadSfzFile(const fs::path& file) // Set the default frequencies on equalizers if needed if (region->equalizers.size() > 0 - && region->equalizers[0].frequency == Default::eqFrequencyUnset) - { + && region->equalizers[0].frequency == Default::eqFrequencyUnset) { region->equalizers[0].frequency = Default::eqFrequency1; if (region->equalizers.size() > 1 - && region->equalizers[1].frequency == Default::eqFrequencyUnset) - { + && region->equalizers[1].frequency == Default::eqFrequencyUnset) { region->equalizers[1].frequency = Default::eqFrequency2; if (region->equalizers.size() > 2 - && region->equalizers[2].frequency == Default::eqFrequencyUnset) - { + && region->equalizers[2].frequency == Default::eqFrequencyUnset) { region->equalizers[2].frequency = Default::eqFrequency3; } } @@ -425,7 +422,7 @@ bool sfz::Synth::loadSfzFile(const fs::path& file) regions.resize(remainingRegions); modificationTime = checkModificationTime(); - for (auto& voice: voices) { + for (auto& voice : voices) { voice->setMaxFiltersPerVoice(maxFilters); voice->setMaxEQsPerVoice(maxEQs); } @@ -468,7 +465,6 @@ int sfz::Synth::getNumActiveVoices() const noexcept void sfz::Synth::garbageCollect() noexcept { - } void sfz::Synth::setSamplesPerBlock(int samplesPerBlock) noexcept @@ -487,7 +483,7 @@ void sfz::Synth::setSamplesPerBlock(int samplesPerBlock) noexcept for (auto& voice : voices) voice->setSamplesPerBlock(samplesPerBlock); - for (auto& bus: effectBuses) { + for (auto& bus : effectBuses) { if (bus) bus->setSamplesPerBlock(samplesPerBlock); } @@ -507,7 +503,7 @@ void sfz::Synth::setSampleRate(float sampleRate) noexcept resources.filterPool.setSampleRate(sampleRate); resources.eqPool.setSampleRate(sampleRate); - for (auto& bus: effectBuses) { + for (auto& bus : effectBuses) { if (bus) bus->setSampleRate(sampleRate); } @@ -532,7 +528,7 @@ void sfz::Synth::renderBlock(AudioSpan buffer) noexcept { // Prepare the effect inputs. They are mixes of per-region outputs. ScopedTiming logger { callbackBreakdown.effects }; - for (auto& bus: effectBuses) { + for (auto& bus : effectBuses) { if (bus) bus->clearInputs(numFrames); } @@ -576,7 +572,7 @@ void sfz::Synth::renderBlock(AudioSpan buffer) noexcept // without any , the signal is just going to flow through it. ScopedTiming logger { callbackBreakdown.effects, ScopedTiming::Operation::addToDuration }; - for (auto& bus: effectBuses) { + for (auto& bus : effectBuses) { if (bus) { bus->process(numFrames); bus->mixOutputsTo(buffer, tempMixNode, numFrames); @@ -711,11 +707,11 @@ void sfz::Synth::pitchWheel(int delay, int pitch) noexcept ScopedTiming logger { dispatchDuration, ScopedTiming::Operation::addToDuration }; resources.midiState.pitchBendEvent(delay, pitch); - for (auto& region: regions) { + for (auto& region : regions) { region->registerPitchWheel(pitch); } - for (auto& voice: voices) { + for (auto& voice : voices) { voice->registerPitchWheel(delay, pitch); } } @@ -753,10 +749,9 @@ std::string sfz::Synth::exportMidnam(absl::string_view model) const if (model.empty()) model = config::midnamModel; - doc.append_child(pugi::node_doctype).set_value( - "MIDINameDocument PUBLIC" - " \"-//MIDI Manufacturers Association//DTD MIDINameDocument 1.0//EN\"" - " \"http://www.midi.org/dtds/MIDINameDocument10.dtd\""); + doc.append_child(pugi::node_doctype).set_value("MIDINameDocument PUBLIC" + " \"-//MIDI Manufacturers Association//DTD MIDINameDocument 1.0//EN\"" + " \"http://www.midi.org/dtds/MIDINameDocument10.dtd\""); pugi::xml_node root = doc.append_child("MIDINameDocument"); @@ -767,9 +762,11 @@ std::string sfz::Synth::exportMidnam(absl::string_view model) const pugi::xml_node device = root.append_child("MasterDeviceNames"); device.append_child("Manufacturer") - .append_child(pugi::node_pcdata).set_value(std::string(manufacturer).c_str()); + .append_child(pugi::node_pcdata) + .set_value(std::string(manufacturer).c_str()); device.append_child("Model") - .append_child(pugi::node_pcdata).set_value(std::string(model).c_str()); + .append_child(pugi::node_pcdata) + .set_value(std::string(model).c_str()); { pugi::xml_node devmode = device.append_child("CustomDeviceMode"); @@ -795,7 +792,8 @@ std::string sfz::Synth::exportMidnam(absl::string_view model) const } chns.append_child("UsesControlNameList") - .append_attribute("Name").set_value("Controls"); + .append_attribute("Name") + .set_value("Controls"); } { @@ -876,7 +874,7 @@ void sfz::Synth::setNumVoices(int numVoices) noexcept void sfz::Synth::resetVoices(int numVoices) { - AtomicDisabler callbackDisabler{ canEnterCallback }; + AtomicDisabler callbackDisabler { canEnterCallback }; while (inCallback) { std::this_thread::sleep_for(std::chrono::milliseconds(1)); } @@ -885,7 +883,7 @@ void sfz::Synth::resetVoices(int numVoices) for (int i = 0; i < numVoices; ++i) voices.push_back(absl::make_unique(resources)); - for (auto& voice: voices) { + for (auto& voice : voices) { voice->setSampleRate(this->sampleRate); voice->setSamplesPerBlock(this->samplesPerBlock); } @@ -896,12 +894,12 @@ void sfz::Synth::resetVoices(int numVoices) void sfz::Synth::setOversamplingFactor(sfz::Oversampling factor) noexcept { - AtomicDisabler callbackDisabler{ canEnterCallback }; + AtomicDisabler callbackDisabler { canEnterCallback }; while (inCallback) { std::this_thread::sleep_for(std::chrono::milliseconds(1)); } - for (auto& voice: voices) + for (auto& voice : voices) voice->reset(); resources.filePool.emptyFileLoadingQueues(); @@ -916,7 +914,7 @@ sfz::Oversampling sfz::Synth::getOversamplingFactor() const noexcept void sfz::Synth::setPreloadSize(uint32_t preloadSize) noexcept { - AtomicDisabler callbackDisabler{ canEnterCallback }; + AtomicDisabler callbackDisabler { canEnterCallback }; while (inCallback) { std::this_thread::sleep_for(std::chrono::milliseconds(1)); } @@ -951,13 +949,13 @@ void sfz::Synth::resetAllControllers(int delay) noexcept return; resources.midiState.resetAllControllers(delay); - for (auto& voice: voices) { + for (auto& voice : voices) { voice->registerPitchWheel(delay, 0); for (unsigned cc = 0; cc < config::numCCs; ++cc) voice->registerCC(delay, cc, 0); } - for (auto& region: regions) { + for (auto& region : regions) { for (unsigned cc = 0; cc < config::numCCs; ++cc) region->registerCC(cc, 0); } @@ -996,13 +994,13 @@ void sfz::Synth::disableLogging() noexcept void sfz::Synth::allSoundOff() noexcept { - AtomicDisabler callbackDisabler{ canEnterCallback }; + AtomicDisabler callbackDisabler { canEnterCallback }; while (inCallback) { std::this_thread::sleep_for(std::chrono::milliseconds(1)); } - for (auto &voice: voices) + for (auto& voice : voices) voice->reset(); - for (auto& effectBus: effectBuses) + for (auto& effectBus : effectBuses) effectBus->clear(); } diff --git a/tests/FilesT.cpp b/tests/FilesT.cpp index 6284ec6c..c58976a5 100644 --- a/tests/FilesT.cpp +++ b/tests/FilesT.cpp @@ -5,9 +5,11 @@ // If not, contact the sfizz maintainers at https://github.com/sfztools/sfizz #include "sfizz/Synth.h" +#include "sfizz/SfzHelpers.h" #include "catch2/catch.hpp" #include "ghc/fs_std.hpp" using namespace Catch::literals; +using namespace sfz::literals; TEST_CASE("[Files] Single region (regions_one.sfz)") { @@ -137,11 +139,11 @@ TEST_CASE("[Files] Group from AVL") REQUIRE(synth.getRegionView(i)->volume == 6.0f); REQUIRE(synth.getRegionView(i)->keyRange == sfz::Range(36, 36)); } - REQUIRE(synth.getRegionView(0)->velocityRange == sfz::Range(1, 26)); - REQUIRE(synth.getRegionView(1)->velocityRange == sfz::Range(27, 52)); - REQUIRE(synth.getRegionView(2)->velocityRange == sfz::Range(53, 77)); - REQUIRE(synth.getRegionView(3)->velocityRange == sfz::Range(78, 102)); - REQUIRE(synth.getRegionView(4)->velocityRange == sfz::Range(103, 127)); + REQUIRE(synth.getRegionView(0)->velocityRange == sfz::Range(1_norm, 26_norm)); + REQUIRE(synth.getRegionView(1)->velocityRange == sfz::Range(27_norm, 52_norm)); + REQUIRE(synth.getRegionView(2)->velocityRange == sfz::Range(53_norm, 77_norm)); + REQUIRE(synth.getRegionView(3)->velocityRange == sfz::Range(78_norm, 102_norm)); + REQUIRE(synth.getRegionView(4)->velocityRange == sfz::Range(103_norm, 127_norm)); } TEST_CASE("[Files] Full hierarchy") @@ -232,7 +234,7 @@ TEST_CASE("[Files] Pizz basic") REQUIRE(synth.getNumRegions() == 4); for (int i = 0; i < synth.getNumRegions(); ++i) { REQUIRE(synth.getRegionView(i)->keyRange == sfz::Range(12, 22)); - REQUIRE(synth.getRegionView(i)->velocityRange == sfz::Range(97, 127)); + REQUIRE(synth.getRegionView(i)->velocityRange == sfz::Range(97_norm, 127_norm)); REQUIRE(synth.getRegionView(i)->pitchKeycenter == 21); REQUIRE(synth.getRegionView(i)->ccConditions.getWithDefault(107) == sfz::Range(0, 13)); } diff --git a/tests/RegionT.cpp b/tests/RegionT.cpp index f65ad406..35af3f8c 100644 --- a/tests/RegionT.cpp +++ b/tests/RegionT.cpp @@ -6,8 +6,10 @@ #include "sfizz/MidiState.h" #include "sfizz/Region.h" +#include "sfizz/SfzHelpers.h" #include "catch2/catch.hpp" using namespace Catch::literals; +using namespace sfz::literals; TEST_CASE("[Region] Parsing opcodes") { @@ -204,19 +206,19 @@ TEST_CASE("[Region] Parsing opcodes") SECTION("lovel, hivel") { - REQUIRE(region.velocityRange == sfz::Range(0, 127)); + REQUIRE(region.velocityRange == sfz::Range(0_norm, 127_norm)); region.parseOpcode({ "lovel", "37" }); - REQUIRE(region.velocityRange == sfz::Range(37, 127)); + REQUIRE(region.velocityRange == sfz::Range(37_norm, 127_norm)); region.parseOpcode({ "lovel", "128" }); - REQUIRE(region.velocityRange == sfz::Range(127, 127)); + REQUIRE(region.velocityRange == sfz::Range(127_norm, 127_norm)); region.parseOpcode({ "lovel", "-3" }); - REQUIRE(region.velocityRange == sfz::Range(0, 127)); + REQUIRE(region.velocityRange == sfz::Range(0_norm, 127_norm)); region.parseOpcode({ "hivel", "65" }); - REQUIRE(region.velocityRange == sfz::Range(0, 65)); + REQUIRE(region.velocityRange == sfz::Range(0_norm, 65_norm)); region.parseOpcode({ "hivel", "-1" }); - REQUIRE(region.velocityRange == sfz::Range(0, 0)); + REQUIRE(region.velocityRange == sfz::Range(0_norm, 0_norm)); region.parseOpcode({ "hivel", "128" }); - REQUIRE(region.velocityRange == sfz::Range(0, 127)); + REQUIRE(region.velocityRange == sfz::Range(0_norm, 127_norm)); } SECTION("lobend, hibend") @@ -563,9 +565,9 @@ TEST_CASE("[Region] Parsing opcodes") SECTION("amp_velcurve") { region.parseOpcode({ "amp_velcurve_6", "0.4" }); - REQUIRE(region.velocityPoints.back() == std::make_pair(6, 0.4f)); + REQUIRE(region.velocityPoints.back() == std::make_pair(6_norm, 0.4f)); region.parseOpcode({ "amp_velcurve_127", "-1.0" }); - REQUIRE(region.velocityPoints.back() == std::make_pair(127, 0.0f)); + REQUIRE(region.velocityPoints.back() == std::make_pair(127_norm, 0.0f)); } SECTION("xfin_lokey, xfin_hikey") @@ -589,21 +591,21 @@ TEST_CASE("[Region] Parsing opcodes") SECTION("xfin_lovel, xfin_hivel") { - REQUIRE(region.crossfadeVelInRange == sfz::Range(0, 0)); + REQUIRE(region.crossfadeVelInRange == sfz::Range(0_norm, 0_norm)); region.parseOpcode({ "xfin_lovel", "4" }); - REQUIRE(region.crossfadeVelInRange == sfz::Range(4, 4)); + REQUIRE(region.crossfadeVelInRange == sfz::Range(4_norm, 4_norm)); region.parseOpcode({ "xfin_lovel", "128" }); - REQUIRE(region.crossfadeVelInRange == sfz::Range(127, 127)); + REQUIRE(region.crossfadeVelInRange == sfz::Range(127_norm, 127_norm)); region.parseOpcode({ "xfin_lovel", "59" }); - REQUIRE(region.crossfadeVelInRange == sfz::Range(59, 127)); + REQUIRE(region.crossfadeVelInRange == sfz::Range(59_norm, 127_norm)); region.parseOpcode({ "xfin_hivel", "59" }); - REQUIRE(region.crossfadeVelInRange == sfz::Range(59, 59)); + REQUIRE(region.crossfadeVelInRange == sfz::Range(59_norm, 59_norm)); region.parseOpcode({ "xfin_hivel", "128" }); - REQUIRE(region.crossfadeVelInRange == sfz::Range(59, 127)); + REQUIRE(region.crossfadeVelInRange == sfz::Range(59_norm, 127_norm)); region.parseOpcode({ "xfin_hivel", "0" }); - REQUIRE(region.crossfadeVelInRange == sfz::Range(0, 0)); + REQUIRE(region.crossfadeVelInRange == sfz::Range(0_norm, 0_norm)); region.parseOpcode({ "xfin_hivel", "-1" }); - REQUIRE(region.crossfadeVelInRange == sfz::Range(0, 0)); + REQUIRE(region.crossfadeVelInRange == sfz::Range(0_norm, 0_norm)); } SECTION("xfout_lokey, xfout_hikey") @@ -627,21 +629,21 @@ TEST_CASE("[Region] Parsing opcodes") SECTION("xfout_lovel, xfout_hivel") { - REQUIRE(region.crossfadeVelOutRange == sfz::Range(127, 127)); + REQUIRE(region.crossfadeVelOutRange == sfz::Range(127_norm, 127_norm)); region.parseOpcode({ "xfout_lovel", "4" }); - REQUIRE(region.crossfadeVelOutRange == sfz::Range(4, 127)); + REQUIRE(region.crossfadeVelOutRange == sfz::Range(4_norm, 127_norm)); region.parseOpcode({ "xfout_lovel", "128" }); - REQUIRE(region.crossfadeVelOutRange == sfz::Range(127, 127)); + REQUIRE(region.crossfadeVelOutRange == sfz::Range(127_norm, 127_norm)); region.parseOpcode({ "xfout_lovel", "59" }); - REQUIRE(region.crossfadeVelOutRange == sfz::Range(59, 127)); + REQUIRE(region.crossfadeVelOutRange == sfz::Range(59_norm, 127_norm)); region.parseOpcode({ "xfout_hivel", "59" }); - REQUIRE(region.crossfadeVelOutRange == sfz::Range(59, 59)); + REQUIRE(region.crossfadeVelOutRange == sfz::Range(59_norm, 59_norm)); region.parseOpcode({ "xfout_hivel", "128" }); - REQUIRE(region.crossfadeVelOutRange == sfz::Range(59, 127)); + REQUIRE(region.crossfadeVelOutRange == sfz::Range(59_norm, 127_norm)); region.parseOpcode({ "xfout_hivel", "0" }); - REQUIRE(region.crossfadeVelOutRange == sfz::Range(0, 0)); + REQUIRE(region.crossfadeVelOutRange == sfz::Range(0_norm, 0_norm)); region.parseOpcode({ "xfout_hivel", "-1" }); - REQUIRE(region.crossfadeVelOutRange == sfz::Range(0, 0)); + REQUIRE(region.crossfadeVelOutRange == sfz::Range(0_norm, 0_norm)); } SECTION("xfin_locc, xfin_hicc")