Skip to content

Commit

Permalink
Merge pull request #854 from paulfd/extended-ccs-2
Browse files Browse the repository at this point in the history
Store extended CCs in the midistate
  • Loading branch information
paulfd authored Apr 24, 2021
2 parents acd866f + e2c667c commit f5bed98
Show file tree
Hide file tree
Showing 8 changed files with 218 additions and 28 deletions.
4 changes: 1 addition & 3 deletions src/sfizz/Layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ bool Layer::registerNoteOn(int noteNumber, float velocity, float randValue) noex
return false;

if (region.velocityOverride == VelocityOverride::previous)
velocity = midiState_.getLastVelocity();
velocity = midiState_.getVelocityOverride();

const bool velOk = region.velocityRange.containsWithEnd(velocity);
const bool randOk = region.randRange.contains(randValue) || (randValue >= 1.0f && region.randRange.isValid() && region.randRange.getEnd() >= 1.0f);
Expand Down Expand Up @@ -131,8 +131,6 @@ bool Layer::registerNoteOff(int noteNumber, float velocity, float randValue) noe

bool Layer::registerCC(int ccNumber, float ccValue) noexcept
{
ASSERT(ccValue >= 0.0f && ccValue <= 1.0f);

const Region& region = region_;

if (ccNumber == region.sustainCC)
Expand Down
23 changes: 18 additions & 5 deletions src/sfizz/MidiState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,19 @@ void sfz::MidiState::noteOnEvent(int delay, int noteNumber, float velocity) noex
ASSERT(velocity >= 0 && velocity <= 1.0);

if (noteNumber >= 0 && noteNumber < 128) {
velocityOverride = lastNoteVelocities[lastNotePlayed];
lastNoteVelocities[noteNumber] = velocity;
noteOnTimes[noteNumber] = internalClock + static_cast<unsigned>(delay);
lastNotePlayed = noteNumber;
activeNotes++;
noteStates[noteNumber] = true;
ccEvent(delay, ExtendedCCs::noteOnVelocity, velocity);
ccEvent(delay, ExtendedCCs::keyboardNoteNumber, normalize7Bits(noteNumber));
ccEvent(delay, ExtendedCCs::unipolarRandom, unipolarDist(Random::randomGenerator));
ccEvent(delay, ExtendedCCs::bipolarRandom, bipolarDist(Random::randomGenerator));
ccEvent(delay, ExtendedCCs::keyboardNoteGate, activeNotes > 0 ? 1.0f : 0.0f);
activeNotes++;

ccEvent(delay, ExtendedCCs::alternate, alternate);
alternate = alternate == 0.0f ? 1.0f : 0.0f;
}

Expand All @@ -37,6 +45,10 @@ void sfz::MidiState::noteOffEvent(int delay, int noteNumber, float velocity) noe
UNUSED(velocity);
if (noteNumber >= 0 && noteNumber < 128) {
noteOffTimes[noteNumber] = internalClock + static_cast<unsigned>(delay);
ccEvent(delay, ExtendedCCs::noteOffVelocity, velocity);
ccEvent(delay, ExtendedCCs::keyboardNoteNumber, normalize7Bits(noteNumber));
ccEvent(delay, ExtendedCCs::unipolarRandom, unipolarDist(Random::randomGenerator));
ccEvent(delay, ExtendedCCs::bipolarRandom, bipolarDist(Random::randomGenerator));
if (activeNotes > 0)
activeNotes--;
noteStates[noteNumber] = false;
Expand Down Expand Up @@ -121,9 +133,9 @@ float sfz::MidiState::getNoteVelocity(int noteNumber) const noexcept
return lastNoteVelocities[noteNumber];
}

float sfz::MidiState::getLastVelocity() const noexcept
float sfz::MidiState::getVelocityOverride() const noexcept
{
return lastNoteVelocities[lastNotePlayed];
return velocityOverride;
}

void sfz::MidiState::insertEventInVector(EventVector& events, int delay, float value)
Expand Down Expand Up @@ -172,7 +184,7 @@ float sfz::MidiState::getPolyAftertouch(int noteNumber) const noexcept
{
if (noteNumber < 0 || noteNumber > 127)
return 0.0f;

ASSERT(polyAftertouchEvents[noteNumber].size() > 0);
return polyAftertouchEvents[noteNumber].back().value;
}
Expand All @@ -191,7 +203,7 @@ float sfz::MidiState::getCCValue(int ccNumber) const noexcept
void sfz::MidiState::reset() noexcept
{
for (auto& velocity: lastNoteVelocities)
velocity = 0;
velocity = 0.0f;

auto clearEvents = [] (EventVector& events) {
events.clear();
Expand All @@ -207,6 +219,7 @@ void sfz::MidiState::reset() noexcept
clearEvents(pitchEvents);
clearEvents(channelAftertouchEvents);

velocityOverride = 0.0f;
activeNotes = 0;
internalClock = 0;
lastNotePlayed = 0;
Expand Down
18 changes: 9 additions & 9 deletions src/sfizz/MidiState.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,11 @@ class MidiState
float getNoteVelocity(int noteNumber) const noexcept;

/**
* @brief Get the velocity of the last note played
* @brief Get the velocity override value (sw_vel in SFZ)
*
* @return float
*/
float getLastVelocity() const noexcept;
float getVelocityOverride() const noexcept;

/**
* @brief Register a pitch bend event
Expand Down Expand Up @@ -190,13 +190,6 @@ class MidiState
const EventVector& getPitchEvents() const noexcept;
const EventVector& getChannelAftertouchEvents() const noexcept;

/**
* @brief Get the alternate state value, for extended CC 137
*
* @return float
*/
float getAlternateState() const noexcept { return alternate; }

private:

/**
Expand Down Expand Up @@ -236,6 +229,11 @@ class MidiState
*/
MidiNoteArray<float> lastNoteVelocities;

/**
* @brief Velocity override value (sw_vel in SFZ)
*/
float velocityOverride;

/**
* @brief Last note played
*/
Expand Down Expand Up @@ -272,5 +270,7 @@ class MidiState
int samplesPerBlock { config::defaultSamplesPerBlock };
float alternate { 0.0f };
unsigned internalClock { 0 };
fast_real_distribution<float> unipolarDist { 0.0f, 1.0f };
fast_real_distribution<float> bipolarDist { -1.0f, 1.0f };
};
}
5 changes: 2 additions & 3 deletions src/sfizz/Synth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1073,8 +1073,8 @@ void Synth::hdNoteOn(int delay, int noteNumber, float normalizedVelocity) noexce
ASSERT(noteNumber >= 0);
Impl& impl = *impl_;
ScopedTiming logger { impl.dispatchDuration_, ScopedTiming::Operation::addToDuration };
impl.noteOnDispatch(delay, noteNumber, normalizedVelocity);
impl.resources_.midiState.noteOnEvent(delay, noteNumber, normalizedVelocity);
impl.noteOnDispatch(delay, noteNumber, normalizedVelocity);
}

