You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
rosegarden/src/base/MidiTypes.cpp

318 lines
7.6 KiB

/*
Rosegarden
A sequencer and musical notation editor.
This program is Copyright 2000-2008
Guillaume Laurent <glaurent@telegraph-road.org>,
Chris Cannam <cannam@all-day-breakfast.com>,
Richard Bown <bownie@bownie.com>
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;
}
}