|
From: Lasse Kärkkäi. <tr...@us...> - 2011-02-25 18:19:42
|
Author: Lasse Kärkkäinen <tronic+ndrm at trn.iki.fi> Date: Fri Feb 25 18:33:11 2011 +0100 Writing events for midifile. --- midifile.cc | 26 ++++++++++++++++++++++++++ midifile.hh | 1 + 2 files changed, 27 insertions(+), 0 deletions(-) diff --git a/midifile.cc b/midifile.cc index b4f7102..9386910 100644 --- a/midifile.cc +++ b/midifile.cc @@ -2,6 +2,7 @@ #include <fstream> #include <iomanip> #include <iostream> +#include <iterator> #include <sstream> using namespace mid; @@ -98,6 +99,31 @@ bool Reader::parseEvent(Event& ev) { return true; } +void Writer::writeEvent(Event const& ev) { + write_varlen(ev.timecode); + if (ev.type & ~0xF0 || ev.type < 0x80) throw std::logic_error("Invalid MIDI event type"); + if (ev.type & ~0x0F) throw std::logic_error("Invalid MIDI channel number"); + write<1>(ev.type | ev.channel); + if (ev.type != Event::SPECIAL || ev.channel >= 8) write<1>(ev.arg1); // Everything except System Common takes one argument + switch (ev.type) { + case Event::NOTE_ON: + case Event::NOTE_OFF: + case Event::NOTE_AFTERTOUCH: + case Event::CONTROLLER: + case Event::PITCH_BEND: + write<1>(ev.arg2); + break; + case Event::PROGRAM_CHANGE: + case Event::CHANNEL_AFTERTOUCH: + if (ev.arg2 != 0) throw std::logic_error("MIDI event with non-zero arg2 for event that only takes one arg"); + break; // No arg2 for these + case Event::SPECIAL: // Special category (system exclusive or meta event) + write_varlen(ev.end - ev.begin); // data size + std::copy(ev.begin, ev.end, std::back_inserter(m_data)); + break; + } +} + // Debugging facilities follow namespace { diff --git a/midifile.hh b/midifile.hh index 6dd7718..4983d4b 100644 --- a/midifile.hh +++ b/midifile.hh @@ -105,6 +105,7 @@ namespace mid { void writeMTrk() { beginRiff("MTrk"); } + void writeEvent(Event const& ev); void beginRiff(char const* name) { m_riffBegin = m_data.size(); m_data.resize(m_riffBegin + 8); // Add space for header |