void Synth::noteOff(int delay, int noteNumber, int velocity) noexcept
Expand All @@ -1087,20 +1087,19 @@ void Synth::hdNoteOff(int delay, int noteNumber, float normalizedVelocity) noexc
{
ASSERT(noteNumber < 128);
ASSERT(noteNumber >= 0);
UNUSED(normalizedVelocity);
Impl& impl = *impl_;
ScopedTiming logger { impl.dispatchDuration_, ScopedTiming::Operation::addToDuration };

// FIXME: Some keyboards (e.g. Casio PX5S) can send a real note-off velocity. In this case, do we have a
// way in sfz to specify that a release trigger should NOT use the note-on velocity?
// auto replacedVelocity = (velocity == 0 ? getNoteVelocity(noteNumber) : velocity);
impl.resources_.midiState.noteOffEvent(delay, noteNumber, normalizedVelocity);
const auto replacedVelocity = impl.resources_.midiState.getNoteVelocity(noteNumber);

for (auto& voice : impl.voiceManager_)
voice.registerNoteOff(delay, noteNumber, replacedVelocity);

impl.noteOffDispatch(delay, noteNumber, replacedVelocity);
impl.resources_.midiState.noteOffEvent(delay, noteNumber, normalizedVelocity);
}

void Synth::Impl::startVoice(Layer* layer, int delay, const TriggerEvent& triggerEvent, SisterVoiceRingBuilder& ring) noexcept
Expand Down
10 changes: 10 additions & 0 deletions src/sfizz/SynthMessaging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1454,6 +1454,16 @@ void sfz::Synth::dispatchMessage(Client& client, int delay, const char* path, co

} break;

