Skip to content

Commit

Permalink
Pr midi replace (fixes #836) (#965)
Browse files Browse the repository at this point in the history
* Exclude events in replace mode

* Update

* Fixes

* Don't play events in replace mode

* Update changelog

* Cleanup
  • Loading branch information
kybos committed Feb 12, 2021
1 parent 173bdec commit bbf2741
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 36 deletions.
2 changes: 2 additions & 0 deletions muse3/ChangeLog
@@ -1,3 +1,5 @@
12.02.2021
- Fix #836: Don't play existing midi events in replace mode. (kybos)
11.02.2021
- Fixed wrong exclusive indicators (radiobuttons) in some submenus. (kybos)
08.02.2021
Expand Down
98 changes: 62 additions & 36 deletions muse3/muse/midi.cpp
Expand Up @@ -1326,6 +1326,15 @@ void Audio::collectEvents(MusECore::MidiTrack* track, unsigned int cts,

const unsigned int pos_fr = _pos.frame() + latency_offset;
const unsigned int next_pos_fr = pos_fr + frames;

// at least one punch is set at this point
const bool replaceMode = recording && track->recordFlag() && MusEGlobal::song->recMode() == MusEGlobal::song->REC_REPLACE;
const bool punchboth = MusEGlobal::song->punchin() && MusEGlobal::song->punchout();
const bool punchin = MusEGlobal::song->punchin() && !MusEGlobal::song->punchout();
const bool punchout = MusEGlobal::song->punchout() && !MusEGlobal::song->punchin();
const unsigned int rangeStart = MusEGlobal::song->lPos().tick();
const unsigned int rangeEnd = MusEGlobal::song->rPos().tick();


DEBUG_MIDI_TIMING(stderr, "Audio::collectEvents: pos_fr:%u next_pos_fr:%u\n", pos_fr, next_pos_fr);

Expand Down Expand Up @@ -1375,8 +1384,19 @@ void Audio::collectEvents(MusECore::MidiTrack* track, unsigned int cts,
if (ev.isNote() && track->drummap()[instr].mute)
continue;
}
unsigned tick = ev.tick() + offset;

if (replaceMode) {
unsigned eventStart = ev.tick() + partTick;
if (punchboth && (eventStart >= rangeStart && eventStart < rangeEnd))
continue;
else if (punchin && eventStart >= rangeStart)
continue;
else if (punchout && eventStart < rangeEnd)
continue;
}

unsigned tick = ev.tick() + offset;

DEBUG_MIDI_TIMING(stderr, "Audio::collectEvents: event tick:%u\n", tick);

//-----------------------------------------------------------------
Expand Down Expand Up @@ -1745,48 +1765,54 @@ void Audio::processMidi(unsigned int frames)
MidiTrack* track = *t;
const int t_port = track->outPort();
const int t_channel = track->outChannel();
MidiPort* mp = 0;
MidiPort* mp = nullptr;
if(t_port >= 0 && t_port < MusECore::MIDI_PORTS)
mp = &MusEGlobal::midiPorts[t_port];
MidiDevice* md = 0;
MidiDevice* md = nullptr;
if(mp)
md = mp->device();

// only add track events if the track is unmuted and turned on
if(!track->isMute() && !track->off())
{
if(playing)
{
unsigned int lat_offset = 0;
unsigned int cur_tick = curTickPos;
unsigned int next_tick = nextTickPos;

//--------------------------------------------------------------------
// Account for the midi track's latency correction and/or compensation.
//--------------------------------------------------------------------
// TODO How to handle when external sync is on. For now, don't try to correct.
if(MusEGlobal::config.enableLatencyCorrection && !extsync)
// don't render existing events in replace mode (except when punch is active - to be filtered later)
if (!(recording && track->recordFlag() && MusEGlobal::song->recMode() == MusEGlobal::song->REC_REPLACE
&& !MusEGlobal::song->punchin() && !MusEGlobal::song->punchout()))
{
const TrackLatencyInfo& li = track->getLatencyInfo(false);
// This value is negative for correction.
const float mlat = li._sourceCorrectionValue;
if((int)mlat < 0)
{
// Convert to a positive offset.
const unsigned int l = (unsigned int)(-mlat);
if(l > lat_offset)
lat_offset = l;
}
if(lat_offset != 0)
{
Pos ppp(_pos.frame() + lat_offset, false);
cur_tick = ppp.tick();
ppp += frames;
next_tick = ppp.tick();
}
}
if(playing)
{
unsigned int lat_offset = 0;
unsigned int cur_tick = curTickPos;
unsigned int next_tick = nextTickPos;

//--------------------------------------------------------------------
// Account for the midi track's latency correction and/or compensation.
//--------------------------------------------------------------------
// TODO How to handle when external sync is on. For now, don't try to correct.
if(MusEGlobal::config.enableLatencyCorrection && !extsync)
{
const TrackLatencyInfo& li = track->getLatencyInfo(false);
// This value is negative for correction.
const float mlat = li._sourceCorrectionValue;
if((int)mlat < 0)
{
// Convert to a positive offset.
const unsigned int l = (unsigned int)(-mlat);
if(l > lat_offset)
lat_offset = l;
}
if(lat_offset != 0)
{
Pos ppp(_pos.frame() + lat_offset, false);
cur_tick = ppp.tick();
ppp += frames;
next_tick = ppp.tick();
}
}

collectEvents(track, cur_tick, next_tick, frames, lat_offset);
}
collectEvents(track, cur_tick, next_tick, frames, lat_offset);
}
}
}

//
Expand Down Expand Up @@ -1918,7 +1944,7 @@ void Audio::processMidi(unsigned int frames)
MidiRecordEvent event(rf.peek(i));
int defaultPort = devport;
int drumRecPitch=0; //prevent compiler warning: variable used without initialization
MidiController *mc = 0;
MidiController *mc = nullptr;
int ctl = 0;
int prePitch = 0, preVelo = 0;

Expand Down Expand Up @@ -2597,7 +2623,7 @@ void Audio::processPrecount(unsigned int frames)
"_precountFramePos:%u precountMidiClickFrame:%u nextPrecountFramePos:%u clickno:%d\n",
syncFrame, _pos.frame(), _precountFramePos, precountMidiClickFrame, nextPrecountFramePos, clickno);

MidiDevice* md = 0;
MidiDevice* md = nullptr;
if(metro_settings->midiClickFlag)
md = MusEGlobal::midiPorts[metro_settings->clickPort].device();

Expand Down

0 comments on commit bbf2741

Please sign in to comment.