Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Maybe fix ghost notes issue? #3288

Open
wants to merge 2 commits into
base: community
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions src/deluge/gui/ui/keyboard/keyboard_screen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -328,11 +328,10 @@ void KeyboardScreen::updateActiveNotes() {
// in MelodicInstrument and Kit
if (isUIModeActive(UI_MODE_RECORD_COUNT_IN)) { // It definitely will be auditioning if we're here
ModelStackWithNoteRow* modelStackWithNoteRow = modelStackWithTimelineCounter->addNoteRow(0, NULL);
((MelodicInstrument*)activeInstrument)
->earlyNotes.emplace(newNote,
MelodicInstrument::EarlyNoteInfo{
static_cast<uint8_t>(currentNotesState.notes[idx].velocity),
getCurrentInstrumentClip()->allowNoteTails(modelStackWithNoteRow)});
static_cast<MelodicInstrument*>(activeInstrument)->earlyNotes[newNote] = {
.velocity = static_cast<uint8_t>(currentNotesState.notes[idx].velocity),
.still_active = getCurrentInstrumentClip()->allowNoteTails(modelStackWithNoteRow),
};
}

else {
Expand Down
33 changes: 18 additions & 15 deletions src/deluge/gui/views/automation_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3445,7 +3445,7 @@ void AutomationView::auditionPadAction(int32_t velocity, int32_t yDisplay, bool

// Or if synth
else if (outputType == OutputType::SYNTH) {
if (velocity) {
if (velocity != 0) {
if (getCurrentUI() == &soundEditor && soundEditor.getCurrentMenuItem() == &menu_item::multiRangeMenu) {
menu_item::multiRangeMenu.noteOnToChangeRange(clip->getYNoteFromYDisplay(yDisplay, currentSong)
+ ((SoundInstrument*)output)->transpose);
Expand All @@ -3457,27 +3457,29 @@ void AutomationView::auditionPadAction(int32_t velocity, int32_t yDisplay, bool
if (clipIsActiveOnInstrument && playbackHandler.shouldRecordNotesNow() && currentSong->isClipActive(clip)) {

// Note-on
if (velocity) {
if (velocity != 0) {

// If count-in is on, we only got here if it's very nearly finished, so pre-empt that note.
// This is basic. For MIDI input, we do this in a couple more cases - see
// noteMessageReceived() in MelodicInstrument and Kit
if (isUIModeActive(UI_MODE_RECORD_COUNT_IN)) {
if (isKit) {
if (drum) {
drum->recordNoteOnEarly(
(velocity == USE_DEFAULT_VELOCITY) ? ((Instrument*)output)->defaultVelocity : velocity,
clip->allowNoteTails(modelStackWithNoteRowOnCurrentClip));
drum->recordNoteOnEarly((velocity == USE_DEFAULT_VELOCITY)
? (static_cast<Instrument*>(output)->defaultVelocity)
: velocity,
clip->allowNoteTails(modelStackWithNoteRowOnCurrentClip));
}
}
else {
// NoteRow is allowed to be NULL in this case.
int32_t yNote = clip->getYNoteFromYDisplay(yDisplay, currentSong);
((MelodicInstrument*)output)
->earlyNotes.emplace(yNote, MelodicInstrument::EarlyNoteInfo{
((Instrument*)output)->defaultVelocity,
clip->allowNoteTails(modelStackWithNoteRowOnCurrentClip),
});
static_cast<MelodicInstrument*>(output)->earlyNotes[yNote] = {
.velocity = (velocity == USE_DEFAULT_VELOCITY)
? (static_cast<Instrument*>(output)->defaultVelocity)
: static_cast<uint8_t>(velocity),
.still_active = clip->allowNoteTails(modelStackWithNoteRowOnCurrentClip),
};
}
}

Expand All @@ -3491,9 +3493,10 @@ void AutomationView::auditionPadAction(int32_t velocity, int32_t yDisplay, bool
}

if (modelStackWithNoteRowOnCurrentClip->getNoteRowAllowNull()) {
clip->recordNoteOn(modelStackWithNoteRowOnCurrentClip, (velocity == USE_DEFAULT_VELOCITY)
? ((Instrument*)output)->defaultVelocity
: velocity);
clip->recordNoteOn(modelStackWithNoteRowOnCurrentClip,
(velocity == USE_DEFAULT_VELOCITY)
? static_cast<Instrument*>(output)->defaultVelocity
: velocity);
}
}
}
Expand Down Expand Up @@ -3528,7 +3531,7 @@ void AutomationView::auditionPadAction(int32_t velocity, int32_t yDisplay, bool
}

// If note on...
if (velocity) {
if (velocity != 0) {
int32_t velocityToSound = velocity;
if (velocityToSound == USE_DEFAULT_VELOCITY) {
velocityToSound = ((Instrument*)output)->defaultVelocity;
Expand All @@ -3537,7 +3540,7 @@ void AutomationView::auditionPadAction(int32_t velocity, int32_t yDisplay, bool
// Yup, need to do this even if we're going to do a "silent" audition, so pad lights up etc.
instrumentClipView.auditionPadIsPressed[yDisplay] = velocityToSound;

if (noteRowOnActiveClip) {
if (noteRowOnActiveClip != nullptr) {
// Ensure our auditioning doesn't override a note playing in the sequence
if (playbackHandler.isEitherClockActive() && noteRowOnActiveClip->sequenced) {
goto doSilentAudition;
Expand Down
11 changes: 5 additions & 6 deletions src/deluge/gui/views/instrument_clip_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4668,12 +4668,11 @@ void InstrumentClipView::recordNoteOnEarly(int32_t velocity, int32_t yDisplay, I
else {
// NoteRow is allowed to be NULL in this case.
int32_t yNote = getCurrentInstrumentClip()->getYNoteFromYDisplay(yDisplay, currentSong);
((MelodicInstrument*)instrument)
->earlyNotes.emplace(yNote,
MelodicInstrument::EarlyNoteInfo{
instrument->defaultVelocity,
getCurrentInstrumentClip()->allowNoteTails(modelStackWithNoteRowOnCurrentClip),
});
static_cast<MelodicInstrument*>(instrument)->earlyNotes[yNote] = {
.velocity =
(velocity == USE_DEFAULT_VELOCITY) ? instrument->defaultVelocity : static_cast<uint8_t>(velocity),
.still_active = getCurrentInstrumentClip()->allowNoteTails(modelStackWithNoteRowOnCurrentClip),
};
}
}

Expand Down
13 changes: 6 additions & 7 deletions src/deluge/model/clip/instrument_clip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -479,17 +479,17 @@ Error InstrumentClip::beginLinearRecording(ModelStackWithTimelineCounter* modelS
bool scaleAltered = false;

for (auto [note, noteInfo] : melodicInstrument->earlyNotes) {
const auto [velocity, stillActive] = noteInfo;
const auto [velocity, still_active] = noteInfo;

ModelStackWithNoteRow* modelStackWithNoteRow =
getOrCreateNoteRowForYNote(note, modelStack, action, &scaleAltered);
NoteRow* noteRow = modelStackWithNoteRow->getNoteRowAllowNull();
if (noteRow) {
if (noteRow != nullptr) {
int32_t probability = noteRow->getDefaultProbability();
Iterance iterance = noteRow->getDefaultIterance();
int32_t fill = noteRow->getDefaultFill(modelStackWithNoteRow);
noteRow->attemptNoteAdd(0, 1, velocity, probability, iterance, fill, modelStackWithNoteRow, action);
if (!stillActive) {
if (!still_active) {
// We just inserted a note-on for an "early" note that is still sounding at time 0, so ignore
// note-ons until at least tick 1 to avoid double-playing that note
noteRow->ignoreNoteOnsBefore_ = 1;
Expand All @@ -498,12 +498,11 @@ Error InstrumentClip::beginLinearRecording(ModelStackWithTimelineCounter* modelS
}

// If this caused the scale to change, update scroll
if (action && scaleAltered) {
if (action != nullptr && scaleAltered) {
action->updateYScrollClipViewAfter();
}
melodicInstrument->earlyNotes.clear();
}

melodicInstrument->earlyNotes.clear();
}

return Clip::beginLinearRecording(modelStack, buttonPressLatency);
Expand Down Expand Up @@ -4652,7 +4651,7 @@ void InstrumentClip::yDisplayNoLongerAuditioning(int32_t yDisplay, Song* song) {

else {
int32_t yNote = getYNoteFromYDisplay(yDisplay, song);
((MelodicInstrument*)output)->notesAuditioned.erase(yNote);
static_cast<MelodicInstrument*>(output)->notesAuditioned.erase(yNote);
}

expectEvent();
Expand Down
6 changes: 0 additions & 6 deletions src/deluge/model/instrument/instrument.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,6 @@
#include <cstring>
#include <new>

Instrument::Instrument(OutputType newType) : Output(newType) {
editedByUser = false;
existsOnCard = false;
defaultVelocity = FlashStorage::defaultVelocity;
}

/*
Instrument::~Instrument() {
// Arrangement-only Clips won't get deallocated here - that'll happen from the Song.
Expand Down
9 changes: 5 additions & 4 deletions src/deluge/model/instrument/instrument.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "io/midi/learned_midi.h"
#include "model/clip/clip_instance_vector.h"
#include "model/output.h"
#include "storage/flash_storage.h"

class StereoSample;
class ModControllable;
Expand All @@ -43,14 +44,14 @@ class ModelStackWithThreeMainThings;

class Instrument : public Output {
public:
Instrument(OutputType newType);
Instrument(OutputType newType) : Output(newType) {}
// This needs to be initialized / defaulted to "SYNTHS" or "KITS" (for those Instrument types). The constructor does
// not do this, partly because I don't want it doing memory allocation, and also because in many cases, the function
// creating the object hard-sets this anyway.
String dirPath;

bool editedByUser;
bool existsOnCard;
bool editedByUser = false;
bool existsOnCard = false;
bool shouldHibernate{true};
bool matchesPreset(OutputType otherType, int32_t channel, int32_t channelSuffix, char const* otherName,
char const* otherPath) override {
Expand Down Expand Up @@ -86,7 +87,7 @@ class Instrument : public Output {

virtual bool isAnyAuditioningHappening() = 0;

uint8_t defaultVelocity;
uint8_t defaultVelocity = FlashStorage::defaultVelocity;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just want to make sure, the flash storage is already read before this default variable is initialized?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question. The timing hasn't changed by moving it here (initialization still happens at instantiation), so I presume it is fully set up.

LearnedMIDI midiInput;

protected:
Expand Down
13 changes: 8 additions & 5 deletions src/deluge/model/instrument/melodic_instrument.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,10 @@ void MelodicInstrument::receivedNote(ModelStackWithTimelineCounter* modelStack,
}
else if (currentUIMode == UI_MODE_RECORD_COUNT_IN) {
recordingEarly:
earlyNotes.emplace(note,
EarlyNoteInfo{static_cast<uint8_t>(velocity),
instrumentClip->allowNoteTails(modelStackWithNoteRow)});
earlyNotes[note] = {
.velocity = static_cast<uint8_t>(velocity),
.still_active = instrumentClip->allowNoteTails(modelStackWithNoteRow),
};
goto justAuditionNote;
}

Expand Down Expand Up @@ -541,7 +542,9 @@ void MelodicInstrument::beginAuditioningForNote(ModelStack* modelStack, int32_t
}

if (!activeClip || ((InstrumentClip*)activeClip)->allowNoteTails(modelStackWithNoteRow)) {
notesAuditioned.emplace(note, EarlyNoteInfo{static_cast<uint8_t>(velocity)});
notesAuditioned[note] = {
.velocity = static_cast<uint8_t>(velocity),
};
}

ParamManager* paramManager = getParamManager(modelStackWithNoteRow->song);
Expand All @@ -554,7 +557,7 @@ void MelodicInstrument::beginAuditioningForNote(ModelStack* modelStack, int32_t
void MelodicInstrument::endAuditioningForNote(ModelStack* modelStack, int32_t note, int32_t velocity) {

notesAuditioned.erase(note);
earlyNotes[note].stillActive = false; // set no longer active
earlyNotes[note].still_active = false; // set no longer active
if (!activeClip) {
return;
}
Expand Down
2 changes: 1 addition & 1 deletion src/deluge/model/instrument/melodic_instrument.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class MelodicInstrument : public Instrument {

struct EarlyNoteInfo {
uint8_t velocity;
bool stillActive = false;
bool still_active = false;
};

deluge::fast_map<int16_t, EarlyNoteInfo> earlyNotes; // note value, velocity, still_active
Expand Down
Loading