diff options
Diffstat (limited to 'src/base/MidiTypes.cpp')
-rw-r--r-- | src/base/MidiTypes.cpp | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/src/base/MidiTypes.cpp b/src/base/MidiTypes.cpp new file mode 100644 index 0000000..4118502 --- /dev/null +++ b/src/base/MidiTypes.cpp @@ -0,0 +1,320 @@ +// -*- c-basic-offset: 4 -*- + + +/* + Rosegarden + A sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <[email protected]>, + Chris Cannam <[email protected]>, + Richard Bown <[email protected]> + + The moral right of the authors to claim authorship of this work + has been asserted. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#include "MidiTypes.h" + +namespace Rosegarden +{ + +static MidiByte getByte(const Event &e, const PropertyName &name) { + long value = -1; + try { + value = e.get<Int>(name); + } catch (...) { } + if (value < 0 || value > 255) throw MIDIValueOutOfRange(name.getName()); + return MidiByte(value); +} + +////////////////////////////////////////////////////////////////////// +// PitchBend +////////////////////////////////////////////////////////////////////// + +const std::string PitchBend::EventType = "pitchbend"; +const int PitchBend::EventSubOrdering = -5; + +const PropertyName PitchBend::MSB = "msb"; +const PropertyName PitchBend::LSB = "lsb"; + +PitchBend::PitchBend(Rosegarden::MidiByte msb, + Rosegarden::MidiByte lsb) : + m_msb(msb), + m_lsb(lsb) +{ +} + +PitchBend::PitchBend(const Event &e) +{ + if (e.getType() != EventType) { + throw Event::BadType("PitchBend model event", EventType, e.getType()); + } + m_msb = getByte(e, MSB); + m_lsb = getByte(e, LSB); +} + +PitchBend::~PitchBend() +{ +} + +Event* +PitchBend::getAsEvent(timeT absoluteTime) const +{ + Event *e = new Event(EventType, absoluteTime, 0, EventSubOrdering); + e->set<Int>(MSB, (long)m_msb); + e->set<Int>(LSB, (long)m_lsb); + return e; +} + + +////////////////////////////////////////////////////////////////////// +// Controller +////////////////////////////////////////////////////////////////////// + +const std::string Controller::EventType = "controller"; +const int Controller::EventSubOrdering = -5; + +const PropertyName Controller::NUMBER = "number"; +const PropertyName Controller::VALUE = "value"; + +Controller::Controller(Rosegarden::MidiByte number, + Rosegarden::MidiByte value): + m_number(number), + m_value(value) +{ +} + +Controller::Controller(const Event &e) +{ + if (e.getType() != EventType) { + throw Event::BadType("Controller model event", EventType, e.getType()); + } + m_number = getByte(e, NUMBER); + m_value = getByte(e, VALUE); +} + +Controller::~Controller() +{ +} + +Event* +Controller::getAsEvent(timeT absoluteTime) const +{ + Event *e = new Event(EventType, absoluteTime, 0, EventSubOrdering); + e->set<Int>(NUMBER, (long)m_number); + e->set<Int>(VALUE, (long)m_value); + return e; +} + + +////////////////////////////////////////////////////////////////////// +// Key Pressure +////////////////////////////////////////////////////////////////////// + +const std::string KeyPressure::EventType = "keypressure"; +const int KeyPressure::EventSubOrdering = -5; + +const PropertyName KeyPressure::PITCH = "pitch"; +const PropertyName KeyPressure::PRESSURE = "pressure"; + +KeyPressure::KeyPressure(Rosegarden::MidiByte pitch, + Rosegarden::MidiByte pressure): + m_pitch(pitch), + m_pressure(pressure) +{ +} + +KeyPressure::KeyPressure(const Event &e) +{ + if (e.getType() != EventType) { + throw Event::BadType("KeyPressure model event", EventType, e.getType()); + } + m_pitch = getByte(e, PITCH); + m_pressure = getByte(e, PRESSURE); +} + +KeyPressure::~KeyPressure() +{ +} + +Event* +KeyPressure::getAsEvent(timeT absoluteTime) const +{ + Event *e = new Event(EventType, absoluteTime, 0, EventSubOrdering); + e->set<Int>(PITCH, (long)m_pitch); + e->set<Int>(PRESSURE, (long)m_pressure); + return e; +} + + +////////////////////////////////////////////////////////////////////// +// Channel Pressure +////////////////////////////////////////////////////////////////////// + +const std::string ChannelPressure::EventType = "channelpressure"; +const int ChannelPressure::EventSubOrdering = -5; + +const PropertyName ChannelPressure::PRESSURE = "pressure"; + +ChannelPressure::ChannelPressure(Rosegarden::MidiByte pressure): + m_pressure(pressure) +{ +} + +ChannelPressure::ChannelPressure(const Event &e) +{ + if (e.getType() != EventType) { + throw Event::BadType("ChannelPressure model event", EventType, e.getType()); + } + m_pressure = getByte(e, PRESSURE); +} + +ChannelPressure::~ChannelPressure() +{ +} + +Event* +ChannelPressure::getAsEvent(timeT absoluteTime) const +{ + Event *e = new Event(EventType, absoluteTime, 0, EventSubOrdering); + e->set<Int>(PRESSURE, (long)m_pressure); + return e; +} + + +////////////////////////////////////////////////////////////////////// +// ProgramChange +////////////////////////////////////////////////////////////////////// + +const std::string ProgramChange::EventType = "programchange"; +const int ProgramChange::EventSubOrdering = -5; + +const PropertyName ProgramChange::PROGRAM = "program"; + +ProgramChange::ProgramChange(Rosegarden::MidiByte program): + m_program(program) +{ +} + +ProgramChange::ProgramChange(const Event &e) +{ + if (e.getType() != EventType) { + throw Event::BadType("ProgramChange model event", EventType, e.getType()); + } + m_program = getByte(e, PROGRAM); +} + +ProgramChange::~ProgramChange() +{ +} + +Event* +ProgramChange::getAsEvent(timeT absoluteTime) const +{ + Event *e = new Event(EventType, absoluteTime, 0, EventSubOrdering); + e->set<Int>(PROGRAM, (long)m_program); + return e; +} + + +////////////////////////////////////////////////////////////////////// +// SystemExclusive +////////////////////////////////////////////////////////////////////// + +const std::string SystemExclusive::EventType = "systemexclusive"; +const int SystemExclusive::EventSubOrdering = -5; + +const PropertyName SystemExclusive::DATABLOCK = "datablock"; + +SystemExclusive::SystemExclusive(std::string rawData) : + m_rawData(rawData) +{ +} + +SystemExclusive::SystemExclusive(const Event &e) +{ + if (e.getType() != EventType) { + throw Event::BadType("SystemExclusive model event", EventType, e.getType()); + } + std::string datablock; + e.get<String>(DATABLOCK, datablock); + m_rawData = toRaw(datablock); +} + +SystemExclusive::~SystemExclusive() +{ +} + +Event* +SystemExclusive::getAsEvent(timeT absoluteTime) const +{ + Event *e = new Event(EventType, absoluteTime, 0, EventSubOrdering); + std::string hex(toHex(m_rawData)); + e->set<String>(DATABLOCK, hex); + return e; +} + +std::string +SystemExclusive::toHex(std::string r) +{ + static char hexchars[] = "0123456789ABCDEF"; + std::string h; + for (unsigned int i = 0; i < r.size(); ++i) { + if (i > 0) h += ' '; + unsigned char b = (unsigned char)r[i]; + h += hexchars[(b / 16) % 16]; + h += hexchars[b % 16]; + } + return h; +} + +std::string +SystemExclusive::toRaw(std::string rh) +{ + std::string r; + std::string h; + + // remove whitespace + for (unsigned int i = 0; i < rh.size(); ++i) { + if (!isspace(rh[i])) h += rh[i]; + } + + for (unsigned int i = 0; i < h.size()/2; ++i) { + unsigned char b = toRawNibble(h[2*i]) * 16 + toRawNibble(h[2*i+1]); + r += b; + } + + return r; +} + +unsigned char +SystemExclusive::toRawNibble(char c) +{ + if (islower(c)) c = toupper(c); + if (isdigit(c)) return c - '0'; + if (c >= 'A' && c <= 'F') return c - 'A' + 10; + throw BadEncoding(); +} + +bool +SystemExclusive::isHex(std::string rh) +{ + // arf + try { + std::string r = toRaw(rh); + } catch (BadEncoding) { + return false; + } + return true; +} + + +} + |