Skip to content

Commit

Permalink
first implementation of vibrato playback
Browse files Browse the repository at this point in the history
  • Loading branch information
lasconic committed Nov 20, 2017
1 parent c333db2 commit 374f9b1
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 22 deletions.
71 changes: 49 additions & 22 deletions libmscore/rendermidi.cpp
Expand Up @@ -662,34 +662,61 @@ void Score::renderSpanners(EventMap* events, int staffIdx)
std::map<int, std::vector<std::pair<int, bool>>> channelPedalEvents = std::map<int, std::vector<std::pair<int, bool>>>();
for (const auto& sp : _spanner.map()) {
Spanner* s = sp.second;
if (s->type() != ElementType::PEDAL || (staffIdx != -1 && s->staffIdx() != staffIdx))
if (staffIdx != -1 && s->staffIdx() != staffIdx)
continue;

This comment has been minimized.

Copy link
@Jojo-Schmitz

Jojo-Schmitz Nov 21, 2017

Contributor

whitespace damage?

This comment has been minimized.

Copy link
@lasconic

lasconic Nov 21, 2017

Author Contributor

Yes indeed. this one went through..

int idx = s->staff()->channel(s->tick(), 0);
int channel = s->part()->instrument(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->type() == ElementType::PEDAL) {
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() >= tick1 && s->tick() < tick2) {
// 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));
if (s->tick() >= tick1 && s->tick() < tick2) {
// 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() >= tick1 && s->tick2() <= tick2) {
int t = s->tick2() + tickOffset + 1;
if (t > repeatList()->last()->utick + repeatList()->last()->len)
t = repeatList()->last()->utick + repeatList()->last()->len;
channelPedalEvents.at(channel).push_back(std::pair<int, bool>(t, false));
}
channelPedalEvents.at(channel).push_back(std::pair<int, bool>(s->tick() + tickOffset + 2, true));
}
if (s->tick2() >= tick1 && s->tick2() <= tick2) {
int t = s->tick2() + tickOffset + 1;
if (t > repeatList()->last()->utick + repeatList()->last()->len)
t = repeatList()->last()->utick + repeatList()->last()->len;
channelPedalEvents.at(channel).push_back(std::pair<int, bool>(t, false));
else if (s->type() == ElementType::TRILL) {
// from start to end of trill, send 0 and 100 bend at regular interval
Trill* t = toTrill(s);
if (t->isVibrato()) {
int lastPointTick = s->tick();
int pitch = -25; // 1/8 (100 is a semitone)
if (t->trillType() == Trill::Type::GUITAR_VIBRATO_WIDE || t->trillType() == Trill::Type::VIBRATO_SAWTOOTH_WIDE)
pitch = -50; // 1/4
int i = 0;
while (lastPointTick < s->tick2()) {
int midiPitch = (pitch * 16384) / 1200 + 8192;
int msb = midiPitch / 128;
int lsb = midiPitch % 128;
NPlayEvent ev(ME_PITCHBEND, channel, lsb, msb);
events->insert(std::pair<int, NPlayEvent>(lastPointTick, ev));
lastPointTick += MScore::division / 8; // 1/8 note
if (i%2 == 1) // 2 period down, 2 period up
pitch *= -1;
i++;
}
}
}
else
continue;
}

for (const auto& pedalEvents : channelPedalEvents) {
Expand Down Expand Up @@ -1284,7 +1311,7 @@ bool renderNoteArticulation(NoteEventList* events, Note * note, bool chromatic,
,{Trill::Type::PRALLPRALL_LINE, SymId::ornamentTrill }
};
auto it = articulationMap.find(trillType);
if (it == articulationMap.cend() )
if (it == articulationMap.cend())
return false;
else
return renderNoteArticulation(events, note, chromatic, it->second, ornamentStyle);
Expand Down
5 changes: 5 additions & 0 deletions libmscore/trill.cpp
Expand Up @@ -42,6 +42,11 @@ int trillTableSize() {
return sizeof(trillTable)/sizeof(TrillTableItem);
}

bool Trill::isVibrato()
{
return _trillType >= Trill::Type::GUITAR_VIBRATO;
}

//---------------------------------------------------------
// draw
//---------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions libmscore/trill.h
Expand Up @@ -101,6 +101,7 @@ class Trill : public SLine {
QString trillTypeUserName() const;
Accidental* accidental() const { return _accidental; }
void setAccidental(Accidental* a) { _accidental = a; }
bool isVibrato();

Segment* segment() const { return (Segment*)parent(); }
virtual void scanElements(void* data, void (*func)(void*, Element*), bool all=true) override;
Expand Down

0 comments on commit 374f9b1

Please sign in to comment.