MATCH("/voice&/remaining_delay", "") {
GET_VOICE_OR_BREAK(indices[0])
client.receive<'i'>(delay, path, voice.getRemainingDelay());
} break;

MATCH("/voice&/source_position", "") {
GET_VOICE_OR_BREAK(indices[0])
client.receive<'i'>(delay, path, voice.getSourcePosition());
} break;

#undef MATCH
// TODO...
}
Expand Down
24 changes: 17 additions & 7 deletions src/sfizz/Voice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -304,8 +304,6 @@ struct Voice::Impl
PowerFollower powerFollower_;

ExtendedCCValues extendedCCValues_;
fast_real_distribution<float> unipolarDist { 0.0f, 1.0f };
fast_real_distribution<float> bipolarDist { -1.0f, 1.0f };
};

Voice::Voice(int voiceNumber, Resources& resources)
Expand Down Expand Up @@ -389,10 +387,10 @@ const ExtendedCCValues& Voice::getExtendedCCValues() const noexcept

void Voice::Impl::updateExtendedCCValues() noexcept
{
extendedCCValues_.unipolar = unipolarDist(Random::randomGenerator);
extendedCCValues_.bipolar = bipolarDist(Random::randomGenerator);
extendedCCValues_.alternate = resources_.midiState.getAlternateState();
extendedCCValues_.noteGate = resources_.midiState.getActiveNotes() > 0 ? 1.0f : 0.0f;
extendedCCValues_.unipolar = resources_.midiState.getCCValue(ExtendedCCs::unipolarRandom);
extendedCCValues_.bipolar = resources_.midiState.getCCValue(ExtendedCCs::bipolarRandom);
extendedCCValues_.alternate = resources_.midiState.getCCValue(ExtendedCCs::alternate);
extendedCCValues_.noteGate = resources_.midiState.getCCValue(ExtendedCCs::keyboardNoteGate);
}

bool Voice::startVoice(Layer* layer, int delay, const TriggerEvent& event) noexcept
Expand All @@ -410,7 +408,7 @@ bool Voice::startVoice(Layer* layer, int delay, const TriggerEvent& event) noexc
impl.triggerEvent_.number = region.pitchKeycenter;

if (region.velocityOverride == VelocityOverride::previous)
impl.triggerEvent_.value = resources.midiState.getLastVelocity();
impl.triggerEvent_.value = resources.midiState.getVelocityOverride();

if (region.disabled()) {
impl.switchState(State::cleanMeUp);
Expand Down Expand Up @@ -2000,6 +1998,18 @@ const Region* Voice::getRegion() const noexcept
return impl.region_;
}

int Voice::getRemainingDelay() const noexcept
{
Impl& impl = *impl_;
return impl.initialDelay_;
}

int Voice::getSourcePosition() const noexcept
{
Impl& impl = *impl_;
return impl.sourcePosition_;
}

LFO* Voice::getLFO(size_t index)
{
Impl& impl = *impl_;
Expand Down
13 changes: 13 additions & 0 deletions src/sfizz/Voice.h
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,19 @@ class Voice {
*/
const ExtendedCCValues& getExtendedCCValues() const noexcept;

/**
* @brief Get the remaining delay before the sample starts, in samples
*
* @return int
*/
int getRemainingDelay() const noexcept;
/**
* @brief Get the current position in the source sample
*
* @return int
*/
int getSourcePosition() const noexcept;

public:
/**
* @brief Check if the voice already belongs to a sister ring
Expand Down
Loading

0 comments on commit f5bed98

Please sign in to comment.