Skip to content

Commit

Permalink
Generate vibrato and let ring MIDI events.
Browse files Browse the repository at this point in the history
Bug: #55
  • Loading branch information
cameronwhite committed Jun 27, 2015
1 parent 92d3e7e commit 2b90f1b
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 30 deletions.
18 changes: 17 additions & 1 deletion source/midi/midievent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ enum StatusByte : uint8_t

enum Controller : uint8_t
{
ChannelVolume = 0x07
ModWheel = 0x01,
ChannelVolume = 0x07,
HoldPedal = 0x40
};

enum MetaType : uint8_t
Expand Down Expand Up @@ -91,3 +93,17 @@ MidiEvent MidiEvent::programChange(int ticks, uint8_t channel, uint8_t preset)
return MidiEvent(ticks, StatusByte::ProgramChange + channel, { preset },
SystemLocation(), -1, -1);
}

MidiEvent MidiEvent::modWheel(int ticks, uint8_t channel, uint8_t width)
{
return MidiEvent(ticks, StatusByte::ControlChange + channel,
{ Controller::ModWheel, width }, SystemLocation(), -1, -1);
}

MidiEvent MidiEvent::holdPedal(int ticks, uint8_t channel, bool enabled)
{
return MidiEvent(
ticks, StatusByte::ControlChange + channel,
{ Controller::HoldPedal, static_cast<uint8_t>(enabled ? 127 : 0) },
SystemLocation(), -1, -1);
}
2 changes: 2 additions & 0 deletions source/midi/midievent.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ class MidiEvent
const SystemLocation &location);
static MidiEvent volumeChange(int ticks, uint8_t channel, uint8_t level);
static MidiEvent programChange(int ticks, uint8_t channel, uint8_t preset);
static MidiEvent modWheel(int ticks, uint8_t channel, uint8_t width);
static MidiEvent holdPedal(int ticks, uint8_t channel, bool enabled);

private:
MidiEvent(int ticks, uint8_t status, std::vector<uint8_t> data,
Expand Down
67 changes: 38 additions & 29 deletions source/midi/midifile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,22 @@ static Velocity getNoteVelocity(const Position &pos, const Note &note)
return Velocity::DefaultVelocity;
}

static uint8_t getVibratoWidth(const Position &pos)
{
QSettings settings;

if (pos.hasProperty(Position::Vibrato))
{
return settings.value(Settings::MIDI_VIBRATO_LEVEL,
Settings::MIDI_VIBRATO_LEVEL_DEFAULT).toUInt();
}
else
{
return settings.value(Settings::MIDI_WIDE_VIBRATO_LEVEL,
Settings::MIDI_WIDE_VIBRATO_LEVEL_DEFAULT).toUInt();
}
}

int MidiFile::addEventsForBar(std::vector<MidiEventList> &tracks,
int current_tick, const Score &score,
const System &system, int system_index,
Expand Down Expand Up @@ -393,68 +409,61 @@ int MidiFile::addEventsForBar(std::vector<MidiEventList> &tracks,
continue;
}

#if 0
// Vibrato events (these apply to all notes in the position).
if (pos.hasProperty(Position::Vibrato) ||
pos.hasProperty(Position::WideVibrato))
if (pos->hasProperty(Position::Vibrato) ||
pos->hasProperty(Position::WideVibrato))
{
VibratoEvent::VibratoType type = pos.hasProperty(Position::Vibrato)
? VibratoEvent::NormalVibrato : VibratoEvent::WideVibrato;
const uint8_t width = getVibratoWidth(*pos);

for (const ActivePlayer &player : active_players)
{
const int channel = getChannel(player);

// Add vibrato event, and an event to turn off the vibrato after
// the note is done.
eventList.emplace_back(
new VibratoEvent(channel, startTime, position, system_index,
VibratoEvent::VibratoOn, type));
tracks[player.getPlayerNumber()].append(
MidiEvent::modWheel(current_tick, channel, width));

eventList.emplace_back(
new VibratoEvent(channel, startTime + duration, position,
system_index, VibratoEvent::VibratoOff));
tracks[player.getPlayerNumber()].append(
MidiEvent::modWheel(current_tick + duration, channel, 0));
}
}

// Let ring events (applied to all notes in the position).
if (pos.hasProperty(Position::LetRing) && !letRingActive)
if (pos->hasProperty(Position::LetRing) && !let_ring_active)
{
for (const ActivePlayer &player : active_players)
{
eventList.emplace_back(
new LetRingEvent(getChannel(player), startTime, position,
system_index, LetRingEvent::LetRingOn));
tracks[player.getPlayerNumber()].append(MidiEvent::holdPedal(
current_tick, getChannel(player), true));
}

letRingActive = true;
let_ring_active = true;
}
else if (!pos.hasProperty(Position::LetRing) && letRingActive)
else if (!pos->hasProperty(Position::LetRing) && let_ring_active)
{
for (const ActivePlayer &player : active_players)
{
eventList.emplace_back(
new LetRingEvent(getChannel(player), startTime, position,
system_index, LetRingEvent::LetRingOff));
tracks[player.getPlayerNumber()].append(MidiEvent::holdPedal(
current_tick, getChannel(player), false));
}

letRingActive = false;
let_ring_active = false;
}
// Make sure that we end the let ring after the last position in the bar.
else if (letRingActive &&
(&pos == &ScoreUtils::findInRange(voice.getPositions(),
bar_start, bar_end).back()))
else if (let_ring_active &&
(pos ==
&ScoreUtils::findInRange(voice.getPositions(), bar_start,
bar_end) .back()))
{
for (const ActivePlayer &player : active_players)
{
eventList.emplace_back(new LetRingEvent(
getChannel(player), startTime + duration, position,
system_index, LetRingEvent::LetRingOff));
tracks[player.getPlayerNumber()].append(MidiEvent::holdPedal(
current_tick + duration, getChannel(player), false));
}

letRingActive = false;
let_ring_active = false;
}
#endif

for (const Note &note : pos->getNotes())
{
Expand Down

0 comments on commit 2b90f1b

Please sign in to comment.