Skip to content

Commit

Permalink
Merge pull request #1430 from MarcSabatella/38041-midi-pedal
Browse files Browse the repository at this point in the history
fix #38041: pedal not exported to MIDI
  • Loading branch information
lasconic committed Nov 7, 2014
2 parents d04f175 + 0091f23 commit 4ba889b
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 52 deletions.
108 changes: 60 additions & 48 deletions libmscore/rendermidi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,62 @@ void Score::renderStaff(EventMap* events, Staff* staff)
}
}

//---------------------------------------------------------
// renderSpanners
//---------------------------------------------------------

void Score::renderSpanners(EventMap* events, int staffIdx)
{
foreach (const RepeatSegment* rs, *repeatList()) {
int tickOffset = rs->utick - rs->tick;
int utick1 = rs->utick;
int utick2 = utick1 + rs->len;
std::map<int, std::vector<std::pair<int, bool>>> channelPedalEvents = std::map<int, std::vector<std::pair<int, bool>>>();
for (std::pair<int,Spanner*> sp : _spanner.map()) {
Spanner* s = sp.second;
if (s->type() != Element::Type::PEDAL || (staffIdx != -1 && s->staffIdx() != staffIdx))
continue;

int idx = s->staff()->channel(s->tick(), 0);
int channel = s->staff()->part()->instr(s->tick())->channel(idx).channel;
channelPedalEvents.insert({channel, std::vector<std::pair<int, bool>>()});
std::vector<std::pair<int, bool>> pedalEventList = channelPedalEvents.at(channel);
std::pair<int, bool> lastEvent;

if (!pedalEventList.empty())
lastEvent = pedalEventList.back();
else
lastEvent = std::pair<int, bool>(0, true);

if (s->tick() >= utick1 && s->tick() < utick2)
{
// Handle "overlapping" pedal segments (usual case for connected pedal line)
if (lastEvent.second == false && lastEvent.first >= (s->tick() + tickOffset + 2)) {
channelPedalEvents.at(channel).pop_back();
channelPedalEvents.at(channel).push_back(std::pair<int, bool>(s->tick() + tickOffset + 1, false));
}
channelPedalEvents.at(channel).push_back(std::pair<int, bool>(s->tick() + tickOffset + 2, true));
}
if (s->tick2() >= utick1 && s->tick2() < utick2)
channelPedalEvents.at(channel).push_back(std::pair<int, bool>(s->tick2() + tickOffset + 1, false));
}

for (std::pair<int, std::vector<std::pair<int, bool>>> pedalEvents : channelPedalEvents)
{
int channel = pedalEvents.first;
for (std::pair<int, bool> pe : pedalEvents.second)
{
NPlayEvent event;
if (pe.second == true)
event = NPlayEvent(ME_CONTROLLER, channel, CTRL_SUSTAIN, 127);
else
event = NPlayEvent(ME_CONTROLLER, channel, CTRL_SUSTAIN, 0);
events->insert(std::pair<int,NPlayEvent>(pe.first, event));
}
}
}
}

//--------------------------------------------------------
// swingAdjustParams
//--------------------------------------------------------
Expand Down Expand Up @@ -948,9 +1004,13 @@ void Score::renderMidi(EventMap* events)
updateChannel();
updateVelo();

// create note & other events
foreach (Staff* part, _staves)
renderStaff(events, part);

// create sustain pedal events
renderSpanners(events, -1);

