summaryrefslogtreecommitdiffstats
path: root/src/sound/MidiEvent.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/sound/MidiEvent.cpp')
-rw-r--r--src/sound/MidiEvent.cpp289
1 files changed, 289 insertions, 0 deletions
diff --git a/src/sound/MidiEvent.cpp b/src/sound/MidiEvent.cpp
new file mode 100644
index 0000000..975b7aa
--- /dev/null
+++ b/src/sound/MidiEvent.cpp
@@ -0,0 +1,289 @@
+// -*- c-indentation-style:"stroustrup" 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 "Midi.h"
+#include "MidiEvent.h"
+#include <iostream>
+
+// MidiEvent is a representation of MIDI which we use
+// for the import/export of MidiFiles. It uses std::strings for
+// meta event messages which makes them nice and easy to handle.
+//
+//
+namespace Rosegarden
+{
+
+using std::string;
+using std::cout;
+using std::endl;
+
+MidiEvent::MidiEvent()
+{}
+
+MidiEvent::MidiEvent(timeT deltaTime,
+ MidiByte eventCode):
+ m_deltaTime(deltaTime),
+ m_duration(0),
+ m_eventCode(eventCode),
+ m_data1(0),
+ m_data2(0),
+ m_metaEventCode(0),
+ m_metaMessage("")
+{}
+
+MidiEvent::MidiEvent(timeT deltaTime,
+ MidiByte eventCode,
+ MidiByte data1):
+ m_deltaTime(deltaTime),
+ m_duration(0),
+ m_eventCode(eventCode),
+ m_data1(data1),
+ m_data2(0),
+ m_metaEventCode(0),
+ m_metaMessage("")
+{}
+
+MidiEvent::MidiEvent(timeT deltaTime,
+ MidiByte eventCode,
+ MidiByte data1,
+ MidiByte data2):
+ m_deltaTime(deltaTime),
+ m_duration(0),
+ m_eventCode(eventCode),
+ m_data1(data1),
+ m_data2(data2),
+ m_metaEventCode(0),
+ m_metaMessage("")
+
+{}
+
+MidiEvent::MidiEvent(timeT deltaTime,
+ MidiByte eventCode,
+ MidiByte metaEventCode,
+ const string &metaMessage):
+ m_deltaTime(deltaTime),
+ m_duration(0),
+ m_eventCode(eventCode),
+ m_data1(0),
+ m_data2(0),
+ m_metaEventCode(metaEventCode),
+ m_metaMessage(metaMessage)
+{}
+
+MidiEvent::MidiEvent(timeT deltaTime,
+ MidiByte eventCode,
+ const string &sysEx):
+ m_deltaTime(deltaTime),
+ m_duration(0),
+ m_eventCode(eventCode),
+ m_data1(0),
+ m_data2(0),
+ m_metaEventCode(0),
+ m_metaMessage(sysEx)
+{}
+
+MidiEvent::~MidiEvent()
+{}
+
+// Show a representation of our MidiEvent purely for information
+// purposes (also demos how we decode them)
+//
+//
+void
+MidiEvent::print()
+{
+ timeT tempo;
+ int tonality;
+ string sharpflat;
+
+ if (m_metaEventCode) {
+ switch (m_metaEventCode) {
+ case MIDI_SEQUENCE_NUMBER:
+ cout << "MIDI SEQUENCE NUMBER" << endl;
+ break;
+
+ case MIDI_TEXT_EVENT:
+ cout << "MIDI TEXT:\t\"" << m_metaMessage << "\"" << endl;
+ break;
+
+ case MIDI_COPYRIGHT_NOTICE:
+ cout << "COPYRIGHT:\t\"" << m_metaMessage << "\"" << endl;
+
+ case MIDI_TRACK_NAME:
+ cout << "TRACK NAME:\t\"" << m_metaMessage << "\"" << endl;
+ break;
+
+ case MIDI_INSTRUMENT_NAME:
+ cout << "INSTRUMENT NAME:\t\"" << m_metaMessage << "\"" << endl;
+ break;
+
+ case MIDI_LYRIC:
+ cout << "LYRIC:\t\"" << m_metaMessage << "\"" << endl;
+ break;
+
+ case MIDI_TEXT_MARKER:
+ cout << "MARKER:\t\"" << m_metaMessage << "\"" << endl;
+ break;
+
+ case MIDI_CUE_POINT:
+ cout << "CUE POINT:\t\"" << m_metaMessage << "\"" << endl;
+ break;
+
+ // Sets a Channel number for a TRACK before it starts
+ case MIDI_CHANNEL_PREFIX:
+ cout << "CHANNEL PREFIX:\t"
+ << (timeT)m_metaMessage[0]
+ << endl;
+ break;
+
+ // These are actually the same case but this is not an
+ // official META event - it just crops up a lot. We
+ // assume it's a MIDI_CHANNEL_PREFIX though
+ //
+ case MIDI_CHANNEL_PREFIX_OR_PORT:
+ cout << "FIXED CHANNEL PREFIX:\t"
+ << (timeT)m_metaMessage[0] << endl;
+ break;
+
+ case MIDI_END_OF_TRACK:
+ cout << "END OF TRACK" << endl;
+ break;
+
+ case MIDI_SET_TEMPO:
+ tempo =
+ ((timeT)(((MidiByte)m_metaMessage[0]) << 16)) +
+ ((timeT)(((MidiByte)m_metaMessage[1]) << 8)) +
+ (short)(MidiByte)m_metaMessage[2];
+
+ tempo = 60000000 / tempo;
+ cout << "SET TEMPO:\t" << tempo << endl;
+ break;
+
+ case MIDI_SMPTE_OFFSET:
+ cout << "SMPTE TIME CODE:\t"
+ << (timeT)m_metaMessage[0]
+ << ":" << (timeT)m_metaMessage[1]
+ << ":" << (timeT)m_metaMessage[2]
+ << " - fps = " << (timeT)m_metaMessage[3]
+ << " - subdivsperframe = "
+ << (timeT)m_metaMessage[4]
+ << endl;
+ break;
+
+ case MIDI_TIME_SIGNATURE:
+ cout << "TIME SIGNATURE:\t"
+ << (timeT)m_metaMessage[0]
+ << "/"
+ << (1 << (timeT)m_metaMessage[1]) << endl;
+ break;
+
+ case MIDI_KEY_SIGNATURE:
+ tonality = (int)m_metaMessage[0];
+
+ if (tonality < 0) {
+ sharpflat = -tonality + " flat";
+ } else {
+ sharpflat = tonality;
+ sharpflat += " sharp";
+ }
+
+ cout << "KEY SIGNATURE:\t" << sharpflat << " "
+ << (((int)m_metaMessage[1]) == 0 ? "major" : "minor")
+ << endl;
+
+ break;
+
+ case MIDI_SEQUENCER_SPECIFIC:
+ cout << "SEQUENCER SPECIFIC:\t\"" << m_metaMessage << endl;
+ break;
+
+
+ default:
+ cout << "Undefined MIDI META event - "
+ << (timeT)m_metaEventCode << endl;
+ break;
+ }
+ } else {
+ switch (m_eventCode & MIDI_MESSAGE_TYPE_MASK) {
+ case MIDI_NOTE_ON:
+ cout << "NOTE ON:\t" << (int)m_data1 << " - "
+ << (int)m_data2 << endl;
+ break;
+
+ case MIDI_NOTE_OFF:
+ cout << "NOTE OFF:\t" << (int)m_data1 << " - "
+ << (int)m_data2 << endl;
+ break;
+
+ case MIDI_POLY_AFTERTOUCH:
+ cout << "POLY AFTERTOUCH:\t" << (int)m_data1
+ << " - " << (int)m_data2 << endl;
+ break;
+
+ case MIDI_CTRL_CHANGE:
+ cout << "CTRL CHANGE:\t" << (int)m_data1
+ << " - " << (int)m_data2 << endl;
+ break;
+
+ case MIDI_PITCH_BEND:
+ cout << "PITCH BEND:\t" << (int)m_data1
+ << " - " << (int)m_data2 << endl;
+ break;
+
+ case MIDI_PROG_CHANGE:
+ cout << "PROG CHANGE:\t" << (int)m_data1 << endl;
+ break;
+
+ case MIDI_CHNL_AFTERTOUCH:
+ cout << "CHNL AFTERTOUCH\t" << (int)m_data1 << endl;
+ break;
+
+ default:
+ cout << "Undefined MIDI event" << endl;
+ break;
+ }
+ }
+
+
+ return ;
+}
+
+// Adds the argument to _deltaTime and returns the result
+// thus aggregating the times as we go aint
+timeT
+MidiEvent::addTime(const timeT &time)
+{
+ m_deltaTime += time;
+ return m_deltaTime;
+}
+
+
+// Compare based on time
+//
+bool
+operator<(const MidiEvent &a, const MidiEvent &b)
+{
+ return a.getTime() < b.getTime();
+}
+
+
+}
+
+