summaryrefslogtreecommitdiffabout
path: root/include/midillo
Side-by-side diff
Diffstat (limited to 'include/midillo') (more/less context) (ignore whitespace changes)
-rw-r--r--include/midillo/MThd.h74
-rw-r--r--include/midillo/MTrk.h54
-rw-r--r--include/midillo/SMF.h87
-rw-r--r--include/midillo/chunk.h88
-rw-r--r--include/midillo/event.h99
-rw-r--r--include/midillo/exception.h55
-rw-r--r--include/midillo/message.h200
-rw-r--r--include/midillo/util.h63
8 files changed, 720 insertions, 0 deletions
diff --git a/include/midillo/MThd.h b/include/midillo/MThd.h
new file mode 100644
index 0000000..20263cd
--- a/dev/null
+++ b/include/midillo/MThd.h
@@ -0,0 +1,74 @@
+#ifndef __MIDILLO_MTHD_H
+#define __MIDILLO_MTHD_H
+
+#include <istream>
+#include <ostream>
+#include <midillo/chunk.h>
+
+/**
+ * @file
+ * @brief the MThd_t -- MThd header chunk class
+ */
+
+namespace midillo {
+ using std::istream;
+ using std::ostream;
+
+ /**
+ * MThd header chunk container
+ */
+ class MThd_t : public chunk_t {
+ public:
+ enum {
+ fmt_0 = 0, fmt_1 = 1, fmt_2 = 2,
+ fmt_singletrack = fmt_0,
+ fmt_multitrack = fmt_1,
+ fmt_tracksequence = fmt_2
+ };
+ /**
+ * SMF format. 0 for single track, 1 for multitrack, 2 for track
+ * sequence.
+ */
+ int fmt;
+ /**
+ * Number of tracks in the file
+ */
+ int ntracks;
+ /**
+ * The number of pulses per quarter note
+ */
+ int division;
+
+ /**
+ * Load MThd chunk from the stream
+ * @param s input stream
+ */
+ void load(istream& s);
+
+ /**
+ * Read MThd chunk data from the stream. This function assumes that
+ * header is already read.
+ * @param s input stream
+ */
+ void load_data(istream& s);
+
+ /**
+ * Save MThd chunk to the stream
+ * @param s output stream
+ */
+ void save(ostream& s) const;
+
+ /**
+ * Dump textual representation of MThd chunk to stream
+ * @param s output stream
+ */
+ void dump(ostream& s) const;
+ };
+
+ inline ostream& operator<<(ostream& s,const MThd_t& mthd) {
+ mthd.dump(s); return s;
+ }
+
+}
+
+#endif /* MIDILLO_MTHD_H */
diff --git a/include/midillo/MTrk.h b/include/midillo/MTrk.h
new file mode 100644
index 0000000..0884388
--- a/dev/null
+++ b/include/midillo/MTrk.h
@@ -0,0 +1,54 @@
+#ifndef __MIDILLO_MTRK_H
+#define __MIDILLO_MTRK_H
+
+#include <istream>
+#include <ostream>
+#include <list>
+#include <midillo/chunk.h>
+#include <midillo/event.h>
+
+/**
+ * @file
+ * @brief MTrk -- track chunk container
+ */
+
+namespace midillo {
+ using std::istream;
+ using std::ostream;
+
+ /**
+ * MTrk track chunk container class
+ */
+ class MTrk_t : public chunk_t {
+ public:
+ /**
+ * MIDI events contained in the track
+ */
+ events_t events;
+
+ /**
+ * Load MTrk chunk from the stream
+ * @param s input stream
+ */
+ void load(istream& s);
+
+ /**
+ * Save MTrk chunk to the stream
+ * @param s output stream
+ */
+ void save(ostream& s) const;
+
+ /**
+ * Dump textual representation of MTrk chunk to stream
+ * @param s output stream
+ */
+ void dump(ostream& s) const;
+ };
+
+ inline ostream& operator<<(ostream& s,const MTrk_t& mtrk) {
+ mtrk.dump(s); return s;
+ }
+
+}
+
+#endif /* __MIDILLO_MTRK_H */
diff --git a/include/midillo/SMF.h b/include/midillo/SMF.h
new file mode 100644
index 0000000..bec9f7a
--- a/dev/null
+++ b/include/midillo/SMF.h
@@ -0,0 +1,87 @@
+#ifndef __MIDILLO_SMF_H
+#define __MIDILLO_SMF_H
+
+#include <istream>
+#include <ostream>
+#include <list>
+#include <midillo/MThd.h>
+#include <midillo/MTrk.h>
+
+/**
+ * @file
+ * @brief the SMF_t -- standard midi file
+ */
+
+namespace midillo {
+ using std::istream;
+ using std::vector;
+ using std::ostream;
+
+ /**
+ * Standard midi file object
+ */
+ class SMF_t {
+ public:
+ /**
+ * MThd header chunk
+ */
+ MThd_t mthd;
+ /**
+ * The type for collection of MTrk track chunks
+ */
+ typedef list<MTrk_t> tracks_t;
+ /**
+ * MTrk track chunks collection for the file
+ */
+ tracks_t tracks;
+
+ SMF_t() { }
+ /**
+ * Construct object from the file
+ * @see load(const char *f,bool stdinable)
+ */
+ SMF_t(const char *f,bool stdinable=true) { load(f,stdinable); }
+ /**
+ * Construct object from the stream
+ * @see load(istream& s)
+ */
+ SMF_t(istream& s) { load(s); }
+
+ /**
+ * Load MIDI data from the file
+ * @param f filename
+ * @param stdinable true if '-' is treatead as cin input stream
+ */
+ void load(const char *f,bool stdinable=true);
+ /**
+ * Load midi data from the stream
+ * @param s input stream
+ */
+ void load(istream& s);
+
+ /**
+ * Save MIDI data to the file
+ * @param f filename
+ * @param stdoutable true if '-' is treated as cout output stream
+ */
+ void save(const char *f,bool stdoutable=true) const;
+ /**
+ * Save MIDI data to the stream
+ * @param s output stream
+ */
+ void save(ostream& s) const;
+
+ /**
+ * Dump textual representation of SMF to stream
+ * @param s output stream
+ */
+ void dump(ostream& s) const;
+ };
+
+ inline ostream& operator<<(ostream& s,const SMF_t& smf) {
+ smf.dump(s); return s;
+ }
+
+}
+
+#endif /* __MIDILLO_SMF_H */
diff --git a/include/midillo/chunk.h b/include/midillo/chunk.h
new file mode 100644
index 0000000..8b6c034
--- a/dev/null
+++ b/include/midillo/chunk.h
@@ -0,0 +1,88 @@
+#ifndef __MIDILLO_CHUNK_H
+#define __MIDILLO_CHUNK_H
+
+#include <istream>
+#include <ostream>
+
+/**
+ * @file
+ * @brief Generic SMF chunk manipulation
+ */
+
+namespace midillo {
+ using std::istream;
+ using std::ostream;
+
+ enum {
+ chunk_id_MThd = 0x6468544d,
+ chunk_id_MTrk = 0x6b72544d
+ };
+ /**
+ * Chunk header data structure
+ */
+ struct chunk_header_t {
+ /**
+ * Track signature data
+ */
+ union {
+ /**
+ * ASCII representation
+ */
+ char id_chars[4];
+ /**
+ * long integer representation
+ */
+ unsigned long id_number;
+ };
+ /**
+ * Chunk length
+ */
+ unsigned long length;
+
+ chunk_header_t()
+ : id_number(0), length(0) { }
+ chunk_header_t(const chunk_header_t& s)
+ : id_number(s.id_number), length(s.length) { };
+
+ chunk_header_t& operator=(const chunk_header_t& s) {
+ id_number=s.id_number; length=s.length;
+ return *this;
+ }
+
+ /**
+ * Load chunk header from the stream
+ * @param s input stream
+ */
+ void load(istream& s);
+ /**
+ * Save chunk header to the stream
+ * @param s output stream
+ */
+ void save(ostream& s) const;
+
+ /**
+ * Dump textual representation of chunk header to stream
+ * @param s output stream
+ */
+ void dump(ostream& s) const;
+
+ };
+
+ inline ostream& operator<<(ostream& s,const chunk_header_t& ch) {
+ ch.dump(s); return s;
+ }
+
+ /**
+ * Base class for specific chunk containers
+ */
+ class chunk_t {
+ public:
+ /**
+ * Chunk header data
+ */
+ chunk_header_t header;
+ };
+
+}
+
+#endif /* __MIDILLO_CHUNK_H */
diff --git a/include/midillo/event.h b/include/midillo/event.h
new file mode 100644
index 0000000..85f6175
--- a/dev/null
+++ b/include/midillo/event.h
@@ -0,0 +1,99 @@
+#ifndef __MIDILLO_EVENT_H
+#define __MIDILLO_EVENT_H
+
+#include <istream>
+#include <ostream>
+#include <list>
+#include <midillo/message.h>
+
+/**
+ * @file
+ * @brief midi event container
+ */
+
+namespace midillo {
+ using std::istream;
+ using std::ostream;
+ using std::list;
+
+ /**
+ * MIDI event container class
+ */
+ class event_t {
+ public:
+ /**
+ * delta time since the last event
+ */
+ long deltat;
+ /**
+ * MIDI message itself
+ */
+ message_t message;
+
+ /**
+ * Load MIDI event from the stream
+ * @param rs reference to the running status
+ * @param s input stream
+ */
+ void load(int& rs,istream& s);
+
+ /**
+ * Save MIDI event to the stream
+ * @param rs reference to the running status
+ * @param s output stream
+ */
+ void save(int& rs,ostream& s) const;
+
+ /**
+ * Calculate the amount of data that would be written to stream in
+ * case of save
+ * @param rs reference to the running status
+ * @return the number of bytes
+ */
+ unsigned long calculate_save_size(int& rs) const;
+
+ /**
+ * Dump textual representation of event to stream
+ * @param s output stream
+ */
+ void dump(ostream& s) const;
+ };
+
+ inline ostream& operator<<(ostream& s,const event_t& e) {
+ e.dump(s); return s;
+ }
+
+ /**
+ * MIDI events list container
+ */
+ class events_t : public list<event_t> {
+ public:
+
+ /**
+ * Append empty event to the end of the list
+ * @return iterator, pointing to the appended event
+ */
+ iterator append_event();
+
+ /**
+ * Load MIDI events (track data) from the stream
+ * @param s input stream
+ */
+ void load(istream& s);
+ /**
+ * Save MIDI events (track data) to the stream
+ * @param s output stream
+ */
+ void save(ostream& s) const;
+
+ /**
+ * Calculate the size of the track data that would be written to
+ * the stream by save()
+ * @return the number of bytes
+ */
+ unsigned long calculate_save_size() const;
+ };
+
+}
+
+#endif /* __MIDILLO_EVENT_H */
diff --git a/include/midillo/exception.h b/include/midillo/exception.h
new file mode 100644
index 0000000..fb6da27
--- a/dev/null
+++ b/include/midillo/exception.h
@@ -0,0 +1,55 @@
+#ifndef __MIDILLO_EXCEPTION_H
+#define __MIDILLO_EXCEPTION_H
+
+#include <konforka/exception.h>
+
+/**
+ * @file
+ * @brief midillo specific exceptions
+ */
+
+namespace midillo {
+ using std::string;
+
+ /**
+ * Base midillo exception class
+ */
+ class exception : public konforka::exception {
+ public:
+ explicit exception(const string& fi,const string& fu,int l,const string& w)
+ : konforka::exception(fi,fu,l,w) { }
+ };
+
+ class exception_io_error : public exception {
+ public:
+ explicit exception_io_error(const string& fi,const string& fu,int l,const string& w)
+ : exception(fi,fu,l,w) { }
+ };
+
+ class exception_input_error : public exception_io_error {
+ public:
+ explicit exception_input_error(const string& fi,const string& fu,int l,const string& w)
+ : exception_io_error(fi,fu,l,w) { }
+ };
+
+ class exception_invalid_input : public exception_input_error {
+ public:
+ explicit exception_invalid_input(const string& fi,const string& fu,int l,const string& w)
+ : exception_input_error(fi,fu,l,w) { }
+ };
+
+ class exception_unexpected_input : public exception_invalid_input {
+ public:
+ explicit exception_unexpected_input(const string& fi,const string& fu,int l,const string& w)
+ : exception_invalid_input(fi,fu,l,w) { }
+ };
+
+ class exception_output_error : public exception_io_error {
+ public:
+ explicit exception_output_error(const string& fi,const string& fu,int l,const string& w)
+ : exception_io_error(fi,fu,l,w) { }
+ };
+
+};
+
+#endif /* __MIDILLO_EXCEPTION_H */
diff --git a/include/midillo/message.h b/include/midillo/message.h
new file mode 100644
index 0000000..d6f0f36
--- a/dev/null
+++ b/include/midillo/message.h
@@ -0,0 +1,200 @@
+#ifndef __MIDILLO_MESSAGE_H
+#define __MIDILLO_MESSAGE_H
+
+#include <istream>
+#include <ostream>
+#include <vector>
+
+/**
+ * @file
+ * @brief MIDI message
+ */
+
+namespace midillo {
+ using std::istream;
+ using std::ostream;
+ using std::vector;
+
+ enum {
+ // bits
+ status_bit = 0x80,
+ status_event_bits = 0xF0,
+ status_channel_bits = 0x0F,
+ status_system_bits = 0xFF,
+ // channel voice messages
+ status_note_off = 0x80,
+ status_note_on = 0x90,
+ status_polyphonic_key_pressure = 0xA0,
+ status_aftertouch = status_polyphonic_key_pressure,
+ status_control_change = 0xB0,
+ status_program_change = 0xC0,
+ status_channel_pressure = 0xD0,
+ status_pitch_wheel_change = 0xE0,
+ status_system = 0xF0,
+ // system common messages
+ status_system_sysex = 0xF0,
+ status_system_MTC_quarter_frame = 0xF1,
+ status_system_song_position_pointer = 0xF2,
+ status_system_song_select = 0xF3,
+ status_system_tune_request = 0xF6,
+ status_system_end_of_sysex = 0xF7,
+ // system real-time messages
+ status_system_timing_clock = 0xF8,
+ status_system_midi_clock = status_system_timing_clock,
+ status_system_midi_tick = 0xF9,
+ status_system_start = 0xFA,
+ status_system_midi_start = status_system_start,
+ status_system_continue = 0xFB,
+ status_system_midi_continue = status_system_continue,
+ status_system_stop = 0xFC,
+ status_system_midi_stop = status_system_stop,
+ status_system_active_sense = 0xFE,
+ status_system_rest = 0xFF,
+ status_system_reset = status_system_rest,
+ // midi file specific
+ status_system_meta = 0xFF
+ };
+ enum {
+ // meta events
+ meta_sequence_number = 0x00,
+ meta_text = 0x01,
+ meta_copyright = 0x02,
+ meta_seq_track_name = 0x03,
+ meta_instrument = 0x04,
+ meta_lyric = 0x05,
+ meta_marker = 0x06,
+ meta_cue_point = 0x07,
+ meta_patch_name = 0x08,
+ meta_port_name = 0x09,
+ meta_EOT = 0x2F,
+ meta_tempo = 0x51,
+ meta_SMPTE_offset = 0x54,
+ meta_time_sig = 0x58,
+ meta_key_sig = 0x59,
+ meta_proprietary = 0x7F,
+ // obsolete meta events
+ meta_midi_channel = 0x20,
+ meta_midi_port = 0x21
+ };
+
+ /**
+ * MIDI message container
+ */
+ class message_t {
+ public:
+ /**
+ * MIDI status byte
+ */
+ int status;
+ /**
+ * MIDI meta event type
+ */
+ int meta_status;
+ typedef unsigned char byte_t;
+ typedef vector<byte_t> bytes_t;
+ /**
+ * MIDI message data -- content is message-specific
+ */
+ bytes_t data;
+
+ message_t()
+ : status(-1) { }
+ message_t(const message_t& m)
+ : status(m.status), meta_status(m.meta_status), data(m.data) { }
+
+ message_t& operator=(const message_t& m) {
+ status = m.status;
+ meta_status = m.meta_status;
+ data = m.data;
+ return *this;
+ }
+
+ /**
+ * Load MIDI message from the stream
+ * @param rs reference to the running status
+ * @param s input stream
+ */
+ void load(int& rs,istream& s);
+ /**
+ * Save MIDI message to the stream
+ * @param rs reference to the running status
+ * @param s output stream
+ */
+ void save(int& rs,ostream& s) const;
+ /**
+ * Calculate the amount of data that would be written to stream in
+ * case of save()
+ * @param rs reference to the running status
+ * @return the number of bytes
+ */
+ unsigned long calculate_save_size(int& rs) const;
+
+ /**
+ * Load data so that we have c bytes of data for the event
+ * @param s input stream
+ * @param c size of data needed for the event
+ */
+ void load_data(istream& s,int c);
+ /**
+ * Load sysex data from the stream
+ * @param s input stream
+ */
+ void load_sysex(istream& s);
+
+ /**
+ * Save data to the stream
+ * @param s output stream
+ */
+ void save_data(ostream& s) const;
+ /**
+ * Save data to the stream and verify if the amount of data is
+ * correct
+ * @param s output stream
+ * @param c data bytes count
+ */
+ void save_data(ostream& s,int c) const;
+ /**
+ * Save sysex data to the stream
+ * @param s output stream
+ */
+ void save_sysex(ostream& s) const;
+
+ /**
+ * See if the event is meta event
+ * @return true if yes
+ */
+ bool is_meta() const {
+ return status==status_system_meta;
+ }
+ /**
+ * Check whether the event is a specific meta event
+ * @param meta meta event type
+ * @return true if yes
+ */
+ bool is_meta(int meta) const {
+ return is_meta() && (meta_status==meta);
+ }
+
+ /**
+ * See if the event is system event
+ * @return true if yes
+ */
+ bool is_system() const {
+ return (status&status_event_bits)==status_system && !is_meta();
+ }
+
+ /**
+ * Dump textual representation of midi message to stream
+ * @param s output stream
+ */
+ void dump(ostream& s) const;
+
+ };
+
+ inline ostream& operator<<(ostream& s,const message_t& m) {
+ m.dump(s); return s;
+ }
+
+}
+
+#endif /* __MIDILLO_MESSAGE_H */
diff --git a/include/midillo/util.h b/include/midillo/util.h
new file mode 100644
index 0000000..f9c8430
--- a/dev/null
+++ b/include/midillo/util.h
@@ -0,0 +1,63 @@
+#ifndef __MIDILLO_UTIL_H
+#define __MIDILLO_UTIL_H
+
+#include <istream>
+#include <ostream>
+
+/**
+ * @file
+ * @brief utilities
+ */
+
+namespace midillo {
+ using std::istream;
+ using std::ostream;
+
+ /**
+ * read 32 bits word from the stream
+ * @param s input stream
+ * @return the data acquired
+ */
+ unsigned long read32(istream& s);
+ /**
+ * read 16 bits word from the stream
+ * @param s input stream
+ * @return the data acquired
+ */
+ unsigned int read16(istream& s);
+ /**
+ * read the variable length quantity from the stream
+ * @param s input stream
+ * @return the data acquired
+ */
+ unsigned long readVL(istream& s);
+
+ /**
+ * write 32 bits word to the stream
+ * @param s output stream
+ * @param d data to write
+ */
+ void write32(ostream& s,unsigned long d);
+ /**
+ * write 16 bits word to the stream
+ * @param s output stream
+ * @param d data to write
+ */
+ void write16(ostream& s,unsigned int d);
+ /**
+ * write the variable length quantity to the stream
+ * @param s output stream
+ * @param d data to write
+ */
+ void writeVL(ostream& s,unsigned long d);
+
+ /**
+ * calculate the amount of data that would be written by writeVL
+ * @param d data that would be written
+ * @return the number of bytes
+ */
+ unsigned long calcVLsize(unsigned long d);
+
+}
+
+#endif /* __MIDILLO_UTIL_H */