// add metronome ticks
foreach (const RepeatSegment* rs, *repeatList()) {
int startTick = rs->tick;
Expand All @@ -973,54 +1033,6 @@ void Score::renderMidi(EventMap* events)
if (m->tick() + m->ticks() >= endTick)
break;
}
//
// create sustain pedal events
//
int utick1 = rs->utick;
int utick2 = utick1 + rs->len;
std::map<int, std::vector<std::pair<int, bool>>> channelPedalEvents = std::map<int, std::vector<std::pair<int, bool>>>();
for (std::pair<int,Spanner*> sp : _spanner.map()) {
Spanner* s = sp.second;
if (s->type() != Element::Type::PEDAL)
continue;

int idx = s->staff()->channel(s->tick(), 0);
int channel = s->staff()->part()->instr(s->tick())->channel(idx).channel;
channelPedalEvents.insert({channel, std::vector<std::pair<int, bool>>()});
std::vector<std::pair<int, bool>> pedalEventList = channelPedalEvents.at(channel);
std::pair<int, bool> lastEvent;

if (!pedalEventList.empty())
lastEvent = pedalEventList.back();
else
lastEvent = std::pair<int, bool>(0, true);

if (s->tick() >= utick1 && s->tick() < utick2)
{
// Handle "overlapping" pedal segments (usual case for connected pedal line)
if (lastEvent.second == false && lastEvent.first >= (s->tick() + tickOffset + 2)) {
channelPedalEvents.at(channel).pop_back();
channelPedalEvents.at(channel).push_back(std::pair<int, bool>(s->tick() + tickOffset + 1, false));
}
channelPedalEvents.at(channel).push_back(std::pair<int, bool>(s->tick() + tickOffset + 2, true));
}
if (s->tick2() >= utick1 && s->tick2() < utick2)
channelPedalEvents.at(channel).push_back(std::pair<int, bool>(s->tick2() + tickOffset + 1, false));
}

for (std::pair<int, std::vector<std::pair<int, bool>>> pedalEvents : channelPedalEvents)
{
int channel = pedalEvents.first;
for (std::pair<int, bool> pe : pedalEvents.second)
{
NPlayEvent event;
if (pe.second == true)
event = NPlayEvent(ME_CONTROLLER, channel, CTRL_SUSTAIN, 127);
else
event = NPlayEvent(ME_CONTROLLER, channel, CTRL_SUSTAIN, 0);
events->insert(std::pair<int,NPlayEvent>(pe.first, event));
}
}
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions libmscore/score.h
Original file line number Diff line number Diff line change
Expand Up @@ -431,14 +431,15 @@ class Score : public QObject {
bool rewriteMeasures(Measure* fm, Measure* lm, const Fraction&);
bool rewriteMeasures(Measure* fm, const Fraction& ns);
void updateVelo();
void swingAdjustParams(Chord*, int&, int&, int, int);
bool isSubdivided(ChordRest*, int);
void addAudioTrack();
void parseVersion(const QString&);
QList<Fraction> splitGapToMeasureBoundaries(ChordRest*, Fraction);
void pasteChordRest(ChordRest* cr, int tick, const Interval&);
void init();
void removeGeneratedElements(Measure* mb, Measure* end);
qreal cautionaryWidth(Measure* m, bool& hasCourtesy);
void createPlayEvents();

void selectSingle(Element* e, int staffIdx);
void selectAdd(Element* e);
Expand Down Expand Up @@ -737,9 +738,7 @@ class Score : public QObject {
void pasteSymbols(XmlReader& e, ChordRest* dst);
void renderMidi(EventMap* events);
void renderStaff(EventMap* events, Staff*);

void swingAdjustParams(Chord*, int&, int&, int, int);
bool isSubdivided(ChordRest*, int);
void renderSpanners(EventMap* events, int staffIdx);

int mscVersion() const { return _mscVersion; }
void setMscVersion(int v) { _mscVersion = v; }
Expand All @@ -756,6 +755,7 @@ class Score : public QObject {
void rebuildMidiMapping();
void updateChannel();
void updateSwing();
void createPlayEvents();

void cmdConcertPitchChanged(bool, bool /*useSharpsFlats*/);

Expand Down
3 changes: 3 additions & 0 deletions mscore/exportmidi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,8 @@ bool ExportMidi::write(const QString& name, bool midiExpandRepeats)
for (int i = 0; i < cs->nstaves(); ++i)
tracks.append(MidiTrack());

cs->updateSwing();
cs->createPlayEvents();
cs->updateRepeatList(midiExpandRepeats);
writeHeader();

Expand All @@ -236,6 +238,7 @@ bool ExportMidi::write(const QString& name, bool midiExpandRepeats)
// Render each staff only once
EventMap events;
cs->renderStaff(&events, staff);
cs->renderSpanners(&events, staffIdx);

// Pass throught the all instruments in the part
const InstrumentList* il = part->instrList();
Expand Down

0 comments on commit 4ba889b

Please sign in to comment.