summaryrefslogtreecommitdiffabout
Unidiff
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--.gitignore22
-rw-r--r--AUTHORS3
-rw-r--r--COPYING19
-rw-r--r--ChangeLog0
-rw-r--r--Doxyfile.in247
-rw-r--r--Makefile.am22
-rw-r--r--NEWS.xml6
-rw-r--r--NEWS.xsl24
-rw-r--r--README0
-rw-r--r--acinclude.m480
-rwxr-xr-xautogen.sh9
-rw-r--r--configure.ac55
-rw-r--r--include/.gitignore2
-rw-r--r--include/Makefile.am5
-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
-rw-r--r--lib/.gitignore7
-rw-r--r--lib/MThd.cc38
-rw-r--r--lib/MTrk.cc34
-rw-r--r--lib/Makefile.am15
-rw-r--r--lib/SMF.cc62
-rw-r--r--lib/chunk.cc31
-rw-r--r--lib/event.cc58
-rw-r--r--lib/message.cc247
-rw-r--r--lib/util.cc96
-rw-r--r--man/.gitignore2
-rw-r--r--man/Makefile.am3
-rw-r--r--man/midi2f0.185
-rw-r--r--man/mididump.172
-rw-r--r--man/midifilter.193
-rw-r--r--midillo.pc.in11
-rw-r--r--tools/.gitignore11
-rw-r--r--tools/Makefile.am31
-rw-r--r--tools/enflesh_filters_list.sh20
-rw-r--r--tools/filters.list36
-rw-r--r--tools/midi2f0.cc151
-rw-r--r--tools/mididump.cc84
-rw-r--r--tools/midifilter.cc295
44 files changed, 2696 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..204d437
--- a/dev/null
+++ b/.gitignore
@@ -0,0 +1,22 @@
1configure
2Makefile.in
3Doxyfile
4config.log
5depcomp
6config.guess
7config.h
8ltmain.sh
9config.sub
10INSTALL
11NEWS
12Makefile
13config.status
14midillo.pc
15stamp-h1
16config.h.in
17libtool
18autom4te.cache
19missing
20aclocal.m4
21install-sh
22doxydox
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..a9fb0c7
--- a/dev/null
+++ b/AUTHORS
@@ -0,0 +1,3 @@
1Klever dissected:
2 Michael 'hacker' Krelin <hacker@klever.net>
3 Leonid Ivanov <kamel@klever.net>
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..9a21651
--- a/dev/null
+++ b/COPYING
@@ -0,0 +1,19 @@
1Copyright (c) 2006 Klever Group (http://www.klever.net/)
2
3Permission is hereby granted, free of charge, to any person obtaining a copy of
4this software and associated documentation files (the "Software"), to deal in
5the Software without restriction, including without limitation the rights to
6use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7of the Software, and to permit persons to whom the Software is furnished to do
8so, subject to the following conditions:
9
10The above copyright notice and this permission notice shall be included in all
11copies or substantial portions of the Software.
12
13THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19SOFTWARE.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..e69de29
--- a/dev/null
+++ b/ChangeLog
diff --git a/Doxyfile.in b/Doxyfile.in
new file mode 100644
index 0000000..95552d7
--- a/dev/null
+++ b/Doxyfile.in
@@ -0,0 +1,247 @@
1# Doxyfile 1.3.9.1
2
3#---------------------------------------------------------------------------
4# Project related configuration options
5#---------------------------------------------------------------------------
6PROJECT_NAME = @PACKAGE@
7PROJECT_NUMBER = @VERSION@
8OUTPUT_DIRECTORY = @builddir@/doxydox
9CREATE_SUBDIRS = NO
10OUTPUT_LANGUAGE = English
11USE_WINDOWS_ENCODING = NO
12BRIEF_MEMBER_DESC = YES
13REPEAT_BRIEF = YES
14ABBREVIATE_BRIEF =
15ALWAYS_DETAILED_SEC = NO
16INLINE_INHERITED_MEMB = NO
17FULL_PATH_NAMES = YES
18STRIP_FROM_PATH = include
19STRIP_FROM_INC_PATH = include
20SHORT_NAMES = NO
21JAVADOC_AUTOBRIEF = NO
22MULTILINE_CPP_IS_BRIEF = NO
23DETAILS_AT_TOP = NO
24INHERIT_DOCS = YES
25DISTRIBUTE_GROUP_DOC = NO
26TAB_SIZE = 8
27ALIASES =
28OPTIMIZE_OUTPUT_FOR_C = NO
29OPTIMIZE_OUTPUT_JAVA = NO
30SUBGROUPING = YES
31
32#---------------------------------------------------------------------------
33# Build related configuration options
34#---------------------------------------------------------------------------
35
36EXTRACT_ALL = NO
37EXTRACT_PRIVATE = NO
38EXTRACT_STATIC = NO
39EXTRACT_LOCAL_CLASSES = YES
40EXTRACT_LOCAL_METHODS = NO
41HIDE_UNDOC_MEMBERS = NO
42HIDE_UNDOC_CLASSES = NO
43HIDE_FRIEND_COMPOUNDS = NO
44HIDE_IN_BODY_DOCS = NO
45INTERNAL_DOCS = NO
46CASE_SENSE_NAMES = YES
47HIDE_SCOPE_NAMES = NO
48SHOW_INCLUDE_FILES = NO
49INLINE_INFO = YES
50SORT_MEMBER_DOCS = YES
51SORT_BRIEF_DOCS = NO
52SORT_BY_SCOPE_NAME = YES
53GENERATE_TODOLIST = YES
54GENERATE_TESTLIST = YES
55GENERATE_BUGLIST = YES
56GENERATE_DEPRECATEDLIST= YES
57ENABLED_SECTIONS =
58MAX_INITIALIZER_LINES = 30
59SHOW_USED_FILES = NO
60SHOW_DIRECTORIES = YES
61
62#---------------------------------------------------------------------------
63# configuration options related to warning and progress messages
64#---------------------------------------------------------------------------
65
66QUIET = NO
67WARNINGS = YES
68WARN_IF_UNDOCUMENTED = YES
69WARN_IF_DOC_ERROR = YES
70WARN_FORMAT = "$file:$line: $text"
71WARN_LOGFILE =
72
73#---------------------------------------------------------------------------
74# configuration options related to the input files
75#---------------------------------------------------------------------------
76
77INPUT = \
78 @srcdir@/include/midillo/
79FILE_PATTERNS = *.h
80RECURSIVE = NO
81EXCLUDE =
82EXCLUDE_SYMLINKS = NO
83EXCLUDE_PATTERNS =
84EXAMPLE_PATH =
85EXAMPLE_PATTERNS =
86EXAMPLE_RECURSIVE = NO
87IMAGE_PATH =
88INPUT_FILTER =
89FILTER_PATTERNS =
90FILTER_SOURCE_FILES = NO
91
92#---------------------------------------------------------------------------
93# configuration options related to source browsing
94#---------------------------------------------------------------------------
95
96SOURCE_BROWSER = NO
97INLINE_SOURCES = NO
98STRIP_CODE_COMMENTS = YES
99REFERENCED_BY_RELATION = YES
100REFERENCES_RELATION = YES
101VERBATIM_HEADERS = YES
102
103#---------------------------------------------------------------------------
104# configuration options related to the alphabetical class index
105#---------------------------------------------------------------------------
106
107ALPHABETICAL_INDEX = YES
108COLS_IN_ALPHA_INDEX = 2
109IGNORE_PREFIX =
110
111#---------------------------------------------------------------------------
112# configuration options related to the HTML output
113#---------------------------------------------------------------------------
114
115GENERATE_HTML = YES
116HTML_OUTPUT = html
117HTML_FILE_EXTENSION = .html
118HTML_HEADER =
119HTML_FOOTER =
120HTML_STYLESHEET =
121HTML_ALIGN_MEMBERS = YES
122GENERATE_HTMLHELP = NO
123CHM_FILE =
124HHC_LOCATION =
125GENERATE_CHI = NO
126BINARY_TOC = NO
127TOC_EXPAND = NO
128DISABLE_INDEX = NO
129ENUM_VALUES_PER_LINE = 4
130GENERATE_TREEVIEW = NO
131TREEVIEW_WIDTH = 250
132
133#---------------------------------------------------------------------------
134# configuration options related to the LaTeX output
135#---------------------------------------------------------------------------
136
137GENERATE_LATEX = NO
138LATEX_OUTPUT = latex
139LATEX_CMD_NAME = latex
140MAKEINDEX_CMD_NAME = makeindex
141COMPACT_LATEX = NO
142PAPER_TYPE = a4wide
143EXTRA_PACKAGES =
144LATEX_HEADER =
145PDF_HYPERLINKS = NO
146USE_PDFLATEX = NO
147LATEX_BATCHMODE = NO
148LATEX_HIDE_INDICES = NO
149
150#---------------------------------------------------------------------------
151# configuration options related to the RTF output
152#---------------------------------------------------------------------------
153
154GENERATE_RTF = NO
155RTF_OUTPUT = rtf
156COMPACT_RTF = NO
157RTF_HYPERLINKS = NO
158RTF_STYLESHEET_FILE =
159RTF_EXTENSIONS_FILE =
160
161#---------------------------------------------------------------------------
162# configuration options related to the man page output
163#---------------------------------------------------------------------------
164
165GENERATE_MAN = NO
166MAN_OUTPUT = man
167MAN_EXTENSION = .3
168MAN_LINKS = YES
169
170#---------------------------------------------------------------------------
171# configuration options related to the XML output
172#---------------------------------------------------------------------------
173
174GENERATE_XML = YES
175XML_OUTPUT = xml
176XML_SCHEMA =
177XML_DTD =
178XML_PROGRAMLISTING = YES
179
180#---------------------------------------------------------------------------
181# configuration options for the AutoGen Definitions output
182#---------------------------------------------------------------------------
183
184GENERATE_AUTOGEN_DEF = NO
185
186#---------------------------------------------------------------------------
187# configuration options related to the Perl module output
188#---------------------------------------------------------------------------
189
190GENERATE_PERLMOD = NO
191PERLMOD_LATEX = NO
192PERLMOD_PRETTY = YES
193PERLMOD_MAKEVAR_PREFIX =
194
195#---------------------------------------------------------------------------
196# Configuration options related to the preprocessor
197#---------------------------------------------------------------------------
198
199ENABLE_PREPROCESSING = YES
200MACRO_EXPANSION = NO
201EXPAND_ONLY_PREDEF = NO
202SEARCH_INCLUDES = YES
203INCLUDE_PATH =
204INCLUDE_FILE_PATTERNS =
205PREDEFINED =
206EXPAND_AS_DEFINED =
207SKIP_FUNCTION_MACROS = YES
208
209#---------------------------------------------------------------------------
210# Configuration::additions related to external references
211#---------------------------------------------------------------------------
212
213TAGFILES =
214GENERATE_TAGFILE =
215ALLEXTERNALS = NO
216EXTERNAL_GROUPS = YES
217PERL_PATH = /usr/bin/perl
218
219#---------------------------------------------------------------------------
220# Configuration options related to the dot tool
221#---------------------------------------------------------------------------
222
223CLASS_DIAGRAMS = YES
224HIDE_UNDOC_RELATIONS = YES
225HAVE_DOT = @HAVE_DOT@
226CLASS_GRAPH = YES
227COLLABORATION_GRAPH = YES
228UML_LOOK = NO
229TEMPLATE_RELATIONS = YES
230INCLUDE_GRAPH = YES
231INCLUDED_BY_GRAPH = YES
232CALL_GRAPH = NO
233GRAPHICAL_HIERARCHY = YES
234DOT_IMAGE_FORMAT = png
235DOT_PATH = @DOT@
236DOTFILE_DIRS =
237MAX_DOT_GRAPH_WIDTH = 1024
238MAX_DOT_GRAPH_HEIGHT = 1024
239MAX_DOT_GRAPH_DEPTH = 0
240GENERATE_LEGEND = YES
241DOT_CLEANUP = YES
242
243#---------------------------------------------------------------------------
244# Configuration::additions related to the search engine
245#---------------------------------------------------------------------------
246
247SEARCHENGINE = NO
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..5a2a2c7
--- a/dev/null
+++ b/Makefile.am
@@ -0,0 +1,22 @@
1SUBDIRS=include lib tools man
2EXTRA_DIST= NEWS NEWS.xml NEWS.xsl
3
4DISTCHECK_CONFIGURE_FLAGS=--with-pkgconfigdir=$${dc_install_base}/lib/pkgconfig
5if HAVE_PKGCONFIG
6pkgconfigdir=@PKGCONFIG_DIR@
7pkgconfig_DATA=midillo.pc
8endif
9
10all-local: NEWS
11if HAVE_DOXYGEN
12clean-local:
13 rm -rf doxydox
14endif
15
16NEWS: NEWS.xsl NEWS.xml
17 ${XSLTPROC} -o $@ NEWS.xsl NEWS.xml
18
19if HAVE_DOXYGEN
20dox:
21 ${DOXYGEN}
22endif
diff --git a/NEWS.xml b/NEWS.xml
new file mode 100644
index 0000000..f30ed3b
--- a/dev/null
+++ b/NEWS.xml
@@ -0,0 +1,6 @@
1<?xml version="1.0" encoding="us-ascii"?>
2<news>
3 <version version="0.0" date="August 1st, 2006">
4 <ni>Initial release</ni>
5 </version>
6</news>
diff --git a/NEWS.xsl b/NEWS.xsl
new file mode 100644
index 0000000..7c71307
--- a/dev/null
+++ b/NEWS.xsl
@@ -0,0 +1,24 @@
1<?xml version="1.0" encoding="us-ascii"?>
2<xsl:stylesheet version="1.0"
3 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
4 >
5 <xsl:output
6 method="text"
7 encoding="us-ascii"
8 media-type="text/plain" />
9
10 <xsl:template match="news">
11 <xsl:apply-templates/>
12 </xsl:template>
13 <xsl:template match="version">
14 <xsl:value-of select="concat(@version,' (',@date,')&#xA;')"/>
15 <xsl:apply-templates/>
16 </xsl:template>
17 <xsl:template match="ni">
18 <xsl:text> - </xsl:text>
19 <xsl:apply-templates mode="text"/>
20 <xsl:text>&#xA;</xsl:text>
21 </xsl:template>
22 <xsl:template match="*|text()"/>
23
24</xsl:stylesheet>
diff --git a/README b/README
new file mode 100644
index 0000000..e69de29
--- a/dev/null
+++ b/README
diff --git a/acinclude.m4 b/acinclude.m4
new file mode 100644
index 0000000..ec2c50f
--- a/dev/null
+++ b/acinclude.m4
@@ -0,0 +1,80 @@
1dnl AC_WITH_PKGCONFIG([ACTION-IF-FOUND[,ACTION-IF-NOT-FOUND]])
2dnl Outputs:
3dnl AC_SUBST: PKGCONFIG_PKGCONFIG PKGCONFIG_DIR
4dnl AM_CONDTIONAL: HAVE_PKGCONFIG
5AC_DEFUN([AC_WITH_PKGCONFIG],[
6 PKGCONFIG_PKGCONFIG=""
7 PKGCONFIG_DIR=""
8 HAVE_PKGCONFIG="no"
9 EXPLICIT_PKGCONFIGDIR="no"
10 test -z "${WANT_PKGCONFIG}" && WANT_PKGCONFIG=""
11 AC_PATH_PROG([PKGCONFIG_PKGCONFIG],[pkg-config],[false])
12 if test "${PKGCONFIG_PKGCONFIG}" != "false" ; then
13 AC_ARG_WITH([pkgconfigdir],
14 AC_HELP_STRING([--with-pkgconfigdir=dir],[Specify pkgconfig directory]),
15 [
16 if test "${withval}" = "no" ; then
17 WANT_PKGCONFIG="no"
18 else
19 PKGCONFIG_DIR="${withval}"
20 EXPLICIT_PKGCONFIGDIR="yes"
21 fi
22 ],[
23 AC_MSG_CHECKING([for pkgconfig directory])
24 PKGCONFIG_DIR="`${PKGCONFIG_PKGCONFIG} --debug 2>&1 | grep '^Scanning'| head -n 1 | cut -d\' -f2-|cut -d\' -f1`"
25 AC_MSG_RESULT([${PKGCONFIG_DIR}])
26 ]
27 )
28 if test -d "${PKGCONFIG_DIR}" ; then
29 HAVE_PKGCONFIG=yes
30 AC_SUBST([PKGCONFIG_PKGCONFIG])
31 AC_SUBST([PKGCONFIG_DIR])
32 else
33 AC_MSG_NOTICE([unexistent pkgconfig directory: ${PKGCONFIG_DIR}])
34 if test "${EXPLICIT_PKGCONFIGDIR}" = "yes" ; then
35 HAVE_PKGCONFIG=yes
36 AC_SUBST([PKGCONFIG_PKGCONFIG])
37 AC_SUBST([PKGCONFIG_DIR])
38 else
39 ifelse([$2], , :, [$2])
40 fi
41 fi
42 fi
43 AM_CONDITIONAL([HAVE_PKGCONFIG],[test "${HAVE_PKGCONFIG}" = "yes"])
44])
45
46dnl AC_WITH_DOXYGEN([ACTION-IF-FOUND[,ACTION-IF-NOT-FOUND]])
47dnl Outputs:
48dnl AC_SUBST: DOXYGEN HAVE_DOXYGEN
49dnl AM_CONDTIONAL: HAVE_DOXYGEN
50AC_DEFUN([AC_WITH_DOXYGEN],[
51 HAVE_DOXYGEN="no"
52 AC_PATH_PROG([DOXYGEN],[doxygen],[false])
53 if test "${DOXYGEN}" = "false" ; then
54 ifelse([$2], , :, [$2])
55 else
56 HAVE_DOXYGEN="yes"
57 AC_SUBST([DOXYGEN])
58 $1
59 fi
60 AC_SUBST([HAVE_DOXYGEN])
61 AM_CONDITIONAL([HAVE_DOXYGEN],[test "${HAVE_DOXYGEN}" = "yes"])
62])
63
64dnl AC_WITH_DOT([ACTION-IF-FOUND[,ACTION-IF-NOT-FOUND]])
65dnl Outputs:
66dnl AC_SUBST: DOT HAVE_DOT
67dnl AM_CONDITIONAL: HAVE_DOT
68AC_DEFUN([AC_WITH_DOT],[
69 HAVE_DOT="no"
70 AC_PATH_PROG([DOT],[dot],[false])
71 if test "${DOT}" = "false" ; then
72 ifelse([$2], , :, [$2])
73 else
74 HAVE_DOT="yes"
75 AC_SUBST([DOT])
76 $1
77 fi
78AC_SUBST([HAVE_DOT])
79 AM_CONDITIONAL([HAVE_DOT],[test "${HAVE_DOT}" = "yes"])
80])
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..ba27501
--- a/dev/null
+++ b/autogen.sh
@@ -0,0 +1,9 @@
1#!/bin/sh
2WANT_AUTOMAKE=1.8
3export WANT_AUTOMAKE
4libtoolize -f \
5&& aclocal \
6&& autoheader \
7&& automake -a \
8&& autoconf \
9&& ./configure "$@"
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..040b9cf
--- a/dev/null
+++ b/configure.ac
@@ -0,0 +1,55 @@
1AC_INIT([midillo], [0.0], [midillo-bugs@klever.net])
2AC_CONFIG_SRCDIR([include/midillo/SMF.h])
3AC_CONFIG_HEADERS([config.h])
4AM_INIT_AUTOMAKE([dist-bzip2])
5
6AC_PROG_INSTALL
7AC_PROG_AWK
8AC_PROG_CXX
9AC_PROG_CC
10AC_PROG_LIBTOOL
11
12AC_HEADER_STDC
13AC_CHECK_HEADERS([sys/types.h sys/stat.h])
14AC_CHECK_DECLS([environ],,,[
15 #include <unistd.h>
16])
17
18AC_C_CONST
19
20AC_FUNC_MALLOC
21AC_FUNC_REALLOC
22
23AC_PATH_PROG([XSLTPROC],[xsltproc],[true])
24
25AC_WITH_PKGCONFIG
26
27PKG_CHECK_MODULES([KONFORKA],[konforka],,[
28 AC_MSG_ERROR([no konforka library found. get one from http://kin.klever.net/konforka/])
29])
30
31WANT_DOXYGEN="yes"
32AC_ARG_ENABLE([doxygen],
33 AC_HELP_STRING([--disable-doxygen],[do not generate documentation]),
34 [
35 test "${enableval}" = "no" && WANT_DOXYGEN="no"
36 ]
37)
38if test "${WANT_DOXYGEN}" = "yes" ; then
39 AC_WITH_DOXYGEN
40 AC_WITH_DOT
41else
42 AM_CONDITIONAL([HAVE_DOXYGEN],[false])
43 AM_CONDITIONAL([HAVE_DOT],[false])
44fi
45
46AC_CONFIG_FILES([
47 Makefile
48 midillo.pc
49 Doxyfile
50 include/Makefile
51 lib/Makefile
52 tools/Makefile
53 man/Makefile
54])
55AC_OUTPUT
diff --git a/include/.gitignore b/include/.gitignore
new file mode 100644
index 0000000..282522d
--- a/dev/null
+++ b/include/.gitignore
@@ -0,0 +1,2 @@
1Makefile
2Makefile.in
diff --git a/include/Makefile.am b/include/Makefile.am
new file mode 100644
index 0000000..edfb186
--- a/dev/null
+++ b/include/Makefile.am
@@ -0,0 +1,5 @@
1nobase_include_HEADERS = \
2 midillo/util.h midillo/exception.h \
3 midillo/SMF.h \
4 midillo/chunk.h midillo/MTrk.h midillo/MThd.h \
5 midillo/event.h midillo/message.h
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 @@
1#ifndef __MIDILLO_MTHD_H
2#define __MIDILLO_MTHD_H
3
4#include <istream>
5#include <ostream>
6#include <midillo/chunk.h>
7
8/**
9 * @file
10 * @brief the MThd_t -- MThd header chunk class
11 */
12
13namespace midillo {
14 using std::istream;
15 using std::ostream;
16
17 /**
18 * MThd header chunk container
19 */
20 class MThd_t : public chunk_t {
21 public:
22 enum {
23 fmt_0 = 0, fmt_1 = 1, fmt_2 = 2,
24 fmt_singletrack = fmt_0,
25 fmt_multitrack = fmt_1,
26 fmt_tracksequence = fmt_2
27 };
28 /**
29 * SMF format. 0 for single track, 1 for multitrack, 2 for track
30 * sequence.
31 */
32 int fmt;
33 /**
34 * Number of tracks in the file
35 */
36 int ntracks;
37 /**
38 * The number of pulses per quarter note
39 */
40 int division;
41
42 /**
43 * Load MThd chunk from the stream
44 * @param s input stream
45 */
46 void load(istream& s);
47
48 /**
49 * Read MThd chunk data from the stream. This function assumes that
50 * header is already read.
51 * @param s input stream
52 */
53 void load_data(istream& s);
54
55 /**
56 * Save MThd chunk to the stream
57 * @param s output stream
58 */
59 void save(ostream& s) const;
60
61 /**
62 * Dump textual representation of MThd chunk to stream
63 * @param s output stream
64 */
65 void dump(ostream& s) const;
66 };
67
68 inline ostream& operator<<(ostream& s,const MThd_t& mthd) {
69 mthd.dump(s); return s;
70 }
71
72}
73
74#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 @@
1#ifndef __MIDILLO_MTRK_H
2#define __MIDILLO_MTRK_H
3
4#include <istream>
5#include <ostream>
6#include <list>
7#include <midillo/chunk.h>
8#include <midillo/event.h>
9
10/**
11 * @file
12 * @brief MTrk -- track chunk container
13 */
14
15namespace midillo {
16 using std::istream;
17 using std::ostream;
18
19 /**
20 * MTrk track chunk container class
21 */
22 class MTrk_t : public chunk_t {
23 public:
24 /**
25 * MIDI events contained in the track
26 */
27 events_t events;
28
29 /**
30 * Load MTrk chunk from the stream
31 * @param s input stream
32 */
33 void load(istream& s);
34
35 /**
36 * Save MTrk chunk to the stream
37 * @param s output stream
38 */
39 void save(ostream& s) const;
40
41 /**
42 * Dump textual representation of MTrk chunk to stream
43 * @param s output stream
44 */
45 void dump(ostream& s) const;
46 };
47
48 inline ostream& operator<<(ostream& s,const MTrk_t& mtrk) {
49 mtrk.dump(s); return s;
50 }
51
52}
53
54#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 @@
1#ifndef __MIDILLO_SMF_H
2#define __MIDILLO_SMF_H
3
4#include <istream>
5#include <ostream>
6#include <list>
7#include <midillo/MThd.h>
8#include <midillo/MTrk.h>
9
10/**
11 * @file
12 * @brief the SMF_t -- standard midi file
13 */
14
15namespace midillo {
16 using std::istream;
17 using std::vector;
18 using std::ostream;
19
20 /**
21 * Standard midi file object
22 */
23 class SMF_t {
24 public:
25 /**
26 * MThd header chunk
27 */
28 MThd_t mthd;
29 /**
30 * The type for collection of MTrk track chunks
31 */
32 typedef list<MTrk_t> tracks_t;
33 /**
34 * MTrk track chunks collection for the file
35 */
36 tracks_t tracks;
37
38 SMF_t() { }
39 /**
40 * Construct object from the file
41 * @see load(const char *f,bool stdinable)
42 */
43 SMF_t(const char *f,bool stdinable=true) { load(f,stdinable); }
44 /**
45 * Construct object from the stream
46 * @see load(istream& s)
47 */
48 SMF_t(istream& s) { load(s); }
49
50 /**
51 * Load MIDI data from the file
52 * @param f filename
53 * @param stdinable true if '-' is treatead as cin input stream
54 */
55 void load(const char *f,bool stdinable=true);
56 /**
57 * Load midi data from the stream
58 * @param s input stream
59 */
60 void load(istream& s);
61
62 /**
63 * Save MIDI data to the file
64 * @param f filename
65 * @param stdoutable true if '-' is treated as cout output stream
66 */
67 void save(const char *f,bool stdoutable=true) const;
68 /**
69 * Save MIDI data to the stream
70 * @param s output stream
71 */
72 void save(ostream& s) const;
73
74 /**
75 * Dump textual representation of SMF to stream
76 * @param s output stream
77 */
78 void dump(ostream& s) const;
79 };
80
81 inline ostream& operator<<(ostream& s,const SMF_t& smf) {
82 smf.dump(s); return s;
83 }
84
85}
86
87#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 @@
1#ifndef __MIDILLO_CHUNK_H
2#define __MIDILLO_CHUNK_H
3
4#include <istream>
5#include <ostream>
6
7/**
8 * @file
9 * @brief Generic SMF chunk manipulation
10 */
11
12namespace midillo {
13 using std::istream;
14 using std::ostream;
15
16 enum {
17 chunk_id_MThd = 0x6468544d,
18 chunk_id_MTrk = 0x6b72544d
19 };
20 /**
21 * Chunk header data structure
22 */
23 struct chunk_header_t {
24 /**
25 * Track signature data
26 */
27 union {
28 /**
29 * ASCII representation
30 */
31 char id_chars[4];
32 /**
33 * long integer representation
34 */
35 unsigned long id_number;
36 };
37 /**
38 * Chunk length
39 */
40 unsigned long length;
41
42 chunk_header_t()
43 : id_number(0), length(0) { }
44 chunk_header_t(const chunk_header_t& s)
45 : id_number(s.id_number), length(s.length) { };
46
47 chunk_header_t& operator=(const chunk_header_t& s) {
48 id_number=s.id_number; length=s.length;
49 return *this;
50 }
51
52 /**
53 * Load chunk header from the stream
54 * @param s input stream
55 */
56 void load(istream& s);
57 /**
58 * Save chunk header to the stream
59 * @param s output stream
60 */
61 void save(ostream& s) const;
62
63 /**
64 * Dump textual representation of chunk header to stream
65 * @param s output stream
66 */
67 void dump(ostream& s) const;
68
69 };
70
71 inline ostream& operator<<(ostream& s,const chunk_header_t& ch) {
72 ch.dump(s); return s;
73 }
74
75 /**
76 * Base class for specific chunk containers
77 */
78 class chunk_t {
79 public:
80 /**
81 * Chunk header data
82 */
83 chunk_header_t header;
84 };
85
86}
87
88#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 @@
1#ifndef __MIDILLO_EVENT_H
2#define __MIDILLO_EVENT_H
3
4#include <istream>
5#include <ostream>
6#include <list>
7#include <midillo/message.h>
8
9/**
10 * @file
11 * @brief midi event container
12 */
13
14namespace midillo {
15 using std::istream;
16 using std::ostream;
17 using std::list;
18
19 /**
20 * MIDI event container class
21 */
22 class event_t {
23 public:
24 /**
25 * delta time since the last event
26 */
27 long deltat;
28 /**
29 * MIDI message itself
30 */
31 message_t message;
32
33 /**
34 * Load MIDI event from the stream
35 * @param rs reference to the running status
36 * @param s input stream
37 */
38 void load(int& rs,istream& s);
39
40 /**
41 * Save MIDI event to the stream
42 * @param rs reference to the running status
43 * @param s output stream
44 */
45 void save(int& rs,ostream& s) const;
46
47 /**
48 * Calculate the amount of data that would be written to stream in
49 * case of save
50 * @param rs reference to the running status
51 * @return the number of bytes
52 */
53 unsigned long calculate_save_size(int& rs) const;
54
55 /**
56 * Dump textual representation of event to stream
57 * @param s output stream
58 */
59 void dump(ostream& s) const;
60 };
61
62 inline ostream& operator<<(ostream& s,const event_t& e) {
63 e.dump(s); return s;
64 }
65
66 /**
67 * MIDI events list container
68 */
69 class events_t : public list<event_t> {
70 public:
71
72 /**
73 * Append empty event to the end of the list
74 * @return iterator, pointing to the appended event
75 */
76 iterator append_event();
77
78 /**
79 * Load MIDI events (track data) from the stream
80 * @param s input stream
81 */
82 void load(istream& s);
83 /**
84 * Save MIDI events (track data) to the stream
85 * @param s output stream
86 */
87 void save(ostream& s) const;
88
89 /**
90 * Calculate the size of the track data that would be written to
91 * the stream by save()
92 * @return the number of bytes
93 */
94 unsigned long calculate_save_size() const;
95 };
96
97}
98
99#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 @@
1#ifndef __MIDILLO_EXCEPTION_H
2#define __MIDILLO_EXCEPTION_H
3
4#include <konforka/exception.h>
5
6/**
7 * @file
8 * @brief midillo specific exceptions
9 */
10
11namespace midillo {
12 using std::string;
13
14 /**
15 * Base midillo exception class
16 */
17 class exception : public konforka::exception {
18 public:
19 explicit exception(const string& fi,const string& fu,int l,const string& w)
20 : konforka::exception(fi,fu,l,w) { }
21 };
22
23 class exception_io_error : public exception {
24 public:
25 explicit exception_io_error(const string& fi,const string& fu,int l,const string& w)
26 : exception(fi,fu,l,w) { }
27 };
28
29 class exception_input_error : public exception_io_error {
30 public:
31 explicit exception_input_error(const string& fi,const string& fu,int l,const string& w)
32 : exception_io_error(fi,fu,l,w) { }
33 };
34
35 class exception_invalid_input : public exception_input_error {
36 public:
37 explicit exception_invalid_input(const string& fi,const string& fu,int l,const string& w)
38 : exception_input_error(fi,fu,l,w) { }
39 };
40
41 class exception_unexpected_input : public exception_invalid_input {
42 public:
43 explicit exception_unexpected_input(const string& fi,const string& fu,int l,const string& w)
44 : exception_invalid_input(fi,fu,l,w) { }
45 };
46
47 class exception_output_error : public exception_io_error {
48 public:
49 explicit exception_output_error(const string& fi,const string& fu,int l,const string& w)
50 : exception_io_error(fi,fu,l,w) { }
51 };
52
53};
54
55#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 @@
1#ifndef __MIDILLO_MESSAGE_H
2#define __MIDILLO_MESSAGE_H
3
4#include <istream>
5#include <ostream>
6#include <vector>
7
8/**
9 * @file
10 * @brief MIDI message
11 */
12
13namespace midillo {
14 using std::istream;
15 using std::ostream;
16 using std::vector;
17
18 enum {
19 // bits
20 status_bit = 0x80,
21 status_event_bits = 0xF0,
22 status_channel_bits = 0x0F,
23 status_system_bits = 0xFF,
24 // channel voice messages
25 status_note_off = 0x80,
26 status_note_on = 0x90,
27 status_polyphonic_key_pressure = 0xA0,
28 status_aftertouch = status_polyphonic_key_pressure,
29 status_control_change = 0xB0,
30 status_program_change = 0xC0,
31 status_channel_pressure = 0xD0,
32 status_pitch_wheel_change = 0xE0,
33 status_system = 0xF0,
34 // system common messages
35 status_system_sysex = 0xF0,
36 status_system_MTC_quarter_frame = 0xF1,
37 status_system_song_position_pointer = 0xF2,
38 status_system_song_select = 0xF3,
39 status_system_tune_request = 0xF6,
40 status_system_end_of_sysex = 0xF7,
41 // system real-time messages
42 status_system_timing_clock = 0xF8,
43 status_system_midi_clock = status_system_timing_clock,
44 status_system_midi_tick = 0xF9,
45 status_system_start = 0xFA,
46 status_system_midi_start = status_system_start,
47 status_system_continue = 0xFB,
48 status_system_midi_continue = status_system_continue,
49 status_system_stop = 0xFC,
50 status_system_midi_stop = status_system_stop,
51 status_system_active_sense = 0xFE,
52 status_system_rest = 0xFF,
53 status_system_reset = status_system_rest,
54 // midi file specific
55 status_system_meta = 0xFF
56 };
57 enum {
58 // meta events
59 meta_sequence_number = 0x00,
60 meta_text = 0x01,
61 meta_copyright = 0x02,
62 meta_seq_track_name = 0x03,
63 meta_instrument = 0x04,
64 meta_lyric = 0x05,
65 meta_marker = 0x06,
66 meta_cue_point = 0x07,
67 meta_patch_name = 0x08,
68 meta_port_name = 0x09,
69 meta_EOT = 0x2F,
70 meta_tempo = 0x51,
71 meta_SMPTE_offset = 0x54,
72 meta_time_sig = 0x58,
73 meta_key_sig = 0x59,
74 meta_proprietary = 0x7F,
75 // obsolete meta events
76 meta_midi_channel = 0x20,
77 meta_midi_port = 0x21
78 };
79
80 /**
81 * MIDI message container
82 */
83 class message_t {
84 public:
85 /**
86 * MIDI status byte
87 */
88 int status;
89 /**
90 * MIDI meta event type
91 */
92 int meta_status;
93 typedef unsigned char byte_t;
94 typedef vector<byte_t> bytes_t;
95 /**
96 * MIDI message data -- content is message-specific
97 */
98 bytes_t data;
99
100 message_t()
101 : status(-1) { }
102 message_t(const message_t& m)
103 : status(m.status), meta_status(m.meta_status), data(m.data) { }
104
105 message_t& operator=(const message_t& m) {
106 status = m.status;
107 meta_status = m.meta_status;
108 data = m.data;
109 return *this;
110 }
111
112 /**
113 * Load MIDI message from the stream
114 * @param rs reference to the running status
115 * @param s input stream
116 */
117 void load(int& rs,istream& s);
118 /**
119 * Save MIDI message to the stream
120 * @param rs reference to the running status
121 * @param s output stream
122 */
123 void save(int& rs,ostream& s) const;
124 /**
125 * Calculate the amount of data that would be written to stream in
126 * case of save()
127 * @param rs reference to the running status
128 * @return the number of bytes
129 */
130 unsigned long calculate_save_size(int& rs) const;
131
132 /**
133 * Load data so that we have c bytes of data for the event
134 * @param s input stream
135 * @param c size of data needed for the event
136 */
137 void load_data(istream& s,int c);
138 /**
139 * Load sysex data from the stream
140 * @param s input stream
141 */
142 void load_sysex(istream& s);
143
144 /**
145 * Save data to the stream
146 * @param s output stream
147 */
148 void save_data(ostream& s) const;
149 /**
150 * Save data to the stream and verify if the amount of data is
151 * correct
152 * @param s output stream
153 * @param c data bytes count
154 */
155 void save_data(ostream& s,int c) const;
156 /**
157 * Save sysex data to the stream
158 * @param s output stream
159 */
160 void save_sysex(ostream& s) const;
161
162 /**
163 * See if the event is meta event
164 * @return true if yes
165 */
166 bool is_meta() const {
167 return status==status_system_meta;
168 }
169 /**
170 * Check whether the event is a specific meta event
171 * @param meta meta event type
172 * @return true if yes
173 */
174 bool is_meta(int meta) const {
175 return is_meta() && (meta_status==meta);
176 }
177
178 /**
179 * See if the event is system event
180 * @return true if yes
181 */
182 bool is_system() const {
183 return (status&status_event_bits)==status_system && !is_meta();
184 }
185
186 /**
187 * Dump textual representation of midi message to stream
188 * @param s output stream
189 */
190 void dump(ostream& s) const;
191
192 };
193
194 inline ostream& operator<<(ostream& s,const message_t& m) {
195 m.dump(s); return s;
196 }
197
198}
199
200#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 @@
1#ifndef __MIDILLO_UTIL_H
2#define __MIDILLO_UTIL_H
3
4#include <istream>
5#include <ostream>
6
7/**
8 * @file
9 * @brief utilities
10 */
11
12namespace midillo {
13 using std::istream;
14 using std::ostream;
15
16 /**
17 * read 32 bits word from the stream
18 * @param s input stream
19 * @return the data acquired
20 */
21 unsigned long read32(istream& s);
22 /**
23 * read 16 bits word from the stream
24 * @param s input stream
25 * @return the data acquired
26 */
27 unsigned int read16(istream& s);
28 /**
29 * read the variable length quantity from the stream
30 * @param s input stream
31 * @return the data acquired
32 */
33 unsigned long readVL(istream& s);
34
35 /**
36 * write 32 bits word to the stream
37 * @param s output stream
38 * @param d data to write
39 */
40 void write32(ostream& s,unsigned long d);
41 /**
42 * write 16 bits word to the stream
43 * @param s output stream
44 * @param d data to write
45 */
46 void write16(ostream& s,unsigned int d);
47 /**
48 * write the variable length quantity to the stream
49 * @param s output stream
50 * @param d data to write
51 */
52 void writeVL(ostream& s,unsigned long d);
53
54 /**
55 * calculate the amount of data that would be written by writeVL
56 * @param d data that would be written
57 * @return the number of bytes
58 */
59 unsigned long calcVLsize(unsigned long d);
60
61}
62
63#endif /* __MIDILLO_UTIL_H */
diff --git a/lib/.gitignore b/lib/.gitignore
new file mode 100644
index 0000000..dc5e416
--- a/dev/null
+++ b/lib/.gitignore
@@ -0,0 +1,7 @@
1*.lo
2*.o
3Makefile.in
4.libs
5.deps
6Makefile
7*.la
diff --git a/lib/MThd.cc b/lib/MThd.cc
new file mode 100644
index 0000000..110c98a
--- a/dev/null
+++ b/lib/MThd.cc
@@ -0,0 +1,38 @@
1#include <midillo/MThd.h>
2#include <midillo/util.h>
3#include <midillo/exception.h>
4
5namespace midillo {
6 using std::endl;
7
8 void MThd_t::load(istream& s) {
9 header.load(s);
10 if(header.id_number!=chunk_id_MThd)
11 throw exception_unexpected_input(CODEPOINT,"MThd chunk expected");
12 if(header.length!=6)
13 throw exception_invalid_input(CODEPOINT,"MThd chunk is not 6 bytes long");
14 load_data(s);
15 }
16
17 void MThd_t::load_data(istream& s) {
18 fmt = read16(s);
19 ntracks = read16(s);
20 division = read16(s);
21 }
22
23 void MThd_t::save(ostream& s) const {
24 header.save(s);
25 write16(s,fmt);
26 write16(s,ntracks);
27 write16(s,division);
28 }
29
30 void MThd_t::dump(ostream& s) const {
31 std::ios::fmtflags ff = s.flags();
32 s.unsetf(std::ios::hex); s.setf(std::ios::dec);
33 s << " " << header << endl
34 << " fmt=" << fmt << ", " << ntracks << " track(s), division=" << division << endl;
35 s.flags(ff);
36 }
37
38}
diff --git a/lib/MTrk.cc b/lib/MTrk.cc
new file mode 100644
index 0000000..fa1e0f8
--- a/dev/null
+++ b/lib/MTrk.cc
@@ -0,0 +1,34 @@
1#include <algorithm>
2#include <iterator>
3#include <midillo/MTrk.h>
4#include <midillo/exception.h>
5
6namespace midillo {
7 using std::copy;
8 using std::ostream_iterator;
9 using std::endl;
10
11 void MTrk_t::load(istream& s) {
12 header.load(s);
13 if(header.id_number!=chunk_id_MTrk)
14 throw exception_unexpected_input(CODEPOINT,"MTrk chunk expected");
15 events.load(s);
16 }
17
18 void MTrk_t::save(ostream& s) const {
19 chunk_header_t h = header;
20 h.id_number = chunk_id_MTrk;
21 h.length = events.calculate_save_size();
22 h.save(s);
23 events.save(s);
24 }
25
26 void MTrk_t::dump(ostream& s) const {
27 s << " " << header << endl
28 << " ";
29 copy(
30 events.begin(), events.end(),
31 ostream_iterator<event_t>(s,"\n ") );
32 }
33
34}
diff --git a/lib/Makefile.am b/lib/Makefile.am
new file mode 100644
index 0000000..de49c97
--- a/dev/null
+++ b/lib/Makefile.am
@@ -0,0 +1,15 @@
1lib_LTLIBRARIES = libmidillo.la
2
3INCLUDES = -I${top_srcdir}/include -I${top_srcdir}
4AM_CXXFLAGS = ${KONFORKA_CFLAGS}
5LDADD = ${KONFORKA_LIBS}
6
7libmidillo_la_SOURCES = \
8 util.cc \
9 SMF.cc \
10 chunk.cc \
11 MThd.cc MTrk.cc \
12 event.cc \
13 message.cc
14
15libmidillo_la_LDFLAGS = -version-info 0:0:0
diff --git a/lib/SMF.cc b/lib/SMF.cc
new file mode 100644
index 0000000..ba3179d
--- a/dev/null
+++ b/lib/SMF.cc
@@ -0,0 +1,62 @@
1#include <iostream>
2#include <fstream>
3#include <algorithm>
4#include <iterator>
5#include <midillo/SMF.h>
6
7namespace midillo {
8 using std::ifstream;
9 using std::ofstream;
10 using std::cin;
11 using std::cout;
12 using std::copy;
13 using std::ostream_iterator;
14 using std::endl;
15
16 void SMF_t::load(const char *f,bool stdinable) {
17 if(stdinable && !strcmp(f,"-")) {
18 load(cin);
19 }else{
20 ifstream s(f,std::ios::in|std::ios::binary);
21 load(s);
22 }
23 }
24
25 void SMF_t::load(istream& s) {
26 mthd.load(s);
27 tracks.resize(mthd.ntracks);
28 tracks_t::iterator i = tracks.begin();
29 for(int t=0;t<mthd.ntracks;++t,++i) {
30 i->load(s);
31 }
32 }
33
34 void SMF_t::save(const char *f,bool stdoutable) const {
35 if(stdoutable && !strcmp(f,"-")) {
36 save(cout);
37 }else{
38 ofstream s(f,std::ios::out|std::ios::trunc|std::ios::binary);
39 save(s);
40 }
41 }
42
43 void SMF_t::save(ostream& s) const {
44 mthd.save(s);
45 for(tracks_t::const_iterator i=tracks.begin();i!=tracks.end();++i) {
46 i->save(s);
47 }
48 }
49
50 void SMF_t::dump(ostream& s) const {
51 std::ios::fmtflags ff = s.flags();
52 s.unsetf(std::ios::hex); s.setf(std::ios::dec);
53 s
54 << "SMF with " << tracks.size() << " track(s)" << endl
55 << mthd << endl;
56 copy(
57 tracks.begin(), tracks.end(),
58 ostream_iterator<MTrk_t>(s,"\n") );
59 s.flags(ff);
60 }
61
62}
diff --git a/lib/chunk.cc b/lib/chunk.cc
new file mode 100644
index 0000000..7cc15ff
--- a/dev/null
+++ b/lib/chunk.cc
@@ -0,0 +1,31 @@
1#include <midillo/chunk.h>
2#include <midillo/util.h>
3#include <midillo/exception.h>
4
5namespace midillo {
6
7 void chunk_header_t::load(istream& s) {
8 s.read((char*)id_chars,sizeof(id_chars));
9 if(!s.good())
10 throw exception_input_error(CODEPOINT,"Error reading chunk header");
11 length = read32(s);
12 }
13
14 void chunk_header_t::save(ostream& s) const {
15 s.write((char*)id_chars,sizeof(id_chars));
16 if(!s.good())
17 throw exception_output_error(CODEPOINT,"Error writing chunk header");
18 write32(s,length);
19 }
20
21 void chunk_header_t::dump(ostream& s) const {
22 std::ios::fmtflags ff = s.flags();
23 s.unsetf(std::ios::hex); s.setf(std::ios::dec);
24 s
25 << id_chars[0] << id_chars[1]
26 << id_chars[2] << id_chars[3]
27 << " chunk of " << length << " byte(s)";
28 s.flags(ff);
29 }
30
31}
diff --git a/lib/event.cc b/lib/event.cc
new file mode 100644
index 0000000..39438fa
--- a/dev/null
+++ b/lib/event.cc
@@ -0,0 +1,58 @@
1#include <midillo/event.h>
2#include <midillo/util.h>
3
4namespace midillo {
5
6 void event_t::load(int& rs,istream& s) {
7 deltat = readVL(s);
8 message.load(rs,s);
9 }
10
11 void event_t::save(int& rs,ostream& s) const {
12 writeVL(s,deltat);
13 message.save(rs,s);
14 }
15
16 unsigned long event_t::calculate_save_size(int& rs) const {
17 return calcVLsize(deltat) + message.calculate_save_size(rs);
18 }
19
20 void event_t::dump(ostream& s) const {
21 std::ios::fmtflags ff = s.flags();
22 s.unsetf(std::ios::hex); s.setf(std::ios::dec);
23 s << "deltat=" << deltat << " [" << message << "]";
24 s.flags(ff);
25 }
26
27
28 events_t::iterator events_t::append_event() {
29 static event_t empty;
30 return insert(end(),empty);
31 }
32
33 void events_t::load(istream& s) {
34 int rs = -1;
35 for(;;) {
36 iterator i=append_event();
37 i->load(rs,s);
38 if(i->message.is_meta(meta_EOT))
39 break;
40 }
41 }
42
43 void events_t::save(ostream& s) const {
44 int rs = -1;
45 for(const_iterator i=begin();i!=end();++i) {
46 i->save(rs,s);
47 }
48 }
49
50 unsigned long events_t::calculate_save_size() const {
51 unsigned long rv = 0;
52 int rs = -1;
53 for(const_iterator i=begin();i!=end();++i) {
54 rv += i->calculate_save_size(rs);
55 }
56 return rv;
57 }
58}
diff --git a/lib/message.cc b/lib/message.cc
new file mode 100644
index 0000000..8f9e68a
--- a/dev/null
+++ b/lib/message.cc
@@ -0,0 +1,247 @@
1#include <algorithm>
2#include <iterator>
3#include <midillo/message.h>
4#include <midillo/util.h>
5#include <midillo/exception.h>
6
7namespace midillo {
8 using std::copy;
9 using std::ostream_iterator;
10
11 unsigned long message_t::calculate_save_size(int& rs) const {
12 unsigned long rv = 0;
13 if(status!=rs) {
14 ++rv;
15 rs = status;
16 }else if((status&status_event_bits)==status_system) {
17 rs = -1;
18 ++rv; // XXX: is it really needed?
19 }
20 switch(status&status_event_bits) {
21 case status_note_off:
22 case status_note_on:
23 case status_polyphonic_key_pressure: // aka status_aftertouch
24 case status_control_change:
25 case status_pitch_wheel_change:
26 rv += 2; break;
27 case status_program_change:
28 case status_channel_pressure:
29 ++rv; break;
30 case status_system:
31 switch(status&status_system_bits) {
32 case status_system_sysex:
33 case status_system_end_of_sysex:
34 rv += data.size()+1; break;
35 case status_system_MTC_quarter_frame:
36 case status_system_song_select:
37 ++rv; break;
38 case status_system_song_position_pointer:
39 rv += 2; break;
40 case status_system_tune_request:
41 case status_system_timing_clock: // aka status_system_midi_clock
42 case status_system_midi_tick:
43 case status_system_start: // aka status_system_midi_start
44 case status_system_stop: // aka status_system_midi_stop
45 case status_system_continue: // aka status_system_midi_continue
46 case status_system_active_sense:
47 break; /* XXX: ensure there is no data? */
48 case status_system_meta: // also reset, but not for the purpose of midi file
49 ++rv;
50 rv += calcVLsize(data.size());
51 rv += data.size();
52 break;
53 default:
54 throw exception(CODEPOINT,"Internal error");
55 break;
56 }
57 break;
58 default:
59 throw exception(CODEPOINT,"Internal error");
60 break;
61 }
62 return rv;
63 }
64
65 void message_t::save(int& rs,ostream& s) const {
66 if(status!=rs) {
67 s.put(status);
68 if(!s.good())
69 throw exception_output_error(CODEPOINT,"Error writing midi status byte");
70 rs = status;
71 }else if((status&status_event_bits)==status_system) {
72 rs = -1;
73 s.put(status); // XXX: is it really needed?
74 if(!s.good())
75 throw exception_output_error(CODEPOINT,"Error writing midi system status byte");
76 }
77 switch(status&status_event_bits) {
78 case status_note_off:
79 case status_note_on:
80 case status_polyphonic_key_pressure: // aka status_aftertouch
81 case status_control_change:
82 case status_pitch_wheel_change:
83 save_data(s,2); break;
84 case status_program_change:
85 case status_channel_pressure:
86 save_data(s,1); break;
87 case status_system:
88 switch(status&status_system_bits) {
89 case status_system_sysex:
90 case status_system_end_of_sysex:
91 save_sysex(s); break;
92 case status_system_MTC_quarter_frame:
93 case status_system_song_select:
94 save_data(s,1); break;
95 case status_system_song_position_pointer:
96 save_data(s,2); break;
97 case status_system_tune_request:
98 case status_system_timing_clock: // aka status_system_midi_clock
99 case status_system_midi_tick:
100 case status_system_start: // aka status_system_midi_start
101 case status_system_stop: // aka status_system_midi_stop
102 case status_system_continue: // aka status_system_midi_continue
103 case status_system_active_sense:
104 break; /* XXX: ensure there is no data? */
105 case status_system_meta: // also reset, but not for the purpose of midi file
106 s.put(meta_status&0xFF);
107 if(!s.good())
108 throw exception_output_error(CODEPOINT,"Error writing meta event");
109 writeVL(s,data.size());
110 save_data(s);
111 break;
112 default:
113 throw exception(CODEPOINT,"Internal error");
114 break;
115 }
116 break;
117 default:
118 throw exception(CODEPOINT,"Internal error");
119 break;
120 }
121 }
122
123 void message_t::load(int& rs,istream& s) {
124 data.clear();
125 status = s.get();
126 if(!s.good())
127 throw exception_input_error(CODEPOINT,"Error reading MIDI event status byte");
128 if(status&status_bit) {
129 if((status&status_event_bits)!=status_system)
130 rs = status;
131 }else{
132 if(rs<0)
133 throw exception_invalid_input(CODEPOINT,"Attempt to rely on the absent running status");
134 data.push_back(status);
135 status = rs;
136 }
137 switch(status&status_event_bits) {
138 case status_note_off:
139 case status_note_on:
140 case status_polyphonic_key_pressure: // a.k.a. status_aftertouch
141 case status_control_change:
142 case status_pitch_wheel_change:
143 load_data(s,2); break;
144 case status_program_change:
145 case status_channel_pressure:
146 load_data(s,1); break;
147 case status_system:
148 switch(status&status_system_bits) {
149 case status_system_sysex:
150 case status_system_end_of_sysex:
151 load_sysex(s); break;
152 case status_system_MTC_quarter_frame:
153 case status_system_song_select:
154 load_data(s,1); break;
155 case status_system_song_position_pointer:
156 load_data(s,2); break;
157 case status_system_tune_request:
158 case status_system_timing_clock: // a.k.a. status_system_midi_clock
159 case status_system_midi_tick:
160 case status_system_start: // a.k.a. status_system_midi_start
161 case status_system_stop: // a.k.a. status_system_midi_stop
162 case status_system_continue: // a.k.a. status_system_midi_continue
163 case status_system_active_sense:
164 break;
165 case status_system_meta: // also, reset, but not in midi files
166 {
167 meta_status = s.get();
168 if(!s.good())
169 throw exception_input_error(CODEPOINT,"Error reading meta event type");
170 int l = readVL(s);
171 load_data(s,l);
172 }
173 break;
174 default:
175 throw exception(CODEPOINT,"Internal error");
176 break;
177 }
178 break;
179 default:
180 throw exception(CODEPOINT,"Internal error");
181 break;
182 }
183 }
184
185 void message_t::save_data(ostream& s,int c) const {
186 if(c!=data.size())
187 throw exception(CODEPOINT,"Writing corrupt data");
188 save_data(s);
189 }
190
191 void message_t::save_data(ostream& s) const {
192 for(bytes_t::const_iterator i=data.begin();i!=data.end();++i)
193 s.put(*i);
194 if(!s.good())
195 throw exception_output_error(CODEPOINT,"Error writing MIDI message data");
196 }
197
198 void message_t::load_data(istream& s,int c) {
199 c -= data.size();
200 if(c<0)
201 throw exception(CODEPOINT,"Internal error");
202 while(c-- > 0) {
203 data.push_back(s.get());
204 if(!s.good())
205 throw exception_input_error(CODEPOINT,"Error reading MIDI data");
206 }
207 }
208
209 void message_t::save_sysex(ostream& s) const {
210 save_data(s);
211 s.put(0xF7); /* XXX: Or is it better to put it into data? */
212 if(!s.good())
213 throw exception_output_error(CODEPOINT,"Error writing sysex data");
214 }
215
216 void message_t::load_sysex(istream& s) {
217 int b = s.get();
218 if(!s.good())
219 throw exception_input_error(CODEPOINT,"Error reading sysex data");
220 assert(!(b&0x80)); // manufacturer ought to be 7 bit. not sure if it belongs here, it may well be continuation.
221 do {
222 data.push_back(b);
223 b = s.get();
224 if(!s.good())
225 throw exception_input_error(CODEPOINT,"Error reading sysex data");
226 }while(b!=0xF7);
227 }
228
229 void message_t::dump(ostream& s) const {
230 std::ios::fmtflags ff = s.flags();
231 int w = s.width(2);
232 s.unsetf(std::ios::dec); s.setf(std::ios::hex);
233 s << "status=" << status;
234 if(is_meta()) {
235 s << ", meta_status=" << meta_status;
236 }
237 if(!data.empty()) {
238 s << ", data: ";
239 copy(
240 data.begin(), data.end(),
241 ostream_iterator<int>(s," ") );
242 }
243 s.width(w);
244 s.flags(ff);
245 }
246
247}
diff --git a/lib/util.cc b/lib/util.cc
new file mode 100644
index 0000000..4bbe6f3
--- a/dev/null
+++ b/lib/util.cc
@@ -0,0 +1,96 @@
1#include <midillo/util.h>
2#include <midillo/exception.h>
3
4namespace midillo {
5
6 unsigned long read32(istream& s) {
7 unsigned long rv = 0;
8 for(int t=0;t<4;++t) {
9 rv<<=8;
10 rv|=0xFF&s.get();
11 if(!s.good())
12 throw exception_input_error(CODEPOINT,"Input error");
13 }
14 return rv;
15 }
16
17 unsigned int read16(istream& s) {
18 unsigned int rv = 0;
19 for(int t=0;t<2;++t) {
20 rv<<=8;
21 rv|=0xFF&s.get();
22 if(!s.good())
23 throw exception_input_error(CODEPOINT,"Input error");
24 }
25 return rv;
26 }
27
28 unsigned long readVL(istream& s) {
29 unsigned long rv=s.get();
30 if(!s.good())
31 throw exception_input_error(CODEPOINT,"Error reading VLQ");
32 int b;
33 if(rv&0x80) {
34 rv&=0x7F;
35 do {
36 rv = (rv<<7)|( (b=s.get())&0x7F );
37 if(!s.good())
38 throw exception_input_error(CODEPOINT,"Error reading VLQ");
39 }while(b&0x80);
40 }
41 return rv;
42 }
43
44 void write32(ostream& s,unsigned long d) {
45 for(int t=3;t>=0;--t) {
46 s.put(((const char*)&d)[t]);
47 if(!s.good())
48 throw exception_output_error(CODEPOINT,"Output error");
49 }
50 }
51
52 void write16(ostream& s,unsigned int d) {
53 for(int t=1;t>=0;--t) {
54 s.put(((const char*)&d)[t]);
55 if(!s.good())
56 throw exception_output_error(CODEPOINT,"Output error");
57 }
58 }
59
60 void writeVL(ostream& s,unsigned long d) {
61 // TODO: I don't think this is perfectly written code
62 unsigned long tmp = d&0x7F;
63 while(d>>=7) {
64 tmp<<=8;
65 tmp |=((d&0x7F)|0x80);
66 }
67 for(;;) {
68 s.put(tmp&0xFF);
69 if(!s.good())
70 throw exception_output_error(CODEPOINT,"Error writing VLQ");
71 if(tmp&0x80)
72 tmp>>=8;
73 else
74 break;
75 }
76 }
77
78 unsigned long calcVLsize(unsigned long d) {
79 unsigned long rv = 0;
80 // TODO: imperfect code revisited
81 unsigned long tmp = d&0x7F;
82 while(d>>=7) {
83 tmp<<=8;
84 tmp |=((d&0x7F)|0x80);
85 }
86 for(;;) {
87 ++rv;
88 if(tmp&0x80)
89 tmp>>=8;
90 else
91 break;
92 }
93 return rv;
94 }
95
96}
diff --git a/man/.gitignore b/man/.gitignore
new file mode 100644
index 0000000..3dda729
--- a/dev/null
+++ b/man/.gitignore
@@ -0,0 +1,2 @@
1Makefile.in
2Makefile
diff --git a/man/Makefile.am b/man/Makefile.am
new file mode 100644
index 0000000..13bcb82
--- a/dev/null
+++ b/man/Makefile.am
@@ -0,0 +1,3 @@
1man_MANS = midi2f0.1 midifilter.1 mididump.1
2
3EXTRA_DIST=${man_MANS}
diff --git a/man/midi2f0.1 b/man/midi2f0.1
new file mode 100644
index 0000000..ae89ea8
--- a/dev/null
+++ b/man/midi2f0.1
@@ -0,0 +1,85 @@
1.TH midi2f0 1 "August 11th, 2006" "midi2f0(1)" "Klever Group (http://www.klever.net/)"
2.hla en
3
4.SH NAME
5
6midi2f0 \- Standard MIDI File converter
7
8.SH SYNOPSYS
9
10\fBmidi2f0\fR
11[\fB-h\fR | \fB--help\fR | \fB--usage\fR]
12[\fB-V\fR | \fB--version\fR]
13[\fB-L\fR | \fB--license\fR]
14[<input-file>[ <output-file>]]
15
16.SH DESCRIPTION
17
18midi2f0 converts Standard MIDI Files to Standard MIDI Files format 0, which
19is single track midi file. You may want to perform such conversion before
20putting the file on the memory card for some MIDI keyboard consumption.
21
22if you want to load file from standard input or dump results to standard output
23just omit corresponding file or specify '-'.
24
25.SH OPTIONS
26
27.TP
28\fB-h\fR, \fB--help\fR, \fB--usage\fR
29Display short usage message and exit.
30.TP
31\fB-V\fR, \fB--version\fR
32Report version and exit.
33.TP
34\fB-L\fR, \fB--license\fR
35Show licensing terms.
36
37.SH EXAMPLE
38
39.TP
40.nf
41\fBmidi2f0\fR midifile.mid \\
42| \fBmidifilter\fR \fB-f\fR \fBsysex,meta_unknown,meta_obsolete,meta_texts\fR \\
43>/mnt/card/casio_md/midifile.mid
44.fi
45
46This command converts file to SMF0 file, strips events not understood and not
47used by the keyboard and puts it to the memory card.
48
49.SH EXIT STATUS
50
51Zero in case of success, non-zero otherwise.
52
53.SH AUTHOR
54
55Written by Michael 'hacker' Krelin <hacker@klever.net>
56
57.SH COPYRIGHT
58
59Copyright (c) 2006 Klever Group (http://www.klever.net/)
60
61Permission is hereby granted, free of charge, to any person obtaining a copy of
62this software and associated documentation files (the "Software"), to deal in
63the Software without restriction, including without limitation the rights to
64use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
65of the Software, and to permit persons to whom the Software is furnished to do
66so, subject to the following conditions:
67
68The above copyright notice and this permission notice shall be included in all
69copies or substantial portions of the Software.
70
71THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
72IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
73FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
74AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
75LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
76OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
77SOFTWARE.
78
79.SH BUGS
80
81You tell me. Send reports to <midillo-bugs@klever.net>
82
83.SH SEE ALSO
84\fBmidifilter\fR(1)
85\fBmididump\fR(1)
diff --git a/man/mididump.1 b/man/mididump.1
new file mode 100644
index 0000000..e236ddc
--- a/dev/null
+++ b/man/mididump.1
@@ -0,0 +1,72 @@
1.TH mididump 1 "August 11th, 2006" "mididump(1)" "Klever Group (http://www.klever.net/)"
2.hla en
3
4.SH NAME
5
6mididump \- Standard MIDI File dump
7
8.SH SYNOPSYS
9
10\fBmididump\fR
11[\fB-h\fR | \fB--help\fR | \fB--usage\fR]
12[\fB-V\fR | \fB--version\fR]
13[\fB-L\fR | \fB--license\fR]
14[<input-file>[ <output-file>]]
15
16.SH DESCRIPTION
17
18mididump outputs ascii representation of the input SMF file. At this point it
19may only be useful for debugging purpose.
20
21if you want to load file from standard input or dump results to standard output
22just omit corresponding file or specify '-'.
23
24.SH OPTIONS
25
26.TP
27\fB-h\fR, \fB--help\fR, \fB--usage\fR
28Display short usage message and exit.
29.TP
30\fB-V\fR, \fB--version\fR
31Report version and exit.
32.TP
33\fB-L\fR, \fB--license\fR
34Show licensing terms.
35
36.SH EXIT STATUS
37
38Zero in case of success, non-zero otherwise.
39
40.SH AUTHOR
41
42Written by Michael 'hacker' Krelin <hacker@klever.net>
43
44.SH COPYRIGHT
45
46Copyright (c) 2006 Klever Group (http://www.klever.net/)
47
48Permission is hereby granted, free of charge, to any person obtaining a copy of
49this software and associated documentation files (the "Software"), to deal in
50the Software without restriction, including without limitation the rights to
51use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
52of the Software, and to permit persons to whom the Software is furnished to do
53so, subject to the following conditions:
54
55The above copyright notice and this permission notice shall be included in all
56copies or substantial portions of the Software.
57
58THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
59IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
60FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
61AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
62LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
63OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
64SOFTWARE.
65
66.SH BUGS
67
68You tell me. Send reports to <midillo-bugs@klever.net>
69
70.SH SEE ALSO
71\fBmidi2f0\fR(1)
72\fBmidifilter\fR(1)
diff --git a/man/midifilter.1 b/man/midifilter.1
new file mode 100644
index 0000000..eddd66d
--- a/dev/null
+++ b/man/midifilter.1
@@ -0,0 +1,93 @@
1.TH midifilter 1 "August 11th, 2006" "midifilter(1)" "Klever Group (http://www.klever.net/)"
2.hla en
3
4.SH NAME
5
6midifilter \- Standard MIDI File filter
7
8.SH SYNOPSYS
9
10\fBmidifilter\fR
11[\fB-h\fR | \fB--help\fR | \fB--usage\fR]
12[\fB-V\fR | \fB--version\fR]
13[\fB-L\fR | \fB--license\fR]
14[\fB-f\fR \fI<filters>\fR | \fB--filter=\fI<filters>\fR]
15[\fB-l\fR | \fB--list-filters\fR]
16[<input-file>[ <output-file>]]
17
18.SH DESCRIPTION
19
20midifilter simply strips unwanted events from the Standard MIDI File. You may
21wish to strip some certain events if you know the events may break whatever
22will do any further processing of the file or just to reduce file size.
23
24if you want to load file from standard input or dump results to standard output
25just omit corresponding file or specify '-'.
26
27.SH OPTIONS
28
29.TP
30\fB-h\fR, \fB--help\fR, \fB--usage\fR
31Display short usage message and exit.
32.TP
33\fB-V\fR, \fB--version\fR
34Report version and exit.
35.TP
36\fB-L\fR, \fB--license\fR
37Show licensing terms.
38.TP
39\fB-f\fR \fI<filters>\fR, \fB--filter=\fI<filters\fR
40Specify the list of comma-separated filters to apply.
41.TP
42\fB-l\fR, \fB--list-filters\fR
43List available filters.
44
45.SH EXAMPLE
46
47.TP
48.nf
49\fBmidi2f0\fR midifile.mid \\
50| \fBmidifilter\fR \fB-f\fR \fBsysex,meta_unknown,meta_obsolete,meta_texts\fR \\
51>/mnt/card/casio_md/midifile.mid
52.fi
53
54This command converts file to SMF0 file, strips events not understood and not
55used by the keyboard and puts it to the memory card.
56
57.SH EXIT STATUS
58
59Zero in case of success, non-zero otherwise.
60
61.SH AUTHOR
62
63Written by Michael 'hacker' Krelin <hacker@klever.net>
64
65.SH COPYRIGHT
66
67Copyright (c) 2006 Klever Group (http://www.klever.net/)
68
69Permission is hereby granted, free of charge, to any person obtaining a copy of
70this software and associated documentation files (the "Software"), to deal in
71the Software without restriction, including without limitation the rights to
72use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
73of the Software, and to permit persons to whom the Software is furnished to do
74so, subject to the following conditions:
75
76The above copyright notice and this permission notice shall be included in all
77copies or substantial portions of the Software.
78
79THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
80IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
81FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
82AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
83LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
84OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
85SOFTWARE.
86
87.SH BUGS
88
89You tell me. Send reports to <midillo-bugs@klever.net>
90
91.SH SEE ALSO
92\fBmidi2f0\fR(1)
93\fBmididump\fR(1)
diff --git a/midillo.pc.in b/midillo.pc.in
new file mode 100644
index 0000000..dd57130
--- a/dev/null
+++ b/midillo.pc.in
@@ -0,0 +1,11 @@
1prefix=@prefix@
2exec_prefix=@exec_prefix@
3libdir=@libdir@
4includedir=@includedir@
5
6Name: midillo
7Description: C++ midi manipulation library
8Version: @VERSION@
9Requires: konforka
10Libs: -L${libdir} -lmidillo
11Cflags: -I${includedir}
diff --git a/tools/.gitignore b/tools/.gitignore
new file mode 100644
index 0000000..6d68099
--- a/dev/null
+++ b/tools/.gitignore
@@ -0,0 +1,11 @@
1Makefile.in
2*.o
3midifilter
4midi2f0
5mididump
6.libs
7.deps
8Makefile
9COPYING.cc
10filters_enumeration.cc
11filters_definition.cc
diff --git a/tools/Makefile.am b/tools/Makefile.am
new file mode 100644
index 0000000..811c4f8
--- a/dev/null
+++ b/tools/Makefile.am
@@ -0,0 +1,31 @@
1bin_PROGRAMS = midi2f0 midifilter mididump
2
3INCLUDES = -I${top_srcdir}/include ${KONFORKA_CFLAGS}
4LIBS += ${top_builddir}/lib/libmidillo.la ${KONFORKA_LIBS}
5
6midi2f0_SOURCES = midi2f0.cc \
7 COPYING.cc
8midi2f0_DEPENDENCIES = ${top_builddir}/lib/libmidillo.la
9
10midifilter_SOURCES = midifilter.cc \
11 COPYING.cc \
12 filters.list \
13 enflesh_filters_list.sh
14midifilter_DEPENDENCIES = ${top_builddir}/lib/libmidillo.la
15${srcdir}/midifilter.cc: filters_enumeration.cc filters_definition.cc
16filters_enumeration.cc filters_definition.cc: enflesh_filters_list.sh filters.list
17 sh $^ \
18 filters_enumeration.cc filters_definition.cc
19
20mididump_SOURCES = mididump.cc \
21 COPYING.cc
22mididump_DEPENDENCIES = ${top_builddir}/lib/libmidillo.la
23
24clean-local:
25 rm -f filters_enumeration.cc filters_definition.cc
26
27
28COPYING.cc: ${top_srcdir}/COPYING
29 echo "const char * COPYING =" >$@ || (rm $@;exit 1)
30 sed 's/"/\\"/g' $< | sed 's/^/\"/' | sed 's/$$/\\n\"/' >>$@ || (rm $@;exit 1)
31 echo ";" >>$@ || (rm $@;exit 1)
diff --git a/tools/enflesh_filters_list.sh b/tools/enflesh_filters_list.sh
new file mode 100644
index 0000000..f1d8dfc
--- a/dev/null
+++ b/tools/enflesh_filters_list.sh
@@ -0,0 +1,20 @@
1#!/bin/sh
2srcfile="${1}"
3enumfile="${2}"
4deffile="${3}"
5IFS=':'
6exec 5>${enumfile}
7exec 6>${deffile}
8SEQN=0
9LN=0
10cat ${srcfile} \
11 | while read id ids help ; do
12 LN="`expr ${LN} + 1`"
13 test -z "${id}" && continue
14 test "${id}" != "${id# }" && continue
15 echo "#line ${LN} \"${srcfile}\"" >&5
16 echo " filter_${id} = ${SEQN}," >&5
17 echo "#line ${LN} \"${srcfile}\"" >&6
18 echo ' { { "'$(echo $ids|sed -e 's-/-", "-g')'", 0 }, "'"${help}"'", false },' >&6
19 SEQN="`expr ${SEQN} + 1`"
20 done
diff --git a/tools/filters.list b/tools/filters.list
new file mode 100644
index 0000000..c0fb951
--- a/dev/null
+++ b/tools/filters.list
@@ -0,0 +1,36 @@
1system:system:strip all system messages
2meta:meta:strip all meta events (except for EOT)
3
4sysex:sysex:strip sysex messages
5MTC_quarter_frame:MTC_quarter_frame/quarter_frame:strip 'MTC quarter frame' messages
6song_position_pointer:song_position_pointer:strip 'song position pointer' messages
7song_select:song_select:strip 'song select' messages
8tune_request:tune_request:strip 'tune request' messages
9
10midi_clock:midi_clock/timing_clock:strip 'midi clock' messages
11midi_tick:midi_tick:strip 'midi tick' messages
12midi_start:midi_start/start:strip 'midi start' messages
13midi_continue:midi_continue/continue:strip 'midi continue' messages
14midi_stop:midi_stop/stop:strip 'midi stop' messages
15active_sense:active_sense:strip 'active sense' messages
16
17meta_sequence_number:meta_sequence_number:strip 'sequence number' meta events
18meta_text:meta_text:strip 'text' meta events
19meta_copyright:meta_copyright:strip 'copyright' meta events
20meta_seq_track_name:meta_seq_track_name:strip 'sequence track name' meta events
21meta_instrument:meta_instrument:strip 'instrument' meta events
22meta_lyric:meta_lyric/meta_lyrics:strip 'lyric' meta events
23meta_marker:meta_marker:strip 'marker' meta events
24meta_cue_point:meta_cue_point:strip 'cue point' meta events
25meta_patch_name:meta_patch_name/meta_program_name:strip 'patch name' meta events
26meta_port_name:meta_port_name/meta_device_name:strip 'port name' meta events
27meta_tempo:meta_temp:strip 'tempo' meta events
28meta_SMPTE_offset:meta_SMPTE_offset:strip 'SMPTE offset' meta events
29meta_time_sig:meta_time_sig:strip 'time signature' meta events
30meta_key_sig:meta_key_sig:strip 'key signature' meta events
31meta_proprietary:meta_proprietary:strip 'proprietary' meta events
32
33meta_midi_channel:meta_midi_channel:strip 'midi channel' meta events
34meta_midi_port:meta_midi_port:strip 'midi port' meta events
35
36meta_unknown:meta_unknown:strip meta events not known by midillo
diff --git a/tools/midi2f0.cc b/tools/midi2f0.cc
new file mode 100644
index 0000000..dc95be6
--- a/dev/null
+++ b/tools/midi2f0.cc
@@ -0,0 +1,151 @@
1#include <getopt.h>
2#include <iostream>
3#include <algorithm>
4using namespace std;
5#include <konforka/exception.h>
6#include <midillo/SMF.h>
7using namespace midillo;
8
9#include "config.h"
10#define PHEADER PACKAGE " " VERSION " - midi2f0 - convert to midi format 0"
11#define PCOPY "Copyright (c) 2006 Klever Group"
12
13static void usage(const char *p) {
14 cerr << PHEADER << endl
15 << PCOPY << endl << endl
16 << " " << p << " [options] [<input-file>[ <output-file>]]" << endl << endl
17 << " -h, --help" << endl
18 << " --usage display this text" << endl
19 << " -V, --version display version number" << endl
20 << " -L, --license show license" << endl;
21}
22
23static bool MTrk_is_empty(const MTrk_t& t) {
24 return
25 t.events.empty()
26 || t.events.front().message.is_meta(meta_EOT);
27}
28
29static bool MTrk_deltat_lt(const MTrk_t& a,const MTrk_t& b) {
30 // we assume tracks aren't empty
31 return a.events.front().deltat < b.events.front().deltat;
32}
33
34static bool event_has_nonzero_deltat_or_is_EOT(const event_t& e) {
35 return e.deltat!=0 || e.message.is_meta(meta_EOT);
36}
37
38main(int argc,char **argv) {
39 try {
40 while(true) {
41 static struct option opts[] = {
42 { "help", no_argument, 0, 'h' },
43 { "usage", no_argument, 0, 'h' },
44 { "version", no_argument, 0, 'V' },
45 { "license", no_argument, 0, 'L' },
46 { NULL, 0, 0, 0 }
47 };
48 int c = getopt_long(argc,argv,"hVL",opts,NULL);
49 if(c==-1)
50 break;
51 switch(c) {
52 case 'h':
53 usage(*argv);
54 exit(0);
55 break;
56 case 'V':
57 cerr << VERSION << endl;
58 exit(0);
59 break;
60 case 'L':
61 extern const char *COPYING;
62 cerr << COPYING << endl;
63 exit(0);
64 break;
65 default:
66 cerr << "Huh??" << endl;
67 break;
68 }
69 }
70 const char *infile = "-";
71 if(optind<argc)
72 infile = argv[optind++];
73 const char *oufile = "-";
74 if(optind<argc)
75 oufile = argv[optind++];
76 if(optind<argc) {
77 usage(*argv);
78 exit(1);
79 }
80 SMF_t in(infile);
81 if(in.mthd.fmt==MThd_t::fmt_0) {
82 cerr << "File is already SMF 0" << endl;
83 in.save(oufile);
84 }else if(in.mthd.fmt==MThd_t::fmt_1) {
85 cerr << "Converting from SMF 1 to SMF 0" << endl;
86 SMF_t ou;
87 ou.mthd = in.mthd;
88 ou.mthd.fmt = MThd_t::fmt_0; ou.mthd.ntracks = 1;
89 ou.tracks.resize(1);
90 MTrk_t& mtrk = ou.tracks.front();
91 events_t& evs = mtrk.events;
92 for(;;) {
93 // Cleaning up empty tracks
94 in.tracks.erase(
95 remove_if(
96 in.tracks.begin(),in.tracks.end(),
97 MTrk_is_empty),
98 in.tracks.end() );
99 if(in.tracks.empty())
100 break;
101 // Find the least deltat
102 unsigned long mindt = min_element(
103 in.tracks.begin(), in.tracks.end(),
104 MTrk_deltat_lt )->events.front().deltat;
105 int t=0;
106 bool reset = false;
107 for(SMF_t::tracks_t::iterator i=in.tracks.begin();i!=in.tracks.end();++i) {
108 if(i->events.front().deltat > mindt) {
109 i->events.front().deltat-=mindt;
110 }else{
111 do{
112 evs.splice(
113 evs.end(),
114 i->events,i->events.begin() );
115 if(reset)
116 evs.back().deltat = 0;
117 else
118 reset = true;
119 events_t::iterator lze=find_if(
120 i->events.begin(),i->events.end(),
121 event_has_nonzero_deltat_or_is_EOT );
122 evs.splice(
123 evs.end(),
124 i->events,i->events.begin(),lze );
125 }while( (!MTrk_is_empty(*i)) && i->events.front().deltat==0 );
126 }
127 }
128 }
129 event_t& eot = *evs.append_event();
130 eot.deltat=0;
131 eot.message.status = status_system_meta;
132 eot.message.meta_status = meta_EOT;
133 ou.save(oufile);
134 }else if(in.mthd.fmt==MThd_t::fmt_2) {
135 // TODO
136 cerr << "Not implemented" << endl;
137 }else{
138 cerr << "Unknown MIDI file format" << endl;
139 }
140 return 0;
141 }catch(konforka::exception& e) {
142 cerr << "Oops... Konforka exception:" << endl
143 << " what: " << e.what() << endl
144 << " where: " << e.where() << endl;
145 return 1;
146 }catch(exception& e) {
147 cerr << "Oops... Exception:" << endl
148 << " what: " << e.what() << endl;
149 return 1;
150 }
151}
diff --git a/tools/mididump.cc b/tools/mididump.cc
new file mode 100644
index 0000000..83b7086
--- a/dev/null
+++ b/tools/mididump.cc
@@ -0,0 +1,84 @@
1#include <getopt.h>
2#include <iostream>
3#include <fstream>
4#include <string>
5#include <algorithm>
6using namespace std;
7#include <konforka/exception.h>
8#include <midillo/SMF.h>
9using namespace midillo;
10
11#include "config.h"
12#define PHEADER PACKAGE " " VERSION " - mididump - dump midi files"
13#define PCOPY "Copyright (c) 2006 Klever Group"
14
15static void usage(const char *p) {
16 cerr << PHEADER << endl
17 << PCOPY << endl << endl
18 << " " << p << " [options] [<input-file>[ <output-file>]]" << endl << endl
19 << " -h, --help" << endl
20 << " --usage display this text" << endl
21 << " -V, --version display version number" << endl
22 << " -L, --license show license" << endl;
23}
24
25main(int argc,char **argv) {
26 try {
27 while(true) {
28 static struct option opts[] = {
29 { "help", no_argument, 0, 'h' },
30 { "usage", no_argument, 0, 'h' },
31 { "version", no_argument, 0, 'V' },
32 { "license", no_argument, 0, 'L' },
33 { NULL, 0, 0, 0 }
34 };
35 int c = getopt_long(argc,argv,"f:hVLl",opts,NULL);
36 if(c==-1)
37 break;
38 switch(c) {
39 case 'h':
40 usage(*argv);
41 exit(0);
42 break;
43 case 'V':
44 cerr << VERSION << endl;
45 exit(0);
46 break;
47 case 'L':
48 extern const char *COPYING;
49 cerr << COPYING << endl;
50 exit(0);
51 break;
52 default:
53 cerr << "Huh??" << endl;
54 break;
55 }
56 }
57 const char *infile = "-";
58 if(optind<argc)
59 infile = argv[optind++];
60 const char *oufile = "-";
61 if(optind<argc)
62 oufile = argv[optind++];
63 if(optind<argc) {
64 usage(*argv);
65 exit(1);
66 }
67 SMF_t in(infile);
68 if(strcmp(oufile,"-")) {
69 ofstream s(oufile); s << in;
70 }else{
71 cout << in;
72 }
73 return 0;
74 }catch(konforka::exception& e) {
75 cerr << "Oops... Konforka exception:" << endl
76 << " what: " << e.what() << endl
77 << " where: " << e.where() << endl;
78 return 1;
79 }catch(exception& e) {
80 cerr << "Oops... Exception:" << endl
81 << " what: " << e.what() << endl;
82 return 1;
83 }
84}
diff --git a/tools/midifilter.cc b/tools/midifilter.cc
new file mode 100644
index 0000000..1c130de
--- a/dev/null
+++ b/tools/midifilter.cc
@@ -0,0 +1,295 @@
1#include <getopt.h>
2#include <iostream>
3#include <string>
4#include <algorithm>
5#include <iterator>
6using namespace std;
7#include <konforka/exception.h>
8#include <midillo/SMF.h>
9using namespace midillo;
10
11#include "config.h"
12#define PHEADER PACKAGE " " VERSION " - midifilter - midi filter tool"
13#define PCOPY "Copyright (c) 2006 Klever Group"
14
15enum {
16# include "filters_enumeration.cc"
17 total_filters
18};
19
20struct filter_t {
21 const char *ids[5];
22 const char *help;
23 bool filter;
24} filters[] = {
25# include "filters_definition.cc"
26 {0,0,0}
27};
28#define FILTER(f) filters[filter_##f].filter
29
30inline ostream& operator<<(ostream& s,const filter_t& f) {
31 ios::fmtflags ff = s.flags();
32 int w = s.width(25);
33 s.unsetf(ios::right); s.setf(ios::left);
34 s << *f.ids << " " << f.help;
35 s.width(w);
36 s.flags(ff);
37 return s;
38}
39
40static bool message_is_filtered(const message_t& m) {
41 if(m.is_meta(meta_EOT))
42 return false;
43
44 if(FILTER(sysex) && (m.status==status_system_sysex || m.status==status_system_end_of_sysex))
45 return true;
46 if(FILTER(MTC_quarter_frame) && m.status==status_system_MTC_quarter_frame)
47 return true;
48 if(FILTER(song_position_pointer) && m.status==status_system_song_position_pointer)
49 return true;
50 if(FILTER(song_select) && m.status==status_system_song_select)
51 return true;
52 if(FILTER(tune_request) && m.status==status_system_tune_request)
53 return true;
54 if(FILTER(midi_clock) && m.status==status_system_midi_clock)
55 return true;
56 if(FILTER(midi_tick) && m.status==status_system_midi_tick)
57 return true;
58 if(FILTER(midi_start) && m.status==status_system_midi_start)
59 return true;
60 if(FILTER(midi_continue) && m.status==status_system_midi_continue)
61 return true;
62 if(FILTER(midi_stop) && m.status==status_system_midi_stop)
63 return true;
64 if(FILTER(active_sense) && m.status==status_system_active_sense)
65 return true;
66
67 if(FILTER(meta_sequence_number) && m.is_meta(meta_sequence_number))
68 return true;
69 if(FILTER(meta_text) && m.is_meta(meta_text))
70 return true;
71 if(FILTER(meta_copyright) && m.is_meta(meta_copyright))
72 return true;
73 if(FILTER(meta_seq_track_name) && m.is_meta(meta_seq_track_name))
74 return true;
75 if(FILTER(meta_instrument) && m.is_meta(meta_instrument))
76 return true;
77 if(FILTER(meta_lyric) && m.is_meta(meta_lyric))
78 return true;
79 if(FILTER(meta_marker) && m.is_meta(meta_marker))
80 return true;
81 if(FILTER(meta_cue_point) && m.is_meta(meta_cue_point))
82 return true;
83 if(FILTER(meta_patch_name) && m.is_meta(meta_patch_name))
84 return true;
85 if(FILTER(meta_port_name) && m.is_meta(meta_port_name))
86 return true;
87 if(FILTER(meta_tempo) && m.is_meta(meta_tempo))
88 return true;
89 if(FILTER(meta_SMPTE_offset) && m.is_meta(meta_SMPTE_offset))
90 return true;
91 if(FILTER(meta_time_sig) && m.is_meta(meta_time_sig))
92 return true;
93 if(FILTER(meta_key_sig) && m.is_meta(meta_key_sig))
94 return true;
95 if(FILTER(meta_proprietary) && m.is_meta(meta_proprietary))
96 return true;
97
98 if(FILTER(meta_midi_channel) && m.is_meta(meta_midi_channel))
99 return true;
100 if(FILTER(meta_midi_port) && m.is_meta(meta_midi_port))
101 return true;
102
103 if(FILTER(meta_unknown) && m.is_meta()) {
104 const int known_metas[] = {
105 meta_sequence_number, meta_text, meta_copyright, meta_seq_track_name,
106 meta_instrument, meta_lyric, meta_marker, meta_cue_point,
107 meta_patch_name, meta_port_name, meta_EOT, meta_tempo,
108 meta_SMPTE_offset, meta_time_sig, meta_key_sig, meta_proprietary,
109 meta_midi_channel, meta_midi_port };
110 const int* lastknown = &known_metas[sizeof(known_metas)/sizeof(*known_metas)];
111 if( find(
112 known_metas, lastknown,
113 m.meta_status ) == lastknown ) {
114 return true;
115 }
116 }
117
118 if(FILTER(meta) && m.is_meta())
119 return true;
120
121 return false;
122}
123
124static bool event_is_filtered(const event_t& e) {
125 return message_is_filtered(e.message);
126}
127
128static bool MTrk_is_empty(const MTrk_t& t) {
129 return
130 t.events.empty()
131 || t.events.front().message.is_meta(meta_EOT);
132}
133
134struct filter_preset_t {
135 const char *id;
136 const char *help;
137 int filters[total_filters];
138} filter_presets[] = {
139 { "system_common", "strip system common messages",
140 { filter_sysex, filter_song_position_pointer, filter_song_select,
141 filter_tune_request, -1 } },
142 { "system_runtime", "strip system runtime messages",
143 { filter_midi_clock, filter_midi_tick, filter_midi_start,
144 filter_midi_continue, filter_midi_stop, filter_active_sense, -1 } },
145 { "meta_obsolete", "strip obsolete meta events",
146 { filter_meta_midi_channel, filter_meta_midi_port, -1 } },
147 { "meta_texts", "strip textual meta events",
148 { filter_meta_text, filter_meta_copyright,
149 filter_meta_seq_track_name, filter_meta_instrument,
150 filter_meta_lyric, filter_meta_marker, filter_meta_cue_point,
151 filter_meta_patch_name, filter_meta_port_name, -1 } }
152};
153
154inline ostream& operator<<(ostream& s,const filter_preset_t& fp) {
155 ios::fmtflags ff = s.flags();
156 int w = s.width(25);
157 s.unsetf(ios::right); s.setf(ios::left);
158 s << fp.id << " " << fp.help;
159 s.width(w);
160 s.flags(ff);
161 return s;
162}
163
164static void usage(const char *p) {
165 cerr << PHEADER << endl
166 << PCOPY << endl << endl
167 << " " << p << " [options] [<input-file>[ <output-file>]]" << endl << endl
168 << " -h, --help" << endl
169 << " --usage display this text" << endl
170 << " -V, --version display version number" << endl
171 << " -L, --license show license" << endl
172 << " -f <filters>, --filter=<filters>"
173 << " specify the list of events (comma-separated) to" << endl
174 << " strip" << endl
175 << " -l, --list-filters" << endl
176 << " list available filters" << endl;
177}
178
179main(int argc,char **argv) {
180 try {
181 while(true) {
182 static struct option opts[] = {
183 { "help", no_argument, 0, 'h' },
184 { "usage", no_argument, 0, 'h' },
185 { "version", no_argument, 0, 'V' },
186 { "license", no_argument, 0, 'L' },
187 { "filter", no_argument, 0, 'f' },
188 { "list-filters", no_argument, 0, 'l' },
189 { NULL, 0, 0, 0 }
190 };
191 int c = getopt_long(argc,argv,"f:hVLl",opts,NULL);
192 if(c==-1)
193 break;
194 switch(c) {
195 case 'h':
196 usage(*argv);
197 exit(0);
198 break;
199 case 'V':
200 cerr << VERSION << endl;
201 exit(0);
202 break;
203 case 'L':
204 extern const char *COPYING;
205 cerr << COPYING << endl;
206 exit(0);
207 break;
208 case 'f':
209 {
210 string fs = optarg;
211 while(!fs.empty()) {
212 string::size_type ns = fs.find_first_not_of(" :/,;");
213 if(ns==string::npos)
214 break;
215 if(ns)
216 fs.erase(ns);
217 string::size_type s = fs.find_first_of(" :/,;");
218 string f;
219 if(s==string::npos) {
220 f = fs; fs.clear();
221 }else{
222 f = fs.substr(0,ns);
223 fs.erase(0,ns+1);
224 }
225 for(int fn=0;fn<total_filters;++fn) {
226 filter_t& filter = filters[fn];
227 for(int fid=0;fid<(sizeof(filter.ids)/sizeof(*filter.ids)) && filter.ids[fid];++fid) {
228 if(f == filter.ids[fid])
229 filter.filter = true;
230 }
231 }
232 }
233 }
234 break;
235 case 'l':
236 cerr << PHEADER << endl
237 << PCOPY << endl << endl;
238 copy(
239 filters, &filters[total_filters],
240 ostream_iterator<filter_t>(cerr,"\n") );
241 copy(
242 filter_presets, &filter_presets[sizeof(filter_presets)/sizeof(*filter_presets)],
243 ostream_iterator<filter_preset_t>(cerr,"\n") );
244 exit(0);
245 break;
246 default:
247 cerr << "Huh??" << endl;
248 break;
249 }
250 }
251 const char *infile = "-";
252 if(optind<argc)
253 infile = argv[optind++];
254 const char *oufile = "-";
255 if(optind<argc)
256 oufile = argv[optind++];
257 if(optind<argc) {
258 usage(*argv);
259 exit(1);
260 }
261 SMF_t in(infile);
262 for(SMF_t::tracks_t::iterator t=in.tracks.begin();t!=in.tracks.end();++t) {
263 for(events_t::iterator e=t->events.begin();e!=t->events.end();) {
264 if(event_is_filtered(*e)) {
265 events_t::iterator i = e++;
266 // we assume it is not the last event, since the last event
267 // (meta_EOT) is unfilterable
268 e->deltat += i->deltat;
269 t->events.erase(i);
270 }else
271 ++e;
272 }
273 }
274 in.tracks.erase(
275 remove_if(
276 in.tracks.begin(),in.tracks.end(),
277 MTrk_is_empty),
278 in.tracks.end() );
279 if(in.tracks.empty()) {
280 cerr << "We have no MIDI data in the output file";
281 }
282 in.mthd.ntracks = in.tracks.size();
283 in.save(oufile);
284 return 0;
285 }catch(konforka::exception& e) {
286 cerr << "Oops... Konforka exception:" << endl
287 << " what: " << e.what() << endl
288 << " where: " << e.where() << endl;
289 return 1;
290 }catch(exception& e) {
291 cerr << "Oops... Exception:" << endl
292 << " what: " << e.what() << endl;
293 return 1;
294 }
295}